diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 8cca45e57b..8e7c4135f1 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -3095,5 +3095,16 @@ namespace rsx update(ptimer, sync_address); } } + + occlusion_query_info* ZCULL_control::find_query(vm::addr_t sink_address) + { + for (auto &writer : m_pending_writes) + { + if (writer.sink == sink_address) + return writer.query; + } + + return nullptr; + } } } diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index aaa27e233c..2825979372 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -397,6 +397,9 @@ namespace rsx // Check for pending writes bool has_pending() const { return !m_pending_writes.empty(); } + // Search for query synchronized at address + occlusion_query_info* find_query(vm::addr_t sink_address); + // Backend methods (optional, will return everything as always visible by default) virtual void begin_occlusion_query(occlusion_query_info* /*query*/) {} virtual void end_occlusion_query(occlusion_query_info* /*query*/) {} @@ -614,7 +617,7 @@ namespace rsx // sync void sync(); void read_barrier(u32 memory_address, u32 memory_range); - virtual void sync_hint(FIFO_hint /*hint*/) {} + virtual void sync_hint(FIFO_hint /*hint*/, u32 /*arg*/) {} gsl::span get_raw_index_array(const draw_clause& draw_indexed_clause) const; gsl::span get_raw_vertex_buffer(const rsx::data_array_format_info&, u32 base_offset, const draw_clause& draw_array_clause) const; diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index 15693169ed..6b0f810cd9 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -2157,15 +2157,26 @@ void VKGSRender::flush_command_queue(bool hard_sync) open_command_buffer(); } -void VKGSRender::sync_hint(rsx::FIFO_hint hint) +void VKGSRender::sync_hint(rsx::FIFO_hint hint, u32 arg) { + // Occlusion test result evaluation is coming up, avoid a hard sync if (hint == rsx::FIFO_hint::hint_conditional_render_eval) { - if (m_current_command_buffer->flags & vk::command_buffer::cb_has_occlusion_task) + // Occlusion queries not enabled, do nothing + if (!(m_current_command_buffer->flags & vk::command_buffer::cb_has_occlusion_task)) + return; + + // If a flush request is already enqueued, do nothing + if (m_flush_requests.pending()) + return; + + // Check if the required report is synced to this CB + if (auto occlusion_info = zcull_ctrl->find_query(vm::cast(arg))) { - // Occlusion test result evaluation is coming up, avoid a hard sync - if (!m_flush_requests.pending()) + auto& data = m_occlusion_map[occlusion_info->driver_handle]; + if (data.command_buffer_to_wait == m_current_command_buffer && !data.indices.empty()) { + // Confirmed hard sync coming up, post a sync request m_flush_requests.post(false); m_flush_requests.remove_one(); } diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.h b/rpcs3/Emu/RSX/VK/VKGSRender.h index b19ec8fa3d..4d65be19c7 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.h +++ b/rpcs3/Emu/RSX/VK/VKGSRender.h @@ -463,7 +463,7 @@ public: void set_scissor(bool clip_viewport); void bind_viewport(); - void sync_hint(rsx::FIFO_hint hint) override; + void sync_hint(rsx::FIFO_hint hint, u32 arg) override; void begin_occlusion_query(rsx::reports::occlusion_query_info* query) override; void end_occlusion_query(rsx::reports::occlusion_query_info* query) override; diff --git a/rpcs3/Emu/RSX/rsx_methods.cpp b/rpcs3/Emu/RSX/rsx_methods.cpp index 39aa5d359a..233332feac 100644 --- a/rpcs3/Emu/RSX/rsx_methods.cpp +++ b/rpcs3/Emu/RSX/rsx_methods.cpp @@ -581,7 +581,7 @@ namespace rsx } // Defer conditional render evaluation - rsx->sync_hint(FIFO_hint::hint_conditional_render_eval); + rsx->sync_hint(FIFO_hint::hint_conditional_render_eval, address_ptr); rsx->conditional_render_test_address = address_ptr; rsx->conditional_render_test_failed = false; }