From 6330260f7d0e7322d1162fdd84ff2e6a8db76ab9 Mon Sep 17 00:00:00 2001 From: James Price Date: Mon, 21 Jun 2021 20:27:56 +0000 Subject: [PATCH] Validate that in/out storage classes are not used Use a DisableValidationDecoration to allow these storage classes only for variables generated by the SPIR-V sanitizer. Fix or delete all of the tests that were wrongly using these storage classes. Bug: tint:697 Change-Id: Ife1154f687b18529cfcc7a0ed93407fd25c9868e Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/55404 Reviewed-by: Ben Clayton Kokoro: Kokoro Auto-Submit: James Price Commit-Queue: James Price --- src/ast/disable_validation_decoration.cc | 4 +- src/ast/disable_validation_decoration.h | 6 +- src/program_test.cc | 2 +- src/resolver/decoration_validation_test.cc | 24 ++- src/resolver/intrinsic_test.cc | 30 ++-- src/resolver/resolver.cc | 14 +- src/resolver/resolver_test.cc | 88 +++++----- src/resolver/storage_class_validation_test.cc | 10 +- src/resolver/type_validation_test.cc | 8 +- src/resolver/validation_test.cc | 14 +- src/transform/msl.cc | 3 +- src/transform/msl_test.cc | 16 +- src/transform/spirv.cc | 12 +- src/transform/spirv_test.cc | 82 ++++----- src/writer/append_vector_test.cc | 16 +- src/writer/spirv/builder.cc | 3 +- src/writer/spirv/builder_assign_test.cc | 48 +++--- .../spirv/builder_function_decoration_test.cc | 120 +++----------- .../spirv/builder_global_variable_test.cc | 156 +----------------- .../spirv/builder_ident_expression_test.cc | 6 +- src/writer/spirv/builder_type_test.cc | 6 +- .../wgsl/generator_impl_global_decl_test.cc | 4 +- 22 files changed, 238 insertions(+), 434 deletions(-) diff --git a/src/ast/disable_validation_decoration.cc b/src/ast/disable_validation_decoration.cc index a8786e04ec..28adae45fe 100644 --- a/src/ast/disable_validation_decoration.cc +++ b/src/ast/disable_validation_decoration.cc @@ -34,8 +34,8 @@ std::string DisableValidationDecoration::InternalName() const { return "disable_validation__function_has_no_body"; case DisabledValidation::kBindingPointCollision: return "disable_validation__binding_point_collision"; - case DisabledValidation::kFunctionVarStorageClass: - return "disable_validation__function_var_storage_class"; + case DisabledValidation::kIgnoreStorageClass: + return "disable_validation__ignore_storage_class"; case DisabledValidation::kEntryPointParameter: return "disable_validation__entry_point_parameter"; } diff --git a/src/ast/disable_validation_decoration.h b/src/ast/disable_validation_decoration.h index 344dc7ecdf..e2b7bb956e 100644 --- a/src/ast/disable_validation_decoration.h +++ b/src/ast/disable_validation_decoration.h @@ -31,9 +31,9 @@ enum class DisabledValidation { /// When applied to a module-scoped variable, the validator will not complain /// if two resource variables have the same binding points. kBindingPointCollision, - /// When applied to a function-scoped variable, the validator will not - /// complain if the storage class is not `function`. - kFunctionVarStorageClass, + /// When applied to a variable, the validator will not complain about the + /// declared storage class. + kIgnoreStorageClass, /// When applied to an entry-point function parameter, the validator will not /// check for entry IO decorations. kEntryPointParameter, diff --git a/src/program_test.cc b/src/program_test.cc index acd6355c87..991e178a7e 100644 --- a/src/program_test.cc +++ b/src/program_test.cc @@ -53,7 +53,7 @@ TEST_F(ProgramTest, IDsAreUnique) { } TEST_F(ProgramTest, Assert_GlobalVariable) { - Global("var", ty.f32(), ast::StorageClass::kInput); + Global("var", ty.f32(), ast::StorageClass::kPrivate); Program program(std::move(*this)); EXPECT_TRUE(program.IsValid()); diff --git a/src/resolver/decoration_validation_test.cc b/src/resolver/decoration_validation_test.cc index d43d8f7f76..813149cdba 100644 --- a/src/resolver/decoration_validation_test.cc +++ b/src/resolver/decoration_validation_test.cc @@ -84,6 +84,16 @@ bool IsBindingDecoration(DecorationKind kind) { } } +bool IsShaderIODecoration(DecorationKind kind) { + switch (kind) { + case DecorationKind::kBuiltin: + case DecorationKind::kLocation: + return true; + default: + return false; + } +} + struct TestParams { DecorationKind kind; bool should_pass; @@ -327,8 +337,16 @@ TEST_P(VariableDecorationTest, IsValid) { Global("a", ty.sampler(ast::SamplerKind::kSampler), ast::StorageClass::kNone, nullptr, createDecorations(Source{{12, 34}}, *this, params.kind)); + } else if (IsShaderIODecoration(params.kind)) { + // Shader IO decorations are only valid on global variables when they have + // input/output storage classes, which are only generated internally by the + // SPIR-V sanitizer. + auto decos = createDecorations(Source{{12, 34}}, *this, params.kind); + decos.push_back(ASTNodes().Create( + ID(), ast::DisabledValidation::kIgnoreStorageClass)); + Global("a", ty.f32(), ast::StorageClass::kInput, nullptr, decos); } else { - Global("a", ty.f32(), ast::StorageClass::kInput, nullptr, + Global("a", ty.f32(), ast::StorageClass::kPrivate, nullptr, createDecorations(Source{{12, 34}}, *this, params.kind)); } @@ -506,7 +524,7 @@ TEST_P(ArrayStrideTest, All) { auto* arr = ty.array(Source{{12, 34}}, el_ty, 4, params.stride); - Global("myarray", arr, ast::StorageClass::kInput); + Global("myarray", arr, ast::StorageClass::kPrivate); if (params.should_pass) { EXPECT_TRUE(r()->Resolve()) << r()->error(); @@ -590,7 +608,7 @@ TEST_F(ArrayStrideTest, DuplicateDecoration) { create(Source{{56, 78}}, 4), }); - Global("myarray", arr, ast::StorageClass::kInput); + Global("myarray", arr, ast::StorageClass::kPrivate); EXPECT_FALSE(r()->Resolve()); EXPECT_EQ(r()->error(), diff --git a/src/resolver/intrinsic_test.cc b/src/resolver/intrinsic_test.cc index 34ed7f0273..473598ecf0 100644 --- a/src/resolver/intrinsic_test.cc +++ b/src/resolver/intrinsic_test.cc @@ -52,7 +52,7 @@ using ResolverIntrinsicDerivativeTest = ResolverTestWithParam; TEST_P(ResolverIntrinsicDerivativeTest, Scalar) { auto name = GetParam(); - Global("ident", ty.f32(), ast::StorageClass::kInput); + Global("ident", ty.f32(), ast::StorageClass::kPrivate); auto* expr = Call(name, "ident"); Func("func", {}, ty.void_(), {Ignore(expr)}, @@ -66,7 +66,7 @@ TEST_P(ResolverIntrinsicDerivativeTest, Scalar) { TEST_P(ResolverIntrinsicDerivativeTest, Vector) { auto name = GetParam(); - Global("ident", ty.vec4(), ast::StorageClass::kInput); + Global("ident", ty.vec4(), ast::StorageClass::kPrivate); auto* expr = Call(name, "ident"); Func("func", {}, ty.void_(), {Ignore(expr)}, @@ -111,7 +111,7 @@ using ResolverIntrinsic = ResolverTestWithParam; TEST_P(ResolverIntrinsic, Test) { auto name = GetParam(); - Global("my_var", ty.vec3(), ast::StorageClass::kInput); + Global("my_var", ty.vec3(), ast::StorageClass::kPrivate); auto* expr = Call(name, "my_var"); WrapInFunction(expr); @@ -129,7 +129,7 @@ using ResolverIntrinsicTest_FloatMethod = ResolverTestWithParam; TEST_P(ResolverIntrinsicTest_FloatMethod, Vector) { auto name = GetParam(); - Global("my_var", ty.vec3(), ast::StorageClass::kInput); + Global("my_var", ty.vec3(), ast::StorageClass::kPrivate); auto* expr = Call(name, "my_var"); WrapInFunction(expr); @@ -145,7 +145,7 @@ TEST_P(ResolverIntrinsicTest_FloatMethod, Vector) { TEST_P(ResolverIntrinsicTest_FloatMethod, Scalar) { auto name = GetParam(); - Global("my_var", ty.f32(), ast::StorageClass::kInput); + Global("my_var", ty.f32(), ast::StorageClass::kPrivate); auto* expr = Call(name, "my_var"); WrapInFunction(expr); @@ -159,7 +159,7 @@ TEST_P(ResolverIntrinsicTest_FloatMethod, Scalar) { TEST_P(ResolverIntrinsicTest_FloatMethod, MissingParam) { auto name = GetParam(); - Global("my_var", ty.f32(), ast::StorageClass::kInput); + Global("my_var", ty.f32(), ast::StorageClass::kPrivate); auto* expr = Call(name); WrapInFunction(expr); @@ -176,7 +176,7 @@ TEST_P(ResolverIntrinsicTest_FloatMethod, MissingParam) { TEST_P(ResolverIntrinsicTest_FloatMethod, TooManyParams) { auto name = GetParam(); - Global("my_var", ty.f32(), ast::StorageClass::kInput); + Global("my_var", ty.f32(), ast::StorageClass::kPrivate); auto* expr = Call(name, "my_var", 1.23f); WrapInFunction(expr); @@ -378,7 +378,7 @@ INSTANTIATE_TEST_SUITE_P( TextureTestParams{ast::TextureDimension::k3d})); TEST_F(ResolverIntrinsicTest, Dot_Vec2) { - Global("my_var", ty.vec2(), ast::StorageClass::kInput); + Global("my_var", ty.vec2(), ast::StorageClass::kPrivate); auto* expr = Call("dot", "my_var", "my_var"); WrapInFunction(expr); @@ -390,7 +390,7 @@ TEST_F(ResolverIntrinsicTest, Dot_Vec2) { } TEST_F(ResolverIntrinsicTest, Dot_Vec3) { - Global("my_var", ty.vec3(), ast::StorageClass::kInput); + Global("my_var", ty.vec3(), ast::StorageClass::kPrivate); auto* expr = Call("dot", "my_var", "my_var"); WrapInFunction(expr); @@ -402,7 +402,7 @@ TEST_F(ResolverIntrinsicTest, Dot_Vec3) { } TEST_F(ResolverIntrinsicTest, Dot_Vec4) { - Global("my_var", ty.vec4(), ast::StorageClass::kInput); + Global("my_var", ty.vec4(), ast::StorageClass::kPrivate); auto* expr = Call("dot", "my_var", "my_var"); WrapInFunction(expr); @@ -428,7 +428,7 @@ TEST_F(ResolverIntrinsicTest, Dot_Error_Scalar) { } TEST_F(ResolverIntrinsicTest, Dot_Error_VectorInt) { - Global("my_var", ty.vec4(), ast::StorageClass::kInput); + Global("my_var", ty.vec4(), ast::StorageClass::kPrivate); auto* expr = Call("dot", "my_var", "my_var"); WrapInFunction(expr); @@ -444,9 +444,9 @@ TEST_F(ResolverIntrinsicTest, Dot_Error_VectorInt) { } TEST_F(ResolverIntrinsicTest, Select) { - Global("my_var", ty.vec3(), ast::StorageClass::kInput); + Global("my_var", ty.vec3(), ast::StorageClass::kPrivate); - Global("bool_var", ty.vec3(), ast::StorageClass::kInput); + Global("bool_var", ty.vec3(), ast::StorageClass::kPrivate); auto* expr = Call("select", "my_var", "my_var", "bool_var"); WrapInFunction(expr); @@ -784,7 +784,7 @@ TEST_F(ResolverIntrinsicDataTest, ArrayLength_Vector) { } TEST_F(ResolverIntrinsicDataTest, ArrayLength_Error_ArraySized) { - Global("arr", ty.array(), ast::StorageClass::kInput); + Global("arr", ty.array(), ast::StorageClass::kPrivate); auto* call = Call("arrayLength", AddressOf("arr")); WrapInFunction(call); @@ -792,7 +792,7 @@ TEST_F(ResolverIntrinsicDataTest, ArrayLength_Error_ArraySized) { EXPECT_EQ( r()->error(), - R"(error: no matching call to arrayLength(ptr, read_write>) + R"(error: no matching call to arrayLength(ptr, read_write>) 1 candidate function: arrayLength(ptr, A>) -> u32 diff --git a/src/resolver/resolver.cc b/src/resolver/resolver.cc index e8afe07ab7..25b1dbf3f6 100644 --- a/src/resolver/resolver.cc +++ b/src/resolver/resolver.cc @@ -883,6 +883,15 @@ bool Resolver::ValidateVariable(const VariableInfo* info) { return false; } + if (!IsValidationDisabled(var->decorations(), + ast::DisabledValidation::kIgnoreStorageClass) && + (var->declared_storage_class() == ast::StorageClass::kInput || + var->declared_storage_class() == ast::StorageClass::kOutput)) { + diagnostics_.add_error("invalid use of input/output storage class", + var->source()); + return false; + } + // https://gpuweb.github.io/gpuweb/wgsl/#atomic-types // Atomic types may only be instantiated by variables in the workgroup storage // class or by storage buffer variables with a read_write access mode. @@ -2749,9 +2758,8 @@ bool Resolver::VariableDeclStatement(const ast::VariableDeclStatement* stmt) { if (!var->is_const()) { if (info->storage_class != ast::StorageClass::kFunction && - !IsValidationDisabled( - var->decorations(), - ast::DisabledValidation::kFunctionVarStorageClass)) { + !IsValidationDisabled(var->decorations(), + ast::DisabledValidation::kIgnoreStorageClass)) { if (info->storage_class != ast::StorageClass::kNone) { diagnostics_.add_error( "function variable has a non-function storage class", diff --git a/src/resolver/resolver_test.cc b/src/resolver/resolver_test.cc index c5e7176597..90fe982f47 100644 --- a/src/resolver/resolver_test.cc +++ b/src/resolver/resolver_test.cc @@ -320,7 +320,7 @@ TEST_F(ResolverTest, Stmt_VariableDecl_AliasRedeclared) { TEST_F(ResolverTest, Stmt_VariableDecl_ModuleScope) { auto* init = Expr(2); - Global("my_var", ty.i32(), ast::StorageClass::kInput, init); + Global("my_var", ty.i32(), ast::StorageClass::kPrivate, init); EXPECT_TRUE(r()->Resolve()) << r()->error(); @@ -405,7 +405,7 @@ TEST_F(ResolverTest, Stmt_VariableDecl_ModuleScopeAfterFunctionScope) { Func("func_i32", params, ty.void_(), {fn_i32_decl}, ast::DecorationList{}); // Declare f32 "foo" at module scope - auto* mod_f32 = Var("foo", ty.f32(), ast::StorageClass::kInput, Expr(2.f)); + auto* mod_f32 = Var("foo", ty.f32(), ast::StorageClass::kPrivate, Expr(2.f)); auto* mod_init = mod_f32->constructor(); AST().AddGlobalVariable(mod_f32); @@ -477,7 +477,7 @@ TEST_F(ResolverTest, Expr_ArrayAccessor_Array_Constant) { } TEST_F(ResolverTest, ArrayAccessor_Matrix_Dynamic_F32) { - Global("my_var", ty.mat2x3(), ast::StorageClass::kInput); + Global("my_var", ty.mat2x3(), ast::StorageClass::kPrivate); auto* acc = IndexAccessor("my_var", Expr(Source{{12, 34}}, 1.0f)); WrapInFunction(acc); @@ -487,7 +487,7 @@ TEST_F(ResolverTest, ArrayAccessor_Matrix_Dynamic_F32) { } TEST_F(ResolverTest, ArrayAccessor_Matrix_Dynamic_Ref) { - Global("my_var", ty.mat2x3(), ast::StorageClass::kInput); + Global("my_var", ty.mat2x3(), ast::StorageClass::kPrivate); auto* idx = Var("idx", ty.i32(), Construct(ty.i32())); auto* acc = IndexAccessor("my_var", idx); WrapInFunction(Decl(idx), acc); @@ -496,7 +496,7 @@ TEST_F(ResolverTest, ArrayAccessor_Matrix_Dynamic_Ref) { } TEST_F(ResolverTest, ArrayAccessor_Matrix_BothDimensions_Dynamic_Ref) { - Global("my_var", ty.mat4x4(), ast::StorageClass::kOutput); + Global("my_var", ty.mat4x4(), ast::StorageClass::kPrivate); auto* idx = Var("idx", ty.u32(), Expr(3u)); auto* idy = Var("idy", ty.u32(), Expr(2u)); auto* acc = IndexAccessor(IndexAccessor("my_var", idx), idy); @@ -540,7 +540,7 @@ TEST_F(ResolverTest, ArrayAccessor_Matrix_BothDimension_Dynamic) { } TEST_F(ResolverTest, Expr_ArrayAccessor_Matrix) { - Global("my_var", ty.mat2x3(), ast::StorageClass::kInput); + Global("my_var", ty.mat2x3(), ast::StorageClass::kPrivate); auto* acc = IndexAccessor("my_var", 2); WrapInFunction(acc); @@ -556,7 +556,7 @@ TEST_F(ResolverTest, Expr_ArrayAccessor_Matrix) { } TEST_F(ResolverTest, Expr_ArrayAccessor_Matrix_BothDimensions) { - Global("my_var", ty.mat2x3(), ast::StorageClass::kInput); + Global("my_var", ty.mat2x3(), ast::StorageClass::kPrivate); auto* acc = IndexAccessor(IndexAccessor("my_var", 2), 1); WrapInFunction(acc); @@ -571,7 +571,7 @@ TEST_F(ResolverTest, Expr_ArrayAccessor_Matrix_BothDimensions) { } TEST_F(ResolverTest, Expr_ArrayAccessor_Vector_F32) { - Global("my_var", ty.vec3(), ast::StorageClass::kInput); + Global("my_var", ty.vec3(), ast::StorageClass::kPrivate); auto* acc = IndexAccessor("my_var", Expr(Source{{12, 34}}, 2.0f)); WrapInFunction(acc); @@ -581,7 +581,7 @@ TEST_F(ResolverTest, Expr_ArrayAccessor_Vector_F32) { } TEST_F(ResolverTest, Expr_ArrayAccessor_Vector_Dynamic_Ref) { - Global("my_var", ty.vec3(), ast::StorageClass::kInput); + Global("my_var", ty.vec3(), ast::StorageClass::kPrivate); auto* idx = Var("idx", ty.i32(), Expr(2)); auto* acc = IndexAccessor("my_var", idx); WrapInFunction(Decl(idx), acc); @@ -599,7 +599,7 @@ TEST_F(ResolverTest, Expr_ArrayAccessor_Vector_Dynamic) { } TEST_F(ResolverTest, Expr_ArrayAccessor_Vector) { - Global("my_var", ty.vec3(), ast::StorageClass::kInput); + Global("my_var", ty.vec3(), ast::StorageClass::kPrivate); auto* acc = IndexAccessor("my_var", 2); WrapInFunction(acc); @@ -737,7 +737,7 @@ TEST_F(ResolverTest, Expr_Constructor_Type_Vec4) { } TEST_F(ResolverTest, Expr_Identifier_GlobalVariable) { - auto* my_var = Global("my_var", ty.f32(), ast::StorageClass::kInput); + auto* my_var = Global("my_var", ty.f32(), ast::StorageClass::kPrivate); auto* ident = Expr("my_var"); WrapInFunction(ident); @@ -972,8 +972,6 @@ TEST_F(ResolverTest, Function_RegisterInputOutputVariables) { auto* s = Structure("S", {Member("m", ty.u32())}, {create()}); - auto* in_var = Global("in_var", ty.f32(), ast::StorageClass::kInput); - auto* out_var = Global("out_var", ty.f32(), ast::StorageClass::kOutput); auto* sb_var = Global("sb_var", ty.Of(s), ast::StorageClass::kStorage, ast::Access::kReadWrite, ast::DecorationList{ @@ -985,7 +983,6 @@ TEST_F(ResolverTest, Function_RegisterInputOutputVariables) { auto* func = Func("my_func", ast::VariableList{}, ty.void_(), { - Assign("out_var", "in_var"), Assign("wg_var", "wg_var"), Assign("sb_var", "sb_var"), Assign("priv_var", "priv_var"), @@ -999,20 +996,16 @@ TEST_F(ResolverTest, Function_RegisterInputOutputVariables) { EXPECT_TRUE(func_sem->ReturnType()->Is()); const auto& vars = func_sem->ReferencedModuleVariables(); - ASSERT_EQ(vars.size(), 5u); - EXPECT_EQ(vars[0]->Declaration(), out_var); - EXPECT_EQ(vars[1]->Declaration(), in_var); - EXPECT_EQ(vars[2]->Declaration(), wg_var); - EXPECT_EQ(vars[3]->Declaration(), sb_var); - EXPECT_EQ(vars[4]->Declaration(), priv_var); + ASSERT_EQ(vars.size(), 3u); + EXPECT_EQ(vars[0]->Declaration(), wg_var); + EXPECT_EQ(vars[1]->Declaration(), sb_var); + EXPECT_EQ(vars[2]->Declaration(), priv_var); } TEST_F(ResolverTest, Function_RegisterInputOutputVariables_SubFunction) { auto* s = Structure("S", {Member("m", ty.u32())}, {create()}); - auto* in_var = Global("in_var", ty.f32(), ast::StorageClass::kInput); - auto* out_var = Global("out_var", ty.f32(), ast::StorageClass::kOutput); auto* sb_var = Global("sb_var", ty.Of(s), ast::StorageClass::kStorage, ast::Access::kReadWrite, ast::DecorationList{ @@ -1023,14 +1016,13 @@ TEST_F(ResolverTest, Function_RegisterInputOutputVariables_SubFunction) { auto* priv_var = Global("priv_var", ty.f32(), ast::StorageClass::kPrivate); Func("my_func", ast::VariableList{}, ty.f32(), - {Assign("out_var", "in_var"), Assign("wg_var", "wg_var"), - Assign("sb_var", "sb_var"), Assign("priv_var", "priv_var"), - Return(0.0f)}, + {Assign("wg_var", "wg_var"), Assign("sb_var", "sb_var"), + Assign("priv_var", "priv_var"), Return(0.0f)}, ast::DecorationList{}); auto* func2 = Func("func", ast::VariableList{}, ty.void_(), { - Assign("out_var", Call("my_func")), + WrapInStatement(Call("my_func")), }, ast::DecorationList{}); @@ -1041,12 +1033,10 @@ TEST_F(ResolverTest, Function_RegisterInputOutputVariables_SubFunction) { EXPECT_EQ(func2_sem->Parameters().size(), 0u); const auto& vars = func2_sem->ReferencedModuleVariables(); - ASSERT_EQ(vars.size(), 5u); - EXPECT_EQ(vars[0]->Declaration(), out_var); - EXPECT_EQ(vars[1]->Declaration(), in_var); - EXPECT_EQ(vars[2]->Declaration(), wg_var); - EXPECT_EQ(vars[3]->Declaration(), sb_var); - EXPECT_EQ(vars[4]->Declaration(), priv_var); + ASSERT_EQ(vars.size(), 3u); + EXPECT_EQ(vars[0]->Declaration(), wg_var); + EXPECT_EQ(vars[1]->Declaration(), sb_var); + EXPECT_EQ(vars[2]->Declaration(), priv_var); } TEST_F(ResolverTest, Function_NotRegisterFunctionVariable) { @@ -1285,7 +1275,7 @@ TEST_F(ResolverTest, Function_WorkgroupSize_Mixed) { TEST_F(ResolverTest, Expr_MemberAccessor_Struct) { auto* st = Structure("S", {Member("first_member", ty.i32()), Member("second_member", ty.f32())}); - Global("my_struct", ty.Of(st), ast::StorageClass::kInput); + Global("my_struct", ty.Of(st), ast::StorageClass::kPrivate); auto* mem = MemberAccessor("my_struct", "second_member"); WrapInFunction(mem); @@ -1309,7 +1299,7 @@ TEST_F(ResolverTest, Expr_MemberAccessor_Struct_Alias) { auto* st = Structure("S", {Member("first_member", ty.i32()), Member("second_member", ty.f32())}); auto* alias = Alias("alias", ty.Of(st)); - Global("my_struct", ty.Of(alias), ast::StorageClass::kInput); + Global("my_struct", ty.Of(alias), ast::StorageClass::kPrivate); auto* mem = MemberAccessor("my_struct", "second_member"); WrapInFunction(mem); @@ -1328,7 +1318,7 @@ TEST_F(ResolverTest, Expr_MemberAccessor_Struct_Alias) { } TEST_F(ResolverTest, Expr_MemberAccessor_VectorSwizzle) { - Global("my_vec", ty.vec4(), ast::StorageClass::kInput); + Global("my_vec", ty.vec4(), ast::StorageClass::kPrivate); auto* mem = MemberAccessor("my_vec", "xzyw"); WrapInFunction(mem); @@ -1345,7 +1335,7 @@ TEST_F(ResolverTest, Expr_MemberAccessor_VectorSwizzle) { } TEST_F(ResolverTest, Expr_MemberAccessor_VectorSwizzle_SingleElement) { - Global("my_vec", ty.vec3(), ast::StorageClass::kInput); + Global("my_vec", ty.vec3(), ast::StorageClass::kPrivate); auto* mem = MemberAccessor("my_vec", "b"); WrapInFunction(mem); @@ -1389,7 +1379,7 @@ TEST_F(ResolverTest, Expr_Accessor_MultiLevel) { auto* stB = Structure("B", {Member("foo", ty.vec4())}); auto* stA = Structure("A", {Member("mem", ty.vec(ty.Of(stB), 3))}); - Global("c", ty.Of(stA), ast::StorageClass::kInput); + Global("c", ty.Of(stA), ast::StorageClass::kPrivate); auto* mem = MemberAccessor( MemberAccessor(IndexAccessor(MemberAccessor("c", "mem"), 0), "foo"), @@ -1408,7 +1398,7 @@ TEST_F(ResolverTest, Expr_Accessor_MultiLevel) { TEST_F(ResolverTest, Expr_MemberAccessor_InBinaryOp) { auto* st = Structure("S", {Member("first_member", ty.f32()), Member("second_member", ty.f32())}); - Global("my_struct", ty.Of(st), ast::StorageClass::kInput); + Global("my_struct", ty.Of(st), ast::StorageClass::kPrivate); auto* expr = Add(MemberAccessor("my_struct", "first_member"), MemberAccessor("my_struct", "second_member")); @@ -1714,8 +1704,8 @@ TEST_P(Expr_Binary_Test_Valid, All) { << FriendlyName(rhs_type); SCOPED_TRACE(ss.str()); - Global("lhs", lhs_type, ast::StorageClass::kInput); - Global("rhs", rhs_type, ast::StorageClass::kInput); + Global("lhs", lhs_type, ast::StorageClass::kPrivate); + Global("rhs", rhs_type, ast::StorageClass::kPrivate); auto* expr = create(params.op, Expr("lhs"), Expr("rhs")); @@ -1756,8 +1746,8 @@ TEST_P(Expr_Binary_Test_WithAlias_Valid, All) { << " " << FriendlyName(rhs_type); SCOPED_TRACE(ss.str()); - Global("lhs", lhs_type, ast::StorageClass::kInput); - Global("rhs", rhs_type, ast::StorageClass::kInput); + Global("lhs", lhs_type, ast::StorageClass::kPrivate); + Global("rhs", rhs_type, ast::StorageClass::kPrivate); auto* expr = create(params.op, Expr("lhs"), Expr("rhs")); @@ -1808,8 +1798,8 @@ TEST_P(Expr_Binary_Test_Invalid, All) { ss << FriendlyName(lhs_type) << " " << op << " " << FriendlyName(rhs_type); SCOPED_TRACE(ss.str()); - Global("lhs", lhs_type, ast::StorageClass::kInput); - Global("rhs", rhs_type, ast::StorageClass::kInput); + Global("lhs", lhs_type, ast::StorageClass::kPrivate); + Global("rhs", rhs_type, ast::StorageClass::kPrivate); auto* expr = create(Source{{12, 34}}, op, Expr("lhs"), Expr("rhs")); @@ -1854,8 +1844,8 @@ TEST_P(Expr_Binary_Test_Invalid_VectorMatrixMultiply, All) { is_valid_expr = vec_size == mat_cols; } - Global("lhs", lhs_type, ast::StorageClass::kInput); - Global("rhs", rhs_type, ast::StorageClass::kInput); + Global("lhs", lhs_type, ast::StorageClass::kPrivate); + Global("rhs", rhs_type, ast::StorageClass::kPrivate); auto* expr = Mul(Source{{12, 34}}, Expr("lhs"), Expr("rhs")); WrapInFunction(expr); @@ -1895,8 +1885,8 @@ TEST_P(Expr_Binary_Test_Invalid_MatrixMatrixMultiply, All) { auto* col = create(f32, lhs_mat_rows); auto* result_type = create(col, rhs_mat_cols); - Global("lhs", lhs_type, ast::StorageClass::kInput); - Global("rhs", rhs_type, ast::StorageClass::kInput); + Global("lhs", lhs_type, ast::StorageClass::kPrivate); + Global("rhs", rhs_type, ast::StorageClass::kPrivate); auto* expr = Mul(Source{{12, 34}}, Expr("lhs"), Expr("rhs")); WrapInFunction(expr); @@ -1927,7 +1917,7 @@ using UnaryOpExpressionTest = ResolverTestWithParam; TEST_P(UnaryOpExpressionTest, Expr_UnaryOp) { auto op = GetParam(); - Global("ident", ty.vec4(), ast::StorageClass::kInput); + Global("ident", ty.vec4(), ast::StorageClass::kPrivate); auto* der = create(op, Expr("ident")); WrapInFunction(der); diff --git a/src/resolver/storage_class_validation_test.cc b/src/resolver/storage_class_validation_test.cc index 84e7463e7a..5c6ca3dc81 100644 --- a/src/resolver/storage_class_validation_test.cc +++ b/src/resolver/storage_class_validation_test.cc @@ -50,9 +50,8 @@ TEST_F(ResolverStorageClassValidationTest, StorageBufferBool) { } TEST_F(ResolverStorageClassValidationTest, StorageBufferPointer) { - // var g : ptr; - Global(Source{{56, 78}}, "g", ty.pointer(ast::StorageClass::kInput), - ast::StorageClass::kStorage, + // var g : vec4; + Global(Source{{56, 78}}, "g", ty.vec4(), ast::StorageClass::kStorage, ast::DecorationList{ create(0), create(0), @@ -187,9 +186,8 @@ TEST_F(ResolverStorageClassValidationTest, UniformBufferBool) { } TEST_F(ResolverStorageClassValidationTest, UniformBufferPointer) { - // var g : ptr; - Global(Source{{56, 78}}, "g", ty.pointer(ast::StorageClass::kInput), - ast::StorageClass::kUniform, + // var g : vec4; + Global(Source{{56, 78}}, "g", ty.vec4(), ast::StorageClass::kUniform, ast::DecorationList{ create(0), create(0), diff --git a/src/resolver/type_validation_test.cc b/src/resolver/type_validation_test.cc index d1b1c350eb..b1aea9c78d 100644 --- a/src/resolver/type_validation_test.cc +++ b/src/resolver/type_validation_test.cc @@ -85,17 +85,17 @@ TEST_F(ResolverTypeValidationTest, GlobalConstantNoConstructor_Pass) { } TEST_F(ResolverTypeValidationTest, GlobalVariableWithStorageClass_Pass) { - // var global_var: f32; - Global(Source{{12, 34}}, "global_var", ty.f32(), ast::StorageClass::kInput); + // var global_var: f32; + Global(Source{{12, 34}}, "global_var", ty.f32(), ast::StorageClass::kPrivate); EXPECT_TRUE(r()->Resolve()) << r()->error(); } TEST_F(ResolverTypeValidationTest, GlobalConstantWithStorageClass_Fail) { - // const global_var: f32; + // const global_var: f32; AST().AddGlobalVariable(create( Source{{12, 34}}, Symbols().Register("global_var"), - ast::StorageClass::kInput, ast::Access::kUndefined, ty.f32(), true, + ast::StorageClass::kPrivate, ast::Access::kUndefined, ty.f32(), true, Expr(1.23f), ast::DecorationList{})); EXPECT_FALSE(r()->Resolve()); diff --git a/src/resolver/validation_test.cc b/src/resolver/validation_test.cc index 600a588bed..d288c0464b 100644 --- a/src/resolver/validation_test.cc +++ b/src/resolver/validation_test.cc @@ -349,7 +349,7 @@ TEST_F(ResolverValidationTest, StorageClass_TextureExplicitStorageClass) { } TEST_F(ResolverValidationTest, Expr_MemberAccessor_VectorSwizzle_BadChar) { - Global("my_vec", ty.vec3(), ast::StorageClass::kInput); + Global("my_vec", ty.vec3(), ast::StorageClass::kPrivate); auto* ident = create( Source{{Source::Location{3, 3}, Source::Location{3, 7}}}, @@ -363,7 +363,7 @@ TEST_F(ResolverValidationTest, Expr_MemberAccessor_VectorSwizzle_BadChar) { } TEST_F(ResolverValidationTest, Expr_MemberAccessor_VectorSwizzle_MixedChars) { - Global("my_vec", ty.vec4(), ast::StorageClass::kInput); + Global("my_vec", ty.vec4(), ast::StorageClass::kPrivate); auto* ident = create( Source{{Source::Location{3, 3}, Source::Location{3, 7}}}, @@ -379,7 +379,7 @@ TEST_F(ResolverValidationTest, Expr_MemberAccessor_VectorSwizzle_MixedChars) { } TEST_F(ResolverValidationTest, Expr_MemberAccessor_VectorSwizzle_BadLength) { - Global("my_vec", ty.vec3(), ast::StorageClass::kInput); + Global("my_vec", ty.vec3(), ast::StorageClass::kPrivate); auto* ident = create( Source{{Source::Location{3, 3}, Source::Location{3, 8}}}, @@ -392,7 +392,7 @@ TEST_F(ResolverValidationTest, Expr_MemberAccessor_VectorSwizzle_BadLength) { } TEST_F(ResolverValidationTest, Expr_MemberAccessor_VectorSwizzle_BadIndex) { - Global("my_vec", ty.vec2(), ast::StorageClass::kInput); + Global("my_vec", ty.vec2(), ast::StorageClass::kPrivate); auto* ident = create(Source{{3, 3}}, Symbols().Register("z")); @@ -1848,7 +1848,7 @@ TEST_F(ResolverValidationTest, TEST_F(ResolverValidationTest, Expr_Constructor_Vector_Alias_Argument_Error) { auto* alias = Alias("UnsignedInt", ty.u32()); - Global("uint_var", ty.Of(alias), ast::StorageClass::kInput); + Global("uint_var", ty.Of(alias), ast::StorageClass::kPrivate); auto* tc = vec2(Expr(Source{{12, 34}}, "uint_var")); WrapInFunction(tc); @@ -1862,8 +1862,8 @@ TEST_F(ResolverValidationTest, Expr_Constructor_Vector_Alias_Argument_Error) { TEST_F(ResolverValidationTest, Expr_Constructor_Vector_Alias_Argument_Success) { auto* f32_alias = Alias("Float32", ty.f32()); auto* vec2_alias = Alias("VectorFloat2", ty.vec2()); - Global("my_f32", ty.Of(f32_alias), ast::StorageClass::kInput); - Global("my_vec2", ty.Of(vec2_alias), ast::StorageClass::kInput); + Global("my_f32", ty.Of(f32_alias), ast::StorageClass::kPrivate); + Global("my_vec2", ty.Of(vec2_alias), ast::StorageClass::kPrivate); auto* tc = vec3("my_vec2", "my_f32"); WrapInFunction(tc); diff --git a/src/transform/msl.cc b/src/transform/msl.cc index 6d45462fa1..50e4cc9f1c 100644 --- a/src/transform/msl.cc +++ b/src/transform/msl.cc @@ -207,8 +207,7 @@ void Msl::HandleModuleScopeVariables(CloneContext& ctx) const { // scope. Disable storage class validation on this variable. auto* disable_validation = ctx.dst->ASTNodes().Create( - ctx.dst->ID(), - ast::DisabledValidation::kFunctionVarStorageClass); + ctx.dst->ID(), ast::DisabledValidation::kIgnoreStorageClass); auto* constructor = ctx.Clone(var->Declaration()->constructor()); auto* local_var = ctx.dst->Var( new_var_symbol, store_type, var->StorageClass(), constructor, diff --git a/src/transform/msl_test.cc b/src/transform/msl_test.cc index 6b0968c501..cc83854a62 100644 --- a/src/transform/msl_test.cc +++ b/src/transform/msl_test.cc @@ -36,8 +36,8 @@ fn main() { auto* expect = R"( [[stage(compute)]] fn main([[builtin(local_invocation_index)]] local_invocation_index : u32) { - [[internal(disable_validation__function_var_storage_class)]] var tint_symbol_1 : f32; - [[internal(disable_validation__function_var_storage_class)]] var tint_symbol_2 : f32; + [[internal(disable_validation__ignore_storage_class)]] var tint_symbol_1 : f32; + [[internal(disable_validation__ignore_storage_class)]] var tint_symbol_2 : f32; if ((local_invocation_index == 0u)) { tint_symbol_1 = f32(); } @@ -93,8 +93,8 @@ fn foo(a : f32, tint_symbol_3 : ptr, tint_symbol_4 : ptr tint_symbol_5 : f32; - [[internal(disable_validation__function_var_storage_class)]] var tint_symbol_6 : f32; + [[internal(disable_validation__ignore_storage_class)]] var tint_symbol_5 : f32; + [[internal(disable_validation__ignore_storage_class)]] var tint_symbol_6 : f32; if ((local_invocation_index == 0u)) { tint_symbol_5 = f32(); } @@ -122,8 +122,8 @@ fn main() { auto* expect = R"( [[stage(compute)]] fn main() { - [[internal(disable_validation__function_var_storage_class)]] var tint_symbol : f32 = 1.0; - [[internal(disable_validation__function_var_storage_class)]] var tint_symbol_1 : f32 = f32(); + [[internal(disable_validation__ignore_storage_class)]] var tint_symbol : f32 = 1.0; + [[internal(disable_validation__ignore_storage_class)]] var tint_symbol_1 : f32 = f32(); let x : f32 = (tint_symbol + tint_symbol_1); } )"; @@ -150,8 +150,8 @@ fn main() { auto* expect = R"( [[stage(compute)]] fn main([[builtin(local_invocation_index)]] local_invocation_index : u32) { - [[internal(disable_validation__function_var_storage_class)]] var tint_symbol_1 : f32; - [[internal(disable_validation__function_var_storage_class)]] var tint_symbol_2 : f32; + [[internal(disable_validation__ignore_storage_class)]] var tint_symbol_1 : f32; + [[internal(disable_validation__ignore_storage_class)]] var tint_symbol_2 : f32; if ((local_invocation_index == 0u)) { tint_symbol_1 = f32(); } diff --git a/src/transform/spirv.cc b/src/transform/spirv.cc index 81fdbb9208..874c1142bf 100644 --- a/src/transform/spirv.cc +++ b/src/transform/spirv.cc @@ -18,6 +18,7 @@ #include #include "src/ast/call_statement.h" +#include "src/ast/disable_validation_decoration.h" #include "src/ast/return_statement.h" #include "src/ast/stage_decoration.h" #include "src/program_builder.h" @@ -272,7 +273,10 @@ void Spirv::EmitVertexPointSize(CloneContext& ctx) const { Symbol pointsize = ctx.dst->Symbols().New("tint_pointsize"); ctx.dst->Global( pointsize, ctx.dst->ty.f32(), ast::StorageClass::kOutput, - ast::DecorationList{ctx.dst->Builtin(ast::Builtin::kPointSize)}); + ast::DecorationList{ + ctx.dst->Builtin(ast::Builtin::kPointSize), + ctx.dst->ASTNodes().Create( + ctx.dst->ID(), ast::DisabledValidation::kIgnoreStorageClass)}); // Assign 1.0 to the global at the start of all vertex shader entry points. ctx.ReplaceAll([&ctx, pointsize](ast::Function* func) -> ast::Function* { @@ -309,6 +313,9 @@ Symbol Spirv::HoistToInputVariables( return !deco->IsAnyOf(); }); + new_decorations.push_back( + ctx.dst->ASTNodes().Create( + ctx.dst->ID(), ast::DisabledValidation::kIgnoreStorageClass)); auto global_var_symbol = ctx.dst->Sym(); auto* global_var = ctx.dst->Var(global_var_symbol, ctx.Clone(declared_ty), @@ -363,6 +370,9 @@ void Spirv::HoistToOutputVariables(CloneContext& ctx, return !deco->IsAnyOf(); }); + new_decorations.push_back( + ctx.dst->ASTNodes().Create( + ctx.dst->ID(), ast::DisabledValidation::kIgnoreStorageClass)); auto global_var_symbol = ctx.dst->Sym(); auto* global_var = ctx.dst->Var(global_var_symbol, ctx.Clone(declared_ty), diff --git a/src/transform/spirv_test.cc b/src/transform/spirv_test.cc index 150167aeb8..cf15d8c17c 100644 --- a/src/transform/spirv_test.cc +++ b/src/transform/spirv_test.cc @@ -38,18 +38,18 @@ fn compute_main([[builtin(local_invocation_id)]] local_id : vec3, )"; auto* expect = R"( -[[builtin(position)]] var tint_symbol : vec4; +[[builtin(position), internal(disable_validation__ignore_storage_class)]] var tint_symbol : vec4; -[[location(1)]] var tint_symbol_1 : f32; +[[location(1), internal(disable_validation__ignore_storage_class)]] var tint_symbol_1 : f32; [[stage(fragment)]] fn frag_main() { var col : f32 = (tint_symbol.x * tint_symbol_1); } -[[builtin(local_invocation_id)]] var tint_symbol_2 : vec3; +[[builtin(local_invocation_id), internal(disable_validation__ignore_storage_class)]] var tint_symbol_2 : vec3; -[[builtin(local_invocation_index)]] var tint_symbol_3 : u32; +[[builtin(local_invocation_index), internal(disable_validation__ignore_storage_class)]] var tint_symbol_3 : u32; [[stage(compute)]] fn compute_main() { @@ -74,7 +74,7 @@ fn frag_main([[location(1)]] loc1 : myf32) { auto* expect = R"( type myf32 = f32; -[[location(1)]] var tint_symbol : myf32; +[[location(1), internal(disable_validation__ignore_storage_class)]] var tint_symbol : myf32; [[stage(fragment)]] fn frag_main() { @@ -95,7 +95,7 @@ fn vert_main() -> [[builtin(position)]] vec4 { )"; auto* expect = R"( -[[builtin(position)]] var tint_symbol_1 : vec4; +[[builtin(position), internal(disable_validation__ignore_storage_class)]] var tint_symbol_1 : vec4; fn tint_symbol_2(tint_symbol : vec4) { tint_symbol_1 = tint_symbol; @@ -125,9 +125,9 @@ fn frag_main([[location(0)]] loc_in : u32) -> [[location(0)]] f32 { )"; auto* expect = R"( -[[location(0)]] var tint_symbol : u32; +[[location(0), internal(disable_validation__ignore_storage_class)]] var tint_symbol : u32; -[[location(0)]] var tint_symbol_2 : f32; +[[location(0), internal(disable_validation__ignore_storage_class)]] var tint_symbol_2 : f32; fn tint_symbol_3(tint_symbol_1 : f32) { tint_symbol_2 = tint_symbol_1; @@ -165,9 +165,9 @@ fn frag_main([[location(0)]] loc_in : u32) -> [[location(0)]] myf32 { auto* expect = R"( type myf32 = f32; -[[location(0)]] var tint_symbol : u32; +[[location(0), internal(disable_validation__ignore_storage_class)]] var tint_symbol : u32; -[[location(0)]] var tint_symbol_2 : myf32; +[[location(0), internal(disable_validation__ignore_storage_class)]] var tint_symbol_2 : myf32; fn tint_symbol_3(tint_symbol_1 : myf32) { tint_symbol_2 = tint_symbol_1; @@ -208,9 +208,9 @@ struct FragmentInput { value : f32; }; -[[builtin(position)]] var tint_symbol : vec4; +[[builtin(position), internal(disable_validation__ignore_storage_class)]] var tint_symbol : vec4; -[[location(1)]] var tint_symbol_1 : f32; +[[location(1), internal(disable_validation__ignore_storage_class)]] var tint_symbol_1 : f32; [[stage(fragment)]] fn frag_main() { @@ -240,7 +240,7 @@ struct FragmentInput { value : f32; }; -[[location(1)]] var tint_symbol : f32; +[[location(1), internal(disable_validation__ignore_storage_class)]] var tint_symbol : f32; [[stage(fragment)]] fn frag_main() { @@ -275,9 +275,9 @@ struct VertexOutput { value : f32; }; -[[builtin(position)]] var tint_symbol_1 : vec4; +[[builtin(position), internal(disable_validation__ignore_storage_class)]] var tint_symbol_1 : vec4; -[[location(1)]] var tint_symbol_2 : f32; +[[location(1), internal(disable_validation__ignore_storage_class)]] var tint_symbol_2 : f32; fn tint_symbol_3(tint_symbol : VertexOutput) { tint_symbol_1 = tint_symbol.pos; @@ -318,9 +318,9 @@ struct Interface { value : f32; }; -[[location(1)]] var tint_symbol : f32; +[[location(1), internal(disable_validation__ignore_storage_class)]] var tint_symbol : f32; -[[location(1)]] var tint_symbol_3 : f32; +[[location(1), internal(disable_validation__ignore_storage_class)]] var tint_symbol_3 : f32; fn tint_symbol_4(tint_symbol_2 : Interface) { tint_symbol_3 = tint_symbol_2.value; @@ -363,9 +363,9 @@ struct Interface { value : f32; }; -[[builtin(position)]] var tint_symbol_1 : vec4; +[[builtin(position), internal(disable_validation__ignore_storage_class)]] var tint_symbol_1 : vec4; -[[location(1)]] var tint_symbol_2 : f32; +[[location(1), internal(disable_validation__ignore_storage_class)]] var tint_symbol_2 : f32; fn tint_symbol_3(tint_symbol : Interface) { tint_symbol_1 = tint_symbol.pos; @@ -378,9 +378,9 @@ fn vert_main() { return; } -[[builtin(position)]] var tint_symbol_4 : vec4; +[[builtin(position), internal(disable_validation__ignore_storage_class)]] var tint_symbol_4 : vec4; -[[location(1)]] var tint_symbol_5 : f32; +[[location(1), internal(disable_validation__ignore_storage_class)]] var tint_symbol_5 : f32; [[stage(fragment)]] fn frag_main() { @@ -426,11 +426,11 @@ struct FragmentOutput { value : f32; }; -[[location(1)]] var tint_symbol : f32; +[[location(1), internal(disable_validation__ignore_storage_class)]] var tint_symbol : f32; -[[builtin(position)]] var tint_symbol_1 : vec4; +[[builtin(position), internal(disable_validation__ignore_storage_class)]] var tint_symbol_1 : vec4; -[[location(1)]] var tint_symbol_4 : f32; +[[location(1), internal(disable_validation__ignore_storage_class)]] var tint_symbol_4 : f32; fn tint_symbol_5(tint_symbol_3 : FragmentOutput) { tint_symbol_4 = tint_symbol_3.value; @@ -472,7 +472,7 @@ struct VertexOutput { Position : vec4; }; -[[builtin(position)]] var tint_symbol_1 : vec4; +[[builtin(position), internal(disable_validation__ignore_storage_class)]] var tint_symbol_1 : vec4; fn tint_symbol_2(tint_symbol : VertexOutput) { tint_symbol_1 = tint_symbol.Position; @@ -501,11 +501,11 @@ fn main([[builtin(sample_index)]] sample_index : u32, )"; auto* expect = R"( -[[builtin(sample_index)]] var tint_symbol : u32; +[[builtin(sample_index), internal(disable_validation__ignore_storage_class)]] var tint_symbol : u32; -[[builtin(sample_mask)]] var tint_symbol_1 : array; +[[builtin(sample_mask), internal(disable_validation__ignore_storage_class)]] var tint_symbol_1 : array; -[[builtin(sample_mask)]] var tint_symbol_3 : array; +[[builtin(sample_mask), internal(disable_validation__ignore_storage_class)]] var tint_symbol_3 : array; fn tint_symbol_4(tint_symbol_2 : u32) { tint_symbol_3[0] = tint_symbol_2; @@ -549,9 +549,9 @@ fn set_mask(input : u32) -> u32 { return input; } -[[builtin(sample_mask)]] var tint_symbol : array; +[[builtin(sample_mask), internal(disable_validation__ignore_storage_class)]] var tint_symbol : array; -[[builtin(sample_mask)]] var tint_symbol_2 : array; +[[builtin(sample_mask), internal(disable_validation__ignore_storage_class)]] var tint_symbol_2 : array; fn tint_symbol_3(tint_symbol_1 : u32) { tint_symbol_2[0] = tint_symbol_1; @@ -582,12 +582,12 @@ fn main() -> [[builtin(position)]] vec4 { )"; auto* expect = R"( -[[builtin(pointsize)]] var tint_pointsize : f32; +[[builtin(pointsize), internal(disable_validation__ignore_storage_class)]] var tint_pointsize : f32; fn non_entry_point() { } -[[builtin(position)]] var tint_symbol_1 : vec4; +[[builtin(position), internal(disable_validation__ignore_storage_class)]] var tint_symbol_1 : vec4; fn tint_symbol_2(tint_symbol : vec4) { tint_symbol_1 = tint_symbol; @@ -628,9 +628,9 @@ fn main3() -> [[builtin(position)]] vec4 { )"; auto* expect = R"( -[[builtin(pointsize)]] var tint_pointsize : f32; +[[builtin(pointsize), internal(disable_validation__ignore_storage_class)]] var tint_pointsize : f32; -[[builtin(position)]] var tint_symbol_1 : vec4; +[[builtin(position), internal(disable_validation__ignore_storage_class)]] var tint_symbol_1 : vec4; fn tint_symbol_2(tint_symbol : vec4) { tint_symbol_1 = tint_symbol; @@ -643,7 +643,7 @@ fn main1() { return; } -[[builtin(position)]] var tint_symbol_4 : vec4; +[[builtin(position), internal(disable_validation__ignore_storage_class)]] var tint_symbol_4 : vec4; fn tint_symbol_5(tint_symbol_3 : vec4) { tint_symbol_4 = tint_symbol_3; @@ -656,7 +656,7 @@ fn main2() { return; } -[[builtin(position)]] var tint_symbol_7 : vec4; +[[builtin(position), internal(disable_validation__ignore_storage_class)]] var tint_symbol_7 : vec4; fn tint_symbol_8(tint_symbol_6 : vec4) { tint_symbol_7 = tint_symbol_6; @@ -722,9 +722,9 @@ fn frag_main([[builtin(sample_index)]] sample_index : u32, )"; auto* expect = R"( -[[builtin(pointsize)]] var tint_pointsize : f32; +[[builtin(pointsize), internal(disable_validation__ignore_storage_class)]] var tint_pointsize : f32; -[[builtin(position)]] var tint_symbol_1 : vec4; +[[builtin(position), internal(disable_validation__ignore_storage_class)]] var tint_symbol_1 : vec4; fn tint_symbol_2(tint_symbol : vec4) { tint_symbol_1 = tint_symbol; @@ -737,11 +737,11 @@ fn vert_main() { return; } -[[builtin(sample_index)]] var tint_symbol_3 : u32; +[[builtin(sample_index), internal(disable_validation__ignore_storage_class)]] var tint_symbol_3 : u32; -[[builtin(sample_mask)]] var tint_symbol_4 : array; +[[builtin(sample_mask), internal(disable_validation__ignore_storage_class)]] var tint_symbol_4 : array; -[[builtin(sample_mask)]] var tint_symbol_6 : array; +[[builtin(sample_mask), internal(disable_validation__ignore_storage_class)]] var tint_symbol_6 : array; fn tint_symbol_7(tint_symbol_5 : u32) { tint_symbol_6[0] = tint_symbol_5; diff --git a/src/writer/append_vector_test.cc b/src/writer/append_vector_test.cc index eb5053b32c..8c045b0477 100644 --- a/src/writer/append_vector_test.cc +++ b/src/writer/append_vector_test.cc @@ -87,7 +87,7 @@ TEST_F(AppendVectorTest, Vec3i32_i32) { } TEST_F(AppendVectorTest, Vec2i32Var_i32) { - Global("vec_12", ty.vec2(), ast::StorageClass::kInput); + Global("vec_12", ty.vec2(), ast::StorageClass::kPrivate); auto* vec_12 = Expr("vec_12"); auto* scalar_3 = Expr(3); WrapInFunction(vec_12, scalar_3); @@ -104,7 +104,7 @@ TEST_F(AppendVectorTest, Vec2i32Var_i32) { } TEST_F(AppendVectorTest, Vec2i32_i32Var) { - Global("scalar_3", ty.i32(), ast::StorageClass::kInput); + Global("scalar_3", ty.i32(), ast::StorageClass::kPrivate); auto* scalar_1 = Expr(1); auto* scalar_2 = Expr(2); auto* scalar_3 = Expr("scalar_3"); @@ -124,8 +124,8 @@ TEST_F(AppendVectorTest, Vec2i32_i32Var) { } TEST_F(AppendVectorTest, Vec2i32Var_i32Var) { - Global("vec_12", ty.vec2(), ast::StorageClass::kInput); - Global("scalar_3", ty.i32(), ast::StorageClass::kInput); + Global("vec_12", ty.vec2(), ast::StorageClass::kPrivate); + Global("scalar_3", ty.i32(), ast::StorageClass::kPrivate); auto* vec_12 = Expr("vec_12"); auto* scalar_3 = Expr("scalar_3"); WrapInFunction(vec_12, scalar_3); @@ -142,8 +142,8 @@ TEST_F(AppendVectorTest, Vec2i32Var_i32Var) { } TEST_F(AppendVectorTest, Vec2i32Var_f32Var) { - Global("vec_12", ty.vec2(), ast::StorageClass::kInput); - Global("scalar_3", ty.f32(), ast::StorageClass::kInput); + Global("vec_12", ty.vec2(), ast::StorageClass::kPrivate); + Global("scalar_3", ty.f32(), ast::StorageClass::kPrivate); auto* vec_12 = Expr("vec_12"); auto* scalar_3 = Expr("scalar_3"); WrapInFunction(vec_12, scalar_3); @@ -163,8 +163,8 @@ TEST_F(AppendVectorTest, Vec2i32Var_f32Var) { } TEST_F(AppendVectorTest, Vec2boolVar_boolVar) { - Global("vec_12", ty.vec2(), ast::StorageClass::kInput); - Global("scalar_3", ty.bool_(), ast::StorageClass::kInput); + Global("vec_12", ty.vec2(), ast::StorageClass::kPrivate); + Global("scalar_3", ty.bool_(), ast::StorageClass::kPrivate); auto* vec_12 = Expr("vec_12"); auto* scalar_3 = Expr("scalar_3"); WrapInFunction(vec_12, scalar_3); diff --git a/src/writer/spirv/builder.cc b/src/writer/spirv/builder.cc index 463e8228c0..62caefd8f1 100644 --- a/src/writer/spirv/builder.cc +++ b/src/writer/spirv/builder.cc @@ -20,6 +20,7 @@ #include "spirv/unified1/GLSL.std.450.h" #include "src/ast/call_statement.h" #include "src/ast/fallthrough_statement.h" +#include "src/ast/internal_decoration.h" #include "src/ast/override_decoration.h" #include "src/sem/array.h" #include "src/sem/atomic_type.h" @@ -843,7 +844,7 @@ bool Builder::GenerateGlobalVariable(ast::Variable* var) { Operand::Int(group->value())}); } else if (deco->Is()) { // Spec constants are handled elsewhere - } else { + } else if (!deco->Is()) { error_ = "unknown decoration"; return false; } diff --git a/src/writer/spirv/builder_assign_test.cc b/src/writer/spirv/builder_assign_test.cc index c1894b6f7c..f611143951 100644 --- a/src/writer/spirv/builder_assign_test.cc +++ b/src/writer/spirv/builder_assign_test.cc @@ -23,7 +23,7 @@ namespace { using BuilderTest = TestHelper; TEST_F(BuilderTest, Assign_Var) { - auto* v = Global("var", ty.f32(), ast::StorageClass::kOutput); + auto* v = Global("var", ty.f32(), ast::StorageClass::kPrivate); auto* assign = Assign("var", 1.f); @@ -39,9 +39,9 @@ TEST_F(BuilderTest, Assign_Var) { EXPECT_FALSE(b.has_error()); EXPECT_EQ(DumpInstructions(b.types()), R"(%3 = OpTypeFloat 32 -%2 = OpTypePointer Output %3 +%2 = OpTypePointer Private %3 %4 = OpConstantNull %3 -%1 = OpVariable %2 Output %4 +%1 = OpVariable %2 Private %4 %5 = OpConstant %3 1 )"); @@ -51,7 +51,7 @@ TEST_F(BuilderTest, Assign_Var) { } TEST_F(BuilderTest, Assign_Var_OutsideFunction_IsError) { - auto* v = Global("var", ty.f32(), ast::StorageClass::kOutput); + auto* v = Global("var", ty.f32(), ast::StorageClass::kPrivate); auto* assign = Assign("var", Expr(1.f)); @@ -70,7 +70,7 @@ TEST_F(BuilderTest, Assign_Var_OutsideFunction_IsError) { } TEST_F(BuilderTest, Assign_Var_ZeroConstructor) { - auto* v = Global("var", ty.vec3(), ast::StorageClass::kOutput); + auto* v = Global("var", ty.vec3(), ast::StorageClass::kPrivate); auto* val = vec3(); auto* assign = Assign("var", val); @@ -88,9 +88,9 @@ TEST_F(BuilderTest, Assign_Var_ZeroConstructor) { EXPECT_EQ(DumpInstructions(b.types()), R"(%4 = OpTypeFloat 32 %3 = OpTypeVector %4 3 -%2 = OpTypePointer Output %3 +%2 = OpTypePointer Private %3 %5 = OpConstantNull %3 -%1 = OpVariable %2 Output %5 +%1 = OpVariable %2 Private %5 )"); EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), @@ -101,7 +101,7 @@ TEST_F(BuilderTest, Assign_Var_ZeroConstructor) { TEST_F(BuilderTest, Assign_Var_Complex_ConstructorWithExtract) { auto* init = vec3(vec2(1.f, 2.f), 3.f); - auto* v = Global("var", ty.vec3(), ast::StorageClass::kOutput); + auto* v = Global("var", ty.vec3(), ast::StorageClass::kPrivate); auto* assign = Assign("var", init); @@ -118,9 +118,9 @@ TEST_F(BuilderTest, Assign_Var_Complex_ConstructorWithExtract) { EXPECT_EQ(DumpInstructions(b.types()), R"(%4 = OpTypeFloat 32 %3 = OpTypeVector %4 3 -%2 = OpTypePointer Output %3 +%2 = OpTypePointer Private %3 %5 = OpConstantNull %3 -%1 = OpVariable %2 Output %5 +%1 = OpVariable %2 Private %5 %6 = OpTypeVector %4 2 %7 = OpConstant %4 1 %8 = OpConstant %4 2 @@ -138,7 +138,7 @@ OpStore %1 %13 TEST_F(BuilderTest, Assign_Var_Complex_Constructor) { auto* init = vec3(1.f, 2.f, 3.f); - auto* v = Global("var", ty.vec3(), ast::StorageClass::kOutput); + auto* v = Global("var", ty.vec3(), ast::StorageClass::kPrivate); auto* assign = Assign("var", init); @@ -155,9 +155,9 @@ TEST_F(BuilderTest, Assign_Var_Complex_Constructor) { EXPECT_EQ(DumpInstructions(b.types()), R"(%4 = OpTypeFloat 32 %3 = OpTypeVector %4 3 -%2 = OpTypePointer Output %3 +%2 = OpTypePointer Private %3 %5 = OpConstantNull %3 -%1 = OpVariable %2 Output %5 +%1 = OpVariable %2 Private %5 %6 = OpConstant %4 1 %7 = OpConstant %4 2 %8 = OpConstant %4 3 @@ -213,7 +213,7 @@ OpStore %8 %9 } TEST_F(BuilderTest, Assign_Vector) { - auto* v = Global("var", ty.vec3(), ast::StorageClass::kOutput); + auto* v = Global("var", ty.vec3(), ast::StorageClass::kPrivate); auto* val = vec3(1.f, 1.f, 3.f); auto* assign = Assign("var", val); @@ -231,9 +231,9 @@ TEST_F(BuilderTest, Assign_Vector) { EXPECT_EQ(DumpInstructions(b.types()), R"(%4 = OpTypeFloat 32 %3 = OpTypeVector %4 3 -%2 = OpTypePointer Output %3 +%2 = OpTypePointer Private %3 %5 = OpConstantNull %3 -%1 = OpVariable %2 Output %5 +%1 = OpVariable %2 Private %5 %6 = OpConstant %4 1 %7 = OpConstant %4 3 %8 = OpConstantComposite %3 %6 %6 %7 @@ -247,7 +247,7 @@ TEST_F(BuilderTest, Assign_Vector) { TEST_F(BuilderTest, Assign_Vector_MemberByName) { // var.y = 1 - auto* v = Global("var", ty.vec3(), ast::StorageClass::kOutput); + auto* v = Global("var", ty.vec3(), ast::StorageClass::kPrivate); auto* assign = Assign(MemberAccessor("var", "y"), Expr(1.f)); @@ -264,12 +264,12 @@ TEST_F(BuilderTest, Assign_Vector_MemberByName) { EXPECT_EQ(DumpInstructions(b.types()), R"(%4 = OpTypeFloat 32 %3 = OpTypeVector %4 3 -%2 = OpTypePointer Output %3 +%2 = OpTypePointer Private %3 %5 = OpConstantNull %3 -%1 = OpVariable %2 Output %5 +%1 = OpVariable %2 Private %5 %6 = OpTypeInt 32 0 %7 = OpConstant %6 1 -%8 = OpTypePointer Output %4 +%8 = OpTypePointer Private %4 %10 = OpConstant %4 1 )"); @@ -282,7 +282,7 @@ OpStore %9 %10 TEST_F(BuilderTest, Assign_Vector_MemberByIndex) { // var[1] = 1 - auto* v = Global("var", ty.vec3(), ast::StorageClass::kOutput); + auto* v = Global("var", ty.vec3(), ast::StorageClass::kPrivate); auto* assign = Assign(IndexAccessor("var", 1), Expr(1.f)); @@ -299,12 +299,12 @@ TEST_F(BuilderTest, Assign_Vector_MemberByIndex) { EXPECT_EQ(DumpInstructions(b.types()), R"(%4 = OpTypeFloat 32 %3 = OpTypeVector %4 3 -%2 = OpTypePointer Output %3 +%2 = OpTypePointer Private %3 %5 = OpConstantNull %3 -%1 = OpVariable %2 Output %5 +%1 = OpVariable %2 Private %5 %6 = OpTypeInt 32 1 %7 = OpConstant %6 1 -%8 = OpTypePointer Output %4 +%8 = OpTypePointer Private %4 %10 = OpConstant %4 1 )"); diff --git a/src/writer/spirv/builder_function_decoration_test.cc b/src/writer/spirv/builder_function_decoration_test.cc index c2f8b5ede7..21bb928e57 100644 --- a/src/writer/spirv/builder_function_decoration_test.cc +++ b/src/writer/spirv/builder_function_decoration_test.cc @@ -51,17 +51,22 @@ TEST_P(Decoration_StageTest, Emit) { auto params = GetParam(); ast::Variable* var = nullptr; + ast::Type* ret_type = nullptr; + ast::DecorationList ret_type_decos; ast::StatementList body; if (params.stage == ast::PipelineStage::kVertex) { - var = Global("pos", ty.vec4(), ast::StorageClass::kOutput, nullptr, - ast::DecorationList{Builtin(ast::Builtin::kPosition)}); - body.push_back(Assign("pos", Construct(ty.vec4()))); + ret_type = ty.vec4(); + ret_type_decos.push_back(Builtin(ast::Builtin::kPosition)); + body.push_back(Return(Construct(ty.vec4()))); + } else { + ret_type = ty.void_(); } - auto* func = Func("main", {}, ty.void_(), body, + auto* func = Func("main", {}, ret_type, body, ast::DecorationList{ Stage(params.stage), - }); + }, + ret_type_decos); spirv::Builder& b = Build(); @@ -88,87 +93,6 @@ INSTANTIATE_TEST_SUITE_P( FunctionStageData{ast::PipelineStage::kCompute, SpvExecutionModelGLCompute})); -TEST_F(BuilderTest, Decoration_Stage_WithUnusedInterfaceIds) { - auto* func = Func("main", {}, ty.void_(), ast::StatementList{}, - ast::DecorationList{ - Stage(ast::PipelineStage::kFragment), - }); - - auto* v_in = Global("my_in", ty.f32(), ast::StorageClass::kInput); - auto* v_out = Global("my_out", ty.f32(), ast::StorageClass::kOutput); - auto* v_wg = Global("my_wg", ty.f32(), ast::StorageClass::kWorkgroup); - - spirv::Builder& b = Build(); - - EXPECT_TRUE(b.GenerateGlobalVariable(v_in)) << b.error(); - EXPECT_TRUE(b.GenerateGlobalVariable(v_out)) << b.error(); - EXPECT_TRUE(b.GenerateGlobalVariable(v_wg)) << b.error(); - - ASSERT_TRUE(b.GenerateFunction(func)) << b.error(); - EXPECT_EQ(DumpInstructions(b.debug()), R"(OpName %1 "my_in" -OpName %4 "my_out" -OpName %7 "my_wg" -OpName %11 "main" -)"); - EXPECT_EQ(DumpInstructions(b.types()), R"(%3 = OpTypeFloat 32 -%2 = OpTypePointer Input %3 -%1 = OpVariable %2 Input -%5 = OpTypePointer Output %3 -%6 = OpConstantNull %3 -%4 = OpVariable %5 Output %6 -%8 = OpTypePointer Workgroup %3 -%7 = OpVariable %8 Workgroup -%10 = OpTypeVoid -%9 = OpTypeFunction %10 -)"); - EXPECT_EQ(DumpInstructions(b.entry_points()), - R"(OpEntryPoint Fragment %11 "main" -)"); -} - -TEST_F(BuilderTest, Decoration_Stage_WithUsedInterfaceIds) { - auto* v_in = Global("my_in", ty.f32(), ast::StorageClass::kInput); - auto* v_out = Global("my_out", ty.f32(), ast::StorageClass::kOutput); - auto* v_wg = Global("my_wg", ty.f32(), ast::StorageClass::kWorkgroup); - - auto* func = Func( - "main", {}, ty.void_(), - ast::StatementList{Assign("my_out", "my_in"), Assign("my_wg", "my_wg"), - // Add duplicate usages so we show they - // don't get output multiple times. - Assign("my_out", "my_in")}, - ast::DecorationList{ - Stage(ast::PipelineStage::kFragment), - }); - - spirv::Builder& b = Build(); - - EXPECT_TRUE(b.GenerateGlobalVariable(v_in)) << b.error(); - EXPECT_TRUE(b.GenerateGlobalVariable(v_out)) << b.error(); - EXPECT_TRUE(b.GenerateGlobalVariable(v_wg)) << b.error(); - - ASSERT_TRUE(b.GenerateFunction(func)) << b.error(); - EXPECT_EQ(DumpInstructions(b.debug()), R"(OpName %1 "my_in" -OpName %4 "my_out" -OpName %7 "my_wg" -OpName %11 "main" -)"); - EXPECT_EQ(DumpInstructions(b.types()), R"(%3 = OpTypeFloat 32 -%2 = OpTypePointer Input %3 -%1 = OpVariable %2 Input -%5 = OpTypePointer Output %3 -%6 = OpConstantNull %3 -%4 = OpVariable %5 Output %6 -%8 = OpTypePointer Workgroup %3 -%7 = OpVariable %8 Workgroup -%10 = OpTypeVoid -%9 = OpTypeFunction %10 -)"); - EXPECT_EQ(DumpInstructions(b.entry_points()), - R"(OpEntryPoint Fragment %11 "main" %4 %1 -)"); -} - TEST_F(BuilderTest, Decoration_ExecutionMode_Fragment_OriginUpperLeft) { auto* func = Func("main", {}, ty.void_(), ast::StatementList{}, ast::DecorationList{ @@ -323,22 +247,22 @@ OpFunctionEnd } TEST_F(BuilderTest, Decoration_ExecutionMode_FragDepth) { - Global("fragdepth", ty.f32(), ast::StorageClass::kOutput, nullptr, - ast::DecorationList{ - Builtin(ast::Builtin::kFragDepth), - }); + Func("main", ast::VariableList{}, ty.f32(), + ast::StatementList{ + Return(Expr(1.f)), + }, + ast::DecorationList{Stage(ast::PipelineStage::kFragment)}, + ast::DecorationList{ + Builtin(ast::Builtin::kFragDepth), + }); - auto* func = Func("main", ast::VariableList{}, ty.void_(), - ast::StatementList{ - Assign("fragdepth", Expr(1.f)), - }, - ast::DecorationList{}); + spirv::Builder& b = SanitizeAndBuild(); - spirv::Builder& b = Build(); + ASSERT_TRUE(b.Build()); - ASSERT_TRUE(b.GenerateExecutionModes(func, 3)) << b.error(); EXPECT_EQ(DumpInstructions(b.execution_modes()), - R"(OpExecutionMode %3 DepthReplacing + R"(OpExecutionMode %11 OriginUpperLeft +OpExecutionMode %11 DepthReplacing )"); } diff --git a/src/writer/spirv/builder_global_variable_test.cc b/src/writer/spirv/builder_global_variable_test.cc index c11c12cf49..d7449965a8 100644 --- a/src/writer/spirv/builder_global_variable_test.cc +++ b/src/writer/spirv/builder_global_variable_test.cc @@ -26,7 +26,7 @@ namespace { using BuilderTest = TestHelper; TEST_F(BuilderTest, GlobalVar_WithStorageClass) { - auto* v = Global("var", ty.f32(), ast::StorageClass::kOutput); + auto* v = Global("var", ty.f32(), ast::StorageClass::kPrivate); spirv::Builder& b = Build(); @@ -34,30 +34,16 @@ TEST_F(BuilderTest, GlobalVar_WithStorageClass) { EXPECT_EQ(DumpInstructions(b.debug()), R"(OpName %1 "var" )"); EXPECT_EQ(DumpInstructions(b.types()), R"(%3 = OpTypeFloat 32 -%2 = OpTypePointer Output %3 +%2 = OpTypePointer Private %3 %4 = OpConstantNull %3 -%1 = OpVariable %2 Output %4 -)"); -} - -TEST_F(BuilderTest, GlobalVar_WithStorageClass_Input) { - auto* v = Global("var", ty.f32(), ast::StorageClass::kInput); - - spirv::Builder& b = Build(); - - EXPECT_TRUE(b.GenerateGlobalVariable(v)) << b.error(); - EXPECT_EQ(DumpInstructions(b.debug()), R"(OpName %1 "var" -)"); - EXPECT_EQ(DumpInstructions(b.types()), R"(%3 = OpTypeFloat 32 -%2 = OpTypePointer Input %3 -%1 = OpVariable %2 Input +%1 = OpVariable %2 Private %4 )"); } TEST_F(BuilderTest, GlobalVar_WithConstructor) { auto* init = vec3(1.f, 1.f, 3.f); - auto* v = Global("var", ty.vec3(), ast::StorageClass::kOutput, init); + auto* v = Global("var", ty.vec3(), ast::StorageClass::kPrivate, init); spirv::Builder& b = Build(); @@ -71,8 +57,8 @@ TEST_F(BuilderTest, GlobalVar_WithConstructor) { %3 = OpConstant %2 1 %4 = OpConstant %2 3 %5 = OpConstantComposite %1 %3 %3 %4 -%7 = OpTypePointer Output %1 -%6 = OpVariable %7 Output %5 +%7 = OpTypePointer Private %1 +%6 = OpVariable %7 Private %5 )"); } @@ -141,26 +127,6 @@ TEST_F(BuilderTest, GlobalVar_Complex_ConstructorWithExtract) { )"); } -TEST_F(BuilderTest, GlobalVar_WithLocation) { - auto* v = Global("var", ty.f32(), ast::StorageClass::kOutput, nullptr, - ast::DecorationList{ - Location(5), - }); - - spirv::Builder& b = Build(); - - EXPECT_TRUE(b.GenerateGlobalVariable(v)) << b.error(); - EXPECT_EQ(DumpInstructions(b.debug()), R"(OpName %1 "var" -)"); - EXPECT_EQ(DumpInstructions(b.annots()), R"(OpDecorate %1 Location 5 -)"); - EXPECT_EQ(DumpInstructions(b.types()), R"(%3 = OpTypeFloat 32 -%2 = OpTypePointer Output %3 -%4 = OpConstantNull %3 -%1 = OpVariable %2 Output %4 -)"); -} - TEST_F(BuilderTest, GlobalVar_WithBindingAndGroup) { auto* v = Global("var", ty.sampler(ast::SamplerKind::kSampler), ast::StorageClass::kNone, nullptr, @@ -183,26 +149,6 @@ OpDecorate %1 DescriptorSet 3 )"); } -TEST_F(BuilderTest, GlobalVar_WithBuiltin) { - auto* v = Global("var", ty.f32(), ast::StorageClass::kOutput, nullptr, - ast::DecorationList{ - Builtin(ast::Builtin::kPosition), - }); - - spirv::Builder& b = Build(); - - EXPECT_TRUE(b.GenerateGlobalVariable(v)) << b.error(); - EXPECT_EQ(DumpInstructions(b.debug()), R"(OpName %1 "var" -)"); - EXPECT_EQ(DumpInstructions(b.annots()), R"(OpDecorate %1 BuiltIn Position -)"); - EXPECT_EQ(DumpInstructions(b.types()), R"(%3 = OpTypeFloat 32 -%2 = OpTypePointer Output %3 -%4 = OpConstantNull %3 -%1 = OpVariable %2 Output %4 -)"); -} - TEST_F(BuilderTest, GlobalVar_Override_Bool) { auto* v = GlobalConst("var", ty.bool_(), Expr(true), ast::DecorationList{ @@ -661,96 +607,6 @@ OpDecorate %5 DescriptorSet 0 )"); } -TEST_F(BuilderTest, SampleIndex) { - auto* var = - Global("sample_index", ty.u32(), ast::StorageClass::kInput, nullptr, - ast::DecorationList{ - Builtin(ast::Builtin::kSampleIndex), - }); - - spirv::Builder& b = Build(); - - EXPECT_TRUE(b.GenerateGlobalVariable(var)) << b.error(); - EXPECT_EQ(DumpInstructions(b.capabilities()), - "OpCapability SampleRateShading\n"); - EXPECT_EQ(DumpInstructions(b.annots()), "OpDecorate %1 BuiltIn SampleId\n"); - EXPECT_EQ(DumpInstructions(b.types()), - "%3 = OpTypeInt 32 0\n" - "%2 = OpTypePointer Input %3\n" - "%1 = OpVariable %2 Input\n"); -} - -TEST_F(BuilderTest, SampleMask) { - // Input: - // [[builtin(sample_mask)]] var mask_in : u32; - // [[builtin(sample_mask)]] var mask_out : u32; - // [[stage(fragment)]] - // fn main() { - // mask_out = mask_in; - // } - - // After sanitization: - // [[builtin(sample_mask)]] var mask_in : array; - // [[builtin(sample_mask)]] var mask_out : array; - // [[stage(fragment)]] - // fn main() { - // mask_out[0] = mask_in[0]; - // } - - Global("mask_in", ty.u32(), ast::StorageClass::kInput, nullptr, - ast::DecorationList{ - Builtin(ast::Builtin::kSampleMask), - }); - Global("mask_out", ty.u32(), ast::StorageClass::kOutput, nullptr, - ast::DecorationList{ - Builtin(ast::Builtin::kSampleMask), - }); - Func("main", ast::VariableList{}, ty.void_(), - ast::StatementList{ - Assign("mask_out", "mask_in"), - }, - ast::DecorationList{ - Stage(ast::PipelineStage::kCompute), - }); - - spirv::Builder& b = SanitizeAndBuild(); - - ASSERT_TRUE(b.Build()); - EXPECT_EQ(DumpBuilder(b), R"(OpCapability Shader -OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %11 "main" %6 %1 -OpExecutionMode %11 LocalSize 1 1 1 -OpName %1 "mask_in" -OpName %6 "mask_out" -OpName %11 "main" -OpDecorate %3 ArrayStride 4 -OpDecorate %1 BuiltIn SampleMask -OpDecorate %6 BuiltIn SampleMask -%4 = OpTypeInt 32 0 -%5 = OpConstant %4 1 -%3 = OpTypeArray %4 %5 -%2 = OpTypePointer Input %3 -%1 = OpVariable %2 Input -%7 = OpTypePointer Output %3 -%8 = OpConstantNull %3 -%6 = OpVariable %7 Output %8 -%10 = OpTypeVoid -%9 = OpTypeFunction %10 -%13 = OpTypeInt 32 1 -%14 = OpConstant %13 0 -%15 = OpTypePointer Output %4 -%17 = OpTypePointer Input %4 -%11 = OpFunction %10 None %9 -%12 = OpLabel -%16 = OpAccessChain %15 %6 %14 -%18 = OpAccessChain %17 %1 %14 -%19 = OpLoad %4 %18 -OpStore %16 %19 -OpReturn -OpFunctionEnd -)"); -} - } // namespace } // namespace spirv } // namespace writer diff --git a/src/writer/spirv/builder_ident_expression_test.cc b/src/writer/spirv/builder_ident_expression_test.cc index c57b44affd..2b8299e8e1 100644 --- a/src/writer/spirv/builder_ident_expression_test.cc +++ b/src/writer/spirv/builder_ident_expression_test.cc @@ -46,7 +46,7 @@ TEST_F(BuilderTest, IdentifierExpression_GlobalConst) { } TEST_F(BuilderTest, IdentifierExpression_GlobalVar) { - auto* v = Global("var", ty.f32(), ast::StorageClass::kOutput); + auto* v = Global("var", ty.f32(), ast::StorageClass::kPrivate); auto* expr = Expr("var"); WrapInFunction(expr); @@ -58,9 +58,9 @@ TEST_F(BuilderTest, IdentifierExpression_GlobalVar) { EXPECT_EQ(DumpInstructions(b.debug()), R"(OpName %1 "var" )"); EXPECT_EQ(DumpInstructions(b.types()), R"(%3 = OpTypeFloat 32 -%2 = OpTypePointer Output %3 +%2 = OpTypePointer Private %3 %4 = OpConstantNull %3 -%1 = OpVariable %2 Output %4 +%1 = OpVariable %2 Private %4 )"); EXPECT_EQ(b.GenerateIdentifierExpression(expr), 1u); diff --git a/src/writer/spirv/builder_type_test.cc b/src/writer/spirv/builder_type_test.cc index 1bae74fdfc..45a8d34c7a 100644 --- a/src/writer/spirv/builder_type_test.cc +++ b/src/writer/spirv/builder_type_test.cc @@ -70,7 +70,7 @@ TEST_F(BuilderTest_Type, ReturnsGeneratedRuntimeArray) { TEST_F(BuilderTest_Type, GenerateArray) { auto* ary = ty.array(ty.i32(), 4); - Global("a", ary, ast::StorageClass::kInput); + Global("a", ary, ast::StorageClass::kPrivate); spirv::Builder& b = Build(); @@ -87,7 +87,7 @@ TEST_F(BuilderTest_Type, GenerateArray) { TEST_F(BuilderTest_Type, GenerateArray_WithStride) { auto* ary = ty.array(ty.i32(), 4, 16u); - Global("a", ary, ast::StorageClass::kInput); + Global("a", ary, ast::StorageClass::kPrivate); spirv::Builder& b = Build(); @@ -107,7 +107,7 @@ TEST_F(BuilderTest_Type, GenerateArray_WithStride) { TEST_F(BuilderTest_Type, ReturnsGeneratedArray) { auto* ary = ty.array(ty.i32(), 4); - Global("a", ary, ast::StorageClass::kInput); + Global("a", ary, ast::StorageClass::kPrivate); spirv::Builder& b = Build(); diff --git a/src/writer/wgsl/generator_impl_global_decl_test.cc b/src/writer/wgsl/generator_impl_global_decl_test.cc index fcb5104d2a..c67d9efcf3 100644 --- a/src/writer/wgsl/generator_impl_global_decl_test.cc +++ b/src/writer/wgsl/generator_impl_global_decl_test.cc @@ -55,7 +55,7 @@ TEST_F(WgslGeneratorImplTest, Emit_GlobalsInterleaved) { }, ast::DecorationList{}); - Global("a1", ty.f32(), ast::StorageClass::kOutput); + Global("a1", ty.f32(), ast::StorageClass::kPrivate); auto* s1 = Structure("S1", {Member("a", ty.i32())}); @@ -84,7 +84,7 @@ TEST_F(WgslGeneratorImplTest, Emit_GlobalsInterleaved) { return a0; } - var a1 : f32; + var a1 : f32; struct S1 { a : i32;