From 2a543108766c322a59e98f817c5f92c547f149ae Mon Sep 17 00:00:00 2001 From: nmzik Date: Mon, 7 Sep 2026 07:12:58 +0400 Subject: [PATCH] render: fix depth write state before choosing layouts Co-authored-by: MehmetCambaz --- src/graphics/host_gpu/renderer/debug.cpp | 72 ------------------- .../host_gpu/renderer/depthRenderTarget.cpp | 7 +- .../host_gpu/renderer/depthRenderTarget.h | 5 +- src/graphics/host_gpu/renderer/renderDraw.cpp | 3 +- tests/ShaderRecompilerComputeTests.cpp | 21 +++++- 5 files changed, 24 insertions(+), 84 deletions(-) diff --git a/src/graphics/host_gpu/renderer/debug.cpp b/src/graphics/host_gpu/renderer/debug.cpp index ecc211dfc..396685a92 100644 --- a/src/graphics/host_gpu/renderer/debug.cpp +++ b/src/graphics/host_gpu/renderer/debug.cpp @@ -385,75 +385,6 @@ static void ZPrint(const char* func, const HW::DepthRenderTarget& z) { z.size.valid ? "true" : "false"); } -// NOLINTNEXTLINE(readability-function-cognitive-complexity) -static void ZCheck(const HW::DepthRenderTarget& z, const HW::DepthControl& dc, - const HW::RenderControl& rc) { - const bool depth_active = dc.z_enable || dc.z_write_enable || dc.depth_bounds_enable || - rc.depth_clear_enable || rc.copy_depth_to_color; - const bool stencil_active = - dc.stencil_enable || rc.stencil_clear_enable || rc.copy_stencil_to_color; - if (!depth_active && !stencil_active) { - return; - } - - EXIT_NOT_IMPLEMENTED(rc.copy_depth_to_color || rc.copy_stencil_to_color); - EXIT_NOT_IMPLEMENTED(!z.z_info.HasValidTextureCompatibility()); - EXIT_NOT_IMPLEMENTED(!z.stencil_info.HasValidTextureCompatibility()); - if (z.z_info.format == Prospero::DepthFormat::kInvalid) { - EXIT_NOT_IMPLEMENTED(z.z_info.num_samples != 0); - EXIT_NOT_IMPLEMENTED(z.z_info.htile_acceleration != false); - EXIT_NOT_IMPLEMENTED(z.z_info.expclear_enabled != false); - EXIT_NOT_IMPLEMENTED(z.z_info.partially_resident != false); - EXIT_NOT_IMPLEMENTED(z.z_info.max_mip_level != 0); - } else { - EXIT_NOT_IMPLEMENTED(z.z_info.format != Prospero::DepthFormat::kZ16 && - z.z_info.format != Prospero::DepthFormat::kZ32F); - if (z.z_info.num_samples != 0x00000000) { - static bool logged = false; - if (!logged) { - LOGF("DepthTarget: using native num_samples=0x%08" PRIx32 "\n", - z.z_info.num_samples); - logged = true; - } - } - EXIT_NOT_IMPLEMENTED(z.z_info.expclear_enabled != false); - EXIT_NOT_IMPLEMENTED(z.z_info.partially_resident != false); - EXIT_NOT_IMPLEMENTED(z.z_info.max_mip_level != 0); - } - - if (z.stencil_info.format != Prospero::StencilFormat::kInvalid) { - EXIT_NOT_IMPLEMENTED(z.stencil_info.format != Prospero::StencilFormat::k8UInt); - } - EXIT_NOT_IMPLEMENTED(z.stencil_info.expclear_enabled != false); - EXIT_NOT_IMPLEMENTED(z.stencil_info.partially_resident != false); - - if (z.z_info.format != Prospero::DepthFormat::kInvalid || - z.stencil_info.format != Prospero::StencilFormat::kInvalid) { - if (z.depth_view.current_mip_level != 0x00000000) { - static std::atomic log_count {0}; - if (log_count.fetch_add(1, std::memory_order_relaxed) < 16) { - LOGF("DepthTarget: temporary: ignoring PS5 current mip level=0x%08" PRIx32 "\n", - z.depth_view.current_mip_level); - } - } - if (z.depth_view.depth_write_disable || z.depth_view.stencil_write_disable) { - static std::atomic log_count {0}; - if (log_count.fetch_add(1, std::memory_order_relaxed) < 16) { - LOGF("DepthTarget: honoring write disable depth=%s, stencil=%s\n", - z.depth_view.depth_write_disable ? "true" : "false", - z.depth_view.stencil_write_disable ? "true" : "false"); - } - } - EXIT_NOT_IMPLEMENTED(!z.depth_view.depth_write_disable && - z.z_read_base_addr != z.z_write_base_addr); - EXIT_NOT_IMPLEMENTED(!z.depth_view.stencil_write_disable && - z.stencil_read_base_addr != z.stencil_write_base_addr); - EXIT_NOT_IMPLEMENTED(!z.depth_view.depth_write_disable && z.z_write_base_addr == 0); - // EXIT_NOT_IMPLEMENTED(z.htile_data_base_addr == 0); - EXIT_NOT_IMPLEMENTED(!z.size.valid); - } -} - static void ClipPrint(const char* func, const HW::ClipControl& c) { LOGF("%s\n", func); @@ -977,7 +908,6 @@ void hw_check(const CommandBuffer& buffer) { const auto& bc = hw.GetBlendControl(rt_slot); const auto& bclr = hw.GetBlendColor(); const auto& vp = hw.GetScreenViewport(); - const auto& z = hw.GetDepthRenderTarget(); const auto& c = hw.GetClipControl(); const auto& rc = hw.GetRenderControl(); const auto& d = hw.GetDepthControl(); @@ -1003,8 +933,6 @@ void hw_check(const CommandBuffer& buffer) { RtCheck(rt); log_phase("vp"); VpCheck(vp, smc); - log_phase("z"); - ZCheck(z, d, rc); log_phase("clip"); ClipCheck(c); log_phase("rc"); diff --git a/src/graphics/host_gpu/renderer/depthRenderTarget.cpp b/src/graphics/host_gpu/renderer/depthRenderTarget.cpp index ecbb23790..5836915b5 100644 --- a/src/graphics/host_gpu/renderer/depthRenderTarget.cpp +++ b/src/graphics/host_gpu/renderer/depthRenderTarget.cpp @@ -108,7 +108,7 @@ void RenderExecutor::ResolveRenderDepthTarget(uint64_t submit_id, CommandBuffer& const auto& sc = hw.GetStencilControl(); const auto& sm = hw.GetStencilMask(); const bool has_stencil = z.stencil_info.format != Prospero::StencilFormat::kInvalid; - const bool depth_active = dc.z_enable || dc.z_write_enable || dc.depth_bounds_enable || + const bool depth_active = dc.z_enable || dc.depth_bounds_enable || rc.depth_clear_enable || rc.copy_depth_to_color; const bool stencil_active = has_stencil && (dc.stencil_enable || rc.stencil_clear_enable || rc.copy_stencil_to_color); @@ -239,7 +239,8 @@ void RenderExecutor::ResolveRenderDepthTarget(uint64_t submit_id, CommandBuffer& r.depth_load_clear_enable = r.depth_clear_enable; r.depth_clear_value = hw.GetDepthClearValue(); r.depth_test_enable = dc.z_enable; - r.depth_write_enable = dc.z_write_enable && !z.depth_view.depth_write_disable; + r.depth_write_enable = r.depth_test_enable && dc.z_write_enable && + !z.depth_view.depth_write_disable && !r.depth_clear_enable; r.depth_compare_op = static_cast(dc.zfunc); r.depth_bounds_test_enable = dc.depth_bounds_enable; @@ -328,7 +329,7 @@ vk::ImageAspectFlags RenderDepthInfo::AttachmentWriteAspects() const { const auto available = ImageViewOps::DepthAspectMask(format); vk::ImageAspectFlags writes {}; if ((available & vk::ImageAspectFlagBits::eDepth) && - (depth_load_clear_enable || (depth_test_enable && depth_write_enable))) { + (depth_load_clear_enable || depth_write_enable)) { writes |= vk::ImageAspectFlagBits::eDepth; } if (!(available & vk::ImageAspectFlagBits::eStencil)) { diff --git a/src/graphics/host_gpu/renderer/depthRenderTarget.h b/src/graphics/host_gpu/renderer/depthRenderTarget.h index 65500ee8b..b8150bbcb 100644 --- a/src/graphics/host_gpu/renderer/depthRenderTarget.h +++ b/src/graphics/host_gpu/renderer/depthRenderTarget.h @@ -26,6 +26,7 @@ struct RenderDepthInfo { bool depth_meta_clear_enable = false; float depth_clear_value = 0.0f; bool depth_test_enable = false; + // Effective draw writes; discovery applies test, target-write and clear controls. bool depth_write_enable = false; vk::CompareOp depth_compare_op = vk::CompareOp::eNever; bool depth_bounds_test_enable = false; @@ -43,10 +44,6 @@ struct RenderDepthInfo { [[nodiscard]] vk::ImageAspectFlags AttachmentWriteAspects() const; }; -inline bool depth_attachment_read_only(const RenderDepthInfo& depth) { - return !depth.AttachmentWriteAspects(); -} - inline vk::ImageLayout depth_attachment_layout(const RenderDepthInfo& depth) { const auto available = ImageViewOps::DepthAspectMask(depth.desc.view_info.format); const auto writes = depth.AttachmentWriteAspects(); diff --git a/src/graphics/host_gpu/renderer/renderDraw.cpp b/src/graphics/host_gpu/renderer/renderDraw.cpp index 07b398233..9138d080d 100644 --- a/src/graphics/host_gpu/renderer/renderDraw.cpp +++ b/src/graphics/host_gpu/renderer/renderDraw.cpp @@ -391,8 +391,7 @@ static void SetGraphicsDynamicParams(const CommandBuffer& buffer, vk::CommandBuf const std::array blend_constants {blend.red, blend.green, blend.blue, blend.alpha}; vk_buffer.setBlendConstants(blend_constants.data()); vk_buffer.setDepthTestEnable(depth.depth_test_enable ? VK_TRUE : VK_FALSE); - vk_buffer.setDepthWriteEnable( - depth.depth_write_enable && !depth.depth_clear_enable ? VK_TRUE : VK_FALSE); + vk_buffer.setDepthWriteEnable(depth.depth_write_enable ? VK_TRUE : VK_FALSE); vk_buffer.setDepthCompareOp(depth.depth_compare_op); const auto& mode = ctx.GetModeControl(); diff --git a/tests/ShaderRecompilerComputeTests.cpp b/tests/ShaderRecompilerComputeTests.cpp index 01bf9d256..6235bf4bc 100644 --- a/tests/ShaderRecompilerComputeTests.cpp +++ b/tests/ShaderRecompilerComputeTests.cpp @@ -9574,9 +9574,17 @@ public: phased_depth_target.size.valid = true; registers.SetDepthRenderTarget(phased_depth_target); HW::DepthControl phased_depth_control{}; - phased_depth_control.z_enable = true; phased_depth_control.z_write_enable = true; registers.SetDepthControl(phased_depth_control); + registers.SetRenderControl({}); + RenderDepthInfo disabled_depth{}; + RenderExecutorTestAccess::ResolveRenderDepthTarget( + executor, 1, scheduler.Current(), disabled_depth); + Require(name, "disabled tests with stale depth write enable", + !disabled_depth.image_id, + "a dormant depth write bit bound a depth attachment"); + phased_depth_control.z_enable = true; + registers.SetDepthControl(phased_depth_control); HW::RenderControl phased_render_control{}; phased_render_control.resummarize_enable = true; registers.SetRenderControl(phased_render_control); @@ -9727,7 +9735,7 @@ public: name, "depth-only target with stale stencil state", depth_only.image_id && depth_only.desc.view_info.format == vk::Format::eD32Sfloat && (depth_only.desc.info.metadata.kind == ImageMetadataKind::Htile) && - depth_only.depth_test_enable && depth_only.depth_write_enable && + 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 && @@ -9838,6 +9846,12 @@ public: Require(name, "bounds deferred HTile clear", texture_cache.ClearMeta(depth_only_htile_address), "depth-only HTile was not registered"); + } else { + bounds_target.z_write_base_addr = depth_only_address; + bounds_target.depth_view.depth_write_disable = false; + bounds_control.z_write_enable = true; + registers.SetDepthRenderTarget(bounds_target); + registers.SetDepthControl(bounds_control); } RenderDepthInfo bounds_depth{}; RenderExecutorTestAccess::ResolveRenderDepthTarget( @@ -26397,12 +26411,12 @@ void CheckStencilAttachmentAccess() { void CheckDepthAttachmentWrites() { RenderDepthInfo target{}; target.desc.view_info.format = vk::Format::eD32SfloatS8Uint; - target.depth_write_enable = true; Require("DepthAttachmentWrites", "disabled depth test", !target.AttachmentWriteAspects(), "disabled depth testing claimed a depth write"); target.depth_test_enable = true; + target.depth_write_enable = true; target.depth_compare_op = vk::CompareOp::eLess; Require("DepthAttachmentWrites", "depth write", target.AttachmentWriteAspects() == vk::ImageAspectFlagBits::eDepth, @@ -26506,6 +26520,7 @@ void CheckDynamicRenderingState() { depth_attachment_layout(attachment) == vk::ImageLayout::eDepthStencilReadOnlyOptimal, "a load clear changed the guest depth-write layout"); + attachment.depth_test_enable = true; attachment.depth_write_enable = true; Require("DynamicRenderingState", "depth-write stencil-read layout", depth_attachment_layout(attachment) ==