diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index a809fe9fea..3ecfbd5921 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -93,6 +93,7 @@ void GLGSRender::on_init_thread() gl::set_primary_context_thread(); zcull_ctrl.reset(static_cast<::rsx::reports::ZCULL_control*>(this)); + m_occlusion_type = g_cfg.video.precise_zpass_count ? GL_SAMPLES_PASSED : GL_ANY_SAMPLES_PASSED; gl::init(); @@ -1061,13 +1062,13 @@ void GLGSRender::notify_tile_unbound(u32 tile) void GLGSRender::begin_occlusion_query(rsx::reports::occlusion_query_info* query) { query->result = 0; - glBeginQuery(GL_ANY_SAMPLES_PASSED, query->driver_handle); + glBeginQuery(m_occlusion_type, query->driver_handle); } void GLGSRender::end_occlusion_query(rsx::reports::occlusion_query_info* query) { ensure(query->active); - glEndQuery(GL_ANY_SAMPLES_PASSED); + glEndQuery(m_occlusion_type); } bool GLGSRender::check_occlusion_query_status(rsx::reports::occlusion_query_info* query) @@ -1097,6 +1098,6 @@ void GLGSRender::discard_occlusion_query(rsx::reports::occlusion_query_info* que if (query->active) { //Discard is being called on an active query, close it - glEndQuery(GL_ANY_SAMPLES_PASSED); + glEndQuery(m_occlusion_type); } } diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.h b/rpcs3/Emu/RSX/GL/GLGSRender.h index 1ad11c3350..c3d3b5565c 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.h +++ b/rpcs3/Emu/RSX/GL/GLGSRender.h @@ -139,6 +139,9 @@ private: std::unordered_map> m_null_textures; std::vector m_scratch_buffer; + // Occlusion query type, can be SAMPLES_PASSED or ANY_SAMPLES_PASSED + GLenum m_occlusion_type = GL_ANY_SAMPLES_PASSED; + public: u64 get_cycles() final; GLGSRender(); diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 48b57d7cd3..b5eb716f33 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -3377,7 +3377,10 @@ namespace rsx switch (type) { case CELL_GCM_ZPASS_PIXEL_CNT: - value = value ? u16{umax} : 0; + if (!g_cfg.video.precise_zpass_count) + { + value = value ? u16{ umax } : 0; + } break; case CELL_GCM_ZCULL_STATS3: value = value ? 0 : u16{umax}; @@ -3470,7 +3473,9 @@ namespace rsx ensure(query->pending); const bool implemented = (writer.type == CELL_GCM_ZPASS_PIXEL_CNT || writer.type == CELL_GCM_ZCULL_STATS3); - if (implemented && !result && query->num_draws) + const bool have_result = result && !g_cfg.video.precise_zpass_count; + + if (implemented && !have_result && query->num_draws) { get_occlusion_query_result(query); @@ -3622,55 +3627,30 @@ namespace rsx ensure(query->pending); const bool implemented = (writer.type == CELL_GCM_ZPASS_PIXEL_CNT || writer.type == CELL_GCM_ZCULL_STATS3); - if (force_read) - { - if (implemented && !result && query->num_draws) - { - get_occlusion_query_result(query); + const bool have_result = result && !g_cfg.video.precise_zpass_count; - if (query->result) - { - result += query->result; - if (query->data_type & CELL_GCM_ZPASS_PIXEL_CNT) - { - m_statistics_map[writer.counter_tag] += query->result; - } - } - } - else + if (!implemented || !query->num_draws || have_result) + { + discard_occlusion_query(query); + } + else if (force_read || check_occlusion_query_status(query)) + { + get_occlusion_query_result(query); + + if (query->result) { - //No need to read this - discard_occlusion_query(query); + result += query->result; + if (query->data_type & CELL_GCM_ZPASS_PIXEL_CNT) + { + m_statistics_map[writer.counter_tag] += query->result; + } } } else { - if (implemented && !result && query->num_draws) - { - //Maybe we get lucky and results are ready - if (check_occlusion_query_status(query)) - { - get_occlusion_query_result(query); - if (query->result) - { - result += query->result; - if (query->data_type & CELL_GCM_ZPASS_PIXEL_CNT) - { - m_statistics_map[writer.counter_tag] += query->result; - } - } - } - else - { - //Too early; abort - break; - } - } - else - { - //Not necessary to read the result anymore - discard_occlusion_query(query); - } + // Too early; abort + ensure(!force_read && implemented); + break; } free_query(query); diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index 3d71b51eec..dcdfc4370f 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -426,6 +426,11 @@ VKGSRender::VKGSRender() : GSRender() for (u32 n = 0; n < occlusion_query_count; ++n) m_occlusion_query_data[n].driver_handle = n; + if (g_cfg.video.precise_zpass_count) + { + m_occlusion_query_manager->set_control_flags(VK_QUERY_CONTROL_PRECISE_BIT, 0); + } + //Generate frame contexts const auto& binding_table = m_device->get_pipeline_binding_table(); const u32 num_fs_samplers = binding_table.vertex_textures_first_bind_slot - binding_table.textures_first_bind_slot; @@ -2437,7 +2442,7 @@ bool VKGSRender::check_occlusion_query_status(rsx::reports::occlusion_query_info if (data.is_current(m_current_command_buffer)) return false; - u32 oldest = data.indices.front(); + const u32 oldest = data.indices.front(); return m_occlusion_query_manager->check_query_status(oldest); } @@ -2468,10 +2473,10 @@ void VKGSRender::get_occlusion_query_result(rsx::reports::occlusion_query_info* // Gather data for (const auto occlusion_id : data.indices) { - // We only need one hit - if (m_occlusion_query_manager->get_query_result(occlusion_id)) + query->result += m_occlusion_query_manager->get_query_result(occlusion_id); + if (query->result && !g_cfg.video.precise_zpass_count) { - query->result = 1; + // We only need one hit unless precise zcull is requested break; } } diff --git a/rpcs3/Emu/RSX/VK/VKQueryPool.cpp b/rpcs3/Emu/RSX/VK/VKQueryPool.cpp index 4fc437e2c8..ad0b8ca83b 100644 --- a/rpcs3/Emu/RSX/VK/VKQueryPool.cpp +++ b/rpcs3/Emu/RSX/VK/VKQueryPool.cpp @@ -20,12 +20,14 @@ namespace vk { query.any_passed = true; query.ready = true; + query.data = result[0]; return true; } else if (result[1]) { query.any_passed = false; query.ready = true; + query.data = 0; return true; } @@ -33,10 +35,11 @@ namespace vk } case VK_NOT_READY: { - if (result[0]) + if (result[0] && (flags & VK_QUERY_RESULT_PARTIAL_BIT)) { query.any_passed = true; query.ready = true; + query.data = result[0]; return true; } @@ -123,6 +126,12 @@ namespace vk } } + void query_pool_manager::set_control_flags(VkQueryControlFlags control_, VkQueryResultFlags result_) + { + control_flags = control_; + result_flags = result_; + } + void query_pool_manager::begin_query(vk::command_buffer& cmd, u32 index) { ensure(query_slot_status[index].active == false); @@ -131,7 +140,7 @@ namespace vk query_info.pool = m_current_query_pool.get(); query_info.active = true; - vkCmdBeginQuery(cmd, *query_info.pool, index, 0);//VK_QUERY_CONTROL_PRECISE_BIT); + vkCmdBeginQuery(cmd, *query_info.pool, index, control_flags); } void query_pool_manager::end_query(vk::command_buffer& cmd, u32 index) @@ -141,20 +150,19 @@ namespace vk bool query_pool_manager::check_query_status(u32 index) { - return poke_query(query_slot_status[index], index, VK_QUERY_RESULT_PARTIAL_BIT); + return poke_query(query_slot_status[index], index, result_flags); } u32 query_pool_manager::get_query_result(u32 index) { // Check for cached result auto& query_info = query_slot_status[index]; - while (!query_info.ready) { - poke_query(query_info, index, VK_QUERY_RESULT_PARTIAL_BIT); + poke_query(query_info, index, result_flags); } - return query_info.any_passed ? 1 : 0; + return query_info.data; } void query_pool_manager::get_query_result_indirect(vk::command_buffer& cmd, u32 index, VkBuffer dst, VkDeviceSize dst_offset) diff --git a/rpcs3/Emu/RSX/VK/VKQueryPool.h b/rpcs3/Emu/RSX/VK/VKQueryPool.h index 65b8838486..f235e7bbf6 100644 --- a/rpcs3/Emu/RSX/VK/VKQueryPool.h +++ b/rpcs3/Emu/RSX/VK/VKQueryPool.h @@ -16,13 +16,17 @@ namespace vk bool any_passed; bool active; bool ready; + u32 data; }; std::vector> m_consumed_pools; std::unique_ptr m_current_query_pool; std::deque m_available_slots; u32 m_pool_lifetime_counter = 0; + VkQueryType query_type = VK_QUERY_TYPE_OCCLUSION; + VkQueryResultFlags result_flags = VK_QUERY_RESULT_PARTIAL_BIT; + VkQueryControlFlags control_flags = 0; vk::render_device* owner = nullptr; std::vector query_slot_status; @@ -36,6 +40,8 @@ namespace vk query_pool_manager(vk::render_device& dev, VkQueryType type, u32 num_entries); ~query_pool_manager(); + void set_control_flags(VkQueryControlFlags control_flags, VkQueryResultFlags result_flags); + void begin_query(vk::command_buffer& cmd, u32 index); void end_query(vk::command_buffer& cmd, u32 index); diff --git a/rpcs3/Emu/system_config.h b/rpcs3/Emu/system_config.h index 0123110d80..ceafe41f63 100644 --- a/rpcs3/Emu/system_config.h +++ b/rpcs3/Emu/system_config.h @@ -156,6 +156,7 @@ struct cfg_root : cfg::node cfg::_bool relaxed_zcull_sync{ this, "Relaxed ZCULL Sync", false }; cfg::_bool enable_3d{ this, "Enable 3D", false }; cfg::_bool debug_program_analyser{ this, "Debug Program Analyser", false }; + cfg::_bool precise_zpass_count{ this, "Accurate ZCULL stats", false }; cfg::_int<1, 8> consecutive_frames_to_draw{ this, "Consecutive Frames To Draw", 1, true}; cfg::_int<1, 8> consecutive_frames_to_skip{ this, "Consecutive Frames To Skip", 1, true}; cfg::_int<50, 800> resolution_scale_percent{ this, "Resolution Scale", 100 };