[Spirv] Clamp frag depth using push constant values
Add a way to use pre-created push constant layout generated by
`PreparePushConstants` to find the min and max values used for
frag depth clamping.
Bug: 366291600
Change-Id: I8393c912e48804614fd9fce8c1c1e9228f5b4594
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/221014
Reviewed-by: James Price <jrprice@google.com>
Commit-Queue: Shaobo Yan <shaoboyan@microsoft.com>
diff --git a/src/tint/lang/spirv/writer/raise/BUILD.bazel b/src/tint/lang/spirv/writer/raise/BUILD.bazel
index efd4f60..6b0ee8c 100644
--- a/src/tint/lang/spirv/writer/raise/BUILD.bazel
+++ b/src/tint/lang/spirv/writer/raise/BUILD.bazel
@@ -118,6 +118,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/utils",
@@ -135,6 +136,7 @@
"//src/utils",
] + select({
":tint_build_spv_writer": [
+ "//src/tint/lang/spirv/writer/common",
"//src/tint/lang/spirv/writer/raise",
],
"//conditions:default": [],
diff --git a/src/tint/lang/spirv/writer/raise/BUILD.cmake b/src/tint/lang/spirv/writer/raise/BUILD.cmake
index 57e528c..51a7d8a 100644
--- a/src/tint/lang/spirv/writer/raise/BUILD.cmake
+++ b/src/tint/lang/spirv/writer/raise/BUILD.cmake
@@ -127,6 +127,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_utils
@@ -149,6 +150,7 @@
if(TINT_BUILD_SPV_WRITER)
tint_target_add_dependencies(tint_lang_spirv_writer_raise_test test
+ tint_lang_spirv_writer_common
tint_lang_spirv_writer_raise
)
endif(TINT_BUILD_SPV_WRITER)
diff --git a/src/tint/lang/spirv/writer/raise/BUILD.gn b/src/tint/lang/spirv/writer/raise/BUILD.gn
index ae4dde5..e042ee7 100644
--- a/src/tint/lang/spirv/writer/raise/BUILD.gn
+++ b/src/tint/lang/spirv/writer/raise/BUILD.gn
@@ -121,6 +121,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}/utils",
@@ -137,7 +138,10 @@
]
if (tint_build_spv_writer) {
- deps += [ "${tint_src_dir}/lang/spirv/writer/raise" ]
+ deps += [
+ "${tint_src_dir}/lang/spirv/writer/common",
+ "${tint_src_dir}/lang/spirv/writer/raise",
+ ]
}
}
}
diff --git a/src/tint/lang/spirv/writer/raise/raise.cc b/src/tint/lang/spirv/writer/raise/raise.cc
index 4e28323..5cd98e5 100644
--- a/src/tint/lang/spirv/writer/raise/raise.cc
+++ b/src/tint/lang/spirv/writer/raise/raise.cc
@@ -170,9 +170,11 @@
RUN_TRANSFORM(raise::HandleMatrixArithmetic, module);
RUN_TRANSFORM(raise::MergeReturn, module);
RUN_TRANSFORM(raise::RemoveUnreachableInLoopContinuing, module);
- RUN_TRANSFORM(raise::ShaderIO, module,
- raise::ShaderIOConfig{options.clamp_frag_depth, options.emit_vertex_point_size,
- !options.use_storage_input_output_16});
+ RUN_TRANSFORM(
+ raise::ShaderIO, module,
+ raise::ShaderIOConfig{push_constant_layout.Get(), options.clamp_frag_depth,
+ options.emit_vertex_point_size, !options.use_storage_input_output_16,
+ options.depth_range_offsets});
RUN_TRANSFORM(core::ir::transform::Std140, module);
RUN_TRANSFORM(raise::VarForDynamicIndex, module);
diff --git a/src/tint/lang/spirv/writer/raise/shader_io.cc b/src/tint/lang/spirv/writer/raise/shader_io.cc
index 1477478..b3feb0e 100644
--- a/src/tint/lang/spirv/writer/raise/shader_io.cc
+++ b/src/tint/lang/spirv/writer/raise/shader_io.cc
@@ -190,10 +190,24 @@
/// @param frag_depth the incoming frag_depth value
/// @returns the clamped value
core::ir::Value* ClampFragDepth(core::ir::Builder& builder, core::ir::Value* frag_depth) {
- if (!config.clamp_frag_depth) {
+ if (!config.clamp_frag_depth && !config.depth_range_offsets) {
return frag_depth;
}
+ // Use pre-created push constant block for clamping frag depth if possible.
+ if (config.depth_range_offsets) {
+ 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);
+ }
+
// Create the clamp args struct and variable.
if (!module_state.frag_depth_clamp_args) {
// Check that there are no push constants in the module already.
diff --git a/src/tint/lang/spirv/writer/raise/shader_io.h b/src/tint/lang/spirv/writer/raise/shader_io.h
index 38cd9ad..5d76988 100644
--- a/src/tint/lang/spirv/writer/raise/shader_io.h
+++ b/src/tint/lang/spirv/writer/raise/shader_io.h
@@ -30,6 +30,8 @@
#include <string>
+#include "src/tint/lang/core/ir/transform/prepare_push_constants.h"
+#include "src/tint/lang/spirv/writer/common/options.h"
#include "src/tint/utils/diagnostic/diagnostic.h"
#include "src/tint/utils/result/result.h"
@@ -42,12 +44,17 @@
/// 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;
+
/// true if frag_depth builtin outputs should be clamped
bool clamp_frag_depth = false;
/// true if a vertex point size builtin output should be added
bool emit_vertex_point_size = false;
/// true if f16 IO types should be replaced with f32 types and converted
bool polyfill_f16_io = false;
+ /// offsets for clamping frag depth
+ std::optional<Options::RangeOffsets> depth_range_offsets{};
};
/// ShaderIO is a transform that moves each entry point function's parameters and return value to
diff --git a/src/tint/lang/spirv/writer/raise/shader_io_test.cc b/src/tint/lang/spirv/writer/raise/shader_io_test.cc
index 417b406..888ce74 100644
--- a/src/tint/lang/spirv/writer/raise/shader_io_test.cc
+++ b/src/tint/lang/spirv/writer/raise/shader_io_test.cc
@@ -57,7 +57,8 @@
auto* expect = src;
- ShaderIOConfig config;
+ core::ir::transform::PushConstantLayout push_constants;
+ ShaderIOConfig config{push_constants};
config.clamp_frag_depth = false;
Run(ShaderIO, config);
@@ -138,7 +139,8 @@
}
)";
- ShaderIOConfig config;
+ core::ir::transform::PushConstantLayout push_constants;
+ ShaderIOConfig config{push_constants};
config.clamp_frag_depth = false;
Run(ShaderIO, config);
@@ -290,7 +292,8 @@
}
)";
- ShaderIOConfig config;
+ core::ir::transform::PushConstantLayout push_constants;
+ ShaderIOConfig config{push_constants};
config.clamp_frag_depth = false;
Run(ShaderIO, config);
@@ -412,7 +415,8 @@
}
)";
- ShaderIOConfig config;
+ core::ir::transform::PushConstantLayout push_constants;
+ ShaderIOConfig config{push_constants};
config.clamp_frag_depth = false;
Run(ShaderIO, config);
@@ -459,7 +463,8 @@
}
)";
- ShaderIOConfig config;
+ core::ir::transform::PushConstantLayout push_constants;
+ ShaderIOConfig config{push_constants};
config.clamp_frag_depth = false;
Run(ShaderIO, config);
@@ -505,7 +510,8 @@
}
)";
- ShaderIOConfig config;
+ core::ir::transform::PushConstantLayout push_constants;
+ ShaderIOConfig config{push_constants};
config.clamp_frag_depth = false;
Run(ShaderIO, config);
@@ -615,7 +621,8 @@
}
)";
- ShaderIOConfig config;
+ core::ir::transform::PushConstantLayout push_constants;
+ ShaderIOConfig config{push_constants};
config.clamp_frag_depth = false;
Run(ShaderIO, config);
@@ -702,7 +709,8 @@
}
)";
- ShaderIOConfig config;
+ core::ir::transform::PushConstantLayout push_constants;
+ ShaderIOConfig config{push_constants};
config.clamp_frag_depth = false;
Run(ShaderIO, config);
@@ -843,7 +851,8 @@
}
)";
- ShaderIOConfig config;
+ core::ir::transform::PushConstantLayout push_constants;
+ ShaderIOConfig config{push_constants};
config.clamp_frag_depth = false;
Run(ShaderIO, config);
@@ -940,7 +949,8 @@
}
)";
- ShaderIOConfig config;
+ core::ir::transform::PushConstantLayout push_constants;
+ ShaderIOConfig config{push_constants};
config.clamp_frag_depth = false;
Run(ShaderIO, config);
@@ -1036,7 +1046,8 @@
}
)";
- ShaderIOConfig config;
+ core::ir::transform::PushConstantLayout push_constants;
+ ShaderIOConfig config{push_constants};
config.clamp_frag_depth = false;
Run(ShaderIO, config);
@@ -1187,7 +1198,8 @@
}
)";
- ShaderIOConfig config;
+ core::ir::transform::PushConstantLayout push_constants;
+ ShaderIOConfig config{push_constants};
config.clamp_frag_depth = false;
Run(ShaderIO, config);
@@ -1284,7 +1296,8 @@
}
)";
- ShaderIOConfig config;
+ core::ir::transform::PushConstantLayout push_constants;
+ ShaderIOConfig config{push_constants};
config.clamp_frag_depth = true;
Run(ShaderIO, config);
@@ -1441,13 +1454,285 @@
}
)";
- ShaderIOConfig config;
+ core::ir::transform::PushConstantLayout push_constants;
+ ShaderIOConfig config{push_constants};
config.clamp_frag_depth = true;
Run(ShaderIO, config);
EXPECT_EQ(expect, str());
}
+TEST_F(SpirvWriter_ShaderIOTest, ClampFragDepth_With_Prepared_Push_Constants) {
+ auto* str_ty = ty.Struct(mod.symbols.New("Outputs"),
+ {
+ {
+ mod.symbols.New("color"),
+ ty.f32(),
+ core::IOAttributes{
+ /* location */ 0u,
+ /* blend_src */ std::nullopt,
+ /* color */ std::nullopt,
+ /* builtin */ std::nullopt,
+ /* interpolation */ std::nullopt,
+ /* invariant */ false,
+ },
+ },
+ {
+ mod.symbols.New("depth"),
+ ty.f32(),
+ core::IOAttributes{
+ /* location */ std::nullopt,
+ /* blend_src */ std::nullopt,
+ /* color */ std::nullopt,
+ /* builtin */ core::BuiltinValue::kFragDepth,
+ /* interpolation */ std::nullopt,
+ /* invariant */ false,
+ },
+ },
+ });
+
+ auto* ep = b.Function("foo", str_ty);
+ ep->SetStage(core::ir::Function::PipelineStage::kFragment);
+
+ b.Append(ep->Block(), [&] { //
+ b.Return(ep, b.Construct(str_ty, 0.5_f, 2_f));
+ });
+
+ auto* src = R"(
+Outputs = struct @align(4) {
+ color:f32 @offset(0), @location(0)
+ depth:f32 @offset(4), @builtin(frag_depth)
+}
+
+%foo = @fragment func():Outputs {
+ $B1: {
+ %2:Outputs = construct 0.5f, 2.0f
+ ret %2
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+Outputs = struct @align(4) {
+ color:f32 @offset(0)
+ 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)
+ %foo_frag_depth_Output:ptr<__out, f32, write> = var @builtin(frag_depth)
+}
+
+%foo_inner = func():Outputs {
+ $B2: {
+ %5:Outputs = construct 0.5f, 2.0f
+ ret %5
+ }
+}
+%foo = @fragment func():void {
+ $B3: {
+ %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 %foo_frag_depth_Output, %14
+ ret
+ }
+}
+)";
+
+ 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(SpirvWriter_ShaderIOTest,
+ ClampFragDepth_With_Prepared_Push_Constants_MultipleFragmentShaders) {
+ auto* str_ty = ty.Struct(mod.symbols.New("Outputs"),
+ {
+ {
+ mod.symbols.New("color"),
+ ty.f32(),
+ core::IOAttributes{
+ /* location */ 0u,
+ /* blend_src */ std::nullopt,
+ /* color */ std::nullopt,
+ /* builtin */ std::nullopt,
+ /* interpolation */ std::nullopt,
+ /* invariant */ false,
+ },
+ },
+ {
+ mod.symbols.New("depth"),
+ ty.f32(),
+ core::IOAttributes{
+ /* location */ std::nullopt,
+ /* blend_src */ std::nullopt,
+ /* color */ std::nullopt,
+ /* builtin */ core::BuiltinValue::kFragDepth,
+ /* interpolation */ std::nullopt,
+ /* invariant */ false,
+ },
+ },
+ });
+
+ auto make_entry_point = [&](std::string_view name) {
+ auto* ep = b.Function(name, str_ty);
+ ep->SetStage(core::ir::Function::PipelineStage::kFragment);
+ b.Append(ep->Block(), [&] { //
+ b.Return(ep, b.Construct(str_ty, 0.5_f, 2_f));
+ });
+ };
+ make_entry_point("ep1");
+ make_entry_point("ep2");
+ make_entry_point("ep3");
+
+ auto* src = R"(
+Outputs = struct @align(4) {
+ color:f32 @offset(0), @location(0)
+ depth:f32 @offset(4), @builtin(frag_depth)
+}
+
+%ep1 = @fragment func():Outputs {
+ $B1: {
+ %2:Outputs = construct 0.5f, 2.0f
+ ret %2
+ }
+}
+%ep2 = @fragment func():Outputs {
+ $B2: {
+ %4:Outputs = construct 0.5f, 2.0f
+ ret %4
+ }
+}
+%ep3 = @fragment func():Outputs {
+ $B3: {
+ %6:Outputs = construct 0.5f, 2.0f
+ ret %6
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+Outputs = struct @align(4) {
+ color:f32 @offset(0)
+ 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)
+ %ep1_frag_depth_Output:ptr<__out, f32, write> = var @builtin(frag_depth)
+ %ep2_loc0_Output:ptr<__out, f32, write> = var @location(0)
+ %ep2_frag_depth_Output:ptr<__out, f32, write> = var @builtin(frag_depth)
+ %ep3_loc0_Output:ptr<__out, f32, write> = var @location(0)
+ %ep3_frag_depth_Output:ptr<__out, f32, write> = var @builtin(frag_depth)
+}
+
+%ep1_inner = func():Outputs {
+ $B2: {
+ %9:Outputs = construct 0.5f, 2.0f
+ ret %9
+ }
+}
+%ep2_inner = func():Outputs {
+ $B3: {
+ %11:Outputs = construct 0.5f, 2.0f
+ ret %11
+ }
+}
+%ep3_inner = func():Outputs {
+ $B4: {
+ %13:Outputs = construct 0.5f, 2.0f
+ ret %13
+ }
+}
+%ep1 = @fragment func():void {
+ $B5: {
+ %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 %ep1_frag_depth_Output, %22
+ ret
+ }
+}
+%ep2 = @fragment func():void {
+ $B6: {
+ %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 %ep2_frag_depth_Output, %31
+ ret
+ }
+}
+%ep3 = @fragment func():void {
+ $B7: {
+ %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 %ep3_frag_depth_Output, %40
+ ret
+ }
+}
+)";
+
+ 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(SpirvWriter_ShaderIOTest, EmitVertexPointSize) {
auto* ep = b.Function("foo", ty.vec4<f32>());
ep->SetStage(core::ir::Function::PipelineStage::kVertex);
@@ -1489,7 +1774,8 @@
}
)";
- ShaderIOConfig config;
+ core::ir::transform::PushConstantLayout push_constants;
+ ShaderIOConfig config{push_constants};
config.emit_vertex_point_size = true;
Run(ShaderIO, config);
@@ -1583,7 +1869,8 @@
}
)";
- ShaderIOConfig config;
+ core::ir::transform::PushConstantLayout push_constants;
+ ShaderIOConfig config{push_constants};
config.polyfill_f16_io = false;
Run(ShaderIO, config);
@@ -1681,7 +1968,8 @@
}
)";
- ShaderIOConfig config;
+ core::ir::transform::PushConstantLayout push_constants;
+ ShaderIOConfig config{push_constants};
config.polyfill_f16_io = true;
Run(ShaderIO, config);
diff --git a/test/tint/types/functions/shader_io/fragment_output_builtins.wgsl.expected.spvasm b/test/tint/types/functions/shader_io/fragment_output_builtins.wgsl.expected.spvasm
index 0ac710c..0601e90 100644
--- a/test/tint/types/functions/shader_io/fragment_output_builtins.wgsl.expected.spvasm
+++ b/test/tint/types/functions/shader_io/fragment_output_builtins.wgsl.expected.spvasm
@@ -4,9 +4,10 @@
; SPIR-V
; Version: 1.3
; Generator: Google Tint Compiler; 1
-; Bound: 16
+; Bound: 26
; Schema: 0
OpCapability Shader
+ %25 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %main1 "main1" %main1_frag_depth_Output
OpExecutionMode %main1 OriginUpperLeft
@@ -32,6 +33,10 @@
%float_1 = OpConstant %float 1
%void = OpTypeVoid
%13 = OpTypeFunction %void
+%_ptr_PushConstant_float = OpTypePointer PushConstant %float
+ %uint = OpTypeInt 32 0
+ %uint_0 = OpConstant %uint 0
+ %uint_1 = OpConstant %uint 1
%main1_inner = OpFunction %float None %8
%9 = OpLabel
OpReturnValue %float_1
@@ -39,7 +44,12 @@
%main1 = OpFunction %void None %13
%14 = OpLabel
%15 = OpFunctionCall %float %main1_inner
- OpStore %main1_frag_depth_Output %15 None
+ %16 = OpAccessChain %_ptr_PushConstant_float %tint_push_constants %uint_0
+ %20 = OpLoad %float %16 None
+ %21 = OpAccessChain %_ptr_PushConstant_float %tint_push_constants %uint_1
+ %23 = OpLoad %float %21 None
+ %24 = OpExtInst %float %25 NClamp %15 %20 %23
+ OpStore %main1_frag_depth_Output %24 None
OpReturn
OpFunctionEnd
;
diff --git a/test/tint/types/functions/shader_io/fragment_output_builtins_struct.wgsl.expected.spvasm b/test/tint/types/functions/shader_io/fragment_output_builtins_struct.wgsl.expected.spvasm
index d171bcd..c8a45a0 100644
--- a/test/tint/types/functions/shader_io/fragment_output_builtins_struct.wgsl.expected.spvasm
+++ b/test/tint/types/functions/shader_io/fragment_output_builtins_struct.wgsl.expected.spvasm
@@ -1,9 +1,10 @@
; SPIR-V
; Version: 1.3
; Generator: Google Tint Compiler; 1
-; Bound: 28
+; Bound: 35
; Schema: 0
OpCapability Shader
+ %31 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %main "main" %main_frag_depth_Output %main_sample_mask_Output
OpExecutionMode %main OriginUpperLeft
@@ -44,8 +45,9 @@
%16 = OpConstantComposite %FragmentOutputs %float_1 %uint_1
%void = OpTypeVoid
%20 = OpTypeFunction %void
-%_ptr_Output_uint = OpTypePointer Output %uint
+%_ptr_PushConstant_float = OpTypePointer PushConstant %float
%uint_0 = OpConstant %uint 0
+%_ptr_Output_uint = OpTypePointer Output %uint
%main_inner = OpFunction %FragmentOutputs None %14
%15 = OpLabel
OpReturnValue %16
@@ -54,9 +56,14 @@
%21 = OpLabel
%22 = OpFunctionCall %FragmentOutputs %main_inner
%23 = OpCompositeExtract %float %22 0
- OpStore %main_frag_depth_Output %23 None
- %24 = OpCompositeExtract %uint %22 1
- %25 = OpAccessChain %_ptr_Output_uint %main_sample_mask_Output %uint_0
- OpStore %25 %24 None
+ %24 = OpAccessChain %_ptr_PushConstant_float %tint_push_constants %uint_0
+ %27 = OpLoad %float %24 None
+ %28 = OpAccessChain %_ptr_PushConstant_float %tint_push_constants %uint_1
+ %29 = OpLoad %float %28 None
+ %30 = OpExtInst %float %31 NClamp %23 %27 %29
+ OpStore %main_frag_depth_Output %30 None
+ %32 = OpCompositeExtract %uint %22 1
+ %33 = OpAccessChain %_ptr_Output_uint %main_sample_mask_Output %uint_0
+ OpStore %33 %32 None
OpReturn
OpFunctionEnd
diff --git a/test/tint/types/functions/shader_io/fragment_output_mixed.wgsl.expected.spvasm b/test/tint/types/functions/shader_io/fragment_output_mixed.wgsl.expected.spvasm
index f6a498f..65f1ac6 100644
--- a/test/tint/types/functions/shader_io/fragment_output_mixed.wgsl.expected.spvasm
+++ b/test/tint/types/functions/shader_io/fragment_output_mixed.wgsl.expected.spvasm
@@ -1,9 +1,10 @@
; SPIR-V
; Version: 1.3
; Generator: Google Tint Compiler; 1
-; Bound: 46
+; Bound: 53
; Schema: 0
OpCapability Shader
+ %47 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %main "main" %main_loc0_Output %main_frag_depth_Output %main_loc1_Output %main_loc2_Output %main_sample_mask_Output %main_loc3_Output
OpExecutionMode %main OriginUpperLeft
@@ -75,6 +76,7 @@
%25 = OpConstantComposite %FragmentOutputs %int_1 %float_2 %uint_1 %float_1 %uint_2 %30
%void = OpTypeVoid
%35 = OpTypeFunction %void
+%_ptr_PushConstant_float = OpTypePointer PushConstant %float
%uint_0 = OpConstant %uint 0
%main_inner = OpFunction %FragmentOutputs None %23
%24 = OpLabel
@@ -86,15 +88,20 @@
%38 = OpCompositeExtract %int %37 0
OpStore %main_loc0_Output %38 None
%39 = OpCompositeExtract %float %37 1
- OpStore %main_frag_depth_Output %39 None
- %40 = OpCompositeExtract %uint %37 2
- OpStore %main_loc1_Output %40 None
- %41 = OpCompositeExtract %float %37 3
- OpStore %main_loc2_Output %41 None
- %42 = OpCompositeExtract %uint %37 4
- %43 = OpAccessChain %_ptr_Output_uint %main_sample_mask_Output %uint_0
- OpStore %43 %42 None
- %45 = OpCompositeExtract %v4float %37 5
- OpStore %main_loc3_Output %45 None
+ %40 = OpAccessChain %_ptr_PushConstant_float %tint_push_constants %uint_0
+ %43 = OpLoad %float %40 None
+ %44 = OpAccessChain %_ptr_PushConstant_float %tint_push_constants %uint_1
+ %45 = OpLoad %float %44 None
+ %46 = OpExtInst %float %47 NClamp %39 %43 %45
+ OpStore %main_frag_depth_Output %46 None
+ %48 = OpCompositeExtract %uint %37 2
+ OpStore %main_loc1_Output %48 None
+ %49 = OpCompositeExtract %float %37 3
+ OpStore %main_loc2_Output %49 None
+ %50 = OpCompositeExtract %uint %37 4
+ %51 = OpAccessChain %_ptr_Output_uint %main_sample_mask_Output %uint_0
+ OpStore %51 %50 None
+ %52 = OpCompositeExtract %v4float %37 5
+ OpStore %main_loc3_Output %52 None
OpReturn
OpFunctionEnd
diff --git a/test/tint/types/functions/shader_io/fragment_output_mixed_f16.wgsl.expected.spvasm b/test/tint/types/functions/shader_io/fragment_output_mixed_f16.wgsl.expected.spvasm
index aa28337..ee4eabb 100644
--- a/test/tint/types/functions/shader_io/fragment_output_mixed_f16.wgsl.expected.spvasm
+++ b/test/tint/types/functions/shader_io/fragment_output_mixed_f16.wgsl.expected.spvasm
@@ -1,13 +1,14 @@
; SPIR-V
; Version: 1.3
; Generator: Google Tint Compiler; 1
-; Bound: 59
+; Bound: 66
; Schema: 0
OpCapability Shader
OpCapability Float16
OpCapability UniformAndStorageBuffer16BitAccess
OpCapability StorageBuffer16BitAccess
OpCapability StorageInputOutput16
+ %58 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %main "main" %main_loc0_Output %main_frag_depth_Output %main_loc1_Output %main_loc2_Output %main_sample_mask_Output %main_loc3_Output %main_loc4_Output %main_loc5_Output
OpExecutionMode %main OriginUpperLeft
@@ -98,6 +99,7 @@
%31 = OpConstantComposite %FragmentOutputs %int_1 %float_2 %uint_1 %float_1 %uint_2 %36 %half_0x1_2p_1 %40
%void = OpTypeVoid
%46 = OpTypeFunction %void
+%_ptr_PushConstant_float = OpTypePointer PushConstant %float
%uint_0 = OpConstant %uint 0
%main_inner = OpFunction %FragmentOutputs None %29
%30 = OpLabel
@@ -109,19 +111,24 @@
%49 = OpCompositeExtract %int %48 0
OpStore %main_loc0_Output %49 None
%50 = OpCompositeExtract %float %48 1
- OpStore %main_frag_depth_Output %50 None
- %51 = OpCompositeExtract %uint %48 2
- OpStore %main_loc1_Output %51 None
- %52 = OpCompositeExtract %float %48 3
- OpStore %main_loc2_Output %52 None
- %53 = OpCompositeExtract %uint %48 4
- %54 = OpAccessChain %_ptr_Output_uint %main_sample_mask_Output %uint_0
- OpStore %54 %53 None
- %56 = OpCompositeExtract %v4float %48 5
- OpStore %main_loc3_Output %56 None
- %57 = OpCompositeExtract %half %48 6
- OpStore %main_loc4_Output %57 None
- %58 = OpCompositeExtract %v3half %48 7
- OpStore %main_loc5_Output %58 None
+ %51 = OpAccessChain %_ptr_PushConstant_float %tint_push_constants %uint_0
+ %54 = OpLoad %float %51 None
+ %55 = OpAccessChain %_ptr_PushConstant_float %tint_push_constants %uint_1
+ %56 = OpLoad %float %55 None
+ %57 = OpExtInst %float %58 NClamp %50 %54 %56
+ OpStore %main_frag_depth_Output %57 None
+ %59 = OpCompositeExtract %uint %48 2
+ OpStore %main_loc1_Output %59 None
+ %60 = OpCompositeExtract %float %48 3
+ OpStore %main_loc2_Output %60 None
+ %61 = OpCompositeExtract %uint %48 4
+ %62 = OpAccessChain %_ptr_Output_uint %main_sample_mask_Output %uint_0
+ OpStore %62 %61 None
+ %63 = OpCompositeExtract %v4float %48 5
+ OpStore %main_loc3_Output %63 None
+ %64 = OpCompositeExtract %half %48 6
+ OpStore %main_loc4_Output %64 None
+ %65 = OpCompositeExtract %v3half %48 7
+ OpStore %main_loc5_Output %65 None
OpReturn
OpFunctionEnd