• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "gmock/gmock.h"
16 #include "src/ast/call_statement.h"
17 #include "src/reader/spirv/function.h"
18 #include "src/reader/spirv/parser_impl_test_helper.h"
19 #include "src/reader/spirv/spirv_tools_helpers_test.h"
20 #include "src/sem/call.h"
21 
22 namespace tint {
23 namespace reader {
24 namespace spirv {
25 namespace {
26 
27 using ::testing::Eq;
28 using ::testing::HasSubstr;
29 using ::testing::Not;
30 using ::testing::StartsWith;
31 
ParseAndBuild(std::string spirv)32 Program ParseAndBuild(std::string spirv) {
33   const char* preamble = R"(OpCapability Shader
34             OpMemoryModel Logical GLSL450
35             OpEntryPoint GLCompute %main "main"
36             OpExecutionMode %main LocalSize 1 1 1
37             OpName %main "main"
38 )";
39 
40   auto p = std::make_unique<ParserImpl>(test::Assemble(preamble + spirv));
41   if (!p->BuildAndParseInternalModule()) {
42     ProgramBuilder builder;
43     builder.Diagnostics().add_error(diag::System::Reader, p->error());
44     return Program(std::move(builder));
45   }
46   return p->program();
47 }
48 
TEST_F(SpvParserTest,WorkgroupBarrier)49 TEST_F(SpvParserTest, WorkgroupBarrier) {
50   auto program = ParseAndBuild(R"(
51                OpName %helper "helper"
52        %void = OpTypeVoid
53           %1 = OpTypeFunction %void
54        %uint = OpTypeInt 32 0
55      %uint_2 = OpConstant %uint 2
56    %uint_264 = OpConstant %uint 264
57      %helper = OpFunction %void None %1
58           %4 = OpLabel
59                OpControlBarrier %uint_2 %uint_2 %uint_264
60                OpReturn
61                OpFunctionEnd
62      %main = OpFunction %void None %1
63           %5 = OpLabel
64                OpReturn
65                OpFunctionEnd
66   )");
67   ASSERT_TRUE(program.IsValid()) << program.Diagnostics().str();
68   auto* helper =
69       program.AST().Functions().Find(program.Symbols().Get("helper"));
70   ASSERT_NE(helper, nullptr);
71   ASSERT_GT(helper->body->statements.size(), 0u);
72   auto* call = helper->body->statements[0]->As<ast::CallStatement>();
73   ASSERT_NE(call, nullptr);
74   EXPECT_EQ(call->expr->args.size(), 0u);
75   auto* sem_call = program.Sem().Get(call->expr);
76   ASSERT_NE(sem_call, nullptr);
77   auto* intrinsic = sem_call->Target()->As<sem::Intrinsic>();
78   ASSERT_NE(intrinsic, nullptr);
79   EXPECT_EQ(intrinsic->Type(), sem::IntrinsicType::kWorkgroupBarrier);
80 }
81 
TEST_F(SpvParserTest,StorageBarrier)82 TEST_F(SpvParserTest, StorageBarrier) {
83   auto program = ParseAndBuild(R"(
84                OpName %helper "helper"
85        %void = OpTypeVoid
86           %1 = OpTypeFunction %void
87        %uint = OpTypeInt 32 0
88      %uint_2 = OpConstant %uint 2
89      %uint_1 = OpConstant %uint 1
90     %uint_72 = OpConstant %uint 72
91      %helper = OpFunction %void None %1
92           %4 = OpLabel
93                OpControlBarrier %uint_2 %uint_1 %uint_72
94                OpReturn
95                OpFunctionEnd
96        %main = OpFunction %void None %1
97           %5 = OpLabel
98                OpReturn
99                OpFunctionEnd
100   )");
101   ASSERT_TRUE(program.IsValid()) << program.Diagnostics().str();
102   auto* helper =
103       program.AST().Functions().Find(program.Symbols().Get("helper"));
104   ASSERT_NE(helper, nullptr);
105   ASSERT_GT(helper->body->statements.size(), 0u);
106   auto* call = helper->body->statements[0]->As<ast::CallStatement>();
107   ASSERT_NE(call, nullptr);
108   EXPECT_EQ(call->expr->args.size(), 0u);
109   auto* sem_call = program.Sem().Get(call->expr);
110   ASSERT_NE(sem_call, nullptr);
111   auto* intrinsic = sem_call->Target()->As<sem::Intrinsic>();
112   ASSERT_NE(intrinsic, nullptr);
113   EXPECT_EQ(intrinsic->Type(), sem::IntrinsicType::kStorageBarrier);
114 }
115 
TEST_F(SpvParserTest,ErrBarrierInvalidExecution)116 TEST_F(SpvParserTest, ErrBarrierInvalidExecution) {
117   auto program = ParseAndBuild(R"(
118        %void = OpTypeVoid
119           %1 = OpTypeFunction %void
120        %uint = OpTypeInt 32 0
121      %uint_0 = OpConstant %uint 0
122      %uint_2 = OpConstant %uint 2
123    %uint_264 = OpConstant %uint 264
124        %main = OpFunction %void None %1
125           %4 = OpLabel
126                OpControlBarrier %uint_0 %uint_2 %uint_264
127                OpReturn
128                OpFunctionEnd
129   )");
130   EXPECT_FALSE(program.IsValid());
131   EXPECT_THAT(program.Diagnostics().str(),
132               HasSubstr("unsupported control barrier execution scope"));
133 }
134 
TEST_F(SpvParserTest,ErrBarrierSemanticsMissingAcquireRelease)135 TEST_F(SpvParserTest, ErrBarrierSemanticsMissingAcquireRelease) {
136   auto program = ParseAndBuild(R"(
137        %void = OpTypeVoid
138           %1 = OpTypeFunction %void
139        %uint = OpTypeInt 32 0
140      %uint_2 = OpConstant %uint 2
141      %uint_0 = OpConstant %uint 0
142        %main = OpFunction %void None %1
143           %4 = OpLabel
144                OpControlBarrier %uint_2 %uint_2 %uint_0
145                OpReturn
146                OpFunctionEnd
147   )");
148   EXPECT_FALSE(program.IsValid());
149   EXPECT_THAT(
150       program.Diagnostics().str(),
151       HasSubstr("control barrier semantics requires acquire and release"));
152 }
153 
TEST_F(SpvParserTest,ErrBarrierInvalidSemantics)154 TEST_F(SpvParserTest, ErrBarrierInvalidSemantics) {
155   auto program = ParseAndBuild(R"(
156        %void = OpTypeVoid
157           %1 = OpTypeFunction %void
158        %uint = OpTypeInt 32 0
159      %uint_2 = OpConstant %uint 2
160      %uint_9 = OpConstant %uint 9
161        %main = OpFunction %void None %1
162           %4 = OpLabel
163                OpControlBarrier %uint_2 %uint_2 %uint_9
164                OpReturn
165                OpFunctionEnd
166   )");
167   EXPECT_FALSE(program.IsValid());
168   EXPECT_THAT(program.Diagnostics().str(),
169               HasSubstr("unsupported control barrier semantics"));
170 }
171 
TEST_F(SpvParserTest,ErrWorkgroupBarrierInvalidMemory)172 TEST_F(SpvParserTest, ErrWorkgroupBarrierInvalidMemory) {
173   auto program = ParseAndBuild(R"(
174        %void = OpTypeVoid
175           %1 = OpTypeFunction %void
176        %uint = OpTypeInt 32 0
177      %uint_2 = OpConstant %uint 2
178      %uint_8 = OpConstant %uint 8
179    %uint_264 = OpConstant %uint 264
180        %main = OpFunction %void None %1
181           %4 = OpLabel
182                OpControlBarrier %uint_2 %uint_8 %uint_264
183                OpReturn
184                OpFunctionEnd
185   )");
186   EXPECT_FALSE(program.IsValid());
187   EXPECT_THAT(program.Diagnostics().str(),
188               HasSubstr("workgroupBarrier requires workgroup memory scope"));
189 }
190 
TEST_F(SpvParserTest,ErrStorageBarrierInvalidMemory)191 TEST_F(SpvParserTest, ErrStorageBarrierInvalidMemory) {
192   auto program = ParseAndBuild(R"(
193        %void = OpTypeVoid
194           %1 = OpTypeFunction %void
195        %uint = OpTypeInt 32 0
196      %uint_2 = OpConstant %uint 2
197      %uint_8 = OpConstant %uint 8
198     %uint_72 = OpConstant %uint 72
199        %main = OpFunction %void None %1
200           %4 = OpLabel
201                OpControlBarrier %uint_2 %uint_8 %uint_72
202                OpReturn
203                OpFunctionEnd
204   )");
205   EXPECT_FALSE(program.IsValid());
206   EXPECT_THAT(program.Diagnostics().str(),
207               HasSubstr("storageBarrier requires device memory scope"));
208 }
209 
210 }  // namespace
211 }  // namespace spirv
212 }  // namespace reader
213 }  // namespace tint
214