[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);