mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-08 07:51:28 +12:00
rsx: Robustness fixes
- Track last working state and reset to it if RSX starts to desync -- This is especially useful when running vulkan since the renderer will easily outpace the rest of the system when merely recording draw commands - Ignore empty sets -- Mark empty/invalid IB sets as having 0 element counts.
This commit is contained in:
parent
198e9dce1d
commit
ee009ec99c
6 changed files with 46 additions and 10 deletions
|
@ -244,6 +244,7 @@ s32 sys_rsx_context_attribute(s32 context_id, u32 package_id, u64 a3, u64 a4, u6
|
||||||
render->ctrl->get = a3;
|
render->ctrl->get = a3;
|
||||||
render->ctrl->put = a4;
|
render->ctrl->put = a4;
|
||||||
render->internal_get = a3;
|
render->internal_get = a3;
|
||||||
|
render->restore_point = a3;
|
||||||
render->unpause();
|
render->unpause();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -134,6 +134,12 @@ namespace
|
||||||
command.raw_index_buffer, ptr, type, rsx::method_registers.current_draw_clause.primitive,
|
command.raw_index_buffer, ptr, type, rsx::method_registers.current_draw_clause.primitive,
|
||||||
rsx::method_registers.current_draw_clause.first_count_commands, vertex_count);
|
rsx::method_registers.current_draw_clause.first_count_commands, vertex_count);
|
||||||
|
|
||||||
|
if (min_index >= max_index)
|
||||||
|
{
|
||||||
|
//empty set, do not draw
|
||||||
|
return{ 0, 0, 0, 0, std::make_tuple(get_index_type(type), offset_in_index_buffer) };
|
||||||
|
}
|
||||||
|
|
||||||
//check for vertex arrays with frquency modifiers
|
//check for vertex arrays with frquency modifiers
|
||||||
for (auto &block : m_vertex_layout.interleaved_blocks)
|
for (auto &block : m_vertex_layout.interleaved_blocks)
|
||||||
{
|
{
|
||||||
|
|
|
@ -388,6 +388,7 @@ namespace rsx
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (Emu.IsPaused())
|
while (Emu.IsPaused())
|
||||||
std::this_thread::sleep_for(10ms);
|
std::this_thread::sleep_for(10ms);
|
||||||
|
|
||||||
|
@ -490,6 +491,22 @@ namespace rsx
|
||||||
while (external_interrupt_lock.load()) _mm_pause();
|
while (external_interrupt_lock.load()) _mm_pause();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Set up restore state if needed
|
||||||
|
if (sync_point_request)
|
||||||
|
{
|
||||||
|
if (RSXIOMem.RealAddr(internal_get))
|
||||||
|
{
|
||||||
|
//New internal get is valid, use it
|
||||||
|
restore_point = internal_get.load();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_ERROR(RSX, "Could not update FIFO restore point");
|
||||||
|
}
|
||||||
|
|
||||||
|
sync_point_request = false;
|
||||||
|
}
|
||||||
|
|
||||||
//Now load the FIFO ctrl registers
|
//Now load the FIFO ctrl registers
|
||||||
ctrl->get.store(internal_get.load());
|
ctrl->get.store(internal_get.load());
|
||||||
const u32 put = ctrl->put;
|
const u32 put = ctrl->put;
|
||||||
|
@ -513,13 +530,13 @@ namespace rsx
|
||||||
|
|
||||||
if (mem_faults_count >= 3)
|
if (mem_faults_count >= 3)
|
||||||
{
|
{
|
||||||
LOG_ERROR(RSX, "Application has failed to recover, discarding FIFO queue");
|
LOG_ERROR(RSX, "Application has failed to recover, resetting FIFO queue");
|
||||||
internal_get = put;
|
internal_get = restore_point.load();;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mem_faults_count++;
|
mem_faults_count++;
|
||||||
std::this_thread::sleep_for(1ms);
|
std::this_thread::sleep_for(10ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
invalid_command_interrupt_raised = true;
|
invalid_command_interrupt_raised = true;
|
||||||
|
@ -581,13 +598,13 @@ namespace rsx
|
||||||
|
|
||||||
if (mem_faults_count >= 3)
|
if (mem_faults_count >= 3)
|
||||||
{
|
{
|
||||||
LOG_ERROR(RSX, "Application has failed to recover, discarding FIFO queue");
|
LOG_ERROR(RSX, "Application has failed to recover, resetting FIFO queue");
|
||||||
internal_get = put;
|
internal_get = restore_point.load();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mem_faults_count++;
|
mem_faults_count++;
|
||||||
std::this_thread::sleep_for(1ms);
|
std::this_thread::sleep_for(10ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
invalid_command_interrupt_raised = true;
|
invalid_command_interrupt_raised = true;
|
||||||
|
@ -735,7 +752,8 @@ namespace rsx
|
||||||
{
|
{
|
||||||
//This is almost guaranteed to be heap corruption at this point
|
//This is almost guaranteed to be heap corruption at this point
|
||||||
//Ignore the rest of the chain
|
//Ignore the rest of the chain
|
||||||
internal_get = put;
|
LOG_ERROR(RSX, "FIFO contents may be corrupted. Resetting...");
|
||||||
|
internal_get = restore_point.load();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -233,6 +233,7 @@ namespace rsx
|
||||||
public:
|
public:
|
||||||
RsxDmaControl* ctrl = nullptr;
|
RsxDmaControl* ctrl = nullptr;
|
||||||
atomic_t<u32> internal_get{ 0 };
|
atomic_t<u32> internal_get{ 0 };
|
||||||
|
atomic_t<u32> restore_point{ 0 };
|
||||||
atomic_t<bool> external_interrupt_lock{ false };
|
atomic_t<bool> external_interrupt_lock{ false };
|
||||||
atomic_t<bool> external_interrupt_ack{ false };
|
atomic_t<bool> external_interrupt_ack{ false };
|
||||||
|
|
||||||
|
@ -309,6 +310,7 @@ namespace rsx
|
||||||
public:
|
public:
|
||||||
std::set<u32> m_used_gcm_commands;
|
std::set<u32> m_used_gcm_commands;
|
||||||
bool invalid_command_interrupt_raised = false;
|
bool invalid_command_interrupt_raised = false;
|
||||||
|
bool sync_point_request = false;
|
||||||
bool in_begin_end = false;
|
bool in_begin_end = false;
|
||||||
|
|
||||||
bool conditional_render_test_failed = false;
|
bool conditional_render_test_failed = false;
|
||||||
|
|
|
@ -153,6 +153,9 @@ namespace
|
||||||
dst = gsl::span<gsl::byte>(static_cast<gsl::byte*>(buf), upload_size);
|
dst = gsl::span<gsl::byte>(static_cast<gsl::byte*>(buf), upload_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<std::tuple<VkDeviceSize, VkIndexType>> index_info =
|
||||||
|
std::make_tuple(offset_in_index_buffer, vk::get_index_type(index_type));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Upload index (and expands it if primitive type is not natively supported).
|
* Upload index (and expands it if primitive type is not natively supported).
|
||||||
*/
|
*/
|
||||||
|
@ -165,6 +168,13 @@ namespace
|
||||||
rsx::method_registers.restart_index(), command.ranges_to_fetch_in_index_buffer,
|
rsx::method_registers.restart_index(), command.ranges_to_fetch_in_index_buffer,
|
||||||
[](auto prim) { return !vk::is_primitive_native(prim); });
|
[](auto prim) { return !vk::is_primitive_native(prim); });
|
||||||
|
|
||||||
|
if (min_index >= max_index)
|
||||||
|
{
|
||||||
|
//empty set, do not draw
|
||||||
|
m_index_buffer_ring_info.unmap();
|
||||||
|
return{ prims, 0, 0, 0, 0, index_info };
|
||||||
|
}
|
||||||
|
|
||||||
if (rsx::method_registers.restart_index_enabled() && vk::emulate_primitive_restart())
|
if (rsx::method_registers.restart_index_enabled() && vk::emulate_primitive_restart())
|
||||||
{
|
{
|
||||||
//Emulate primitive restart by breaking up the draw calls
|
//Emulate primitive restart by breaking up the draw calls
|
||||||
|
@ -180,9 +190,6 @@ namespace
|
||||||
|
|
||||||
m_index_buffer_ring_info.unmap();
|
m_index_buffer_ring_info.unmap();
|
||||||
|
|
||||||
std::optional<std::tuple<VkDeviceSize, VkIndexType>> index_info =
|
|
||||||
std::make_tuple(offset_in_index_buffer, vk::get_index_type(index_type));
|
|
||||||
|
|
||||||
//check for vertex arrays with frquency modifiers
|
//check for vertex arrays with frquency modifiers
|
||||||
for (auto &block : m_vertex_layout.interleaved_blocks)
|
for (auto &block : m_vertex_layout.interleaved_blocks)
|
||||||
{
|
{
|
||||||
|
|
|
@ -62,6 +62,7 @@ namespace rsx
|
||||||
|
|
||||||
void semaphore_acquire(thread* rsx, u32 _reg, u32 arg)
|
void semaphore_acquire(thread* rsx, u32 _reg, u32 arg)
|
||||||
{
|
{
|
||||||
|
rsx->sync_point_request = true;
|
||||||
const u32 addr = get_address(method_registers.semaphore_offset_406e(), method_registers.semaphore_context_dma_406e());
|
const u32 addr = get_address(method_registers.semaphore_offset_406e(), method_registers.semaphore_context_dma_406e());
|
||||||
if (vm::ps3::read32(addr) == arg) return;
|
if (vm::ps3::read32(addr) == arg) return;
|
||||||
|
|
||||||
|
@ -109,6 +110,7 @@ namespace rsx
|
||||||
|
|
||||||
void semaphore_release(thread* rsx, u32 _reg, u32 arg)
|
void semaphore_release(thread* rsx, u32 _reg, u32 arg)
|
||||||
{
|
{
|
||||||
|
rsx->sync_point_request = true;
|
||||||
const u32 addr = get_address(method_registers.semaphore_offset_406e(), method_registers.semaphore_context_dma_406e());
|
const u32 addr = get_address(method_registers.semaphore_offset_406e(), method_registers.semaphore_context_dma_406e());
|
||||||
|
|
||||||
if (addr >> 28 == 0x4)
|
if (addr >> 28 == 0x4)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue