• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2018 Google LLC.
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 <sstream>
16 #include <string>
17 
18 #include "gmock/gmock.h"
19 #include "test/unit_spirv.h"
20 #include "test/val/val_fixtures.h"
21 
22 namespace spvtools {
23 namespace val {
24 namespace {
25 
26 using ::testing::HasSubstr;
27 using ::testing::Not;
28 
29 using ValidateBarriers = spvtest::ValidateBase<bool>;
30 
GenerateShaderCodeImpl(const std::string & body,const std::string & capabilities_and_extensions,const std::string & definitions,const std::string & execution_model,const std::string & memory_model)31 std::string GenerateShaderCodeImpl(
32     const std::string& body, const std::string& capabilities_and_extensions,
33     const std::string& definitions, const std::string& execution_model,
34     const std::string& memory_model) {
35   std::ostringstream ss;
36   ss << R"(
37 OpCapability Shader
38 )";
39 
40   ss << capabilities_and_extensions;
41   ss << memory_model << std::endl;
42   ss << "OpEntryPoint " << execution_model << " %main \"main\"\n";
43   if (execution_model == "Fragment") {
44     ss << "OpExecutionMode %main OriginUpperLeft\n";
45   } else if (execution_model == "Geometry") {
46     ss << "OpExecutionMode %main InputPoints\n";
47     ss << "OpExecutionMode %main OutputPoints\n";
48   } else if (execution_model == "GLCompute") {
49     ss << "OpExecutionMode %main LocalSize 1 1 1\n";
50   }
51 
52   ss << R"(
53 %void = OpTypeVoid
54 %func = OpTypeFunction %void
55 %bool = OpTypeBool
56 %f32 = OpTypeFloat 32
57 %u32 = OpTypeInt 32 0
58 
59 %f32_0 = OpConstant %f32 0
60 %f32_1 = OpConstant %f32 1
61 %u32_0 = OpConstant %u32 0
62 %u32_1 = OpConstant %u32 1
63 %u32_4 = OpConstant %u32 4
64 )";
65   ss << definitions;
66   ss << R"(
67 %cross_device = OpConstant %u32 0
68 %device = OpConstant %u32 1
69 %workgroup = OpConstant %u32 2
70 %subgroup = OpConstant %u32 3
71 %invocation = OpConstant %u32 4
72 %queuefamily = OpConstant %u32 5
73 
74 %none = OpConstant %u32 0
75 %acquire = OpConstant %u32 2
76 %release = OpConstant %u32 4
77 %acquire_release = OpConstant %u32 8
78 %acquire_and_release = OpConstant %u32 6
79 %sequentially_consistent = OpConstant %u32 16
80 %acquire_release_uniform_workgroup = OpConstant %u32 328
81 %acquire_uniform_workgroup = OpConstant %u32 322
82 %release_uniform_workgroup = OpConstant %u32 324
83 %acquire_and_release_uniform = OpConstant %u32 70
84 %acquire_release_subgroup = OpConstant %u32 136
85 %acquire_release_workgroup = OpConstant %u32 264
86 %uniform = OpConstant %u32 64
87 %uniform_workgroup = OpConstant %u32 320
88 %workgroup_memory = OpConstant %u32 256
89 %image_memory = OpConstant %u32 2048
90 %uniform_image_memory = OpConstant %u32 2112
91 
92 %main = OpFunction %void None %func
93 %main_entry = OpLabel
94 )";
95 
96   ss << body;
97 
98   ss << R"(
99 OpReturn
100 OpFunctionEnd)";
101 
102   return ss.str();
103 }
104 
GenerateShaderCode(const std::string & body,const std::string & capabilities_and_extensions="",const std::string & execution_model="GLCompute")105 std::string GenerateShaderCode(
106     const std::string& body,
107     const std::string& capabilities_and_extensions = "",
108     const std::string& execution_model = "GLCompute") {
109   const std::string int64_capability = R"(
110 OpCapability Int64
111 )";
112   const std::string int64_declarations = R"(
113 %u64 = OpTypeInt 64 0
114 %u64_0 = OpConstant %u64 0
115 %u64_1 = OpConstant %u64 1
116 )";
117   const std::string memory_model = "OpMemoryModel Logical GLSL450";
118   return GenerateShaderCodeImpl(
119       body, int64_capability + capabilities_and_extensions, int64_declarations,
120       execution_model, memory_model);
121 }
122 
GenerateWebGPUComputeShaderCode(const std::string & body,const std::string & capabilities_and_extensions="",const std::string & execution_model="GLCompute")123 std::string GenerateWebGPUComputeShaderCode(
124     const std::string& body,
125     const std::string& capabilities_and_extensions = "",
126     const std::string& execution_model = "GLCompute") {
127   const std::string vulkan_memory_capability = R"(
128 OpCapability VulkanMemoryModelKHR
129 )";
130   const std::string vulkan_memory_extension = R"(
131 OpExtension "SPV_KHR_vulkan_memory_model"
132 )";
133   const std::string memory_model = "OpMemoryModel Logical VulkanKHR";
134   return GenerateShaderCodeImpl(body,
135                                 vulkan_memory_capability +
136                                     capabilities_and_extensions +
137                                     vulkan_memory_extension,
138                                 "", execution_model, memory_model);
139 }
140 
GenerateWebGPUVertexShaderCode(const std::string & body,const std::string & capabilities_and_extensions="",const std::string & execution_model="Vertex")141 std::string GenerateWebGPUVertexShaderCode(
142     const std::string& body,
143     const std::string& capabilities_and_extensions = "",
144     const std::string& execution_model = "Vertex") {
145   const std::string vulkan_memory_capability = R"(
146 OpCapability VulkanMemoryModelKHR
147 )";
148   const std::string vulkan_memory_extension = R"(
149 OpExtension "SPV_KHR_vulkan_memory_model"
150 )";
151   const std::string memory_model = "OpMemoryModel Logical VulkanKHR";
152   return GenerateShaderCodeImpl(body,
153                                 vulkan_memory_capability +
154                                     capabilities_and_extensions +
155                                     vulkan_memory_extension,
156                                 "", execution_model, memory_model);
157 }
158 
GenerateKernelCode(const std::string & body,const std::string & capabilities_and_extensions="")159 std::string GenerateKernelCode(
160     const std::string& body,
161     const std::string& capabilities_and_extensions = "") {
162   std::ostringstream ss;
163   ss << R"(
164 OpCapability Addresses
165 OpCapability Kernel
166 OpCapability Linkage
167 OpCapability Int64
168 OpCapability NamedBarrier
169 )";
170 
171   ss << capabilities_and_extensions;
172   ss << R"(
173 OpMemoryModel Physical32 OpenCL
174 %void = OpTypeVoid
175 %func = OpTypeFunction %void
176 %bool = OpTypeBool
177 %f32 = OpTypeFloat 32
178 %u32 = OpTypeInt 32 0
179 %u64 = OpTypeInt 64 0
180 
181 %f32_0 = OpConstant %f32 0
182 %f32_1 = OpConstant %f32 1
183 %f32_4 = OpConstant %f32 4
184 %u32_0 = OpConstant %u32 0
185 %u32_1 = OpConstant %u32 1
186 %u32_4 = OpConstant %u32 4
187 %u64_0 = OpConstant %u64 0
188 %u64_1 = OpConstant %u64 1
189 %u64_4 = OpConstant %u64 4
190 
191 %cross_device = OpConstant %u32 0
192 %device = OpConstant %u32 1
193 %workgroup = OpConstant %u32 2
194 %subgroup = OpConstant %u32 3
195 %invocation = OpConstant %u32 4
196 
197 %none = OpConstant %u32 0
198 %acquire = OpConstant %u32 2
199 %release = OpConstant %u32 4
200 %acquire_release = OpConstant %u32 8
201 %acquire_and_release = OpConstant %u32 6
202 %sequentially_consistent = OpConstant %u32 16
203 %acquire_release_workgroup = OpConstant %u32 264
204 
205 %named_barrier = OpTypeNamedBarrier
206 
207 %main = OpFunction %void None %func
208 %main_entry = OpLabel
209 )";
210 
211   ss << body;
212 
213   ss << R"(
214 OpReturn
215 OpFunctionEnd)";
216 
217   return ss.str();
218 }
219 
TEST_F(ValidateBarriers,OpControlBarrierGLComputeSuccess)220 TEST_F(ValidateBarriers, OpControlBarrierGLComputeSuccess) {
221   const std::string body = R"(
222 OpControlBarrier %device %device %none
223 OpControlBarrier %workgroup %workgroup %acquire
224 OpControlBarrier %workgroup %device %release
225 OpControlBarrier %cross_device %cross_device %acquire_release
226 OpControlBarrier %cross_device %cross_device %sequentially_consistent
227 OpControlBarrier %cross_device %cross_device %acquire_release_uniform_workgroup
228 )";
229 
230   CompileSuccessfully(GenerateShaderCode(body));
231   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
232 }
233 
TEST_F(ValidateBarriers,OpControlBarrierKernelSuccess)234 TEST_F(ValidateBarriers, OpControlBarrierKernelSuccess) {
235   const std::string body = R"(
236 OpControlBarrier %device %device %none
237 OpControlBarrier %workgroup %workgroup %acquire
238 OpControlBarrier %workgroup %device %release
239 OpControlBarrier %cross_device %cross_device %acquire_release
240 OpControlBarrier %cross_device %cross_device %sequentially_consistent
241 OpControlBarrier %cross_device %cross_device %acquire_release_workgroup
242 )";
243 
244   CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1);
245   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
246 }
247 
TEST_F(ValidateBarriers,OpControlBarrierTesselationControlSuccess)248 TEST_F(ValidateBarriers, OpControlBarrierTesselationControlSuccess) {
249   const std::string body = R"(
250 OpControlBarrier %device %device %none
251 OpControlBarrier %workgroup %workgroup %acquire
252 OpControlBarrier %workgroup %device %release
253 OpControlBarrier %cross_device %cross_device %acquire_release
254 OpControlBarrier %cross_device %cross_device %sequentially_consistent
255 OpControlBarrier %cross_device %cross_device %acquire_release_uniform_workgroup
256 )";
257 
258   CompileSuccessfully(GenerateShaderCode(body, "OpCapability Tessellation\n",
259                                          "TessellationControl"));
260   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
261 }
262 
TEST_F(ValidateBarriers,OpControlBarrierVulkanSuccess)263 TEST_F(ValidateBarriers, OpControlBarrierVulkanSuccess) {
264   const std::string body = R"(
265 OpControlBarrier %workgroup %device %none
266 OpControlBarrier %workgroup %workgroup %acquire_release_uniform_workgroup
267 )";
268 
269   CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
270   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
271 }
272 
TEST_F(ValidateBarriers,OpControlBarrierWebGPUAcquireReleaseSuccess)273 TEST_F(ValidateBarriers, OpControlBarrierWebGPUAcquireReleaseSuccess) {
274   const std::string body = R"(
275 OpControlBarrier %workgroup %workgroup %acquire_release_workgroup
276 )";
277 
278   CompileSuccessfully(GenerateWebGPUComputeShaderCode(body), SPV_ENV_WEBGPU_0);
279   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0));
280 }
281 
TEST_F(ValidateBarriers,OpControlBarrierWebGPURelaxedFailure)282 TEST_F(ValidateBarriers, OpControlBarrierWebGPURelaxedFailure) {
283   const std::string body = R"(
284 OpControlBarrier %workgroup %workgroup %workgroup
285 )";
286 
287   CompileSuccessfully(GenerateWebGPUComputeShaderCode(body), SPV_ENV_WEBGPU_0);
288   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
289   EXPECT_THAT(getDiagnosticString(),
290               HasSubstr("For WebGPU, AcquireRelease must be set for Memory "
291                         "Semantics of OpControlBarrier"));
292 }
293 
TEST_F(ValidateBarriers,OpControlBarrierWebGPUMissingWorkgroupFailure)294 TEST_F(ValidateBarriers, OpControlBarrierWebGPUMissingWorkgroupFailure) {
295   const std::string body = R"(
296 OpControlBarrier %workgroup %workgroup %acquire_release
297 )";
298 
299   CompileSuccessfully(GenerateWebGPUComputeShaderCode(body), SPV_ENV_WEBGPU_0);
300   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
301   EXPECT_THAT(getDiagnosticString(),
302               HasSubstr("For WebGPU, WorkgroupMemory must be set for Memory "
303                         "Semantics"));
304 }
305 
TEST_F(ValidateBarriers,OpControlBarrierWebGPUUniformFailure)306 TEST_F(ValidateBarriers, OpControlBarrierWebGPUUniformFailure) {
307   const std::string body = R"(
308 OpControlBarrier %workgroup %workgroup %acquire_release_uniform_workgroup
309 )";
310 
311   CompileSuccessfully(GenerateWebGPUComputeShaderCode(body), SPV_ENV_WEBGPU_0);
312   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
313   EXPECT_THAT(
314       getDiagnosticString(),
315       HasSubstr("For WebGPU only WorkgroupMemory and AcquireRelease may be set "
316                 "for Memory Semantics of OpControlBarrier."));
317 }
318 
TEST_F(ValidateBarriers,OpControlBarrierWebGPUReleaseFailure)319 TEST_F(ValidateBarriers, OpControlBarrierWebGPUReleaseFailure) {
320   const std::string body = R"(
321 OpControlBarrier %workgroup %workgroup %release_uniform_workgroup
322 )";
323 
324   CompileSuccessfully(GenerateWebGPUComputeShaderCode(body), SPV_ENV_WEBGPU_0);
325   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
326   EXPECT_THAT(getDiagnosticString(),
327               HasSubstr("For WebGPU, AcquireRelease must be set for Memory "
328                         "Semantics of OpControlBarrier"));
329 }
330 
TEST_F(ValidateBarriers,OpControlBarrierExecutionModelFragmentSpirv12)331 TEST_F(ValidateBarriers, OpControlBarrierExecutionModelFragmentSpirv12) {
332   const std::string body = R"(
333 OpControlBarrier %device %device %none
334 )";
335 
336   CompileSuccessfully(GenerateShaderCode(body, "", "Fragment"),
337                       SPV_ENV_UNIVERSAL_1_2);
338   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_2));
339   EXPECT_THAT(
340       getDiagnosticString(),
341       HasSubstr("OpControlBarrier requires one of the following Execution "
342                 "Models: TessellationControl, GLCompute or Kernel"));
343 }
344 
TEST_F(ValidateBarriers,OpControlBarrierExecutionModelFragmentSpirv13)345 TEST_F(ValidateBarriers, OpControlBarrierExecutionModelFragmentSpirv13) {
346   const std::string body = R"(
347 OpControlBarrier %device %device %none
348 )";
349 
350   CompileSuccessfully(GenerateShaderCode(body, "", "Fragment"),
351                       SPV_ENV_UNIVERSAL_1_3);
352   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
353 }
354 
TEST_F(ValidateBarriers,OpControlBarrierFloatExecutionScope)355 TEST_F(ValidateBarriers, OpControlBarrierFloatExecutionScope) {
356   const std::string body = R"(
357 OpControlBarrier %f32_1 %device %none
358 )";
359 
360   CompileSuccessfully(GenerateShaderCode(body));
361   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
362   EXPECT_THAT(getDiagnosticString(),
363               HasSubstr("ControlBarrier: expected scope to be a 32-bit int"));
364 }
365 
TEST_F(ValidateBarriers,OpControlBarrierU64ExecutionScope)366 TEST_F(ValidateBarriers, OpControlBarrierU64ExecutionScope) {
367   const std::string body = R"(
368 OpControlBarrier %u64_1 %device %none
369 )";
370 
371   CompileSuccessfully(GenerateShaderCode(body));
372   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
373   EXPECT_THAT(getDiagnosticString(),
374               HasSubstr("ControlBarrier: expected scope to be a 32-bit int"));
375 }
376 
TEST_F(ValidateBarriers,OpControlBarrierFloatMemoryScope)377 TEST_F(ValidateBarriers, OpControlBarrierFloatMemoryScope) {
378   const std::string body = R"(
379 OpControlBarrier %device %f32_1 %none
380 )";
381 
382   CompileSuccessfully(GenerateShaderCode(body));
383   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
384   EXPECT_THAT(getDiagnosticString(),
385               HasSubstr("ControlBarrier: expected scope to be a 32-bit int"));
386 }
387 
TEST_F(ValidateBarriers,OpControlBarrierU64MemoryScope)388 TEST_F(ValidateBarriers, OpControlBarrierU64MemoryScope) {
389   const std::string body = R"(
390 OpControlBarrier %device %u64_1 %none
391 )";
392 
393   CompileSuccessfully(GenerateShaderCode(body));
394   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
395   EXPECT_THAT(getDiagnosticString(),
396               HasSubstr("ControlBarrier: expected scope to be a 32-bit int"));
397 }
398 
TEST_F(ValidateBarriers,OpControlBarrierFloatMemorySemantics)399 TEST_F(ValidateBarriers, OpControlBarrierFloatMemorySemantics) {
400   const std::string body = R"(
401 OpControlBarrier %device %device %f32_0
402 )";
403 
404   CompileSuccessfully(GenerateShaderCode(body));
405   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
406   EXPECT_THAT(
407       getDiagnosticString(),
408       HasSubstr(
409           "ControlBarrier: expected Memory Semantics to be a 32-bit int"));
410 }
411 
TEST_F(ValidateBarriers,OpControlBarrierU64MemorySemantics)412 TEST_F(ValidateBarriers, OpControlBarrierU64MemorySemantics) {
413   const std::string body = R"(
414 OpControlBarrier %device %device %u64_0
415 )";
416 
417   CompileSuccessfully(GenerateShaderCode(body));
418   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
419   EXPECT_THAT(
420       getDiagnosticString(),
421       HasSubstr(
422           "ControlBarrier: expected Memory Semantics to be a 32-bit int"));
423 }
424 
TEST_F(ValidateBarriers,OpControlBarrierVulkanExecutionScopeDevice)425 TEST_F(ValidateBarriers, OpControlBarrierVulkanExecutionScopeDevice) {
426   const std::string body = R"(
427 OpControlBarrier %device %workgroup %none
428 )";
429 
430   CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
431   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
432   EXPECT_THAT(getDiagnosticString(),
433               HasSubstr("ControlBarrier: in Vulkan environment Execution Scope "
434                         "is limited to Workgroup and Subgroup"));
435 }
436 
TEST_F(ValidateBarriers,OpControlBarrierWebGPUExecutionScopeDeviceBad)437 TEST_F(ValidateBarriers, OpControlBarrierWebGPUExecutionScopeDeviceBad) {
438   const std::string body = R"(
439 OpControlBarrier %device %workgroup %none
440 )";
441 
442   CompileSuccessfully(GenerateWebGPUComputeShaderCode(body), SPV_ENV_WEBGPU_0);
443   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
444   EXPECT_THAT(getDiagnosticString(),
445               HasSubstr("ControlBarrier: in WebGPU environment Execution Scope "
446                         "is limited to Workgroup"));
447 }
448 
TEST_F(ValidateBarriers,OpControlBarrierWebGPUExecutionScopeSubgroupBad)449 TEST_F(ValidateBarriers, OpControlBarrierWebGPUExecutionScopeSubgroupBad) {
450   const std::string body = R"(
451 OpControlBarrier %subgroup %workgroup %none
452 )";
453 
454   CompileSuccessfully(GenerateWebGPUComputeShaderCode(body), SPV_ENV_WEBGPU_0);
455   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
456   EXPECT_THAT(getDiagnosticString(),
457               HasSubstr("ControlBarrier: in WebGPU environment Execution Scope "
458                         "is limited to Workgroup"));
459 }
460 
TEST_F(ValidateBarriers,OpControlBarrierWebGPUExecutionScopeWorkgroupNonComputeBad)461 TEST_F(ValidateBarriers,
462        OpControlBarrierWebGPUExecutionScopeWorkgroupNonComputeBad) {
463   const std::string body = R"(
464 OpControlBarrier %workgroup %workgroup %acquire_release_workgroup
465 )";
466 
467   CompileSuccessfully(GenerateWebGPUVertexShaderCode(body), SPV_ENV_WEBGPU_0);
468   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_WEBGPU_0));
469   EXPECT_THAT(
470       getDiagnosticString(),
471       HasSubstr(
472           "Workgroup Execution Scope is limited to GLCompute execution model"));
473 }
474 
TEST_F(ValidateBarriers,OpControlBarrierVulkanMemoryScopeSubgroup)475 TEST_F(ValidateBarriers, OpControlBarrierVulkanMemoryScopeSubgroup) {
476   const std::string body = R"(
477 OpControlBarrier %subgroup %subgroup %none
478 )";
479 
480   CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
481   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
482   EXPECT_THAT(
483       getDiagnosticString(),
484       HasSubstr("ControlBarrier: in Vulkan 1.0 environment Memory Scope is "
485                 "limited to Device, Workgroup and Invocation"));
486 }
487 
TEST_F(ValidateBarriers,OpControlBarrierVulkan1p1MemoryScopeSubgroup)488 TEST_F(ValidateBarriers, OpControlBarrierVulkan1p1MemoryScopeSubgroup) {
489   const std::string body = R"(
490 OpControlBarrier %subgroup %subgroup %none
491 )";
492 
493   CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_1);
494   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
495 }
496 
TEST_F(ValidateBarriers,OpControlBarrierVulkan1p1MemoryScopeCrossDevice)497 TEST_F(ValidateBarriers, OpControlBarrierVulkan1p1MemoryScopeCrossDevice) {
498   const std::string body = R"(
499 OpControlBarrier %subgroup %cross_device %none
500 )";
501 
502   CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_1);
503   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_1));
504   EXPECT_THAT(getDiagnosticString(),
505               HasSubstr("ControlBarrier: in Vulkan environment, Memory Scope "
506                         "cannot be CrossDevice"));
507 }
508 
TEST_F(ValidateBarriers,OpControlBarrierWebGPUMemoryScopeNonWorkgroup)509 TEST_F(ValidateBarriers, OpControlBarrierWebGPUMemoryScopeNonWorkgroup) {
510   const std::string body = R"(
511 OpControlBarrier %workgroup %subgroup %acquire_release_workgroup
512 )";
513 
514   CompileSuccessfully(GenerateWebGPUComputeShaderCode(body), SPV_ENV_WEBGPU_0);
515   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
516   EXPECT_THAT(getDiagnosticString(),
517               HasSubstr("ControlBarrier: in WebGPU environment Memory Scope is "
518                         "limited to Workgroup for OpControlBarrier"));
519 }
520 
TEST_F(ValidateBarriers,OpControlBarrierAcquireAndRelease)521 TEST_F(ValidateBarriers, OpControlBarrierAcquireAndRelease) {
522   const std::string body = R"(
523 OpControlBarrier %device %device %acquire_and_release_uniform
524 )";
525 
526   CompileSuccessfully(GenerateShaderCode(body));
527   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
528   EXPECT_THAT(getDiagnosticString(),
529               HasSubstr("ControlBarrier: Memory Semantics can have at most one "
530                         "of the following bits set: Acquire, Release, "
531                         "AcquireRelease or SequentiallyConsistent"));
532 }
533 
534 // TODO(atgoo@github.com): the corresponding check fails Vulkan CTS,
535 // reenable once fixed.
TEST_F(ValidateBarriers,DISABLED_OpControlBarrierVulkanSubgroupStorageClass)536 TEST_F(ValidateBarriers, DISABLED_OpControlBarrierVulkanSubgroupStorageClass) {
537   const std::string body = R"(
538 OpControlBarrier %workgroup %device %acquire_release_subgroup
539 )";
540 
541   CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
542   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
543   EXPECT_THAT(
544       getDiagnosticString(),
545       HasSubstr(
546           "ControlBarrier: expected Memory Semantics to include a "
547           "Vulkan-supported storage class if Memory Semantics is not None"));
548 }
549 
TEST_F(ValidateBarriers,OpControlBarrierSubgroupExecutionFragment1p1)550 TEST_F(ValidateBarriers, OpControlBarrierSubgroupExecutionFragment1p1) {
551   const std::string body = R"(
552 OpControlBarrier %subgroup %subgroup %acquire_release_subgroup
553 )";
554 
555   CompileSuccessfully(GenerateShaderCode(body, "", "Fragment"),
556                       SPV_ENV_VULKAN_1_1);
557   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
558 }
559 
TEST_F(ValidateBarriers,OpControlBarrierWorkgroupExecutionFragment1p1)560 TEST_F(ValidateBarriers, OpControlBarrierWorkgroupExecutionFragment1p1) {
561   const std::string body = R"(
562 OpControlBarrier %workgroup %workgroup %acquire_release
563 )";
564 
565   CompileSuccessfully(GenerateShaderCode(body, "", "Fragment"),
566                       SPV_ENV_VULKAN_1_1);
567   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
568   EXPECT_THAT(getDiagnosticString(),
569               HasSubstr("OpControlBarrier execution scope must be Subgroup for "
570                         "Fragment, Vertex, Geometry and TessellationEvaluation "
571                         "execution models"));
572 }
573 
TEST_F(ValidateBarriers,OpControlBarrierSubgroupExecutionFragment1p0)574 TEST_F(ValidateBarriers, OpControlBarrierSubgroupExecutionFragment1p0) {
575   const std::string body = R"(
576 OpControlBarrier %subgroup %workgroup %acquire_release
577 )";
578 
579   CompileSuccessfully(GenerateShaderCode(body, "", "Fragment"),
580                       SPV_ENV_VULKAN_1_0);
581   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
582   EXPECT_THAT(
583       getDiagnosticString(),
584       HasSubstr("OpControlBarrier requires one of the following Execution "
585                 "Models: TessellationControl, GLCompute or Kernel"));
586 }
587 
TEST_F(ValidateBarriers,OpControlBarrierSubgroupExecutionVertex1p1)588 TEST_F(ValidateBarriers, OpControlBarrierSubgroupExecutionVertex1p1) {
589   const std::string body = R"(
590 OpControlBarrier %subgroup %subgroup %acquire_release_subgroup
591 )";
592 
593   CompileSuccessfully(GenerateShaderCode(body, "", "Vertex"),
594                       SPV_ENV_VULKAN_1_1);
595   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
596 }
597 
TEST_F(ValidateBarriers,OpControlBarrierWorkgroupExecutionVertex1p1)598 TEST_F(ValidateBarriers, OpControlBarrierWorkgroupExecutionVertex1p1) {
599   const std::string body = R"(
600 OpControlBarrier %workgroup %workgroup %acquire_release
601 )";
602 
603   CompileSuccessfully(GenerateShaderCode(body, "", "Vertex"),
604                       SPV_ENV_VULKAN_1_1);
605   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
606   EXPECT_THAT(getDiagnosticString(),
607               HasSubstr("OpControlBarrier execution scope must be Subgroup for "
608                         "Fragment, Vertex, Geometry and TessellationEvaluation "
609                         "execution models"));
610 }
611 
TEST_F(ValidateBarriers,OpControlBarrierSubgroupExecutionVertex1p0)612 TEST_F(ValidateBarriers, OpControlBarrierSubgroupExecutionVertex1p0) {
613   const std::string body = R"(
614 OpControlBarrier %subgroup %workgroup %acquire_release
615 )";
616 
617   CompileSuccessfully(GenerateShaderCode(body, "", "Vertex"),
618                       SPV_ENV_VULKAN_1_0);
619   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
620   EXPECT_THAT(
621       getDiagnosticString(),
622       HasSubstr("OpControlBarrier requires one of the following Execution "
623                 "Models: TessellationControl, GLCompute or Kernel"));
624 }
625 
TEST_F(ValidateBarriers,OpControlBarrierSubgroupExecutionGeometry1p1)626 TEST_F(ValidateBarriers, OpControlBarrierSubgroupExecutionGeometry1p1) {
627   const std::string body = R"(
628 OpControlBarrier %subgroup %subgroup %acquire_release_subgroup
629 )";
630 
631   CompileSuccessfully(
632       GenerateShaderCode(body, "OpCapability Geometry\n", "Geometry"),
633       SPV_ENV_VULKAN_1_1);
634   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
635 }
636 
TEST_F(ValidateBarriers,OpControlBarrierWorkgroupExecutionGeometry1p1)637 TEST_F(ValidateBarriers, OpControlBarrierWorkgroupExecutionGeometry1p1) {
638   const std::string body = R"(
639 OpControlBarrier %workgroup %workgroup %acquire_release
640 )";
641 
642   CompileSuccessfully(
643       GenerateShaderCode(body, "OpCapability Geometry\n", "Geometry"),
644       SPV_ENV_VULKAN_1_1);
645   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
646   EXPECT_THAT(getDiagnosticString(),
647               HasSubstr("OpControlBarrier execution scope must be Subgroup for "
648                         "Fragment, Vertex, Geometry and TessellationEvaluation "
649                         "execution models"));
650 }
651 
TEST_F(ValidateBarriers,OpControlBarrierSubgroupExecutionGeometry1p0)652 TEST_F(ValidateBarriers, OpControlBarrierSubgroupExecutionGeometry1p0) {
653   const std::string body = R"(
654 OpControlBarrier %subgroup %workgroup %acquire_release
655 )";
656 
657   CompileSuccessfully(
658       GenerateShaderCode(body, "OpCapability Geometry\n", "Geometry"),
659       SPV_ENV_VULKAN_1_0);
660   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
661   EXPECT_THAT(
662       getDiagnosticString(),
663       HasSubstr("OpControlBarrier requires one of the following Execution "
664                 "Models: TessellationControl, GLCompute or Kernel"));
665 }
666 
TEST_F(ValidateBarriers,OpControlBarrierSubgroupExecutionTessellationEvaluation1p1)667 TEST_F(ValidateBarriers,
668        OpControlBarrierSubgroupExecutionTessellationEvaluation1p1) {
669   const std::string body = R"(
670 OpControlBarrier %subgroup %subgroup %acquire_release_subgroup
671 )";
672 
673   CompileSuccessfully(GenerateShaderCode(body, "OpCapability Tessellation\n",
674                                          "TessellationEvaluation"),
675                       SPV_ENV_VULKAN_1_1);
676   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
677 }
678 
TEST_F(ValidateBarriers,OpControlBarrierWorkgroupExecutionTessellationEvaluation1p1)679 TEST_F(ValidateBarriers,
680        OpControlBarrierWorkgroupExecutionTessellationEvaluation1p1) {
681   const std::string body = R"(
682 OpControlBarrier %workgroup %workgroup %acquire_release
683 )";
684 
685   CompileSuccessfully(GenerateShaderCode(body, "OpCapability Tessellation\n",
686                                          "TessellationEvaluation"),
687                       SPV_ENV_VULKAN_1_1);
688   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
689   EXPECT_THAT(getDiagnosticString(),
690               HasSubstr("OpControlBarrier execution scope must be Subgroup for "
691                         "Fragment, Vertex, Geometry and TessellationEvaluation "
692                         "execution models"));
693 }
694 
TEST_F(ValidateBarriers,OpControlBarrierSubgroupExecutionTessellationEvaluation1p0)695 TEST_F(ValidateBarriers,
696        OpControlBarrierSubgroupExecutionTessellationEvaluation1p0) {
697   const std::string body = R"(
698 OpControlBarrier %subgroup %workgroup %acquire_release
699 )";
700 
701   CompileSuccessfully(GenerateShaderCode(body, "OpCapability Tessellation\n",
702                                          "TessellationEvaluation"),
703                       SPV_ENV_VULKAN_1_0);
704   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
705   EXPECT_THAT(
706       getDiagnosticString(),
707       HasSubstr("OpControlBarrier requires one of the following Execution "
708                 "Models: TessellationControl, GLCompute or Kernel"));
709 }
710 
TEST_F(ValidateBarriers,OpMemoryBarrierSuccess)711 TEST_F(ValidateBarriers, OpMemoryBarrierSuccess) {
712   const std::string body = R"(
713 OpMemoryBarrier %cross_device %acquire_release_uniform_workgroup
714 OpMemoryBarrier %device %uniform
715 )";
716 
717   CompileSuccessfully(GenerateShaderCode(body));
718   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
719 }
720 
TEST_F(ValidateBarriers,OpMemoryBarrierKernelSuccess)721 TEST_F(ValidateBarriers, OpMemoryBarrierKernelSuccess) {
722   const std::string body = R"(
723 OpMemoryBarrier %cross_device %acquire_release_workgroup
724 OpMemoryBarrier %device %none
725 )";
726 
727   CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1);
728   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
729 }
730 
TEST_F(ValidateBarriers,OpMemoryBarrierVulkanSuccess)731 TEST_F(ValidateBarriers, OpMemoryBarrierVulkanSuccess) {
732   const std::string body = R"(
733 OpMemoryBarrier %workgroup %acquire_release_uniform_workgroup
734 )";
735 
736   CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
737   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
738 }
739 
TEST_F(ValidateBarriers,OpMemoryBarrierWebGPUImageMemorySuccess)740 TEST_F(ValidateBarriers, OpMemoryBarrierWebGPUImageMemorySuccess) {
741   const std::string body = R"(
742 OpMemoryBarrier %workgroup %image_memory
743 )";
744 
745   CompileSuccessfully(GenerateWebGPUComputeShaderCode(body), SPV_ENV_WEBGPU_0);
746   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0));
747 }
748 
TEST_F(ValidateBarriers,OpMemoryBarrierWebGPUDeviceFailure)749 TEST_F(ValidateBarriers, OpMemoryBarrierWebGPUDeviceFailure) {
750   const std::string body = R"(
751 OpMemoryBarrier %subgroup %image_memory
752 )";
753 
754   CompileSuccessfully(GenerateWebGPUComputeShaderCode(body), SPV_ENV_WEBGPU_0);
755   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
756   EXPECT_THAT(getDiagnosticString(),
757               HasSubstr("in WebGPU environment Memory Scope is limited to "
758                         "Workgroup for OpMemoryBarrier"));
759 }
760 
TEST_F(ValidateBarriers,OpMemoryBarrierWebGPUAcquireReleaseFailure)761 TEST_F(ValidateBarriers, OpMemoryBarrierWebGPUAcquireReleaseFailure) {
762   const std::string body = R"(
763 OpMemoryBarrier %workgroup %acquire_release_uniform_workgroup
764 )";
765 
766   CompileSuccessfully(GenerateWebGPUComputeShaderCode(body), SPV_ENV_WEBGPU_0);
767   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
768   EXPECT_THAT(getDiagnosticString(),
769               HasSubstr("ImageMemory must be set for Memory Semantics of "
770                         "OpMemoryBarrier"));
771 }
772 
TEST_F(ValidateBarriers,OpMemoryBarrierWebGPURelaxedFailure)773 TEST_F(ValidateBarriers, OpMemoryBarrierWebGPURelaxedFailure) {
774   const std::string body = R"(
775 OpMemoryBarrier %workgroup %uniform_workgroup
776 )";
777 
778   CompileSuccessfully(GenerateWebGPUComputeShaderCode(body), SPV_ENV_WEBGPU_0);
779   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
780   EXPECT_THAT(getDiagnosticString(),
781               HasSubstr("ImageMemory must be set for Memory Semantics of "
782                         "OpMemoryBarrier"));
783 }
784 
TEST_F(ValidateBarriers,OpMemoryBarrierWebGPUAcquireFailure)785 TEST_F(ValidateBarriers, OpMemoryBarrierWebGPUAcquireFailure) {
786   const std::string body = R"(
787 OpMemoryBarrier %workgroup %acquire_uniform_workgroup
788 )";
789 
790   CompileSuccessfully(GenerateWebGPUComputeShaderCode(body), SPV_ENV_WEBGPU_0);
791   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
792   EXPECT_THAT(getDiagnosticString(),
793               HasSubstr("ImageMemory must be set for Memory Semantics of "
794                         "OpMemoryBarrier"));
795 }
796 
TEST_F(ValidateBarriers,OpMemoryBarrierWebGPUReleaseFailure)797 TEST_F(ValidateBarriers, OpMemoryBarrierWebGPUReleaseFailure) {
798   const std::string body = R"(
799 OpMemoryBarrier %workgroup %release_uniform_workgroup
800 )";
801 
802   CompileSuccessfully(GenerateWebGPUComputeShaderCode(body), SPV_ENV_WEBGPU_0);
803   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
804   EXPECT_THAT(getDiagnosticString(),
805               HasSubstr("ImageMemory must be set for Memory Semantics of "
806                         "OpMemoryBarrier"));
807 }
808 
TEST_F(ValidateBarriers,OpMemoryBarrierWebGPUUniformFailure)809 TEST_F(ValidateBarriers, OpMemoryBarrierWebGPUUniformFailure) {
810   const std::string body = R"(
811 OpMemoryBarrier %workgroup %uniform_image_memory
812 )";
813 
814   CompileSuccessfully(GenerateWebGPUComputeShaderCode(body), SPV_ENV_WEBGPU_0);
815   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
816   EXPECT_THAT(getDiagnosticString(),
817               HasSubstr("only ImageMemory may be set for Memory Semantics of "
818                         "OpMemoryBarrier"));
819 }
820 
TEST_F(ValidateBarriers,OpMemoryBarrierWebGPUWorkgroupNonComputeFailure)821 TEST_F(ValidateBarriers, OpMemoryBarrierWebGPUWorkgroupNonComputeFailure) {
822   const std::string body = R"(
823 OpMemoryBarrier %workgroup %image_memory
824 )";
825 
826   CompileSuccessfully(GenerateWebGPUVertexShaderCode(body), SPV_ENV_WEBGPU_0);
827   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_WEBGPU_0));
828   EXPECT_THAT(
829       getDiagnosticString(),
830       HasSubstr(
831           "Workgroup Memory Scope is limited to GLCompute execution model"));
832 }
833 
TEST_F(ValidateBarriers,OpMemoryBarrierFloatMemoryScope)834 TEST_F(ValidateBarriers, OpMemoryBarrierFloatMemoryScope) {
835   const std::string body = R"(
836 OpMemoryBarrier %f32_1 %acquire_release_uniform_workgroup
837 )";
838 
839   CompileSuccessfully(GenerateShaderCode(body));
840   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
841   EXPECT_THAT(getDiagnosticString(),
842               HasSubstr("MemoryBarrier: expected scope to be a 32-bit int"));
843 }
844 
TEST_F(ValidateBarriers,OpMemoryBarrierU64MemoryScope)845 TEST_F(ValidateBarriers, OpMemoryBarrierU64MemoryScope) {
846   const std::string body = R"(
847 OpMemoryBarrier %u64_1 %acquire_release_uniform_workgroup
848 )";
849 
850   CompileSuccessfully(GenerateShaderCode(body));
851   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
852   EXPECT_THAT(getDiagnosticString(),
853               HasSubstr("MemoryBarrier: expected scope to be a 32-bit int"));
854 }
855 
TEST_F(ValidateBarriers,OpMemoryBarrierFloatMemorySemantics)856 TEST_F(ValidateBarriers, OpMemoryBarrierFloatMemorySemantics) {
857   const std::string body = R"(
858 OpMemoryBarrier %device %f32_0
859 )";
860 
861   CompileSuccessfully(GenerateShaderCode(body));
862   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
863   EXPECT_THAT(
864       getDiagnosticString(),
865       HasSubstr("MemoryBarrier: expected Memory Semantics to be a 32-bit int"));
866 }
867 
TEST_F(ValidateBarriers,OpMemoryBarrierU64MemorySemantics)868 TEST_F(ValidateBarriers, OpMemoryBarrierU64MemorySemantics) {
869   const std::string body = R"(
870 OpMemoryBarrier %device %u64_0
871 )";
872 
873   CompileSuccessfully(GenerateShaderCode(body));
874   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
875   EXPECT_THAT(
876       getDiagnosticString(),
877       HasSubstr("MemoryBarrier: expected Memory Semantics to be a 32-bit int"));
878 }
879 
TEST_F(ValidateBarriers,OpMemoryBarrierVulkanMemoryScopeSubgroup)880 TEST_F(ValidateBarriers, OpMemoryBarrierVulkanMemoryScopeSubgroup) {
881   const std::string body = R"(
882 OpMemoryBarrier %subgroup %acquire_release_uniform_workgroup
883 )";
884 
885   CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
886   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
887   EXPECT_THAT(
888       getDiagnosticString(),
889       HasSubstr("MemoryBarrier: in Vulkan 1.0 environment Memory Scope is "
890                 "limited to Device, Workgroup and Invocation"));
891 }
892 
TEST_F(ValidateBarriers,OpMemoryBarrierVulkan1p1MemoryScopeSubgroup)893 TEST_F(ValidateBarriers, OpMemoryBarrierVulkan1p1MemoryScopeSubgroup) {
894   const std::string body = R"(
895 OpMemoryBarrier %subgroup %acquire_release_uniform_workgroup
896 )";
897 
898   CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_1);
899   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
900 }
901 
TEST_F(ValidateBarriers,OpMemoryBarrierAcquireAndRelease)902 TEST_F(ValidateBarriers, OpMemoryBarrierAcquireAndRelease) {
903   const std::string body = R"(
904 OpMemoryBarrier %device %acquire_and_release_uniform
905 )";
906 
907   CompileSuccessfully(GenerateShaderCode(body));
908   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
909   EXPECT_THAT(getDiagnosticString(),
910               HasSubstr("MemoryBarrier: Memory Semantics can have at most one "
911                         "of the following bits set: Acquire, Release, "
912                         "AcquireRelease or SequentiallyConsistent"));
913 }
914 
TEST_F(ValidateBarriers,OpMemoryBarrierVulkanMemorySemanticsNone)915 TEST_F(ValidateBarriers, OpMemoryBarrierVulkanMemorySemanticsNone) {
916   const std::string body = R"(
917 OpMemoryBarrier %device %none
918 )";
919 
920   CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
921   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
922   EXPECT_THAT(
923       getDiagnosticString(),
924       HasSubstr("MemoryBarrier: Vulkan specification requires Memory Semantics "
925                 "to have one of the following bits set: Acquire, Release, "
926                 "AcquireRelease or SequentiallyConsistent"));
927 }
928 
TEST_F(ValidateBarriers,OpMemoryBarrierVulkanMemorySemanticsAcquire)929 TEST_F(ValidateBarriers, OpMemoryBarrierVulkanMemorySemanticsAcquire) {
930   const std::string body = R"(
931 OpMemoryBarrier %device %acquire
932 )";
933 
934   CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
935   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
936   EXPECT_THAT(getDiagnosticString(),
937               HasSubstr("MemoryBarrier: expected Memory Semantics to include a "
938                         "Vulkan-supported storage class"));
939 }
940 
TEST_F(ValidateBarriers,OpMemoryBarrierVulkanSubgroupStorageClass)941 TEST_F(ValidateBarriers, OpMemoryBarrierVulkanSubgroupStorageClass) {
942   const std::string body = R"(
943 OpMemoryBarrier %device %acquire_release_subgroup
944 )";
945 
946   CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
947   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
948   EXPECT_THAT(getDiagnosticString(),
949               HasSubstr("MemoryBarrier: expected Memory Semantics to include a "
950                         "Vulkan-supported storage class"));
951 }
952 
TEST_F(ValidateBarriers,OpNamedBarrierInitializeSuccess)953 TEST_F(ValidateBarriers, OpNamedBarrierInitializeSuccess) {
954   const std::string body = R"(
955 %barrier = OpNamedBarrierInitialize %named_barrier %u32_4
956 )";
957 
958   CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1);
959   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
960 }
961 
TEST_F(ValidateBarriers,OpNamedBarrierInitializeWrongResultType)962 TEST_F(ValidateBarriers, OpNamedBarrierInitializeWrongResultType) {
963   const std::string body = R"(
964 %barrier = OpNamedBarrierInitialize %u32 %u32_4
965 )";
966 
967   CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1);
968   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
969             ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
970   EXPECT_THAT(getDiagnosticString(),
971               HasSubstr("NamedBarrierInitialize: expected Result Type to be "
972                         "OpTypeNamedBarrier"));
973 }
974 
TEST_F(ValidateBarriers,OpNamedBarrierInitializeFloatSubgroupCount)975 TEST_F(ValidateBarriers, OpNamedBarrierInitializeFloatSubgroupCount) {
976   const std::string body = R"(
977 %barrier = OpNamedBarrierInitialize %named_barrier %f32_4
978 )";
979 
980   CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1);
981   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
982             ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
983   EXPECT_THAT(getDiagnosticString(),
984               HasSubstr("NamedBarrierInitialize: expected Subgroup Count to be "
985                         "a 32-bit int"));
986 }
987 
TEST_F(ValidateBarriers,OpNamedBarrierInitializeU64SubgroupCount)988 TEST_F(ValidateBarriers, OpNamedBarrierInitializeU64SubgroupCount) {
989   const std::string body = R"(
990 %barrier = OpNamedBarrierInitialize %named_barrier %u64_4
991 )";
992 
993   CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1);
994   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
995             ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
996   EXPECT_THAT(getDiagnosticString(),
997               HasSubstr("NamedBarrierInitialize: expected Subgroup Count to be "
998                         "a 32-bit int"));
999 }
1000 
TEST_F(ValidateBarriers,OpMemoryNamedBarrierSuccess)1001 TEST_F(ValidateBarriers, OpMemoryNamedBarrierSuccess) {
1002   const std::string body = R"(
1003 %barrier = OpNamedBarrierInitialize %named_barrier %u32_4
1004 OpMemoryNamedBarrier %barrier %workgroup %acquire_release_workgroup
1005 )";
1006 
1007   CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1);
1008   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
1009 }
1010 
TEST_F(ValidateBarriers,OpMemoryNamedBarrierNotNamedBarrier)1011 TEST_F(ValidateBarriers, OpMemoryNamedBarrierNotNamedBarrier) {
1012   const std::string body = R"(
1013 OpMemoryNamedBarrier %u32_1 %workgroup %acquire_release_workgroup
1014 )";
1015 
1016   CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1);
1017   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
1018             ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
1019   EXPECT_THAT(getDiagnosticString(),
1020               HasSubstr("MemoryNamedBarrier: expected Named Barrier to be of "
1021                         "type OpTypeNamedBarrier"));
1022 }
1023 
TEST_F(ValidateBarriers,OpMemoryNamedBarrierFloatMemoryScope)1024 TEST_F(ValidateBarriers, OpMemoryNamedBarrierFloatMemoryScope) {
1025   const std::string body = R"(
1026 %barrier = OpNamedBarrierInitialize %named_barrier %u32_4
1027 OpMemoryNamedBarrier %barrier %f32_1 %acquire_release_workgroup
1028 )";
1029 
1030   CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1);
1031   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
1032             ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
1033   EXPECT_THAT(
1034       getDiagnosticString(),
1035       HasSubstr("MemoryNamedBarrier: expected scope to be a 32-bit int"));
1036 }
1037 
TEST_F(ValidateBarriers,OpMemoryNamedBarrierFloatMemorySemantics)1038 TEST_F(ValidateBarriers, OpMemoryNamedBarrierFloatMemorySemantics) {
1039   const std::string body = R"(
1040 %barrier = OpNamedBarrierInitialize %named_barrier %u32_4
1041 OpMemoryNamedBarrier %barrier %workgroup %f32_0
1042 )";
1043 
1044   CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1);
1045   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
1046             ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
1047   EXPECT_THAT(
1048       getDiagnosticString(),
1049       HasSubstr(
1050           "MemoryNamedBarrier: expected Memory Semantics to be a 32-bit int"));
1051 }
1052 
TEST_F(ValidateBarriers,OpMemoryNamedBarrierAcquireAndRelease)1053 TEST_F(ValidateBarriers, OpMemoryNamedBarrierAcquireAndRelease) {
1054   const std::string body = R"(
1055 %barrier = OpNamedBarrierInitialize %named_barrier %u32_4
1056 OpMemoryNamedBarrier %barrier %workgroup %acquire_and_release
1057 )";
1058 
1059   CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1);
1060   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
1061             ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
1062   EXPECT_THAT(getDiagnosticString(),
1063               HasSubstr("MemoryNamedBarrier: Memory Semantics can have at most "
1064                         "one of the following bits set: Acquire, Release, "
1065                         "AcquireRelease or SequentiallyConsistent"));
1066 }
1067 
TEST_F(ValidateBarriers,TypeAsMemoryScope)1068 TEST_F(ValidateBarriers, TypeAsMemoryScope) {
1069   const std::string body = R"(
1070 OpMemoryBarrier %u32 %u32_0
1071 )";
1072 
1073   CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1);
1074   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
1075   EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand 5[%uint] cannot be a "
1076                                                "type"));
1077 }
1078 
TEST_F(ValidateBarriers,OpControlBarrierVulkanMemoryModelBanSequentiallyConsistent)1079 TEST_F(ValidateBarriers,
1080        OpControlBarrierVulkanMemoryModelBanSequentiallyConsistent) {
1081   const std::string text = R"(
1082 OpCapability Shader
1083 OpCapability VulkanMemoryModelKHR
1084 OpExtension "SPV_KHR_vulkan_memory_model"
1085 OpMemoryModel Logical VulkanKHR
1086 OpEntryPoint Fragment %1 "func"
1087 OpExecutionMode %1 OriginUpperLeft
1088 %2 = OpTypeVoid
1089 %3 = OpTypeInt 32 0
1090 %4 = OpConstant %3 16
1091 %5 = OpTypeFunction %2
1092 %6 = OpConstant %3 5
1093 %1 = OpFunction %2 None %5
1094 %7 = OpLabel
1095 OpControlBarrier %6 %6 %4
1096 OpReturn
1097 OpFunctionEnd
1098 )";
1099 
1100   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
1101   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1102             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1103   EXPECT_THAT(getDiagnosticString(),
1104               HasSubstr("SequentiallyConsistent memory semantics cannot be "
1105                         "used with the VulkanKHR memory model."));
1106 }
1107 
TEST_F(ValidateBarriers,OpMemoryBarrierVulkanMemoryModelBanSequentiallyConsistent)1108 TEST_F(ValidateBarriers,
1109        OpMemoryBarrierVulkanMemoryModelBanSequentiallyConsistent) {
1110   const std::string text = R"(
1111 OpCapability Shader
1112 OpCapability VulkanMemoryModelKHR
1113 OpExtension "SPV_KHR_vulkan_memory_model"
1114 OpMemoryModel Logical VulkanKHR
1115 OpEntryPoint Fragment %1 "func"
1116 OpExecutionMode %1 OriginUpperLeft
1117 %2 = OpTypeVoid
1118 %3 = OpTypeInt 32 0
1119 %4 = OpConstant %3 16
1120 %5 = OpTypeFunction %2
1121 %6 = OpConstant %3 5
1122 %1 = OpFunction %2 None %5
1123 %7 = OpLabel
1124 OpMemoryBarrier %6 %4
1125 OpReturn
1126 OpFunctionEnd
1127 )";
1128 
1129   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
1130   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1131             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1132   EXPECT_THAT(getDiagnosticString(),
1133               HasSubstr("SequentiallyConsistent memory semantics cannot be "
1134                         "used with the VulkanKHR memory model."));
1135 }
1136 
TEST_F(ValidateBarriers,OutputMemoryKHRRequireVulkanMemoryModelKHR)1137 TEST_F(ValidateBarriers, OutputMemoryKHRRequireVulkanMemoryModelKHR) {
1138   const std::string text = R"(
1139 OpCapability Shader
1140 OpMemoryModel Logical GLSL450
1141 OpEntryPoint Fragment %1 "func"
1142 OpExecutionMode %1 OriginUpperLeft
1143 %2 = OpTypeVoid
1144 %3 = OpTypeInt 32 0
1145 %semantics = OpConstant %3 4104
1146 %5 = OpTypeFunction %2
1147 %device = OpConstant %3 1
1148 %1 = OpFunction %2 None %5
1149 %7 = OpLabel
1150 OpControlBarrier %device %device %semantics
1151 OpReturn
1152 OpFunctionEnd
1153 )";
1154 
1155   CompileSuccessfully(text);
1156   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1157   EXPECT_THAT(getDiagnosticString(),
1158               HasSubstr("ControlBarrier: Memory Semantics OutputMemoryKHR "
1159                         "requires capability VulkanMemoryModelKHR"));
1160 }
1161 
TEST_F(ValidateBarriers,MakeAvailableKHRRequireVulkanMemoryModelKHR)1162 TEST_F(ValidateBarriers, MakeAvailableKHRRequireVulkanMemoryModelKHR) {
1163   const std::string text = R"(
1164 OpCapability Shader
1165 OpMemoryModel Logical GLSL450
1166 OpEntryPoint Fragment %1 "func"
1167 OpExecutionMode %1 OriginUpperLeft
1168 %2 = OpTypeVoid
1169 %3 = OpTypeInt 32 0
1170 %semantics = OpConstant %3 8264
1171 %5 = OpTypeFunction %2
1172 %device = OpConstant %3 1
1173 %1 = OpFunction %2 None %5
1174 %7 = OpLabel
1175 OpControlBarrier %device %device %semantics
1176 OpReturn
1177 OpFunctionEnd
1178 )";
1179 
1180   CompileSuccessfully(text);
1181   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1182   EXPECT_THAT(getDiagnosticString(),
1183               HasSubstr("ControlBarrier: Memory Semantics MakeAvailableKHR "
1184                         "requires capability VulkanMemoryModelKHR"));
1185 }
1186 
TEST_F(ValidateBarriers,MakeVisibleKHRRequireVulkanMemoryModelKHR)1187 TEST_F(ValidateBarriers, MakeVisibleKHRRequireVulkanMemoryModelKHR) {
1188   const std::string text = R"(
1189 OpCapability Shader
1190 OpMemoryModel Logical GLSL450
1191 OpEntryPoint Fragment %1 "func"
1192 OpExecutionMode %1 OriginUpperLeft
1193 %2 = OpTypeVoid
1194 %3 = OpTypeInt 32 0
1195 %semantics = OpConstant %3 16456
1196 %5 = OpTypeFunction %2
1197 %device = OpConstant %3 1
1198 %1 = OpFunction %2 None %5
1199 %7 = OpLabel
1200 OpControlBarrier %device %device %semantics
1201 OpReturn
1202 OpFunctionEnd
1203 )";
1204 
1205   CompileSuccessfully(text);
1206   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1207   EXPECT_THAT(getDiagnosticString(),
1208               HasSubstr("ControlBarrier: Memory Semantics MakeVisibleKHR "
1209                         "requires capability VulkanMemoryModelKHR"));
1210 }
1211 
TEST_F(ValidateBarriers,MakeAvailableKHRRequiresReleaseSemantics)1212 TEST_F(ValidateBarriers, MakeAvailableKHRRequiresReleaseSemantics) {
1213   const std::string text = R"(
1214 OpCapability Shader
1215 OpCapability VulkanMemoryModelKHR
1216 OpExtension "SPV_KHR_vulkan_memory_model"
1217 OpMemoryModel Logical VulkanKHR
1218 OpEntryPoint Fragment %func "func"
1219 OpExecutionMode %func OriginUpperLeft
1220 %void = OpTypeVoid
1221 %int = OpTypeInt 32 0
1222 %workgroup = OpConstant %int 2
1223 %semantics = OpConstant %int 8448
1224 %functy = OpTypeFunction %void
1225 %func = OpFunction %void None %functy
1226 %1 = OpLabel
1227 OpControlBarrier %workgroup %workgroup %semantics
1228 OpReturn
1229 OpFunctionEnd
1230 )";
1231 
1232   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
1233   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1234             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1235   EXPECT_THAT(
1236       getDiagnosticString(),
1237       HasSubstr("ControlBarrier: MakeAvailableKHR Memory Semantics also "
1238                 "requires either Release or AcquireRelease Memory Semantics"));
1239 }
1240 
TEST_F(ValidateBarriers,MakeVisibleKHRRequiresAcquireSemantics)1241 TEST_F(ValidateBarriers, MakeVisibleKHRRequiresAcquireSemantics) {
1242   const std::string text = R"(
1243 OpCapability Shader
1244 OpCapability VulkanMemoryModelKHR
1245 OpExtension "SPV_KHR_vulkan_memory_model"
1246 OpMemoryModel Logical VulkanKHR
1247 OpEntryPoint Fragment %func "func"
1248 OpExecutionMode %func OriginUpperLeft
1249 %void = OpTypeVoid
1250 %int = OpTypeInt 32 0
1251 %workgroup = OpConstant %int 2
1252 %semantics = OpConstant %int 16640
1253 %functy = OpTypeFunction %void
1254 %func = OpFunction %void None %functy
1255 %1 = OpLabel
1256 OpControlBarrier %workgroup %workgroup %semantics
1257 OpReturn
1258 OpFunctionEnd
1259 )";
1260 
1261   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
1262   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1263             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1264   EXPECT_THAT(
1265       getDiagnosticString(),
1266       HasSubstr("ControlBarrier: MakeVisibleKHR Memory Semantics also requires "
1267                 "either Acquire or AcquireRelease Memory Semantics"));
1268 }
1269 
TEST_F(ValidateBarriers,MakeAvailableKHRRequiresStorageSemantics)1270 TEST_F(ValidateBarriers, MakeAvailableKHRRequiresStorageSemantics) {
1271   const std::string text = R"(
1272 OpCapability Shader
1273 OpCapability VulkanMemoryModelKHR
1274 OpExtension "SPV_KHR_vulkan_memory_model"
1275 OpMemoryModel Logical VulkanKHR
1276 OpEntryPoint Fragment %func "func"
1277 OpExecutionMode %func OriginUpperLeft
1278 %void = OpTypeVoid
1279 %int = OpTypeInt 32 0
1280 %workgroup = OpConstant %int 2
1281 %semantics = OpConstant %int 8196
1282 %functy = OpTypeFunction %void
1283 %func = OpFunction %void None %functy
1284 %1 = OpLabel
1285 OpMemoryBarrier %workgroup %semantics
1286 OpReturn
1287 OpFunctionEnd
1288 )";
1289 
1290   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
1291   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1292             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1293   EXPECT_THAT(getDiagnosticString(),
1294               HasSubstr("MemoryBarrier: expected Memory Semantics to include a "
1295                         "storage class"));
1296 }
1297 
TEST_F(ValidateBarriers,MakeVisibleKHRRequiresStorageSemantics)1298 TEST_F(ValidateBarriers, MakeVisibleKHRRequiresStorageSemantics) {
1299   const std::string text = R"(
1300 OpCapability Shader
1301 OpCapability VulkanMemoryModelKHR
1302 OpExtension "SPV_KHR_vulkan_memory_model"
1303 OpMemoryModel Logical VulkanKHR
1304 OpEntryPoint Fragment %func "func"
1305 OpExecutionMode %func OriginUpperLeft
1306 %void = OpTypeVoid
1307 %int = OpTypeInt 32 0
1308 %workgroup = OpConstant %int 2
1309 %semantics = OpConstant %int 16386
1310 %functy = OpTypeFunction %void
1311 %func = OpFunction %void None %functy
1312 %1 = OpLabel
1313 OpMemoryBarrier %workgroup %semantics
1314 OpReturn
1315 OpFunctionEnd
1316 )";
1317 
1318   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
1319   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1320             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1321   EXPECT_THAT(getDiagnosticString(),
1322               HasSubstr("MemoryBarrier: expected Memory Semantics to include a "
1323                         "storage class"));
1324 }
1325 
TEST_F(ValidateBarriers,SemanticsSpecConstantShader)1326 TEST_F(ValidateBarriers, SemanticsSpecConstantShader) {
1327   const std::string spirv = R"(
1328 OpCapability Shader
1329 OpMemoryModel Logical GLSL450
1330 OpEntryPoint Fragment %func "func"
1331 OpExecutionMode %func OriginUpperLeft
1332 %void = OpTypeVoid
1333 %int = OpTypeInt 32 0
1334 %ptr_int_workgroup = OpTypePointer Workgroup %int
1335 %var = OpVariable %ptr_int_workgroup Workgroup
1336 %voidfn = OpTypeFunction %void
1337 %spec_const = OpSpecConstant %int 0
1338 %workgroup = OpConstant %int 2
1339 %func = OpFunction %void None %voidfn
1340 %entry = OpLabel
1341 OpMemoryBarrier %workgroup %spec_const
1342 OpReturn
1343 OpFunctionEnd
1344 )";
1345 
1346   CompileSuccessfully(spirv);
1347   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1348   EXPECT_THAT(getDiagnosticString(),
1349               HasSubstr("Memory Semantics ids must be OpConstant when Shader "
1350                         "capability is present"));
1351 }
1352 
TEST_F(ValidateBarriers,SemanticsSpecConstantKernel)1353 TEST_F(ValidateBarriers, SemanticsSpecConstantKernel) {
1354   const std::string spirv = R"(
1355 OpCapability Kernel
1356 OpCapability Linkage
1357 OpMemoryModel Logical OpenCL
1358 %void = OpTypeVoid
1359 %int = OpTypeInt 32 0
1360 %ptr_int_workgroup = OpTypePointer Workgroup %int
1361 %var = OpVariable %ptr_int_workgroup Workgroup
1362 %voidfn = OpTypeFunction %void
1363 %spec_const = OpSpecConstant %int 0
1364 %workgroup = OpConstant %int 2
1365 %func = OpFunction %void None %voidfn
1366 %entry = OpLabel
1367 OpMemoryBarrier %workgroup %spec_const
1368 OpReturn
1369 OpFunctionEnd
1370 )";
1371 
1372   CompileSuccessfully(spirv);
1373   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1374 }
1375 
TEST_F(ValidateBarriers,ScopeSpecConstantShader)1376 TEST_F(ValidateBarriers, ScopeSpecConstantShader) {
1377   const std::string spirv = R"(
1378 OpCapability Shader
1379 OpMemoryModel Logical GLSL450
1380 OpEntryPoint Fragment %func "func"
1381 OpExecutionMode %func OriginUpperLeft
1382 %void = OpTypeVoid
1383 %int = OpTypeInt 32 0
1384 %ptr_int_workgroup = OpTypePointer Workgroup %int
1385 %var = OpVariable %ptr_int_workgroup Workgroup
1386 %voidfn = OpTypeFunction %void
1387 %spec_const = OpSpecConstant %int 0
1388 %relaxed = OpConstant %int 0
1389 %func = OpFunction %void None %voidfn
1390 %entry = OpLabel
1391 OpMemoryBarrier %spec_const %relaxed
1392 OpReturn
1393 OpFunctionEnd
1394 )";
1395 
1396   CompileSuccessfully(spirv);
1397   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1398   EXPECT_THAT(getDiagnosticString(),
1399               HasSubstr("Scope ids must be OpConstant when Shader "
1400                         "capability is present"));
1401 }
1402 
TEST_F(ValidateBarriers,ScopeSpecConstantKernel)1403 TEST_F(ValidateBarriers, ScopeSpecConstantKernel) {
1404   const std::string spirv = R"(
1405 OpCapability Kernel
1406 OpCapability Linkage
1407 OpMemoryModel Logical OpenCL
1408 %void = OpTypeVoid
1409 %int = OpTypeInt 32 0
1410 %ptr_int_workgroup = OpTypePointer Workgroup %int
1411 %var = OpVariable %ptr_int_workgroup Workgroup
1412 %voidfn = OpTypeFunction %void
1413 %spec_const = OpSpecConstant %int 0
1414 %relaxed = OpConstant %int 0
1415 %func = OpFunction %void None %voidfn
1416 %entry = OpLabel
1417 OpMemoryBarrier %spec_const %relaxed
1418 OpReturn
1419 OpFunctionEnd
1420 )";
1421 
1422   CompileSuccessfully(spirv);
1423   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1424 }
1425 
TEST_F(ValidateBarriers,VulkanMemoryModelDeviceScopeBad)1426 TEST_F(ValidateBarriers, VulkanMemoryModelDeviceScopeBad) {
1427   const std::string text = R"(
1428 OpCapability Shader
1429 OpCapability VulkanMemoryModelKHR
1430 OpExtension "SPV_KHR_vulkan_memory_model"
1431 OpMemoryModel Logical VulkanKHR
1432 OpEntryPoint Fragment %func "func"
1433 OpExecutionMode %func OriginUpperLeft
1434 %void = OpTypeVoid
1435 %int = OpTypeInt 32 0
1436 %device = OpConstant %int 1
1437 %semantics = OpConstant %int 0
1438 %functy = OpTypeFunction %void
1439 %func = OpFunction %void None %functy
1440 %1 = OpLabel
1441 OpMemoryBarrier %device %semantics
1442 OpReturn
1443 OpFunctionEnd
1444 )";
1445 
1446   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
1447   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1448             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1449   EXPECT_THAT(
1450       getDiagnosticString(),
1451       HasSubstr("Use of device scope with VulkanKHR memory model requires the "
1452                 "VulkanMemoryModelDeviceScopeKHR capability"));
1453 }
1454 
TEST_F(ValidateBarriers,VulkanMemoryModelDeviceScopeGood)1455 TEST_F(ValidateBarriers, VulkanMemoryModelDeviceScopeGood) {
1456   const std::string text = R"(
1457 OpCapability Shader
1458 OpCapability VulkanMemoryModelKHR
1459 OpCapability VulkanMemoryModelDeviceScopeKHR
1460 OpExtension "SPV_KHR_vulkan_memory_model"
1461 OpMemoryModel Logical VulkanKHR
1462 OpEntryPoint Fragment %func "func"
1463 OpExecutionMode %func OriginUpperLeft
1464 %void = OpTypeVoid
1465 %int = OpTypeInt 32 0
1466 %device = OpConstant %int 1
1467 %semantics = OpConstant %int 0
1468 %functy = OpTypeFunction %void
1469 %func = OpFunction %void None %functy
1470 %1 = OpLabel
1471 OpMemoryBarrier %device %semantics
1472 OpReturn
1473 OpFunctionEnd
1474 )";
1475 
1476   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
1477   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1478 }
1479 
TEST_F(ValidateBarriers,VolatileMemoryBarrier)1480 TEST_F(ValidateBarriers, VolatileMemoryBarrier) {
1481   const std::string text = R"(
1482 OpCapability Shader
1483 OpCapability VulkanMemoryModelKHR
1484 OpCapability VulkanMemoryModelDeviceScopeKHR
1485 OpCapability Linkage
1486 OpExtension "SPV_KHR_vulkan_memory_model"
1487 OpMemoryModel Logical VulkanKHR
1488 %void = OpTypeVoid
1489 %int = OpTypeInt 32 0
1490 %device = OpConstant %int 1
1491 %semantics = OpConstant %int 32768
1492 %functy = OpTypeFunction %void
1493 %func = OpFunction %void None %functy
1494 %1 = OpLabel
1495 OpMemoryBarrier %device %semantics
1496 OpReturn
1497 OpFunctionEnd
1498 )";
1499 
1500   CompileSuccessfully(text);
1501   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1502   EXPECT_THAT(getDiagnosticString(),
1503               HasSubstr("Memory Semantics Volatile can only be used with "
1504                         "atomic instructions"));
1505 }
1506 
TEST_F(ValidateBarriers,VolatileControlBarrier)1507 TEST_F(ValidateBarriers, VolatileControlBarrier) {
1508   const std::string text = R"(
1509 OpCapability Shader
1510 OpCapability VulkanMemoryModelKHR
1511 OpCapability VulkanMemoryModelDeviceScopeKHR
1512 OpCapability Linkage
1513 OpExtension "SPV_KHR_vulkan_memory_model"
1514 OpMemoryModel Logical VulkanKHR
1515 %void = OpTypeVoid
1516 %int = OpTypeInt 32 0
1517 %device = OpConstant %int 1
1518 %semantics = OpConstant %int 32768
1519 %functy = OpTypeFunction %void
1520 %func = OpFunction %void None %functy
1521 %1 = OpLabel
1522 OpControlBarrier %device %device %semantics
1523 OpReturn
1524 OpFunctionEnd
1525 )";
1526 
1527   CompileSuccessfully(text);
1528   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1529   EXPECT_THAT(getDiagnosticString(),
1530               HasSubstr("Memory Semantics Volatile can only be used with "
1531                         "atomic instructions"));
1532 }
1533 
TEST_F(ValidateBarriers,CooperativeMatrixSpecConstantVolatile)1534 TEST_F(ValidateBarriers, CooperativeMatrixSpecConstantVolatile) {
1535   const std::string text = R"(
1536 OpCapability Shader
1537 OpCapability VulkanMemoryModelKHR
1538 OpCapability VulkanMemoryModelDeviceScopeKHR
1539 OpCapability CooperativeMatrixNV
1540 OpCapability Linkage
1541 OpExtension "SPV_KHR_vulkan_memory_model"
1542 OpExtension "SPV_NV_cooperative_matrix"
1543 OpMemoryModel Logical VulkanKHR
1544 %void = OpTypeVoid
1545 %int = OpTypeInt 32 0
1546 %device = OpConstant %int 1
1547 %semantics = OpSpecConstant %int 32768
1548 %functy = OpTypeFunction %void
1549 %func = OpFunction %void None %functy
1550 %1 = OpLabel
1551 OpControlBarrier %device %device %semantics
1552 OpReturn
1553 OpFunctionEnd
1554 )";
1555 
1556   CompileSuccessfully(text);
1557   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1558 }
1559 
TEST_F(ValidateBarriers,CooperativeMatrixNonConstantSemantics)1560 TEST_F(ValidateBarriers, CooperativeMatrixNonConstantSemantics) {
1561   const std::string text = R"(
1562 OpCapability Shader
1563 OpCapability VulkanMemoryModelKHR
1564 OpCapability VulkanMemoryModelDeviceScopeKHR
1565 OpCapability CooperativeMatrixNV
1566 OpCapability Linkage
1567 OpExtension "SPV_KHR_vulkan_memory_model"
1568 OpExtension "SPV_NV_cooperative_matrix"
1569 OpMemoryModel Logical VulkanKHR
1570 %void = OpTypeVoid
1571 %int = OpTypeInt 32 0
1572 %device = OpConstant %int 1
1573 %semantics = OpUndef %int
1574 %functy = OpTypeFunction %void
1575 %func = OpFunction %void None %functy
1576 %1 = OpLabel
1577 OpControlBarrier %device %device %semantics
1578 OpReturn
1579 OpFunctionEnd
1580 )";
1581 
1582   CompileSuccessfully(text);
1583   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1584   EXPECT_THAT(getDiagnosticString(),
1585               HasSubstr("Memory Semantics must be a constant instruction when "
1586                         "CooperativeMatrixNV capability is present"));
1587 }
1588 
1589 }  // namespace
1590 }  // namespace val
1591 }  // namespace spvtools
1592