diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 3b2606b902..0aeef5487b 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -763,11 +763,18 @@ namespace rsx sync_point_request.release(false); } - // Execute backend-local tasks first - do_local_task(performance_counters.state); + // Update sub-units every 64 cycles. The local handler is invoked for other functions externally on-demand anyway. + // This avoids expensive calls to check timestamps which involves reading some values from TLS storage on windows. + // If something is going on in the backend that requires an update, set the interrupt bit explicitly. + if ((m_cycles_counter++ & 63) == 0 || + m_graphics_state & (rsx::pipeline_state::backend_interrupt_bits)) + { + // Execute backend-local tasks first + do_local_task(performance_counters.state); - // Update sub-units - zcull_ctrl->update(this); + // Update other sub-units + zcull_ctrl->update(this); + } // Execute FIFO queue run_FIFO(); @@ -2952,6 +2959,8 @@ namespace rsx m_invalidated_memory_range = unmap_range; } + + m_graphics_state |= rsx::pipeline_state::backend_interrupt; } } @@ -3143,6 +3152,7 @@ namespace rsx async_flip_buffer = buffer; async_flip_requested |= flip_request::emu_requested; + m_graphics_state |= rsx::pipeline_state::backend_interrupt; } } diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index bfd2c7c961..3c0016acc2 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -132,11 +132,15 @@ namespace rsx push_buffer_arrays_dirty = 0x20000, // Push buffers have data written to them (immediate mode vertex buffers) + backend_interrupt = 0x80000000, // Backend interrupt, must serve immediately + fragment_program_dirty = fragment_program_ucode_dirty | fragment_program_state_dirty, vertex_program_dirty = vertex_program_ucode_dirty | vertex_program_state_dirty, invalidate_pipeline_bits = fragment_program_dirty | vertex_program_dirty, invalidate_zclip_bits = vertex_state_dirty | zclip_config_state_dirty, memory_barrier_bits = framebuffer_reads_dirty, + backend_interrupt_bits = memory_barrier_bits | backend_interrupt, + all_dirty = ~0u }; @@ -424,6 +428,7 @@ namespace rsx { u64 timestamp_ctrl = 0; u64 timestamp_subvalue = 0; + u64 m_cycles_counter = 0; display_flip_info_t m_queued_flip{}; diff --git a/rpcs3/Emu/RSX/RSXZCULL.cpp b/rpcs3/Emu/RSX/RSXZCULL.cpp index f32f5c0946..0621b17697 100644 --- a/rpcs3/Emu/RSX/RSXZCULL.cpp +++ b/rpcs3/Emu/RSX/RSXZCULL.cpp @@ -14,7 +14,22 @@ namespace rsx } ZCULL_control::~ZCULL_control() - {} + { + std::scoped_lock lock(m_pages_mutex); + + for (auto& block : m_locked_pages) + { + for (auto& p : block) + { + if (p.second.prot != utils::protection::rw) + { + utils::memory_protect(vm::base(p.first), 4096, utils::protection::rw); + } + } + + block.clear(); + } + } void ZCULL_control::set_active(class ::rsx::thread* ptimer, bool state, bool flush_queue) { diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index 3155ea3e86..c552666384 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -804,6 +804,7 @@ bool VKGSRender::on_access_violation(u32 address, bool is_writing) g_fxo->get().set_mem_fault_flag(); m_queue_status |= flush_queue_state::deadlock; + m_graphics_state |= rsx::pipeline_state::backend_interrupt; // Wait for deadlock to clear while (m_queue_status & flush_queue_state::deadlock) @@ -1646,6 +1647,9 @@ void VKGSRender::sync_hint(rsx::FIFO_hint hint, void* args) void VKGSRender::do_local_task(rsx::FIFO_state state) { + // Clear interrupt bit if set + m_graphics_state &= ~rsx::pipeline_state::backend_interrupt; + if (m_queue_status & flush_queue_state::deadlock) { // Clear offloader deadlock