Run occlusion queries when requested by a game

This commit is contained in:
Marcin Mikołajczyk 2025-05-26 23:53:51 +01:00
parent abdc557262
commit cb69968d47
3 changed files with 37 additions and 6 deletions

View File

@ -621,13 +621,13 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span<const u32> dcb, std::span<c
if ((event->Address<u64>() & 0x8) == 0) { if ((event->Address<u64>() & 0x8) == 0) {
// occlusion query start // occlusion query start
if (rasterizer) { if (rasterizer) {
rasterizer->StartOcclusionQuery(); rasterizer->StartOcclusionQuery(event->Address<VAddr>());
} }
} }
else { else {
// occlusion query end // occlusion query end
if (rasterizer) { if (rasterizer) {
rasterizer->EndOcclusionQuery(); rasterizer->EndOcclusionQuery(event->Address<VAddr>() & ~0xF);
} }
} }
} }

View File

@ -17,6 +17,10 @@
#undef MemoryBarrier #undef MemoryBarrier
#endif #endif
namespace {
const int OCCLUSION_QUERIES_COUNT = 16;
}
namespace Vulkan { namespace Vulkan {
static Shader::PushData MakeUserData(const AmdGpu::Liverpool::Regs& regs) { static Shader::PushData MakeUserData(const AmdGpu::Liverpool::Regs& regs) {
@ -43,6 +47,11 @@ Rasterizer::Rasterizer(const Instance& instance_, Scheduler& scheduler_,
liverpool->BindRasterizer(this); liverpool->BindRasterizer(this);
} }
memory->SetRasterizer(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; 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<const void*>(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 } // namespace Vulkan

View File

@ -57,8 +57,8 @@ public:
void StartPredication(); void StartPredication();
void EndPredication(); void EndPredication();
void StartOcclusionQuery(); void StartOcclusionQuery(VAddr addr);
void EndOcclusionQuery(); void EndOcclusionQuery(VAddr addr);
void InlineData(VAddr address, const void* value, u32 num_bytes, bool is_gds); void InlineData(VAddr address, const void* value, u32 num_bytes, bool is_gds);
u32 ReadDataFromGds(u32 gsd_offset); u32 ReadDataFromGds(u32 gsd_offset);
@ -127,6 +127,9 @@ private:
boost::icl::interval_set<VAddr> mapped_ranges; boost::icl::interval_set<VAddr> mapped_ranges;
std::shared_mutex mapped_ranges_mutex; std::shared_mutex mapped_ranges_mutex;
PipelineCache pipeline_cache; PipelineCache pipeline_cache;
vk::QueryPool occlusion_query_pool;
u32 occlusion_current_index{};
std::map<VAddr, u32> occlusion_index_mapping;
boost::container::static_vector< boost::container::static_vector<
std::pair<VideoCore::ImageId, VideoCore::TextureCache::RenderTargetDesc>, 8> std::pair<VideoCore::ImageId, VideoCore::TextureCache::RenderTargetDesc>, 8>