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 154f223621..64b8c14380 100644 --- a/src/video_core/renderer_vulkan/vk_query_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_query_cache.cpp @@ -1385,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) { { @@ -1517,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;