[glsl] Clamp frag depth using push constant values Use the push constant layout generated by `PreparePushConstants` to find the min and max values used for frag depth clamping. Bug: 42251044 Change-Id: I2f3930e7bf39e1fa01c884465e3b2c23aa8343db Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/209835 Commit-Queue: James Price <jrprice@google.com> Reviewed-by: dan sinclair <dsinclair@chromium.org>
diff --git a/src/tint/lang/glsl/writer/raise/BUILD.bazel b/src/tint/lang/glsl/writer/raise/BUILD.bazel index 19351da..8122943 100644 --- a/src/tint/lang/glsl/writer/raise/BUILD.bazel +++ b/src/tint/lang/glsl/writer/raise/BUILD.bazel
@@ -113,6 +113,7 @@ "//src/tint/lang/core/constant", "//src/tint/lang/core/intrinsic", "//src/tint/lang/core/ir", + "//src/tint/lang/core/ir/transform", "//src/tint/lang/core/ir/transform:test", "//src/tint/lang/core/type", "//src/tint/lang/wgsl",
diff --git a/src/tint/lang/glsl/writer/raise/BUILD.cmake b/src/tint/lang/glsl/writer/raise/BUILD.cmake index b1b1a71..0893974 100644 --- a/src/tint/lang/glsl/writer/raise/BUILD.cmake +++ b/src/tint/lang/glsl/writer/raise/BUILD.cmake
@@ -121,6 +121,7 @@ tint_lang_core_constant tint_lang_core_intrinsic tint_lang_core_ir + tint_lang_core_ir_transform tint_lang_core_ir_transform_test tint_lang_core_type tint_lang_wgsl
diff --git a/src/tint/lang/glsl/writer/raise/BUILD.gn b/src/tint/lang/glsl/writer/raise/BUILD.gn index 51b4f74..3886a8a 100644 --- a/src/tint/lang/glsl/writer/raise/BUILD.gn +++ b/src/tint/lang/glsl/writer/raise/BUILD.gn
@@ -117,6 +117,7 @@ "${tint_src_dir}/lang/core/constant", "${tint_src_dir}/lang/core/intrinsic", "${tint_src_dir}/lang/core/ir", + "${tint_src_dir}/lang/core/ir/transform", "${tint_src_dir}/lang/core/ir/transform:unittests", "${tint_src_dir}/lang/core/type", "${tint_src_dir}/lang/wgsl",
diff --git a/src/tint/lang/glsl/writer/raise/raise.cc b/src/tint/lang/glsl/writer/raise/raise.cc index 91d2037..b2e66e8 100644 --- a/src/tint/lang/glsl/writer/raise/raise.cc +++ b/src/tint/lang/glsl/writer/raise/raise.cc
@@ -188,7 +188,8 @@ RUN_TRANSFORM(core::ir::transform::AddEmptyEntryPoint, module); - RUN_TRANSFORM(raise::ShaderIO, module, raise::ShaderIOConfig{options.depth_range_offsets}); + RUN_TRANSFORM(raise::ShaderIO, module, + raise::ShaderIOConfig{push_constant_layout.Get(), options.depth_range_offsets}); RUN_TRANSFORM(core::ir::transform::Std140, module);
diff --git a/src/tint/lang/glsl/writer/raise/shader_io.cc b/src/tint/lang/glsl/writer/raise/shader_io.cc index 4e67e94..2e6054c 100644 --- a/src/tint/lang/glsl/writer/raise/shader_io.cc +++ b/src/tint/lang/glsl/writer/raise/shader_io.cc
@@ -243,12 +243,16 @@ /// @returns the clamped value core::ir::Value* ClampFragDepth([[maybe_unused]] core::ir::Builder& builder, core::ir::Value* frag_depth) { - // TODO(dsinclair): Add a clamp frag depth implementation. The `depth_offsets.{min,max}` are - // offsets into a push_constant structure, not the actual values as was done here. - // - // This needs to create a the `push_constant` structure (or append to the existing one if it - // was already created) and add these members. - return frag_depth; + if (!config.depth_range_offsets) { + return frag_depth; + } + + auto* push_constants = config.push_constant_layout.var; + auto min_idx = u32(config.push_constant_layout.IndexOf(config.depth_range_offsets->min)); + auto max_idx = u32(config.push_constant_layout.IndexOf(config.depth_range_offsets->max)); + auto* min = builder.Load(builder.Access<ptr<push_constant, f32>>(push_constants, min_idx)); + auto* max = builder.Load(builder.Access<ptr<push_constant, f32>>(push_constants, max_idx)); + return builder.Call<f32>(core::BuiltinFn::kClamp, frag_depth, min, max)->Result(0); } /// @copydoc ShaderIO::BackendState::NeedsVertexPointSize
diff --git a/src/tint/lang/glsl/writer/raise/shader_io.h b/src/tint/lang/glsl/writer/raise/shader_io.h index d847718..d857e05 100644 --- a/src/tint/lang/glsl/writer/raise/shader_io.h +++ b/src/tint/lang/glsl/writer/raise/shader_io.h
@@ -30,6 +30,7 @@ #include <string> +#include "src/tint/lang/core/ir/transform/prepare_push_constants.h" #include "src/tint/lang/glsl/writer/common/options.h" #include "src/tint/utils/diagnostic/diagnostic.h" #include "src/tint/utils/result/result.h" @@ -43,12 +44,15 @@ /// ShaderIOConfig describes the set of configuration options for the ShaderIO transform. struct ShaderIOConfig { + /// push constant layout information + const core::ir::transform::PushConstantLayout& push_constant_layout; + /// offsets for clamping frag depth - std::optional<Options::RangeOffsets> depth_range_offsets; + std::optional<Options::RangeOffsets> depth_range_offsets{}; }; /// ShaderIO is a transform that moves each entry point function's parameters and return value to -/// global variables to prepare them for SPIR-V codegen. +/// global variables to prepare them for GLSL codegen. /// @param module the module to transform /// @param config the configuration /// @returns success or failure
diff --git a/src/tint/lang/glsl/writer/raise/shader_io_test.cc b/src/tint/lang/glsl/writer/raise/shader_io_test.cc index 638540f..67cb91a 100644 --- a/src/tint/lang/glsl/writer/raise/shader_io_test.cc +++ b/src/tint/lang/glsl/writer/raise/shader_io_test.cc
@@ -59,7 +59,8 @@ auto* expect = src; - ShaderIOConfig config; + core::ir::transform::PushConstantLayout push_constants; + ShaderIOConfig config{push_constants}; Run(ShaderIO, config); EXPECT_EQ(expect, str()); @@ -139,7 +140,8 @@ } )"; - ShaderIOConfig config; + core::ir::transform::PushConstantLayout push_constants; + ShaderIOConfig config{push_constants}; Run(ShaderIO, config); EXPECT_EQ(expect, str()); @@ -290,7 +292,8 @@ } )"; - ShaderIOConfig config; + core::ir::transform::PushConstantLayout push_constants; + ShaderIOConfig config{push_constants}; Run(ShaderIO, config); EXPECT_EQ(expect, str()); @@ -411,7 +414,8 @@ } )"; - ShaderIOConfig config; + core::ir::transform::PushConstantLayout push_constants; + ShaderIOConfig config{push_constants}; Run(ShaderIO, config); EXPECT_EQ(expect, str()); @@ -467,7 +471,8 @@ } )"; - ShaderIOConfig config; + core::ir::transform::PushConstantLayout push_constants; + ShaderIOConfig config{push_constants}; Run(ShaderIO, config); EXPECT_EQ(expect, str()); @@ -512,7 +517,8 @@ } )"; - ShaderIOConfig config; + core::ir::transform::PushConstantLayout push_constants; + ShaderIOConfig config{push_constants}; Run(ShaderIO, config); EXPECT_EQ(expect, str()); @@ -631,7 +637,8 @@ } )"; - ShaderIOConfig config; + core::ir::transform::PushConstantLayout push_constants; + ShaderIOConfig config{push_constants}; Run(ShaderIO, config); EXPECT_EQ(expect, str()); @@ -717,7 +724,8 @@ } )"; - ShaderIOConfig config; + core::ir::transform::PushConstantLayout push_constants; + ShaderIOConfig config{push_constants}; Run(ShaderIO, config); EXPECT_EQ(expect, str()); @@ -867,7 +875,8 @@ } )"; - ShaderIOConfig config; + core::ir::transform::PushConstantLayout push_constants; + ShaderIOConfig config{push_constants}; Run(ShaderIO, config); EXPECT_EQ(expect, str()); @@ -973,7 +982,8 @@ } )"; - ShaderIOConfig config; + core::ir::transform::PushConstantLayout push_constants; + ShaderIOConfig config{push_constants}; Run(ShaderIO, config); EXPECT_EQ(expect, str()); @@ -1070,7 +1080,8 @@ } )"; - ShaderIOConfig config; + core::ir::transform::PushConstantLayout push_constants; + ShaderIOConfig config{push_constants}; Run(ShaderIO, config); EXPECT_EQ(expect, str()); @@ -1230,13 +1241,14 @@ } )"; - ShaderIOConfig config; + core::ir::transform::PushConstantLayout push_constants; + ShaderIOConfig config{push_constants}; Run(ShaderIO, config); EXPECT_EQ(expect, str()); } -TEST_F(GlslWriter_ShaderIOTest, DISABLED_ClampFragDepth) { +TEST_F(GlslWriter_ShaderIOTest, ClampFragDepth) { auto* str_ty = ty.Struct(mod.symbols.New("Outputs"), { { @@ -1293,38 +1305,54 @@ depth:f32 @offset(4) } +tint_push_constant_struct = struct @align(4), @block { + depth_min:f32 @offset(4) + depth_max:f32 @offset(8) +} + $B1: { # root + %tint_push_constants:ptr<push_constant, tint_push_constant_struct, read> = var %foo_loc0_Output:ptr<__out, f32, write> = var @location(0) %gl_FragDepth:ptr<__out, f32, write> = var @builtin(frag_depth) } %foo_inner = func():Outputs { $B2: { - %4:Outputs = construct 0.5f, 2.0f - ret %4 + %5:Outputs = construct 0.5f, 2.0f + ret %5 } } %foo = @fragment func():void { $B3: { - %6:Outputs = call %foo_inner - %7:f32 = access %6, 0u - store %foo_loc0_Output, %7 - %8:f32 = access %6, 1u - %9:f32 = clamp %8, 2.0f, 3.0f - store %gl_FragDepth, %9 + %7:Outputs = call %foo_inner + %8:f32 = access %7, 0u + store %foo_loc0_Output, %8 + %9:f32 = access %7, 1u + %10:ptr<push_constant, f32, read> = access %tint_push_constants, 0u + %11:f32 = load %10 + %12:ptr<push_constant, f32, read> = access %tint_push_constants, 1u + %13:f32 = load %12 + %14:f32 = clamp %9, %11, %13 + store %gl_FragDepth, %14 ret } } )"; - ShaderIOConfig config; - config.depth_range_offsets = {2, 3}; + core::ir::transform::PreparePushConstantsConfig push_constants_config; + push_constants_config.AddInternalConstant(4, mod.symbols.New("depth_min"), ty.f32()); + push_constants_config.AddInternalConstant(8, mod.symbols.New("depth_max"), ty.f32()); + auto push_constants = PreparePushConstants(mod, push_constants_config); + EXPECT_EQ(push_constants, Success); + + ShaderIOConfig config{push_constants.Get()}; + config.depth_range_offsets = {4, 8}; Run(ShaderIO, config); EXPECT_EQ(expect, str()); } -TEST_F(GlslWriter_ShaderIOTest, DISABLED_ClampFragDepth_MultipleFragmentShaders) { +TEST_F(GlslWriter_ShaderIOTest, ClampFragDepth_MultipleFragmentShaders) { auto* str_ty = ty.Struct(mod.symbols.New("Outputs"), { { @@ -1397,7 +1425,13 @@ depth:f32 @offset(4) } +tint_push_constant_struct = struct @align(4), @block { + depth_min:f32 @offset(4) + depth_max:f32 @offset(8) +} + $B1: { # root + %tint_push_constants:ptr<push_constant, tint_push_constant_struct, read> = var %ep1_loc0_Output:ptr<__out, f32, write> = var @location(0) %gl_FragDepth:ptr<__out, f32, write> = var @builtin(frag_depth) %ep2_loc0_Output:ptr<__out, f32, write> = var @location(0) @@ -1408,58 +1442,77 @@ %ep1_inner = func():Outputs { $B2: { - %8:Outputs = construct 0.5f, 2.0f - ret %8 + %9:Outputs = construct 0.5f, 2.0f + ret %9 } } %ep2_inner = func():Outputs { $B3: { - %10:Outputs = construct 0.5f, 2.0f - ret %10 + %11:Outputs = construct 0.5f, 2.0f + ret %11 } } %ep3_inner = func():Outputs { $B4: { - %12:Outputs = construct 0.5f, 2.0f - ret %12 + %13:Outputs = construct 0.5f, 2.0f + ret %13 } } %ep1 = @fragment func():void { $B5: { - %14:Outputs = call %ep1_inner - %15:f32 = access %14, 0u - store %ep1_loc0_Output, %15 - %16:f32 = access %14, 1u - %17:f32 = clamp %16, 0.0f, 0.0f - store %gl_FragDepth, %17 + %15:Outputs = call %ep1_inner + %16:f32 = access %15, 0u + store %ep1_loc0_Output, %16 + %17:f32 = access %15, 1u + %18:ptr<push_constant, f32, read> = access %tint_push_constants, 0u + %19:f32 = load %18 + %20:ptr<push_constant, f32, read> = access %tint_push_constants, 1u + %21:f32 = load %20 + %22:f32 = clamp %17, %19, %21 + store %gl_FragDepth, %22 ret } } %ep2 = @fragment func():void { $B6: { - %19:Outputs = call %ep2_inner - %20:f32 = access %19, 0u - store %ep2_loc0_Output, %20 - %21:f32 = access %19, 1u - %22:f32 = clamp %21, 0.0f, 0.0f - store %gl_FragDepth_1, %22 + %24:Outputs = call %ep2_inner + %25:f32 = access %24, 0u + store %ep2_loc0_Output, %25 + %26:f32 = access %24, 1u + %27:ptr<push_constant, f32, read> = access %tint_push_constants, 0u + %28:f32 = load %27 + %29:ptr<push_constant, f32, read> = access %tint_push_constants, 1u + %30:f32 = load %29 + %31:f32 = clamp %26, %28, %30 + store %gl_FragDepth_1, %31 ret } } %ep3 = @fragment func():void { $B7: { - %24:Outputs = call %ep3_inner - %25:f32 = access %24, 0u - store %ep3_loc0_Output, %25 - %26:f32 = access %24, 1u - %27:f32 = clamp %26, 0.0f, 0.0f - store %gl_FragDepth_2, %27 + %33:Outputs = call %ep3_inner + %34:f32 = access %33, 0u + store %ep3_loc0_Output, %34 + %35:f32 = access %33, 1u + %36:ptr<push_constant, f32, read> = access %tint_push_constants, 0u + %37:f32 = load %36 + %38:ptr<push_constant, f32, read> = access %tint_push_constants, 1u + %39:f32 = load %38 + %40:f32 = clamp %35, %37, %39 + store %gl_FragDepth_2, %40 ret } } )"; - ShaderIOConfig config; + core::ir::transform::PreparePushConstantsConfig push_constants_config; + push_constants_config.AddInternalConstant(4, mod.symbols.New("depth_min"), ty.f32()); + push_constants_config.AddInternalConstant(8, mod.symbols.New("depth_max"), ty.f32()); + auto push_constants = PreparePushConstants(mod, push_constants_config); + EXPECT_EQ(push_constants, Success); + + ShaderIOConfig config{push_constants.Get()}; + config.depth_range_offsets = {4, 8}; Run(ShaderIO, config); EXPECT_EQ(expect, str());
diff --git a/test/tint/types/functions/shader_io/fragment_output_builtins.wgsl.expected.ir.glsl b/test/tint/types/functions/shader_io/fragment_output_builtins.wgsl.expected.ir.glsl index 789ea76..0fab68e 100644 --- a/test/tint/types/functions/shader_io/fragment_output_builtins.wgsl.expected.ir.glsl +++ b/test/tint/types/functions/shader_io/fragment_output_builtins.wgsl.expected.ir.glsl
@@ -13,7 +13,8 @@ return 1.0f; } void main() { - gl_FragDepth = main1_inner(); + float v = main1_inner(); + gl_FragDepth = clamp(v, tint_push_constants.tint_frag_depth_min, tint_push_constants.tint_frag_depth_max); } #version 310 es #extension GL_OES_sample_variables: require
diff --git a/test/tint/types/functions/shader_io/fragment_output_builtins_struct.wgsl.expected.ir.glsl b/test/tint/types/functions/shader_io/fragment_output_builtins_struct.wgsl.expected.ir.glsl index 3d6f909..9d3e79b 100644 --- a/test/tint/types/functions/shader_io/fragment_output_builtins_struct.wgsl.expected.ir.glsl +++ b/test/tint/types/functions/shader_io/fragment_output_builtins_struct.wgsl.expected.ir.glsl
@@ -20,6 +20,6 @@ } void main() { FragmentOutputs v = tint_symbol_inner(); - gl_FragDepth = v.frag_depth; + gl_FragDepth = clamp(v.frag_depth, tint_push_constants.tint_frag_depth_min, tint_push_constants.tint_frag_depth_max); gl_SampleMask[0u] = int(v.sample_mask); }
diff --git a/test/tint/types/functions/shader_io/fragment_output_mixed.wgsl.expected.ir.glsl b/test/tint/types/functions/shader_io/fragment_output_mixed.wgsl.expected.ir.glsl index 42f7bc4..a56141e 100644 --- a/test/tint/types/functions/shader_io/fragment_output_mixed.wgsl.expected.ir.glsl +++ b/test/tint/types/functions/shader_io/fragment_output_mixed.wgsl.expected.ir.glsl
@@ -29,7 +29,7 @@ void main() { FragmentOutputs v = tint_symbol_inner(); tint_symbol_loc0_Output = v.loc0; - gl_FragDepth = v.frag_depth; + gl_FragDepth = clamp(v.frag_depth, tint_push_constants.tint_frag_depth_min, tint_push_constants.tint_frag_depth_max); tint_symbol_loc1_Output = v.loc1; tint_symbol_loc2_Output = v.loc2; gl_SampleMask[0u] = int(v.sample_mask);
diff --git a/test/tint/types/functions/shader_io/fragment_output_mixed_f16.wgsl.expected.ir.glsl b/test/tint/types/functions/shader_io/fragment_output_mixed_f16.wgsl.expected.ir.glsl index 8a9b3d8..f78dbb0 100644 --- a/test/tint/types/functions/shader_io/fragment_output_mixed_f16.wgsl.expected.ir.glsl +++ b/test/tint/types/functions/shader_io/fragment_output_mixed_f16.wgsl.expected.ir.glsl
@@ -34,7 +34,7 @@ void main() { FragmentOutputs v = tint_symbol_inner(); tint_symbol_loc0_Output = v.loc0; - gl_FragDepth = v.frag_depth; + gl_FragDepth = clamp(v.frag_depth, tint_push_constants.tint_frag_depth_min, tint_push_constants.tint_frag_depth_max); tint_symbol_loc1_Output = v.loc1; tint_symbol_loc2_Output = v.loc2; gl_SampleMask[0u] = int(v.sample_mask);