diff --git a/src/video_core/amdgpu/liverpool.cpp b/src/video_core/amdgpu/liverpool.cpp index 21a2c9288..6e698038c 100644 --- a/src/video_core/amdgpu/liverpool.cpp +++ b/src/video_core/amdgpu/liverpool.cpp @@ -621,13 +621,13 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span dcb, std::spanAddress() & 0x8) == 0) { // occlusion query start if (rasterizer) { - rasterizer->StartOcclusionQuery(); + rasterizer->StartOcclusionQuery(event->Address()); } } else { // occlusion query end if (rasterizer) { - rasterizer->EndOcclusionQuery(); + rasterizer->EndOcclusionQuery(event->Address() & ~0xF); } } } diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 970d68ecb..a9920e310 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -17,6 +17,10 @@ #undef MemoryBarrier #endif +namespace { + const int OCCLUSION_QUERIES_COUNT = 16; +} + namespace Vulkan { static Shader::PushData MakeUserData(const AmdGpu::Liverpool::Regs& regs) { @@ -43,6 +47,11 @@ Rasterizer::Rasterizer(const Instance& instance_, Scheduler& scheduler_, liverpool->BindRasterizer(this); } memory->SetRasterizer(this); + occlusion_query_pool = Check<"occlusion query pool">(instance.GetDevice().createQueryPool({ + .queryType = vk::QueryType::eOcclusion, + .queryCount = OCCLUSION_QUERIES_COUNT, + })); + instance.GetDevice().resetQueryPool(occlusion_query_pool, 0, OCCLUSION_QUERIES_COUNT); } Rasterizer::~Rasterizer() = default; @@ -1271,12 +1280,31 @@ void Rasterizer::EndPredication() { } -void Rasterizer::StartOcclusionQuery() { +void Rasterizer::StartOcclusionQuery(VAddr addr) { + LOG_DEBUG(Render_Vulkan, "addr = {:#x}, index = {}", addr, occlusion_current_index); + const auto cmdbuf = scheduler.CommandBuffer(); + cmdbuf.resetQueryPool(occlusion_query_pool, occlusion_current_index, 1); + ScopeMarkerBegin("gfx:{}:occlusionQuery", fmt::ptr(reinterpret_cast(addr))); + cmdbuf.beginQuery(occlusion_query_pool, occlusion_current_index, vk::QueryControlFlags()); + + occlusion_index_mapping.insert_or_assign(addr, occlusion_current_index); + + occlusion_current_index++; + if (occlusion_current_index > OCCLUSION_QUERIES_COUNT - 1) { + occlusion_current_index = 0; + } } -void Rasterizer::EndOcclusionQuery() { +void Rasterizer::EndOcclusionQuery(VAddr addr) { + ASSERT(occlusion_index_mapping.contains(addr)); + auto index = occlusion_index_mapping[addr]; + LOG_DEBUG(Render_Vulkan, "addr = {:#x}, index = {}", addr, index); + + const auto cmdbuf = scheduler.CommandBuffer(); + cmdbuf.endQuery(occlusion_query_pool, index); + ScopeMarkerEnd(); } } // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h index 22b62e9d4..5be1748a8 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.h +++ b/src/video_core/renderer_vulkan/vk_rasterizer.h @@ -57,8 +57,8 @@ public: void StartPredication(); void EndPredication(); - void StartOcclusionQuery(); - void EndOcclusionQuery(); + void StartOcclusionQuery(VAddr addr); + void EndOcclusionQuery(VAddr addr); void InlineData(VAddr address, const void* value, u32 num_bytes, bool is_gds); u32 ReadDataFromGds(u32 gsd_offset); @@ -127,6 +127,9 @@ private: boost::icl::interval_set mapped_ranges; std::shared_mutex mapped_ranges_mutex; PipelineCache pipeline_cache; + vk::QueryPool occlusion_query_pool; + u32 occlusion_current_index{}; + std::map occlusion_index_mapping; boost::container::static_vector< std::pair, 8>