From 984010227f027e7c18e64bc4d2261cb8a4caeec6 Mon Sep 17 00:00:00 2001 From: nmzik Date: Mon, 5 Oct 2026 22:37:40 +0400 Subject: [PATCH] graphics: make depth bounds dynamic to reuse pipelines Co-authored-by: TheCruZ --- .../host_gpu/renderer/depthRenderTarget.cpp | 2 -- .../host_gpu/renderer/depthRenderTarget.h | 2 -- .../renderer/pipeline/pipelineCache.cpp | 3 -- .../renderer/pipeline/pipelineCache.h | 5 +--- .../host_gpu/renderer/pipeline/shaders.cpp | 10 ++----- src/graphics/host_gpu/renderer/renderDraw.cpp | 6 ++++ tests/ShaderRecompilerComputeTests.cpp | 28 +++++++++++++++++++ 7 files changed, 37 insertions(+), 19 deletions(-) diff --git a/src/graphics/host_gpu/renderer/depthRenderTarget.cpp b/src/graphics/host_gpu/renderer/depthRenderTarget.cpp index c7f883ae..482334af 100644 --- a/src/graphics/host_gpu/renderer/depthRenderTarget.cpp +++ b/src/graphics/host_gpu/renderer/depthRenderTarget.cpp @@ -315,8 +315,6 @@ void RenderExecutor::ResolveRenderDepthTarget(CommandBuffer& buffer, RenderDepth r.depth_compare_op = static_cast(dc.zfunc); r.depth_bounds_test_enable = dc.depth_bounds_enable; - r.depth_min_bounds = hw.GetDepthBoundsMin(); - r.depth_max_bounds = hw.GetDepthBoundsMax(); r.stencil_clear_enable = has_stencil && rc.stencil_clear_enable && !z.depth_view.stencil_write_disable; diff --git a/src/graphics/host_gpu/renderer/depthRenderTarget.h b/src/graphics/host_gpu/renderer/depthRenderTarget.h index 6b3ff0d8..612f8d2b 100644 --- a/src/graphics/host_gpu/renderer/depthRenderTarget.h +++ b/src/graphics/host_gpu/renderer/depthRenderTarget.h @@ -29,8 +29,6 @@ struct RenderDepthInfo { bool depth_write_enable = false; vk::CompareOp depth_compare_op = vk::CompareOp::eNever; bool depth_bounds_test_enable = false; - float depth_min_bounds = 0.0f; - float depth_max_bounds = 0.0f; bool stencil_clear_enable = false; uint8_t stencil_clear_value = 0; bool stencil_test_enable = false; diff --git a/src/graphics/host_gpu/renderer/pipeline/pipelineCache.cpp b/src/graphics/host_gpu/renderer/pipeline/pipelineCache.cpp index d40aeb17..38bcc3aa 100644 --- a/src/graphics/host_gpu/renderer/pipeline/pipelineCache.cpp +++ b/src/graphics/host_gpu/renderer/pipeline/pipelineCache.cpp @@ -831,9 +831,6 @@ PipelineCache::Pipeline& PipelineCache::GetGraphicsPipeline( if (static_params.sample_shading_enable && !m_graphics.sample_rate_shading_enabled) { EXIT("Pipeline: sample-rate shading is required but unsupported by the host\n"); } - static_params.depth_bounds_test_enable = depth.depth_bounds_test_enable; - static_params.depth_min_bounds = depth.depth_min_bounds; - static_params.depth_max_bounds = depth.depth_max_bounds; const bool rect_list = Prospero::IsRectList(command.GetUserConfig().GetPrimType()); static_params.cull_back = !rect_list && mc.cull_back; static_params.cull_front = !rect_list && mc.cull_front; diff --git a/src/graphics/host_gpu/renderer/pipeline/pipelineCache.h b/src/graphics/host_gpu/renderer/pipeline/pipelineCache.h index 4be29854..1554d5db 100644 --- a/src/graphics/host_gpu/renderer/pipeline/pipelineCache.h +++ b/src/graphics/host_gpu/renderer/pipeline/pipelineCache.h @@ -38,9 +38,6 @@ struct PipelineStaticParameters { bool primitive_restart_enable = false; uint32_t samples = 1; bool sample_shading_enable = false; - bool depth_bounds_test_enable = false; - float depth_min_bounds = 0.0f; - float depth_max_bounds = 0.0f; uint32_t color_mask[RENDER_COLOR_ATTACHMENTS_MAX] = {}; bool cull_front = false; bool cull_back = false; @@ -64,7 +61,7 @@ struct PipelineStaticParameters { static_assert(std::is_trivially_copyable_v); static_assert(std::is_standard_layout_v); static_assert(alignof(PipelineStaticParameters) == 1); -static_assert(sizeof(PipelineStaticParameters) == 125); +static_assert(sizeof(PipelineStaticParameters) == 116); struct PipelineRenderingState { std::array color_formats {}; diff --git a/src/graphics/host_gpu/renderer/pipeline/shaders.cpp b/src/graphics/host_gpu/renderer/pipeline/shaders.cpp index b56b702b..f564ee8a 100644 --- a/src/graphics/host_gpu/renderer/pipeline/shaders.cpp +++ b/src/graphics/host_gpu/renderer/pipeline/shaders.cpp @@ -471,14 +471,6 @@ void CreatePipelineInternal(GraphicContext& graphics, PipelineCache::Pipeline& p EXIT_NOT_IMPLEMENTED(pipeline.pipeline_layout == nullptr); vk::PipelineDepthStencilStateCreateInfo depth_stencil_info {}; - depth_stencil_info.depthBoundsTestEnable = -#if defined(__APPLE__) - VK_FALSE; // MoltenVK lacks the depthBounds feature; depth-bounds testing is disabled -#else - (static_params.depth_bounds_test_enable ? VK_TRUE : VK_FALSE); -#endif - depth_stencil_info.minDepthBounds = static_params.depth_min_bounds; - depth_stencil_info.maxDepthBounds = static_params.depth_max_bounds; std::vector dynamic_states { vk::DynamicState::eViewportWithCount, @@ -497,6 +489,8 @@ void CreatePipelineInternal(GraphicContext& graphics, PipelineCache::Pipeline& p vk::DynamicState::eBlendConstants, }; #if !defined(__APPLE__) + dynamic_states.push_back(vk::DynamicState::eDepthBoundsTestEnable); + dynamic_states.push_back(vk::DynamicState::eDepthBounds); if (rendering.color_count != 0) { dynamic_states.push_back(vk::DynamicState::eColorWriteEnableEXT); } diff --git a/src/graphics/host_gpu/renderer/renderDraw.cpp b/src/graphics/host_gpu/renderer/renderDraw.cpp index 04689eff..82663396 100644 --- a/src/graphics/host_gpu/renderer/renderDraw.cpp +++ b/src/graphics/host_gpu/renderer/renderDraw.cpp @@ -379,6 +379,12 @@ static void SetGraphicsDynamicParams(const CommandBuffer& buffer, vk::CommandBuf vk_buffer.setDepthTestEnable(depth.depth_test_enable ? VK_TRUE : VK_FALSE); vk_buffer.setDepthWriteEnable(depth.depth_write_enable ? VK_TRUE : VK_FALSE); vk_buffer.setDepthCompareOp(depth.depth_compare_op); +#if !defined(__APPLE__) + vk_buffer.setDepthBoundsTestEnable(depth.depth_bounds_test_enable ? VK_TRUE : VK_FALSE); + if (depth.depth_bounds_test_enable) { + vk_buffer.setDepthBounds(ctx.GetDepthBoundsMin(), ctx.GetDepthBoundsMax()); + } +#endif const auto& mode = ctx.GetModeControl(); const auto& poly_offset = ctx.GetPolyOffset(); diff --git a/tests/ShaderRecompilerComputeTests.cpp b/tests/ShaderRecompilerComputeTests.cpp index ea5f1660..ebce9aa6 100644 --- a/tests/ShaderRecompilerComputeTests.cpp +++ b/tests/ShaderRecompilerComputeTests.cpp @@ -15678,6 +15678,12 @@ public: cmd.setDepthTestEnable(depth.depth_test_enable); cmd.setDepthWriteEnable(depth.depth_write_enable); cmd.setDepthCompareOp(depth.depth_compare_op); +#if !defined(__APPLE__) + cmd.setDepthBoundsTestEnable(depth.depth_bounds_test_enable); + if (depth.depth_bounds_test_enable) { + cmd.setDepthBounds(registers.GetDepthBoundsMin(), registers.GetDepthBoundsMax()); + } +#endif cmd.setDepthBiasEnable(false); cmd.setStencilTestEnable(depth.stencil_test_enable); if (depth.stencil_test_enable) { @@ -15734,6 +15740,26 @@ public: "depth feedback lost a prior write or the read-only draw changed depth"); } } + depth.depth_test_enable = false; + for (uint32_t pass = 0; pass < 3; pass++) { + depth.depth_bounds_test_enable = pass != 2; + registers.SetDepthBoundsMin(pass == 0 ? 0.5f : 0.625f); + registers.SetDepthBoundsMax(pass == 0 ? 0.5625f : 0.6875f); + Require(name, "dynamic depth bounds pipeline reuse", + pipeline(true, 2, 2).pipeline == filled.pipeline, + "changing depth bounds or their enable state created another pipeline"); + draw(filled); + const auto bounded_pixels = read_color(); + for (size_t index = 0; index < stored_depth.size(); index++) { + const auto z = std::bit_cast(stored_depth[index]); + const bool passes = !depth.depth_bounds_test_enable || + (z >= registers.GetDepthBoundsMin() && + z <= registers.GetDepthBoundsMax()); + Require(name, "dynamic stored-depth bounds", + bounded_pixels[index * 4] == (passes ? stored_depth[index] : 0u), + "depth bounds did not filter stored depth independently of the depth test"); + } + } } else { auto &wireframe = pipeline(true, 1, 1); Require(name, "pipeline cache", filled.pipeline != wireframe.pipeline && @@ -17935,6 +17961,7 @@ private: "vertex layer output is not supported"); m_rasterization_supported = available_features.fillModeNonSolid && available_features.tessellationShader && + available_features.depthBounds && available_depth_clip.depthClipEnable && available_clip_control.depthClipControl && available_color_write.colorWriteEnable && @@ -18017,6 +18044,7 @@ private: device_features.shaderFloat64 = available_features.shaderFloat64; device_features.fillModeNonSolid = m_rasterization_supported; device_features.tessellationShader = m_rasterization_supported; + device_features.depthBounds = m_rasterization_supported; device_info.pEnabledFeatures = &device_features; std::vector device_extensions{ VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME,