From fb5ecec455cf6c67154134429485ffccbfc34203 Mon Sep 17 00:00:00 2001 From: nmzik Date: Sun, 2 Aug 2026 14:14:32 +0200 Subject: [PATCH] renderer: ignore stale stencil state for depth-only targets --- .../host_gpu/renderer/depthRenderTarget.cpp | 18 ++++----- tests/ShaderRecompilerComputeTests.cpp | 37 +++++++++++++++++++ 2 files changed, 46 insertions(+), 9 deletions(-) diff --git a/src/graphics/host_gpu/renderer/depthRenderTarget.cpp b/src/graphics/host_gpu/renderer/depthRenderTarget.cpp index 83f2e915c..eda3b1c4b 100644 --- a/src/graphics/host_gpu/renderer/depthRenderTarget.cpp +++ b/src/graphics/host_gpu/renderer/depthRenderTarget.cpp @@ -96,9 +96,11 @@ void RenderExecutor::ResolveRenderDepthTarget(uint64_t submit_id, RenderCommandB const auto& dc = hw.GetDepthControl(); const auto& sc = hw.GetStencilControl(); const auto& sm = hw.GetStencilMask(); - const bool depth_active = + const bool has_stencil = + z.stencil_info.format != Prospero::GpuEnumValue(Prospero::StencilFormat::kInvalid); + const bool depth_active = dc.z_enable || dc.z_write_enable || dc.depth_bounds_enable || rc.depth_clear_enable; - const bool stencil_active = dc.stencil_enable || rc.stencil_clear_enable; + const bool stencil_active = has_stencil && (dc.stencil_enable || rc.stencil_clear_enable); if (!depth_active && !stencil_active) { return; } @@ -139,8 +141,6 @@ void RenderExecutor::ResolveRenderDepthTarget(uint64_t submit_id, RenderCommandB } return; } - const bool has_stencil = - z.stencil_info.format != Prospero::GpuEnumValue(Prospero::StencilFormat::kInvalid); const bool has_htile = z.z_info.htile_acceleration; const auto samples = render_sample_count(z.z_info.num_samples); if (samples == 0) { @@ -156,8 +156,8 @@ void RenderExecutor::ResolveRenderDepthTarget(uint64_t submit_id, RenderCommandB DepthFatal("invalid depth view: base=%u last=%u", z.depth_view.slice_start, z.depth_view.slice_max); } - if ((stencil_active && !has_stencil) || rc.resummarize_enable || rc.copy_centroid || - rc.copy_sample != 0 || z.z_info.expclear_enabled || z.stencil_info.expclear_enabled || + if (rc.resummarize_enable || rc.copy_centroid || rc.copy_sample != 0 || + z.z_info.expclear_enabled || z.stencil_info.expclear_enabled || z.z_info.partially_resident || z.stencil_info.partially_resident || z.z_info.max_mip_level != 0 || z.depth_view.current_mip_level != 0 || z.depth_info.addr5_swizzle_mask != 0 || z.depth_info.array_mode != 0 || @@ -279,10 +279,10 @@ void RenderExecutor::ResolveRenderDepthTarget(uint64_t submit_id, RenderCommandB r.depth_min_bounds = hw.GetDepthBoundsMin(); r.depth_max_bounds = hw.GetDepthBoundsMax(); - r.stencil_clear_enable = rc.stencil_clear_enable; + r.stencil_clear_enable = has_stencil && rc.stencil_clear_enable; r.stencil_clear_value = hw.GetStencilClearValue(); - r.stencil_test_enable = dc.stencil_enable; - if (dc.stencil_enable) { + r.stencil_test_enable = has_stencil && dc.stencil_enable; + if (r.stencil_test_enable) { if (dc.stencilfunc > static_cast(vk::CompareOp::eAlways) || (dc.backface_enable && dc.stencilfunc_bf > static_cast(vk::CompareOp::eAlways)) || diff --git a/tests/ShaderRecompilerComputeTests.cpp b/tests/ShaderRecompilerComputeTests.cpp index 8da259a46..58046bc3c 100644 --- a/tests/ShaderRecompilerComputeTests.cpp +++ b/tests/ShaderRecompilerComputeTests.cpp @@ -5520,6 +5520,43 @@ public: "state at the final acquisition boundary"); RenderExecutorTestAccess::ResetBindings(executor); + constexpr uint64_t depth_only_address = base + 0x140000; + HW::DepthRenderTarget depth_only_target {}; + depth_only_target.z_info.format = + Prospero::GpuEnumValue(Prospero::DepthFormat::kZ32F); + depth_only_target.z_info.z_compare_base = Prospero::ZCompareBase::kZMax; + depth_only_target.stencil_info.htile_stencil_disabled = true; + depth_only_target.z_read_base_addr = depth_only_address; + depth_only_target.z_write_base_addr = depth_only_address; + depth_only_target.size = {63, 63, true}; + registers.SetDepthRenderTarget(depth_only_target); + HW::DepthControl depth_only_control {}; + depth_only_control.stencil_enable = true; + depth_only_control.z_enable = true; + depth_only_control.z_write_enable = true; + depth_only_control.zfunc = static_cast(vk::CompareOp::eAlways); + registers.SetDepthControl(depth_only_control); + HW::RenderControl depth_only_render_control {}; + depth_only_render_control.depth_clear_enable = true; + depth_only_render_control.stencil_clear_enable = true; + registers.SetRenderControl(depth_only_render_control); + RenderDepthInfo depth_only {}; + RenderExecutorTestAccess::ResolveRenderDepthTarget(executor, 1, scheduler.Current(), + depth_only); + Require( + name, "depth-only target with stale stencil state", + depth_only.image_id && depth_only.format == vk::Format::eD32Sfloat && + depth_only.depth_test_enable && depth_only.depth_write_enable && + depth_only.depth_clear_enable && !depth_only.stencil_test_enable && + !depth_only.stencil_clear_enable && depth_only.stencil_buffer_vaddr == 0 && + depth_only.stencil_buffer_size == 0 && depth_only.desc.info.stencil.Empty() && + depth_only.depth_buffer_size != 0 && + depth_only_address + depth_only.depth_buffer_size <= base + allocation_size && + depth_only.vaddr_num == 1 && + depth_only.AttachmentWriteAspects() == vk::ImageAspectFlagBits::eDepth, + "raw stencil test or clear state leaked into a depth-only attachment"); + RenderExecutorTestAccess::ResetBindings(executor); + auto video_subresource = make_target_desc(base + 0x20000, target_mip_size, {1, 1, 1}); video_subresource.type = BindingType::VideoOut; video_subresource.info.pixel_format = vk::Format::eR8G8B8A8Srgb;