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