diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index e48f294a5a..8f8ca783a1 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp @@ -582,6 +582,8 @@ void Maxwell3D::ProcessQueryCondition() { break; } } + + rasterizer->SetConditionalRenderingPredicate(execute_on); } void Maxwell3D::ProcessCounterReset() { diff --git a/src/video_core/query_cache/query_cache.h b/src/video_core/query_cache/query_cache.h index 3aeeb8dcab..849a34f41a 100644 --- a/src/video_core/query_cache/query_cache.h +++ b/src/video_core/query_cache/query_cache.h @@ -381,6 +381,11 @@ void QueryCacheBase::NotifySegment(bool resume) { } } +template +void QueryCacheBase::SetHostConditionalRenderingResult(bool condition_passed) { + impl->runtime.SetHostConditionalRenderingResult(condition_passed); +} + template bool QueryCacheBase::AccelerateHostConditionalRendering() { bool qc_dirty = false; diff --git a/src/video_core/query_cache/query_cache_base.h b/src/video_core/query_cache/query_cache_base.h index 242e24388f..0626b316f5 100644 --- a/src/video_core/query_cache/query_cache_base.h +++ b/src/video_core/query_cache/query_cache_base.h @@ -115,6 +115,8 @@ public: void NotifySegment(bool resume); + void SetHostConditionalRenderingResult(bool condition_passed); + void BindToChannel(s32 id) override; protected: diff --git a/src/video_core/rasterizer_interface.h b/src/video_core/rasterizer_interface.h index 481efbf53b..351f461b5b 100644 --- a/src/video_core/rasterizer_interface.h +++ b/src/video_core/rasterizer_interface.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -146,6 +149,8 @@ public: return false; } + virtual void SetConditionalRenderingPredicate(bool enabled) {} + /// Attempt to use a faster method to perform a surface copy [[nodiscard]] virtual bool AccelerateSurfaceCopy( const Tegra::Engines::Fermi2D::Surface& src, const Tegra::Engines::Fermi2D::Surface& dst, diff --git a/src/video_core/renderer_vulkan/vk_query_cache.cpp b/src/video_core/renderer_vulkan/vk_query_cache.cpp index d8073b5447..64b8c14380 100644 --- a/src/video_core/renderer_vulkan/vk_query_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_query_cache.cpp @@ -226,8 +226,7 @@ public: } PauseCounter(); const auto driver_id = device.GetDriverID(); - if (driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY || - driver_id == VK_DRIVER_ID_ARM_PROPRIETARY || driver_id == VK_DRIVER_ID_MESA_TURNIP) { + if (driver_id == VK_DRIVER_ID_ARM_PROPRIETARY) { ApplyBanksWideOp( pending_sync, [](SamplesQueryBank* bank, size_t start, size_t amount) { bank->Sync(start, amount); }); @@ -253,13 +252,13 @@ public: } }); - total += GetAmendValue(); + const u64 final_total = total + GetAmendValue(); query->value = total; query->flags |= VideoCommon::QueryFlagBits::IsHostSynced; query->flags |= VideoCommon::QueryFlagBits::IsFinalValueSynced; direct_sync_values.emplace_back(VideoCommon::SyncValuesStruct{ .address = query->guest_address, - .value = total, + .value = final_total, .size = SamplesQueryBank::QUERY_SIZE, }); @@ -633,16 +632,16 @@ private: std::deque> pending_flush_sets; // State Machine - size_t current_bank_slot; - size_t current_bank_id; - SamplesQueryBank* current_bank; - VkQueryPool current_query_pool; - size_t current_query_id; + size_t current_bank_slot{}; + size_t current_bank_id{}; + SamplesQueryBank* current_bank{}; + VkQueryPool current_query_pool{}; + size_t current_query_id{}; size_t num_slots_used{}; size_t first_accumulation_checkpoint{}; size_t last_accumulation_checkpoint{}; bool accumulation_since_last_sync{}; - VideoCommon::HostQueryBase* current_query; + VideoCommon::HostQueryBase* current_query{}; bool has_started{}; std::mutex flush_guard; @@ -1386,6 +1385,35 @@ void QueryCacheRuntime::ResumeHostConditionalRendering() { impl->is_hcr_running = true; } +void QueryCacheRuntime::SetHostConditionalRenderingResult(bool condition_passed) { + if (!impl->device.IsExtConditionalRendering()) { + return; + } + + const bool was_running = impl->is_hcr_running; + if (was_running) { + PauseHostConditionalRendering(); + } + + impl->scheduler.RequestOutsideRenderPassOperationContext(); + impl->scheduler.Record( + [buffer = *impl->hcr_resolve_buffer, value = condition_passed ? 1u : 0u](vk::CommandBuffer cmdbuf) { + cmdbuf.FillBuffer(buffer, 0, sizeof(u32), value); + }); + + impl->hcr_setup.buffer = *impl->hcr_resolve_buffer; + impl->hcr_setup.offset = 0; + impl->hcr_setup.flags = 0; + impl->hcr_buffer = *impl->hcr_resolve_buffer; + impl->hcr_offset = 0; + impl->hcr_is_set = true; + impl->is_hcr_running = false; + + if (was_running) { + ResumeHostConditionalRendering(); + } +} + void QueryCacheRuntime::HostConditionalRenderingCompareValueImpl(VideoCommon::LookupData object, bool is_equal) { { @@ -1518,7 +1546,7 @@ bool QueryCacheRuntime::HostConditionalRenderingCompareValues(VideoCommon::Looku if (driver_blocks_pair_resolve || !is_gpu_high) { EndHostConditionalRendering(); - return true; + return false; } if (!is_in_bc[0] && !is_in_bc[1]) { diff --git a/src/video_core/renderer_vulkan/vk_query_cache.h b/src/video_core/renderer_vulkan/vk_query_cache.h index e2aa4d991e..563ad43e98 100644 --- a/src/video_core/renderer_vulkan/vk_query_cache.h +++ b/src/video_core/renderer_vulkan/vk_query_cache.h @@ -48,6 +48,8 @@ public: void ResumeHostConditionalRendering(); + void SetHostConditionalRenderingResult(bool condition_passed); + bool HostConditionalRenderingCompareValue(VideoCommon::LookupData object_1, bool qc_dirty); bool HostConditionalRenderingCompareValues(VideoCommon::LookupData object_1, diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 504769689a..fb942dd577 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -1346,6 +1346,10 @@ bool RasterizerVulkan::AccelerateConditionalRendering() { return query_cache.AccelerateHostConditionalRendering(); } +void RasterizerVulkan::SetConditionalRenderingPredicate(bool enabled) { + query_cache.SetHostConditionalRenderingResult(enabled); +} + bool RasterizerVulkan::AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Surface& src, const Tegra::Engines::Fermi2D::Surface& dst, const Tegra::Engines::Fermi2D::Config& copy_config) { diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h index 92889f47e4..2a8df89847 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.h +++ b/src/video_core/renderer_vulkan/vk_rasterizer.h @@ -122,6 +122,7 @@ public: void FlushCommands() override; void TickFrame() override; bool AccelerateConditionalRendering() override; + void SetConditionalRenderingPredicate(bool enabled) override; bool AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Surface& src, const Tegra::Engines::Fermi2D::Surface& dst, const Tegra::Engines::Fermi2D::Config& copy_config) override;