[glsl][ir] Add `SampleMask` to ShaderIO.
This CL updates the ShaderIO polyfill for GLSL IR to support the needed
SampleMask conversions. In GLSL, the `in` mask is named
`gl_SampleMaskIn` and is an array of `i32` values. The output mask is
`gl_SampleMask` and is an array of `i32` values. The ShaderIO code is
updated to access the given arrays and bitcast the values to/from the
WGSL `u32` sample mask values.
Bug: 42251044
Change-Id: I9498a988f00d8fa8f2f4aca3a0de443643b34b56
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/208334
Commit-Queue: dan sinclair <dsinclair@chromium.org>
Reviewed-by: James Price <jrprice@google.com>
diff --git a/src/tint/lang/glsl/writer/raise/shader_io.cc b/src/tint/lang/glsl/writer/raise/shader_io.cc
index c1f9189..a13a9c6 100644
--- a/src/tint/lang/glsl/writer/raise/shader_io.cc
+++ b/src/tint/lang/glsl/writer/raise/shader_io.cc
@@ -124,8 +124,15 @@
for (auto io : entries) {
StringStream name;
+ const core::type::MemoryView* ptr = nullptr;
if (io.attributes.builtin) {
name << GLSLBuiltinToString(*io.attributes.builtin, addrspace);
+
+ if (io.attributes.builtin == core::BuiltinValue::kSampleMask) {
+ ptr = ty.ptr(addrspace, ty.array(ty.i32(), 1), access);
+ } else {
+ ptr = ty.ptr(addrspace, io.type, access);
+ }
} else {
name << ir.NameOf(func).Name();
@@ -136,10 +143,10 @@
}
}
name << name_suffix;
+ ptr = ty.ptr(addrspace, io.type, access);
}
// Create an IO variable and add it to the root block.
- auto* ptr = ty.ptr(addrspace, io.type, access);
auto* var = b.Var(name.str(), ptr);
var->SetAttributes(io.attributes);
ir.root_block->Append(var);
@@ -164,30 +171,27 @@
auto* from = input_vars[idx]->Result(0);
auto* value = builder.Load(from)->Result(0);
- // TODO(dsinclair): Enable when `bitcast` is supported
- // auto& builtin = inputs[idx].attributes.builtin;
- // if (builtin.has_value()) {
- // switch (builtin.value()) {
- // case core::BuiltinValue::kVertexIndex:
- // case core::BuiltinValue::kInstanceIndex:
- // case core::BuiltinValue::kSampleIndex: {
- // // GLSL uses i32 for these, so bitcast to u32.
- // value = builder.Bitcast(ty.u32(), value)->Result(0);
- // break;
- // }
- // case core::BuiltinValue::kSampleMask: {
- // // gl_SampleMask is an array of i32. Retrieve the first element and
- // // bitcast it to u32.
- // auto* ptr = ty.ptr(core::AddressSpace::kOut, ty.i32(), core::Access::kWrite);
-
- // auto* elem = builder.Load(builder.Access(ptr, value, 0_u));
- // value = builder.Bitcast(ty.u32(), elem)->Result(0);
- // break;
- // }
- // default:
- // break;
- // }
- // }
+ auto& builtin = inputs[idx].attributes.builtin;
+ if (builtin.has_value()) {
+ switch (builtin.value()) {
+ case core::BuiltinValue::kVertexIndex:
+ case core::BuiltinValue::kInstanceIndex:
+ case core::BuiltinValue::kSampleIndex: {
+ // GLSL uses i32 for these, so convert to u32.
+ value = builder.Convert(ty.u32(), value)->Result(0);
+ break;
+ }
+ case core::BuiltinValue::kSampleMask: {
+ // gl_SampleMaskIn is an array of i32. Retrieve the first element and
+ // convert it to u32.
+ auto* elem = builder.Access(ty.i32(), value, 0_u);
+ value = builder.Convert(ty.u32(), elem)->Result(0);
+ break;
+ }
+ default:
+ break;
+ }
+ }
return value;
}
@@ -201,6 +205,13 @@
// Store the output to the global variable declared earlier.
auto* to = output_vars[idx]->Result(0);
+
+ if (outputs[idx].attributes.builtin == core::BuiltinValue::kSampleMask) {
+ auto* ptr = ty.ptr(core::AddressSpace::kOut, ty.i32(), core::Access::kWrite);
+ to = builder.Access(ptr, to, 0_u)->Result(0);
+ value = builder.Convert(ty.i32(), value)->Result(0);
+ }
+
builder.Store(to, value);
if (outputs[idx].attributes.builtin == core::BuiltinValue::kPosition) {
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 a258636..638540f 100644
--- a/src/tint/lang/glsl/writer/raise/shader_io_test.cc
+++ b/src/tint/lang/glsl/writer/raise/shader_io_test.cc
@@ -979,7 +979,7 @@
EXPECT_EQ(expect, str());
}
-// Test that we change the type of the sample mask builtin to an array for SPIR-V.
+// Test that we change the type of the sample mask builtin to an array for GLSL
TEST_F(GlslWriter_ShaderIOTest, SampleMask) {
auto* str_ty = ty.Struct(mod.symbols.New("Outputs"),
{
@@ -1042,9 +1042,9 @@
}
$B1: { # root
- %gl_SampleMaskIn:ptr<__in, u32, read> = var @builtin(sample_mask)
+ %gl_SampleMaskIn:ptr<__in, array<i32, 1>, read> = var @builtin(sample_mask)
%foo_loc0_Output:ptr<__out, f32, write> = var @location(0)
- %gl_SampleMask:ptr<__out, u32, write> = var @builtin(sample_mask)
+ %gl_SampleMask:ptr<__out, array<i32, 1>, write> = var @builtin(sample_mask)
}
%foo_inner = func(%mask_in:u32):Outputs {
@@ -1055,12 +1055,16 @@
}
%foo = @fragment func():void {
$B3: {
- %8:u32 = load %gl_SampleMaskIn
- %9:Outputs = call %foo_inner, %8
- %10:f32 = access %9, 0u
- store %foo_loc0_Output, %10
- %11:u32 = access %9, 1u
- store %gl_SampleMask, %11
+ %8:array<i32, 1> = load %gl_SampleMaskIn
+ %9:i32 = access %8, 0u
+ %10:u32 = convert %9
+ %11:Outputs = call %foo_inner, %10
+ %12:f32 = access %11, 0u
+ store %foo_loc0_Output, %12
+ %13:u32 = access %11, 1u
+ %14:ptr<__out, i32, write> = access %gl_SampleMask, 0u
+ %15:i32 = convert %13
+ store %14, %15
ret
}
}