writer/spirv: Implement invariant attribute
Bug: tint:772
Change-Id: I94f8e95f7c1206f33dbf4defba2d22d95a5cfb1e
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/57643
Reviewed-by: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
diff --git a/src/transform/spirv.cc b/src/transform/spirv.cc
index 0d84459..1582db4 100644
--- a/src/transform/spirv.cc
+++ b/src/transform/spirv.cc
@@ -145,9 +145,9 @@
for (auto* member : struct_ty->members()) {
ast::DecorationList new_decorations = RemoveDecorations(
&ctx, member->decorations(), [](const ast::Decoration* deco) {
- return deco
- ->IsAnyOf<ast::BuiltinDecoration, ast::InterpolateDecoration,
- ast::LocationDecoration>();
+ return deco->IsAnyOf<
+ ast::BuiltinDecoration, ast::InterpolateDecoration,
+ ast::InvariantDecoration, ast::LocationDecoration>();
});
new_struct_members.push_back(
ctx.dst->Member(ctx.Clone(member->symbol()),
@@ -316,9 +316,9 @@
// Base case: create a global variable and return.
ast::DecorationList new_decorations =
RemoveDecorations(&ctx, decorations, [](const ast::Decoration* deco) {
- return !deco->IsAnyOf<ast::BuiltinDecoration,
- ast::InterpolateDecoration,
- ast::LocationDecoration>();
+ return !deco->IsAnyOf<
+ ast::BuiltinDecoration, ast::InterpolateDecoration,
+ ast::InvariantDecoration, ast::LocationDecoration>();
});
new_decorations.push_back(
ctx.dst->ASTNodes().Create<ast::DisableValidationDecoration>(
@@ -382,9 +382,9 @@
// Create a global variable.
ast::DecorationList new_decorations =
RemoveDecorations(&ctx, decorations, [](const ast::Decoration* deco) {
- return !deco->IsAnyOf<ast::BuiltinDecoration,
- ast::InterpolateDecoration,
- ast::LocationDecoration>();
+ return !deco->IsAnyOf<
+ ast::BuiltinDecoration, ast::InterpolateDecoration,
+ ast::InvariantDecoration, ast::LocationDecoration>();
});
new_decorations.push_back(
ctx.dst->ASTNodes().Create<ast::DisableValidationDecoration>(
diff --git a/src/transform/spirv_test.cc b/src/transform/spirv_test.cc
index f897004..6edfb24 100644
--- a/src/transform/spirv_test.cc
+++ b/src/transform/spirv_test.cc
@@ -601,6 +601,58 @@
EXPECT_EQ(expect, str(got));
}
+TEST_F(SpirvTest, HandleEntryPointIOTypes_InvariantAttributes) {
+ auto* src = R"(
+struct VertexOut {
+ [[builtin(position), invariant]] pos : vec4<f32>;
+};
+
+[[stage(vertex)]]
+fn main1() -> VertexOut {
+ return VertexOut();
+}
+
+[[stage(vertex)]]
+fn main2() -> [[builtin(position), invariant]] vec4<f32> {
+ return vec4<f32>();
+}
+)";
+
+ auto* expect = R"(
+struct VertexOut {
+ pos : vec4<f32>;
+};
+
+[[builtin(position), invariant, internal(disable_validation__ignore_storage_class)]] var<out> tint_symbol_1 : vec4<f32>;
+
+fn tint_symbol_2(tint_symbol : VertexOut) {
+ tint_symbol_1 = tint_symbol.pos;
+}
+
+[[stage(vertex)]]
+fn main1() {
+ tint_symbol_2(VertexOut());
+ return;
+}
+
+[[builtin(position), invariant, internal(disable_validation__ignore_storage_class)]] var<out> tint_symbol_4 : vec4<f32>;
+
+fn tint_symbol_5(tint_symbol_3 : vec4<f32>) {
+ tint_symbol_4 = tint_symbol_3;
+}
+
+[[stage(vertex)]]
+fn main2() {
+ tint_symbol_5(vec4<f32>());
+ return;
+}
+)";
+
+ auto got = Run<Spirv>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
TEST_F(SpirvTest, HandleEntryPointIOTypes_StructLayoutDecorations) {
auto* src = R"(
[[block]]
diff --git a/src/writer/spirv/builder.cc b/src/writer/spirv/builder.cc
index aca145a..9382362 100644
--- a/src/writer/spirv/builder.cc
+++ b/src/writer/spirv/builder.cc
@@ -853,6 +853,9 @@
} else if (auto* interpolate = deco->As<ast::InterpolateDecoration>()) {
AddInterpolationDecorations(var_id, interpolate->type(),
interpolate->sampling());
+ } else if (deco->Is<ast::InvariantDecoration>()) {
+ push_annot(spv::Op::OpDecorate,
+ {Operand::Int(var_id), Operand::Int(SpvDecorationInvariant)});
} else if (auto* binding = deco->As<ast::BindingDecoration>()) {
push_annot(spv::Op::OpDecorate,
{Operand::Int(var_id), Operand::Int(SpvDecorationBinding),
diff --git a/test/shader_io/invariant.wgsl.expected.spvasm b/test/shader_io/invariant.wgsl.expected.spvasm
index 93feddc..7759407 100644
--- a/test/shader_io/invariant.wgsl.expected.spvasm
+++ b/test/shader_io/invariant.wgsl.expected.spvasm
@@ -1,9 +1,40 @@
-SKIP: FAILED
-
-
-[[stage(vertex)]]
-fn main() -> [[builtin(position), invariant]] vec4<f32> {
- return vec4<f32>();
-}
-
-Failed to generate: unknown decoration
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 19
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Vertex %main "main" %tint_pointsize %tint_symbol_1
+ OpName %tint_pointsize "tint_pointsize"
+ OpName %tint_symbol_1 "tint_symbol_1"
+ OpName %tint_symbol_2 "tint_symbol_2"
+ OpName %tint_symbol "tint_symbol"
+ OpName %main "main"
+ OpDecorate %tint_pointsize BuiltIn PointSize
+ OpDecorate %tint_symbol_1 BuiltIn Position
+ OpDecorate %tint_symbol_1 Invariant
+ %float = OpTypeFloat 32
+%_ptr_Output_float = OpTypePointer Output %float
+ %4 = OpConstantNull %float
+%tint_pointsize = OpVariable %_ptr_Output_float Output %4
+ %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+ %8 = OpConstantNull %v4float
+%tint_symbol_1 = OpVariable %_ptr_Output_v4float Output %8
+ %void = OpTypeVoid
+ %9 = OpTypeFunction %void %v4float
+ %14 = OpTypeFunction %void
+ %float_1 = OpConstant %float 1
+%tint_symbol_2 = OpFunction %void None %9
+%tint_symbol = OpFunctionParameter %v4float
+ %13 = OpLabel
+ OpStore %tint_symbol_1 %tint_symbol
+ OpReturn
+ OpFunctionEnd
+ %main = OpFunction %void None %14
+ %16 = OpLabel
+ OpStore %tint_pointsize %float_1
+ %18 = OpFunctionCall %void %tint_symbol_2 %8
+ OpReturn
+ OpFunctionEnd
diff --git a/test/shader_io/invariant_struct_member.wgsl.expected.spvasm b/test/shader_io/invariant_struct_member.wgsl.expected.spvasm
index 08c28fc..b062a96 100644
--- a/test/shader_io/invariant_struct_member.wgsl.expected.spvasm
+++ b/test/shader_io/invariant_struct_member.wgsl.expected.spvasm
@@ -1,14 +1,46 @@
-SKIP: FAILED
-
-
-struct Out {
- [[builtin(position), invariant]]
- pos : vec4<f32>;
-};
-
-[[stage(vertex)]]
-fn main() -> Out {
- return Out();
-}
-
-Failed to generate: unknown decoration
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 22
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Vertex %main "main" %tint_pointsize %tint_symbol_1
+ OpName %tint_pointsize "tint_pointsize"
+ OpName %tint_symbol_1 "tint_symbol_1"
+ OpName %Out "Out"
+ OpMemberName %Out 0 "pos"
+ OpName %tint_symbol_2 "tint_symbol_2"
+ OpName %tint_symbol "tint_symbol"
+ OpName %main "main"
+ OpDecorate %tint_pointsize BuiltIn PointSize
+ OpDecorate %tint_symbol_1 BuiltIn Position
+ OpDecorate %tint_symbol_1 Invariant
+ OpMemberDecorate %Out 0 Offset 0
+ %float = OpTypeFloat 32
+%_ptr_Output_float = OpTypePointer Output %float
+ %4 = OpConstantNull %float
+%tint_pointsize = OpVariable %_ptr_Output_float Output %4
+ %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+ %8 = OpConstantNull %v4float
+%tint_symbol_1 = OpVariable %_ptr_Output_v4float Output %8
+ %void = OpTypeVoid
+ %Out = OpTypeStruct %v4float
+ %9 = OpTypeFunction %void %Out
+ %16 = OpTypeFunction %void
+ %float_1 = OpConstant %float 1
+ %21 = OpConstantNull %Out
+%tint_symbol_2 = OpFunction %void None %9
+%tint_symbol = OpFunctionParameter %Out
+ %14 = OpLabel
+ %15 = OpCompositeExtract %v4float %tint_symbol 0
+ OpStore %tint_symbol_1 %15
+ OpReturn
+ OpFunctionEnd
+ %main = OpFunction %void None %16
+ %18 = OpLabel
+ OpStore %tint_pointsize %float_1
+ %20 = OpFunctionCall %void %tint_symbol_2 %21
+ OpReturn
+ OpFunctionEnd