mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-01-30 21:32:50 +00:00
rsx fifo: Stability improvements
* Restore stack in fifo error handling * Update get register after the cmd execution * Fix put pause in the middle of command * Add restore points when branching to self * Precise nopcmd detection * Test all invalid cmds for early treatment of queue corruption
This commit is contained in:
parent
835a552d8d
commit
87988e9da8
@ -18,6 +18,23 @@ namespace rsx
|
||||
m_ctrl = pctrl->ctrl;
|
||||
}
|
||||
|
||||
void FIFO_control::inc_get()
|
||||
{
|
||||
m_internal_get += 4;
|
||||
|
||||
// Check if put allows to procceed execution
|
||||
while (m_ctrl->put == m_internal_get)
|
||||
{
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
sync_get();
|
||||
std::this_thread::yield();
|
||||
}
|
||||
}
|
||||
|
||||
void FIFO_control::set_put(u32 put)
|
||||
{
|
||||
if (m_ctrl->put == put)
|
||||
@ -63,7 +80,15 @@ namespace rsx
|
||||
{
|
||||
m_command_reg += m_command_inc;
|
||||
m_args_ptr += 4;
|
||||
m_remaining_commands--;
|
||||
|
||||
if (--m_remaining_commands)
|
||||
{
|
||||
inc_get();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_internal_get += 4;
|
||||
}
|
||||
|
||||
data.reg = m_command_reg;
|
||||
data.value = vm::read32(m_args_ptr);
|
||||
@ -129,16 +154,7 @@ namespace rsx
|
||||
data = { cmd, 0, m_internal_get };
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (UNLIKELY((cmd & RSX_METHOD_NOP_MASK) == RSX_METHOD_NOP_CMD))
|
||||
{
|
||||
m_ctrl->get.store(m_internal_get + 4);
|
||||
data = { RSX_METHOD_NOP_CMD, 0, m_internal_get };
|
||||
return;
|
||||
}
|
||||
else if (UNLIKELY(cmd & 0x3))
|
||||
{
|
||||
// Malformed command, optional recovery
|
||||
data.reg = FIFO_ERROR;
|
||||
return;
|
||||
@ -154,29 +170,27 @@ namespace rsx
|
||||
}
|
||||
|
||||
verify(HERE), !m_remaining_commands;
|
||||
u32 count = (cmd >> 18) & 0x7ff;
|
||||
const u32 count = (cmd >> 18) & 0x7ff;
|
||||
|
||||
if (!count)
|
||||
{
|
||||
m_ctrl->get.store(m_internal_get + 4);
|
||||
data.reg = FIFO_NOP;
|
||||
return;
|
||||
}
|
||||
|
||||
if (count > 1)
|
||||
{
|
||||
// Stop command execution if put will be equal to get ptr during the execution itself
|
||||
if (UNLIKELY(count * 4 + 4 > put - m_internal_get))
|
||||
{
|
||||
count = (put - m_internal_get) / 4 - 1;
|
||||
}
|
||||
|
||||
// Set up readback parameters
|
||||
m_command_reg = cmd & 0xfffc;
|
||||
m_command_inc = ((cmd & RSX_METHOD_NON_INCREMENT_CMD_MASK) == RSX_METHOD_NON_INCREMENT_CMD) ? 0 : 4;
|
||||
m_remaining_commands = count - 1;
|
||||
}
|
||||
|
||||
m_ctrl->get.store(m_internal_get + (count * 4 + 4));
|
||||
data = { m_command_reg, vm::read32(m_args_ptr), m_internal_get };
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ctrl->get.store(m_internal_get + 8);
|
||||
data = { cmd & 0xfffc, vm::read32(m_args_ptr), m_internal_get };
|
||||
}
|
||||
inc_get();
|
||||
m_internal_get += 4;
|
||||
|
||||
data = { cmd & 0xfffc, vm::read32(m_args_ptr), m_internal_get };
|
||||
}
|
||||
|
||||
flattening_helper::flattening_helper()
|
||||
@ -376,6 +390,16 @@ namespace rsx
|
||||
// Check for special FIFO commands
|
||||
switch (cmd)
|
||||
{
|
||||
case FIFO::FIFO_NOP:
|
||||
{
|
||||
if (performance_counters.state == FIFO_state::running)
|
||||
{
|
||||
performance_counters.FIFO_idle_timestamp = get_system_time();
|
||||
performance_counters.state = FIFO_state::nop;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
case FIFO::FIFO_EMPTY:
|
||||
{
|
||||
if (performance_counters.state == FIFO_state::running)
|
||||
@ -400,6 +424,7 @@ namespace rsx
|
||||
// Error. Should reset the queue
|
||||
LOG_ERROR(RSX, "FIFO error: possible desync event");
|
||||
fifo_ctrl->set_get(restore_point);
|
||||
m_return_addr = restore_ret;
|
||||
std::this_thread::sleep_for(1ms);
|
||||
return;
|
||||
}
|
||||
@ -415,6 +440,7 @@ namespace rsx
|
||||
if (performance_counters.state == FIFO_state::running)
|
||||
{
|
||||
performance_counters.FIFO_idle_timestamp = get_system_time();
|
||||
sync_point_request = true;
|
||||
}
|
||||
|
||||
performance_counters.state = FIFO_state::spinning;
|
||||
@ -433,6 +459,7 @@ namespace rsx
|
||||
if (performance_counters.state == FIFO_state::running)
|
||||
{
|
||||
performance_counters.FIFO_idle_timestamp = get_system_time();
|
||||
sync_point_request = true;
|
||||
}
|
||||
|
||||
performance_counters.state = FIFO_state::spinning;
|
||||
@ -474,16 +501,6 @@ namespace rsx
|
||||
// If we reached here, this is likely an error
|
||||
fmt::throw_exception("Unexpected command 0x%x" HERE, cmd);
|
||||
}
|
||||
else if (cmd == RSX_METHOD_NOP_CMD)
|
||||
{
|
||||
if (performance_counters.state == FIFO_state::running)
|
||||
{
|
||||
performance_counters.FIFO_idle_timestamp = get_system_time();
|
||||
performance_counters.state = FIFO_state::nop;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (performance_counters.state != FIFO_state::running)
|
||||
{
|
||||
@ -580,5 +597,7 @@ namespace rsx
|
||||
method(this, reg, value);
|
||||
}
|
||||
}
|
||||
|
||||
fifo_ctrl->sync_get();
|
||||
}
|
||||
}
|
@ -6,6 +6,7 @@
|
||||
#include <Utilities/Thread.h>
|
||||
|
||||
#include "rsx_utils.h"
|
||||
#include "Emu/Cell/lv2/sys_rsx.h"
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
@ -26,7 +27,7 @@ namespace rsx
|
||||
{
|
||||
enum internal_commands : u32
|
||||
{
|
||||
NOP = 0,
|
||||
FIFO_NOP = 0xBABEF1F4,
|
||||
FIFO_EMPTY = 0xDEADF1F0,
|
||||
FIFO_BUSY = 0xBABEF1F0,
|
||||
FIFO_ERROR = 0xDEADBEEF,
|
||||
@ -108,6 +109,8 @@ namespace rsx
|
||||
FIFO_control(rsx::thread* pctrl);
|
||||
~FIFO_control() {}
|
||||
|
||||
void sync_get() { m_ctrl->get.store(m_internal_get); }
|
||||
void inc_get();
|
||||
void set_get(u32 get, bool spinning = false);
|
||||
void set_put(u32 put);
|
||||
|
||||
|
@ -676,6 +676,7 @@ namespace rsx
|
||||
if (sync_point_request)
|
||||
{
|
||||
restore_point = ctrl->get;
|
||||
restore_ret = m_return_addr;
|
||||
sync_point_request = false;
|
||||
}
|
||||
|
||||
|
@ -369,7 +369,7 @@ namespace rsx
|
||||
protected:
|
||||
std::thread::id m_rsx_thread;
|
||||
atomic_t<bool> m_rsx_thread_exiting{true};
|
||||
s32 m_return_addr{-1}, restore_ret_addr{-1};
|
||||
s32 m_return_addr{-1}, restore_ret{-1};
|
||||
std::array<push_buffer_vertex_info, 16> vertex_push_buffers;
|
||||
std::vector<u32> element_push_buffer;
|
||||
|
||||
|
@ -1060,7 +1060,7 @@ enum Method
|
||||
RSX_METHOD_RETURN_MASK = 0xffff0003,
|
||||
|
||||
RSX_METHOD_NOP_CMD = 0x00000000,
|
||||
RSX_METHOD_NOP_MASK = 0x1ffc0000,
|
||||
RSX_METHOD_NOP_MASK = 0xbfff0003,
|
||||
};
|
||||
|
||||
//Fog
|
||||
|
Loading…
x
Reference in New Issue
Block a user