rsx/FIFO: Reimplement grabbing command args as a contiguous pointer

- Allows grabbing indefinite size of buffer as long as the data is contiguously mapped.
This commit is contained in:
kd-11 2025-03-08 20:45:28 +03:00 committed by kd-11
parent ec120d1cbb
commit 93899bf5a9
5 changed files with 35 additions and 21 deletions

View file

@ -96,14 +96,8 @@ namespace rsx
const u32 count = std::min<u32>({ fifo_args_cnt, fifo_read_limit, method_range });
// Clamp by the count of methods this function is responsible to
std::span<const u32> command_span = RSX(ctx)->fifo_ctrl->get_current_arg_ptr();
if (command_span.size() > count)
{
command_span = command_span.subspan(0, count);
}
ensure(!command_span.empty());
std::span<const u32> command_span = RSX(ctx)->fifo_ctrl->get_current_arg_ptr(count);
ensure(!command_span.empty() && command_span.size() <= count);
u32* const dst_regs = &REGS(ctx)->registers[reg];

View file

@ -42,7 +42,7 @@ namespace rsx
const u32 x = REGS(ctx)->nv308a_x() + index;
const u32 y = REGS(ctx)->nv308a_y();
const auto fifo_span = RSX(ctx)->fifo_ctrl->get_current_arg_ptr();
const auto fifo_span = RSX(ctx)->fifo_ctrl->get_current_arg_ptr(count);
if (fifo_span.size() < count)
{

View file

@ -98,7 +98,7 @@ namespace rsx
const auto values = &REGS(ctx)->transform_constants[load + constant_id][subreg];
const auto fifo_span = RSX(ctx)->fifo_ctrl->get_current_arg_ptr();
const auto fifo_span = RSX(ctx)->fifo_ctrl->get_current_arg_ptr(rcount);
if (fifo_span.size() < rcount)
{
@ -148,7 +148,7 @@ namespace rsx
rcount -= max - (max_vertex_program_instructions * 4);
}
const auto fifo_span = RSX(ctx)->fifo_ctrl->get_current_arg_ptr();
const auto fifo_span = RSX(ctx)->fifo_ctrl->get_current_arg_ptr(rcount);
if (fifo_span.size() < rcount)
{

View file

@ -223,22 +223,42 @@ namespace rsx
m_remaining_commands = 0;
}
std::span<const u32> FIFO_control::get_current_arg_ptr() const
std::span<const u32> FIFO_control::get_current_arg_ptr(u32 length_in_words) const
{
if (g_cfg.core.rsx_fifo_accuracy)
{
// Return a pointer to the cache storage with confined access
return {reinterpret_cast<const u32*>(&m_cache) + (m_internal_get - m_cache_addr) / 4, (m_cache_size - (m_internal_get - m_cache_addr)) / 4};
const u32 cache_offset_in_words = (m_internal_get - m_cache_addr) / 4;
const u32 cache_size_in_words = m_cache_size / 4;
return {reinterpret_cast<const u32*>(&m_cache) + cache_offset_in_words, cache_size_in_words - cache_offset_in_words};
}
else
{
// Return a raw pointer with no limited access
constexpr u32 _1m = 0x100000;
const u32 base = m_iotable->get_addr(m_internal_get);
const u32 base_1m = m_iotable->get_addr(m_internal_get + _1m);
return {static_cast<const u32*>(vm::base(base)), (base_1m - _1m == base ? _1m : (_1m - (m_internal_get % _1m))) / 4 };
// Return a raw pointer to contiguous memory
constexpr u32 _1M = 0x100000;
const u32 size = length_in_words * sizeof(u32);
const u32 from = m_iotable->get_addr(m_internal_get);
for (u32 remaining = size, addr = m_internal_get, ptr = from; remaining > 0;)
{
const u32 next_block = utils::align(addr, _1M);
const u32 available = (next_block - addr);
if (remaining <= available)
{
return { static_cast<const u32*>(vm::base(from)), length_in_words };
}
remaining -= available;
const u32 next_ptr = m_iotable->get_addr(next_block);
if (next_ptr != (ptr + available))
{
return { static_cast<const u32*>(vm::base(from)), (size - remaining) / sizeof(u32)};
}
ptr = next_ptr;
addr = next_block;
}
fmt::throw_exception("Unreachable");
}
bool FIFO_control::read_unsafe(register_pair& data)

View file

@ -159,7 +159,7 @@ namespace rsx
u32 get_pos() const { return m_internal_get; }
u32 last_cmd() const { return m_cmd; }
void sync_get() const;
std::span<const u32> get_current_arg_ptr() const;
std::span<const u32> get_current_arg_ptr(u32 length_in_words) const;
u32 get_remaining_args_count() const { return m_remaining_commands; }
void restore_state(u32 cmd, u32 count);
void inc_get(bool wait);