diff --git a/src/ast/disable_validation_decoration.cc b/src/ast/disable_validation_decoration.cc index 28adae45fe..a8786e04ec 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::kIgnoreStorageClass: - return "disable_validation__ignore_storage_class"; + case DisabledValidation::kFunctionVarStorageClass: + return "disable_validation__function_var_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 e2b7bb956e..344dc7ecdf 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 variable, the validator will not complain about the - /// declared storage class. - kIgnoreStorageClass, + /// When applied to a function-scoped variable, the validator will not + /// complain if the storage class is not `function`. + kFunctionVarStorageClass, /// 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 991e178a7e..acd6355c87 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::kPrivate); + Global("var", ty.f32(), ast::StorageClass::kInput); 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 813149cdba..d43d8f7f76 100644 --- a/src/resolver/decoration_validation_test.cc +++ b/src/resolver/decoration_validation_test.cc @@ -84,16 +84,6 @@ 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; @@ -337,16 +327,8 @@ 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::kPrivate, nullptr, + Global("a", ty.f32(), ast::StorageClass::kInput, nullptr, createDecorations(Source{{12, 34}}, *this, params.kind)); } @@ -524,7 +506,7 @@ TEST_P(ArrayStrideTest, All) { auto* arr = ty.array(Source{{12, 34}}, el_ty, 4, params.stride); - Global("myarray", arr, ast::StorageClass::kPrivate); + Global("myarray", arr, ast::StorageClass::kInput); if (params.should_pass) { EXPECT_TRUE(r()->Resolve()) << r()->error(); @@ -608,7 +590,7 @@ TEST_F(ArrayStrideTest, DuplicateDecoration) { create(Source{{56, 78}}, 4), }); - Global("myarray", arr, ast::StorageClass::kPrivate); + Global("myarray", arr, ast::StorageClass::kInput); EXPECT_FALSE(r()->Resolve()); EXPECT_EQ(r()->error(), diff --git a/src/resolver/intrinsic_test.cc b/src/resolver/intrinsic_test.cc index 473598ecf0..34ed7f0273 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::kPrivate); + Global("ident", ty.f32(), ast::StorageClass::kInput); 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::kPrivate); + Global("ident", ty.vec4(), ast::StorageClass::kInput); 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::kPrivate); + Global("my_var", ty.vec3(), ast::StorageClass::kInput); 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::kPrivate); + Global("my_var", ty.vec3(), ast::StorageClass::kInput); 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::kPrivate); + Global("my_var", ty.f32(), ast::StorageClass::kInput); 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::kPrivate); + Global("my_var", ty.f32(), ast::StorageClass::kInput); 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::kPrivate); + Global("my_var", ty.f32(), ast::StorageClass::kInput); 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::kPrivate); + Global("my_var", ty.vec2(), ast::StorageClass::kInput); 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::kPrivate); + Global("my_var", ty.vec3(), ast::StorageClass::kInput); 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::kPrivate); + Global("my_var", ty.vec4(), ast::StorageClass::kInput); 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::kPrivate); + Global("my_var", ty.vec4(), ast::StorageClass::kInput); 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::kPrivate); + Global("my_var", ty.vec3(), ast::StorageClass::kInput); - Global("bool_var", ty.vec3(), ast::StorageClass::kPrivate); + Global("bool_var", ty.vec3(), ast::StorageClass::kInput); 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::kPrivate); + Global("arr", ty.array(), ast::StorageClass::kInput); 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 5d01d6442b..8f56d3dc94 100644 --- a/src/resolver/resolver.cc +++ b/src/resolver/resolver.cc @@ -909,15 +909,6 @@ 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. @@ -2791,8 +2782,9 @@ bool Resolver::VariableDeclStatement(const ast::VariableDeclStatement* stmt) { if (!var->is_const()) { if (info->storage_class != ast::StorageClass::kFunction && - !IsValidationDisabled(var->decorations(), - ast::DisabledValidation::kIgnoreStorageClass)) { + !IsValidationDisabled( + var->decorations(), + ast::DisabledValidation::kFunctionVarStorageClass)) { 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 90fe982f47..c5e7176597 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::kPrivate, init); + Global("my_var", ty.i32(), ast::StorageClass::kInput, 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::kPrivate, Expr(2.f)); + auto* mod_f32 = Var("foo", ty.f32(), ast::StorageClass::kInput, 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::kPrivate); + Global("my_var", ty.mat2x3(), ast::StorageClass::kInput); 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::kPrivate); + Global("my_var", ty.mat2x3(), ast::StorageClass::kInput); 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::kPrivate); + Global("my_var", ty.mat4x4(), ast::StorageClass::kOutput); 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::kPrivate); + Global("my_var", ty.mat2x3(), ast::StorageClass::kInput); 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::kPrivate); + Global("my_var", ty.mat2x3(), ast::StorageClass::kInput); 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::kPrivate); + Global("my_var", ty.vec3(), ast::StorageClass::kInput); 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::kPrivate); + Global("my_var", ty.vec3(), ast::StorageClass::kInput); 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::kPrivate); + Global("my_var", ty.vec3(), ast::StorageClass::kInput); 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::kPrivate); + auto* my_var = Global("my_var", ty.f32(), ast::StorageClass::kInput); auto* ident = Expr("my_var"); WrapInFunction(ident); @@ -972,6 +972,8 @@ 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{ @@ -983,6 +985,7 @@ 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"), @@ -996,16 +999,20 @@ TEST_F(ResolverTest, Function_RegisterInputOutputVariables) { EXPECT_TRUE(func_sem->ReturnType()->Is()); const auto& vars = func_sem->ReferencedModuleVariables(); - 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); + 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); } 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{ @@ -1016,13 +1023,14 @@ 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("wg_var", "wg_var"), Assign("sb_var", "sb_var"), - Assign("priv_var", "priv_var"), Return(0.0f)}, + {Assign("out_var", "in_var"), 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_(), { - WrapInStatement(Call("my_func")), + Assign("out_var", Call("my_func")), }, ast::DecorationList{}); @@ -1033,10 +1041,12 @@ TEST_F(ResolverTest, Function_RegisterInputOutputVariables_SubFunction) { EXPECT_EQ(func2_sem->Parameters().size(), 0u); const auto& vars = func2_sem->ReferencedModuleVariables(); - 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); + 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); } TEST_F(ResolverTest, Function_NotRegisterFunctionVariable) { @@ -1275,7 +1285,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::kPrivate); + Global("my_struct", ty.Of(st), ast::StorageClass::kInput); auto* mem = MemberAccessor("my_struct", "second_member"); WrapInFunction(mem); @@ -1299,7 +1309,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::kPrivate); + Global("my_struct", ty.Of(alias), ast::StorageClass::kInput); auto* mem = MemberAccessor("my_struct", "second_member"); WrapInFunction(mem); @@ -1318,7 +1328,7 @@ TEST_F(ResolverTest, Expr_MemberAccessor_Struct_Alias) { } TEST_F(ResolverTest, Expr_MemberAccessor_VectorSwizzle) { - Global("my_vec", ty.vec4(), ast::StorageClass::kPrivate); + Global("my_vec", ty.vec4(), ast::StorageClass::kInput); auto* mem = MemberAccessor("my_vec", "xzyw"); WrapInFunction(mem); @@ -1335,7 +1345,7 @@ TEST_F(ResolverTest, Expr_MemberAccessor_VectorSwizzle) { } TEST_F(ResolverTest, Expr_MemberAccessor_VectorSwizzle_SingleElement) { - Global("my_vec", ty.vec3(), ast::StorageClass::kPrivate); + Global("my_vec", ty.vec3(), ast::StorageClass::kInput); auto* mem = MemberAccessor("my_vec", "b"); WrapInFunction(mem); @@ -1379,7 +1389,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::kPrivate); + Global("c", ty.Of(stA), ast::StorageClass::kInput); auto* mem = MemberAccessor( MemberAccessor(IndexAccessor(MemberAccessor("c", "mem"), 0), "foo"), @@ -1398,7 +1408,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::kPrivate); + Global("my_struct", ty.Of(st), ast::StorageClass::kInput); auto* expr = Add(MemberAccessor("my_struct", "first_member"), MemberAccessor("my_struct", "second_member")); @@ -1704,8 +1714,8 @@ TEST_P(Expr_Binary_Test_Valid, All) { << FriendlyName(rhs_type); SCOPED_TRACE(ss.str()); - Global("lhs", lhs_type, ast::StorageClass::kPrivate); - Global("rhs", rhs_type, ast::StorageClass::kPrivate); + Global("lhs", lhs_type, ast::StorageClass::kInput); + Global("rhs", rhs_type, ast::StorageClass::kInput); auto* expr = create(params.op, Expr("lhs"), Expr("rhs")); @@ -1746,8 +1756,8 @@ TEST_P(Expr_Binary_Test_WithAlias_Valid, All) { << " " << FriendlyName(rhs_type); SCOPED_TRACE(ss.str()); - Global("lhs", lhs_type, ast::StorageClass::kPrivate); - Global("rhs", rhs_type, ast::StorageClass::kPrivate); + Global("lhs", lhs_type, ast::StorageClass::kInput); + Global("rhs", rhs_type, ast::StorageClass::kInput); auto* expr = create(params.op, Expr("lhs"), Expr("rhs")); @@ -1798,8 +1808,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::kPrivate); - Global("rhs", rhs_type, ast::StorageClass::kPrivate); + Global("lhs", lhs_type, ast::StorageClass::kInput); + Global("rhs", rhs_type, ast::StorageClass::kInput); auto* expr = create(Source{{12, 34}}, op, Expr("lhs"), Expr("rhs")); @@ -1844,8 +1854,8 @@ TEST_P(Expr_Binary_Test_Invalid_VectorMatrixMultiply, All) { is_valid_expr = vec_size == mat_cols; } - Global("lhs", lhs_type, ast::StorageClass::kPrivate); - Global("rhs", rhs_type, ast::StorageClass::kPrivate); + Global("lhs", lhs_type, ast::StorageClass::kInput); + Global("rhs", rhs_type, ast::StorageClass::kInput); auto* expr = Mul(Source{{12, 34}}, Expr("lhs"), Expr("rhs")); WrapInFunction(expr); @@ -1885,8 +1895,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::kPrivate); - Global("rhs", rhs_type, ast::StorageClass::kPrivate); + Global("lhs", lhs_type, ast::StorageClass::kInput); + Global("rhs", rhs_type, ast::StorageClass::kInput); auto* expr = Mul(Source{{12, 34}}, Expr("lhs"), Expr("rhs")); WrapInFunction(expr); @@ -1917,7 +1927,7 @@ using UnaryOpExpressionTest = ResolverTestWithParam; TEST_P(UnaryOpExpressionTest, Expr_UnaryOp) { auto op = GetParam(); - Global("ident", ty.vec4(), ast::StorageClass::kPrivate); + Global("ident", ty.vec4(), ast::StorageClass::kInput); 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 5c6ca3dc81..84e7463e7a 100644 --- a/src/resolver/storage_class_validation_test.cc +++ b/src/resolver/storage_class_validation_test.cc @@ -50,8 +50,9 @@ TEST_F(ResolverStorageClassValidationTest, StorageBufferBool) { } TEST_F(ResolverStorageClassValidationTest, StorageBufferPointer) { - // var g : vec4; - Global(Source{{56, 78}}, "g", ty.vec4(), ast::StorageClass::kStorage, + // var g : ptr; + Global(Source{{56, 78}}, "g", ty.pointer(ast::StorageClass::kInput), + ast::StorageClass::kStorage, ast::DecorationList{ create(0), create(0), @@ -186,8 +187,9 @@ TEST_F(ResolverStorageClassValidationTest, UniformBufferBool) { } TEST_F(ResolverStorageClassValidationTest, UniformBufferPointer) { - // var g : vec4; - Global(Source{{56, 78}}, "g", ty.vec4(), ast::StorageClass::kUniform, + // var g : ptr; + Global(Source{{56, 78}}, "g", ty.pointer(ast::StorageClass::kInput), + 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 b1aea9c78d..d1b1c350eb 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::kPrivate); + // var global_var: f32; + Global(Source{{12, 34}}, "global_var", ty.f32(), ast::StorageClass::kInput); 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::kPrivate, ast::Access::kUndefined, ty.f32(), true, + ast::StorageClass::kInput, 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 d288c0464b..600a588bed 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::kPrivate); + Global("my_vec", ty.vec3(), ast::StorageClass::kInput); 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::kPrivate); + Global("my_vec", ty.vec4(), ast::StorageClass::kInput); 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::kPrivate); + Global("my_vec", ty.vec3(), ast::StorageClass::kInput); 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::kPrivate); + Global("my_vec", ty.vec2(), ast::StorageClass::kInput); 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::kPrivate); + Global("uint_var", ty.Of(alias), ast::StorageClass::kInput); 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::kPrivate); - Global("my_vec2", ty.Of(vec2_alias), ast::StorageClass::kPrivate); + Global("my_f32", ty.Of(f32_alias), ast::StorageClass::kInput); + Global("my_vec2", ty.Of(vec2_alias), ast::StorageClass::kInput); auto* tc = vec3("my_vec2", "my_f32"); WrapInFunction(tc); diff --git a/src/transform/msl.cc b/src/transform/msl.cc index 50e4cc9f1c..6d45462fa1 100644 --- a/src/transform/msl.cc +++ b/src/transform/msl.cc @@ -207,7 +207,8 @@ 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::kIgnoreStorageClass); + ctx.dst->ID(), + ast::DisabledValidation::kFunctionVarStorageClass); 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 cc83854a62..6b0968c501 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__ignore_storage_class)]] var tint_symbol_1 : f32; - [[internal(disable_validation__ignore_storage_class)]] var tint_symbol_2 : f32; + [[internal(disable_validation__function_var_storage_class)]] var tint_symbol_1 : f32; + [[internal(disable_validation__function_var_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__ignore_storage_class)]] var tint_symbol_6 : f32; + [[internal(disable_validation__function_var_storage_class)]] var tint_symbol_5 : f32; + [[internal(disable_validation__function_var_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__ignore_storage_class)]] var tint_symbol : f32 = 1.0; - [[internal(disable_validation__ignore_storage_class)]] var tint_symbol_1 : f32 = f32(); + [[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(); 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__ignore_storage_class)]] var tint_symbol_1 : f32; - [[internal(disable_validation__ignore_storage_class)]] var tint_symbol_2 : f32; + [[internal(disable_validation__function_var_storage_class)]] var tint_symbol_1 : f32; + [[internal(disable_validation__function_var_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 874c1142bf..81fdbb9208 100644 --- a/src/transform/spirv.cc +++ b/src/transform/spirv.cc @@ -18,7 +18,6 @@ #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" @@ -273,10 +272,7 @@ 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), - ctx.dst->ASTNodes().Create( - ctx.dst->ID(), ast::DisabledValidation::kIgnoreStorageClass)}); + ast::DecorationList{ctx.dst->Builtin(ast::Builtin::kPointSize)}); // Assign 1.0 to the global at the start of all vertex shader entry points. ctx.ReplaceAll([&ctx, pointsize](ast::Function* func) -> ast::Function* { @@ -313,9 +309,6 @@ 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), @@ -370,9 +363,6 @@ 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 cf15d8c17c..150167aeb8 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), internal(disable_validation__ignore_storage_class)]] var tint_symbol : vec4; +[[builtin(position)]] var tint_symbol : vec4; -[[location(1), internal(disable_validation__ignore_storage_class)]] var tint_symbol_1 : f32; +[[location(1)]] var tint_symbol_1 : f32; [[stage(fragment)]] fn frag_main() { var col : f32 = (tint_symbol.x * tint_symbol_1); } -[[builtin(local_invocation_id), internal(disable_validation__ignore_storage_class)]] var tint_symbol_2 : vec3; +[[builtin(local_invocation_id)]] var tint_symbol_2 : vec3; -[[builtin(local_invocation_index), internal(disable_validation__ignore_storage_class)]] var tint_symbol_3 : u32; +[[builtin(local_invocation_index)]] 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), internal(disable_validation__ignore_storage_class)]] var tint_symbol : myf32; +[[location(1)]] var tint_symbol : myf32; [[stage(fragment)]] fn frag_main() { @@ -95,7 +95,7 @@ fn vert_main() -> [[builtin(position)]] vec4 { )"; auto* expect = R"( -[[builtin(position), internal(disable_validation__ignore_storage_class)]] var tint_symbol_1 : vec4; +[[builtin(position)]] 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), internal(disable_validation__ignore_storage_class)]] var tint_symbol : u32; +[[location(0)]] var tint_symbol : u32; -[[location(0), internal(disable_validation__ignore_storage_class)]] var tint_symbol_2 : f32; +[[location(0)]] 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), internal(disable_validation__ignore_storage_class)]] var tint_symbol : u32; +[[location(0)]] var tint_symbol : u32; -[[location(0), internal(disable_validation__ignore_storage_class)]] var tint_symbol_2 : myf32; +[[location(0)]] 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), internal(disable_validation__ignore_storage_class)]] var tint_symbol : vec4; +[[builtin(position)]] var tint_symbol : vec4; -[[location(1), internal(disable_validation__ignore_storage_class)]] var tint_symbol_1 : f32; +[[location(1)]] var tint_symbol_1 : f32; [[stage(fragment)]] fn frag_main() { @@ -240,7 +240,7 @@ struct FragmentInput { value : f32; }; -[[location(1), internal(disable_validation__ignore_storage_class)]] var tint_symbol : f32; +[[location(1)]] var tint_symbol : f32; [[stage(fragment)]] fn frag_main() { @@ -275,9 +275,9 @@ struct VertexOutput { value : f32; }; -[[builtin(position), internal(disable_validation__ignore_storage_class)]] var tint_symbol_1 : vec4; +[[builtin(position)]] var tint_symbol_1 : vec4; -[[location(1), internal(disable_validation__ignore_storage_class)]] var tint_symbol_2 : f32; +[[location(1)]] 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), internal(disable_validation__ignore_storage_class)]] var tint_symbol : f32; +[[location(1)]] var tint_symbol : f32; -[[location(1), internal(disable_validation__ignore_storage_class)]] var tint_symbol_3 : f32; +[[location(1)]] 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), internal(disable_validation__ignore_storage_class)]] var tint_symbol_1 : vec4; +[[builtin(position)]] var tint_symbol_1 : vec4; -[[location(1), internal(disable_validation__ignore_storage_class)]] var tint_symbol_2 : f32; +[[location(1)]] 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), internal(disable_validation__ignore_storage_class)]] var tint_symbol_4 : vec4; +[[builtin(position)]] var tint_symbol_4 : vec4; -[[location(1), internal(disable_validation__ignore_storage_class)]] var tint_symbol_5 : f32; +[[location(1)]] var tint_symbol_5 : f32; [[stage(fragment)]] fn frag_main() { @@ -426,11 +426,11 @@ struct FragmentOutput { value : f32; }; -[[location(1), internal(disable_validation__ignore_storage_class)]] var tint_symbol : f32; +[[location(1)]] var tint_symbol : f32; -[[builtin(position), internal(disable_validation__ignore_storage_class)]] var tint_symbol_1 : vec4; +[[builtin(position)]] var tint_symbol_1 : vec4; -[[location(1), internal(disable_validation__ignore_storage_class)]] var tint_symbol_4 : f32; +[[location(1)]] 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), internal(disable_validation__ignore_storage_class)]] var tint_symbol_1 : vec4; +[[builtin(position)]] 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), internal(disable_validation__ignore_storage_class)]] var tint_symbol : u32; +[[builtin(sample_index)]] var tint_symbol : u32; -[[builtin(sample_mask), internal(disable_validation__ignore_storage_class)]] var tint_symbol_1 : array; +[[builtin(sample_mask)]] var tint_symbol_1 : array; -[[builtin(sample_mask), internal(disable_validation__ignore_storage_class)]] var tint_symbol_3 : array; +[[builtin(sample_mask)]] 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), internal(disable_validation__ignore_storage_class)]] var tint_symbol : array; +[[builtin(sample_mask)]] var tint_symbol : array; -[[builtin(sample_mask), internal(disable_validation__ignore_storage_class)]] var tint_symbol_2 : array; +[[builtin(sample_mask)]] 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), internal(disable_validation__ignore_storage_class)]] var tint_pointsize : f32; +[[builtin(pointsize)]] var tint_pointsize : f32; fn non_entry_point() { } -[[builtin(position), internal(disable_validation__ignore_storage_class)]] var tint_symbol_1 : vec4; +[[builtin(position)]] 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), internal(disable_validation__ignore_storage_class)]] var tint_pointsize : f32; +[[builtin(pointsize)]] var tint_pointsize : f32; -[[builtin(position), internal(disable_validation__ignore_storage_class)]] var tint_symbol_1 : vec4; +[[builtin(position)]] 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), internal(disable_validation__ignore_storage_class)]] var tint_symbol_4 : vec4; +[[builtin(position)]] 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), internal(disable_validation__ignore_storage_class)]] var tint_symbol_7 : vec4; +[[builtin(position)]] 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), internal(disable_validation__ignore_storage_class)]] var tint_pointsize : f32; +[[builtin(pointsize)]] var tint_pointsize : f32; -[[builtin(position), internal(disable_validation__ignore_storage_class)]] var tint_symbol_1 : vec4; +[[builtin(position)]] 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), internal(disable_validation__ignore_storage_class)]] var tint_symbol_3 : u32; +[[builtin(sample_index)]] var tint_symbol_3 : u32; -[[builtin(sample_mask), internal(disable_validation__ignore_storage_class)]] var tint_symbol_4 : array; +[[builtin(sample_mask)]] var tint_symbol_4 : array; -[[builtin(sample_mask), internal(disable_validation__ignore_storage_class)]] var tint_symbol_6 : array; +[[builtin(sample_mask)]] 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 8c045b0477..eb5053b32c 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::kPrivate); + Global("vec_12", ty.vec2(), ast::StorageClass::kInput); 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::kPrivate); + Global("scalar_3", ty.i32(), ast::StorageClass::kInput); 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::kPrivate); - Global("scalar_3", ty.i32(), ast::StorageClass::kPrivate); + Global("vec_12", ty.vec2(), ast::StorageClass::kInput); + Global("scalar_3", ty.i32(), ast::StorageClass::kInput); 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::kPrivate); - Global("scalar_3", ty.f32(), ast::StorageClass::kPrivate); + Global("vec_12", ty.vec2(), ast::StorageClass::kInput); + Global("scalar_3", ty.f32(), ast::StorageClass::kInput); 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::kPrivate); - Global("scalar_3", ty.bool_(), ast::StorageClass::kPrivate); + Global("vec_12", ty.vec2(), ast::StorageClass::kInput); + Global("scalar_3", ty.bool_(), ast::StorageClass::kInput); 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 62caefd8f1..463e8228c0 100644 --- a/src/writer/spirv/builder.cc +++ b/src/writer/spirv/builder.cc @@ -20,7 +20,6 @@ #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" @@ -844,7 +843,7 @@ bool Builder::GenerateGlobalVariable(ast::Variable* var) { Operand::Int(group->value())}); } else if (deco->Is()) { // Spec constants are handled elsewhere - } else if (!deco->Is()) { + } else { error_ = "unknown decoration"; return false; } diff --git a/src/writer/spirv/builder_assign_test.cc b/src/writer/spirv/builder_assign_test.cc index f611143951..c1894b6f7c 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::kPrivate); + auto* v = Global("var", ty.f32(), ast::StorageClass::kOutput); 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 Private %3 +%2 = OpTypePointer Output %3 %4 = OpConstantNull %3 -%1 = OpVariable %2 Private %4 +%1 = OpVariable %2 Output %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::kPrivate); + auto* v = Global("var", ty.f32(), ast::StorageClass::kOutput); 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::kPrivate); + auto* v = Global("var", ty.vec3(), ast::StorageClass::kOutput); 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 Private %3 +%2 = OpTypePointer Output %3 %5 = OpConstantNull %3 -%1 = OpVariable %2 Private %5 +%1 = OpVariable %2 Output %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::kPrivate); + auto* v = Global("var", ty.vec3(), ast::StorageClass::kOutput); 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 Private %3 +%2 = OpTypePointer Output %3 %5 = OpConstantNull %3 -%1 = OpVariable %2 Private %5 +%1 = OpVariable %2 Output %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::kPrivate); + auto* v = Global("var", ty.vec3(), ast::StorageClass::kOutput); 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 Private %3 +%2 = OpTypePointer Output %3 %5 = OpConstantNull %3 -%1 = OpVariable %2 Private %5 +%1 = OpVariable %2 Output %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::kPrivate); + auto* v = Global("var", ty.vec3(), ast::StorageClass::kOutput); 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 Private %3 +%2 = OpTypePointer Output %3 %5 = OpConstantNull %3 -%1 = OpVariable %2 Private %5 +%1 = OpVariable %2 Output %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::kPrivate); + auto* v = Global("var", ty.vec3(), ast::StorageClass::kOutput); 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 Private %3 +%2 = OpTypePointer Output %3 %5 = OpConstantNull %3 -%1 = OpVariable %2 Private %5 +%1 = OpVariable %2 Output %5 %6 = OpTypeInt 32 0 %7 = OpConstant %6 1 -%8 = OpTypePointer Private %4 +%8 = OpTypePointer Output %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::kPrivate); + auto* v = Global("var", ty.vec3(), ast::StorageClass::kOutput); 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 Private %3 +%2 = OpTypePointer Output %3 %5 = OpConstantNull %3 -%1 = OpVariable %2 Private %5 +%1 = OpVariable %2 Output %5 %6 = OpTypeInt 32 1 %7 = OpConstant %6 1 -%8 = OpTypePointer Private %4 +%8 = OpTypePointer Output %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 21bb928e57..c2f8b5ede7 100644 --- a/src/writer/spirv/builder_function_decoration_test.cc +++ b/src/writer/spirv/builder_function_decoration_test.cc @@ -51,22 +51,17 @@ 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) { - 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_(); + var = Global("pos", ty.vec4(), ast::StorageClass::kOutput, nullptr, + ast::DecorationList{Builtin(ast::Builtin::kPosition)}); + body.push_back(Assign("pos", Construct(ty.vec4()))); } - auto* func = Func("main", {}, ret_type, body, + auto* func = Func("main", {}, ty.void_(), body, ast::DecorationList{ Stage(params.stage), - }, - ret_type_decos); + }); spirv::Builder& b = Build(); @@ -93,6 +88,87 @@ 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{ @@ -247,22 +323,22 @@ OpFunctionEnd } TEST_F(BuilderTest, Decoration_ExecutionMode_FragDepth) { - Func("main", ast::VariableList{}, ty.f32(), - ast::StatementList{ - Return(Expr(1.f)), - }, - ast::DecorationList{Stage(ast::PipelineStage::kFragment)}, - ast::DecorationList{ - Builtin(ast::Builtin::kFragDepth), - }); + Global("fragdepth", ty.f32(), ast::StorageClass::kOutput, nullptr, + ast::DecorationList{ + Builtin(ast::Builtin::kFragDepth), + }); - spirv::Builder& b = SanitizeAndBuild(); + auto* func = Func("main", ast::VariableList{}, ty.void_(), + ast::StatementList{ + Assign("fragdepth", Expr(1.f)), + }, + ast::DecorationList{}); - ASSERT_TRUE(b.Build()); + spirv::Builder& b = Build(); + ASSERT_TRUE(b.GenerateExecutionModes(func, 3)) << b.error(); EXPECT_EQ(DumpInstructions(b.execution_modes()), - R"(OpExecutionMode %11 OriginUpperLeft -OpExecutionMode %11 DepthReplacing + R"(OpExecutionMode %3 DepthReplacing )"); } diff --git a/src/writer/spirv/builder_global_variable_test.cc b/src/writer/spirv/builder_global_variable_test.cc index d7449965a8..c11c12cf49 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::kPrivate); + auto* v = Global("var", ty.f32(), ast::StorageClass::kOutput); spirv::Builder& b = Build(); @@ -34,16 +34,30 @@ 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 Private %3 +%2 = OpTypePointer Output %3 %4 = OpConstantNull %3 -%1 = OpVariable %2 Private %4 +%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 )"); } TEST_F(BuilderTest, GlobalVar_WithConstructor) { auto* init = vec3(1.f, 1.f, 3.f); - auto* v = Global("var", ty.vec3(), ast::StorageClass::kPrivate, init); + auto* v = Global("var", ty.vec3(), ast::StorageClass::kOutput, init); spirv::Builder& b = Build(); @@ -57,8 +71,8 @@ TEST_F(BuilderTest, GlobalVar_WithConstructor) { %3 = OpConstant %2 1 %4 = OpConstant %2 3 %5 = OpConstantComposite %1 %3 %3 %4 -%7 = OpTypePointer Private %1 -%6 = OpVariable %7 Private %5 +%7 = OpTypePointer Output %1 +%6 = OpVariable %7 Output %5 )"); } @@ -127,6 +141,26 @@ 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, @@ -149,6 +183,26 @@ 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{ @@ -607,6 +661,96 @@ 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 2b8299e8e1..c57b44affd 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::kPrivate); + auto* v = Global("var", ty.f32(), ast::StorageClass::kOutput); 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 Private %3 +%2 = OpTypePointer Output %3 %4 = OpConstantNull %3 -%1 = OpVariable %2 Private %4 +%1 = OpVariable %2 Output %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 45a8d34c7a..1bae74fdfc 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::kPrivate); + Global("a", ary, ast::StorageClass::kInput); 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::kPrivate); + Global("a", ary, ast::StorageClass::kInput); 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::kPrivate); + Global("a", ary, ast::StorageClass::kInput); 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 c67d9efcf3..fcb5104d2a 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::kPrivate); + Global("a1", ty.f32(), ast::StorageClass::kOutput); 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;