1 // Copyright 2021 The Tint Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "src/resolver/resolver.h"
16
17 #include "gmock/gmock.h"
18 #include "src/ast/struct_block_decoration.h"
19 #include "src/resolver/resolver_test_helper.h"
20 #include "src/sem/struct.h"
21
22 namespace tint {
23 namespace resolver {
24 namespace {
25
26 using ResolverHostShareableValidationTest = ResolverTest;
27
TEST_F(ResolverHostShareableValidationTest,BoolMember)28 TEST_F(ResolverHostShareableValidationTest, BoolMember) {
29 auto* s = Structure("S", {Member(Source{{12, 34}}, "x", ty.bool_())},
30 {create<ast::StructBlockDecoration>()});
31
32 Global(Source{{56, 78}}, "g", ty.Of(s), ast::StorageClass::kStorage,
33 ast::Access::kRead,
34 ast::DecorationList{
35 create<ast::BindingDecoration>(0),
36 create<ast::GroupDecoration>(0),
37 });
38
39 ASSERT_FALSE(r()->Resolve());
40
41 EXPECT_EQ(
42 r()->error(),
43 R"(56:78 error: Type 'bool' cannot be used in storage class 'storage' as it is non-host-shareable
44 12:34 note: while analysing structure member S.x
45 56:78 note: while instantiating variable g)");
46 }
47
TEST_F(ResolverHostShareableValidationTest,BoolVectorMember)48 TEST_F(ResolverHostShareableValidationTest, BoolVectorMember) {
49 auto* s = Structure("S", {Member(Source{{12, 34}}, "x", ty.vec3<bool>())},
50 {create<ast::StructBlockDecoration>()});
51
52 Global(Source{{56, 78}}, "g", ty.Of(s), ast::StorageClass::kStorage,
53 ast::Access::kRead,
54 ast::DecorationList{
55 create<ast::BindingDecoration>(0),
56 create<ast::GroupDecoration>(0),
57 });
58
59 ASSERT_FALSE(r()->Resolve());
60
61 EXPECT_EQ(
62 r()->error(),
63 R"(56:78 error: Type 'vec3<bool>' cannot be used in storage class 'storage' as it is non-host-shareable
64 12:34 note: while analysing structure member S.x
65 56:78 note: while instantiating variable g)");
66 }
67
TEST_F(ResolverHostShareableValidationTest,Aliases)68 TEST_F(ResolverHostShareableValidationTest, Aliases) {
69 auto* a1 = Alias("a1", ty.bool_());
70 auto* s = Structure("S", {Member(Source{{12, 34}}, "x", ty.Of(a1))},
71 {create<ast::StructBlockDecoration>()});
72 auto* a2 = Alias("a2", ty.Of(s));
73 Global(Source{{56, 78}}, "g", ty.Of(a2), ast::StorageClass::kStorage,
74 ast::Access::kRead,
75 ast::DecorationList{
76 create<ast::BindingDecoration>(0),
77 create<ast::GroupDecoration>(0),
78 });
79
80 ASSERT_FALSE(r()->Resolve());
81
82 EXPECT_EQ(
83 r()->error(),
84 R"(56:78 error: Type 'bool' cannot be used in storage class 'storage' as it is non-host-shareable
85 12:34 note: while analysing structure member S.x
86 56:78 note: while instantiating variable g)");
87 }
88
TEST_F(ResolverHostShareableValidationTest,NestedStructures)89 TEST_F(ResolverHostShareableValidationTest, NestedStructures) {
90 auto* i1 = Structure("I1", {Member(Source{{1, 2}}, "x", ty.bool_())});
91 auto* i2 = Structure("I2", {Member(Source{{3, 4}}, "y", ty.Of(i1))});
92 auto* i3 = Structure("I3", {Member(Source{{5, 6}}, "z", ty.Of(i2))});
93
94 auto* s = Structure("S", {Member(Source{{7, 8}}, "m", ty.Of(i3))},
95 {create<ast::StructBlockDecoration>()});
96
97 Global(Source{{9, 10}}, "g", ty.Of(s), ast::StorageClass::kStorage,
98 ast::Access::kRead,
99 ast::DecorationList{
100 create<ast::BindingDecoration>(0),
101 create<ast::GroupDecoration>(0),
102 });
103
104 ASSERT_FALSE(r()->Resolve());
105
106 EXPECT_EQ(
107 r()->error(),
108 R"(9:10 error: Type 'bool' cannot be used in storage class 'storage' as it is non-host-shareable
109 1:2 note: while analysing structure member I1.x
110 3:4 note: while analysing structure member I2.y
111 5:6 note: while analysing structure member I3.z
112 7:8 note: while analysing structure member S.m
113 9:10 note: while instantiating variable g)");
114 }
115
TEST_F(ResolverHostShareableValidationTest,NoError)116 TEST_F(ResolverHostShareableValidationTest, NoError) {
117 auto* i1 =
118 Structure("I1", {
119 Member(Source{{1, 1}}, "x1", ty.f32()),
120 Member(Source{{2, 1}}, "y1", ty.vec3<f32>()),
121 Member(Source{{3, 1}}, "z1", ty.array<i32, 4>()),
122 });
123 auto* a1 = Alias("a1", ty.Of(i1));
124 auto* i2 = Structure("I2", {
125 Member(Source{{4, 1}}, "x2", ty.mat2x2<f32>()),
126 Member(Source{{5, 1}}, "y2", ty.Of(i1)),
127 });
128 auto* a2 = Alias("a2", ty.Of(i2));
129 auto* i3 = Structure("I3", {
130 Member(Source{{4, 1}}, "x3", ty.Of(a1)),
131 Member(Source{{5, 1}}, "y3", ty.Of(i2)),
132 Member(Source{{6, 1}}, "z3", ty.Of(a2)),
133 });
134
135 auto* s = Structure("S", {Member(Source{{7, 8}}, "m", ty.Of(i3))},
136 {create<ast::StructBlockDecoration>()});
137
138 Global(Source{{9, 10}}, "g", ty.Of(s), ast::StorageClass::kStorage,
139 ast::Access::kRead,
140 ast::DecorationList{
141 create<ast::BindingDecoration>(0),
142 create<ast::GroupDecoration>(0),
143 });
144 WrapInFunction();
145
146 ASSERT_TRUE(r()->Resolve()) << r()->error();
147 }
148
149 } // namespace
150 } // namespace resolver
151 } // namespace tint
152