• 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               HasSubstr("ControlBarrier: in Vulkan environment Execution Scope "
350                         "is limited to Workgroup and Subgroup"));
351 }
352 
TEST_F(ValidateBarriers,OpControlBarrierVulkanMemoryScopeSubgroup)353 TEST_F(ValidateBarriers, OpControlBarrierVulkanMemoryScopeSubgroup) {
354   const std::string body = R"(
355 OpControlBarrier %subgroup %subgroup %none
356 )";
357 
358   CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
359   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
360   EXPECT_THAT(getDiagnosticString(),
361               AnyVUID("VUID-StandaloneSpirv-None-04638"));
362   EXPECT_THAT(
363       getDiagnosticString(),
364       HasSubstr("ControlBarrier: in Vulkan 1.0 environment Memory Scope is "
365                 "limited to Device, Workgroup and Invocation"));
366 }
367 
TEST_F(ValidateBarriers,OpControlBarrierVulkan1p1MemoryScopeSubgroup)368 TEST_F(ValidateBarriers, OpControlBarrierVulkan1p1MemoryScopeSubgroup) {
369   const std::string body = R"(
370 OpControlBarrier %subgroup %subgroup %none
371 )";
372 
373   CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_1);
374   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
375 }
376 
TEST_F(ValidateBarriers,OpControlBarrierVulkan1p1MemoryScopeCrossDevice)377 TEST_F(ValidateBarriers, OpControlBarrierVulkan1p1MemoryScopeCrossDevice) {
378   const std::string body = R"(
379 OpControlBarrier %subgroup %cross_device %none
380 )";
381 
382   CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_1);
383   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_1));
384   EXPECT_THAT(getDiagnosticString(),
385               AnyVUID("VUID-StandaloneSpirv-None-04638"));
386   EXPECT_THAT(getDiagnosticString(),
387               HasSubstr("ControlBarrier: in Vulkan environment, Memory Scope "
388                         "cannot be CrossDevice"));
389 }
390 
TEST_F(ValidateBarriers,OpControlBarrierVulkan1p1WorkgroupNonComputeFailure)391 TEST_F(ValidateBarriers, OpControlBarrierVulkan1p1WorkgroupNonComputeFailure) {
392   const std::string body = R"(
393 OpControlBarrier %workgroup %workgroup %acquire
394 )";
395 
396   CompileSuccessfully(GenerateVulkanVertexShaderCode(body), SPV_ENV_VULKAN_1_1);
397   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
398   EXPECT_THAT(getDiagnosticString(),
399               AnyVUID("VUID-StandaloneSpirv-None-04639"));
400   EXPECT_THAT(getDiagnosticString(),
401               HasSubstr("Workgroup Memory Scope is limited to MeshNV, TaskNV, "
402                         "and GLCompute execution model"));
403 }
404 
TEST_F(ValidateBarriers,OpControlBarrierVulkan1p1WorkgroupNonComputeSuccess)405 TEST_F(ValidateBarriers, OpControlBarrierVulkan1p1WorkgroupNonComputeSuccess) {
406   const std::string body = R"(
407 OpControlBarrier %workgroup %workgroup %acquire
408 )";
409 
410   CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_1);
411   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
412 }
413 
TEST_F(ValidateBarriers,OpControlBarrierAcquireAndRelease)414 TEST_F(ValidateBarriers, OpControlBarrierAcquireAndRelease) {
415   const std::string body = R"(
416 OpControlBarrier %device %device %acquire_and_release_uniform
417 )";
418 
419   CompileSuccessfully(GenerateShaderCode(body));
420   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
421   EXPECT_THAT(getDiagnosticString(),
422               HasSubstr("ControlBarrier: Memory Semantics can have at most one "
423                         "of the following bits set: Acquire, Release, "
424                         "AcquireRelease or SequentiallyConsistent"));
425 }
426 
427 // TODO(atgoo@github.com): the corresponding check fails Vulkan CTS,
428 // reenable once fixed.
TEST_F(ValidateBarriers,DISABLED_OpControlBarrierVulkanSubgroupStorageClass)429 TEST_F(ValidateBarriers, DISABLED_OpControlBarrierVulkanSubgroupStorageClass) {
430   const std::string body = R"(
431 OpControlBarrier %workgroup %device %acquire_release_subgroup
432 )";
433 
434   CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
435   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
436   EXPECT_THAT(
437       getDiagnosticString(),
438       HasSubstr(
439           "ControlBarrier: expected Memory Semantics to include a "
440           "Vulkan-supported storage class if Memory Semantics is not None"));
441 }
442 
TEST_F(ValidateBarriers,OpControlBarrierSubgroupExecutionFragment1p1)443 TEST_F(ValidateBarriers, OpControlBarrierSubgroupExecutionFragment1p1) {
444   const std::string body = R"(
445 OpControlBarrier %subgroup %subgroup %acquire_release_subgroup
446 )";
447 
448   CompileSuccessfully(GenerateShaderCode(body, "", "Fragment"),
449                       SPV_ENV_VULKAN_1_1);
450   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
451 }
452 
TEST_F(ValidateBarriers,OpControlBarrierWorkgroupExecutionFragment1p1)453 TEST_F(ValidateBarriers, OpControlBarrierWorkgroupExecutionFragment1p1) {
454   const std::string body = R"(
455 OpControlBarrier %workgroup %workgroup %acquire_release
456 )";
457 
458   CompileSuccessfully(GenerateShaderCode(body, "", "Fragment"),
459                       SPV_ENV_VULKAN_1_1);
460   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
461   EXPECT_THAT(getDiagnosticString(),
462               HasSubstr("OpControlBarrier execution scope must be Subgroup for "
463                         "Fragment, Vertex, Geometry and TessellationEvaluation "
464                         "execution models"));
465 }
466 
TEST_F(ValidateBarriers,OpControlBarrierSubgroupExecutionFragment1p0)467 TEST_F(ValidateBarriers, OpControlBarrierSubgroupExecutionFragment1p0) {
468   const std::string body = R"(
469 OpControlBarrier %subgroup %workgroup %acquire_release
470 )";
471 
472   CompileSuccessfully(GenerateShaderCode(body, "", "Fragment"),
473                       SPV_ENV_VULKAN_1_0);
474   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
475   EXPECT_THAT(
476       getDiagnosticString(),
477       HasSubstr("OpControlBarrier requires one of the following Execution "
478                 "Models: TessellationControl, GLCompute or Kernel"));
479 }
480 
TEST_F(ValidateBarriers,OpControlBarrierSubgroupExecutionVertex1p1)481 TEST_F(ValidateBarriers, OpControlBarrierSubgroupExecutionVertex1p1) {
482   const std::string body = R"(
483 OpControlBarrier %subgroup %subgroup %acquire_release_subgroup
484 )";
485 
486   CompileSuccessfully(GenerateShaderCode(body, "", "Vertex"),
487                       SPV_ENV_VULKAN_1_1);
488   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
489 }
490 
TEST_F(ValidateBarriers,OpControlBarrierWorkgroupExecutionVertex1p1)491 TEST_F(ValidateBarriers, OpControlBarrierWorkgroupExecutionVertex1p1) {
492   const std::string body = R"(
493 OpControlBarrier %workgroup %workgroup %acquire_release
494 )";
495 
496   CompileSuccessfully(GenerateShaderCode(body, "", "Vertex"),
497                       SPV_ENV_VULKAN_1_1);
498   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
499   EXPECT_THAT(getDiagnosticString(),
500               HasSubstr("OpControlBarrier execution scope must be Subgroup for "
501                         "Fragment, Vertex, Geometry and TessellationEvaluation "
502                         "execution models"));
503 }
504 
TEST_F(ValidateBarriers,OpControlBarrierSubgroupExecutionVertex1p0)505 TEST_F(ValidateBarriers, OpControlBarrierSubgroupExecutionVertex1p0) {
506   const std::string body = R"(
507 OpControlBarrier %subgroup %workgroup %acquire_release
508 )";
509 
510   CompileSuccessfully(GenerateShaderCode(body, "", "Vertex"),
511                       SPV_ENV_VULKAN_1_0);
512   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
513   EXPECT_THAT(
514       getDiagnosticString(),
515       HasSubstr("OpControlBarrier requires one of the following Execution "
516                 "Models: TessellationControl, GLCompute or Kernel"));
517 }
518 
TEST_F(ValidateBarriers,OpControlBarrierSubgroupExecutionGeometry1p1)519 TEST_F(ValidateBarriers, OpControlBarrierSubgroupExecutionGeometry1p1) {
520   const std::string body = R"(
521 OpControlBarrier %subgroup %subgroup %acquire_release_subgroup
522 )";
523 
524   CompileSuccessfully(
525       GenerateShaderCode(body, "OpCapability Geometry\n", "Geometry"),
526       SPV_ENV_VULKAN_1_1);
527   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
528 }
529 
TEST_F(ValidateBarriers,OpControlBarrierWorkgroupExecutionGeometry1p1)530 TEST_F(ValidateBarriers, OpControlBarrierWorkgroupExecutionGeometry1p1) {
531   const std::string body = R"(
532 OpControlBarrier %workgroup %workgroup %acquire_release
533 )";
534 
535   CompileSuccessfully(
536       GenerateShaderCode(body, "OpCapability Geometry\n", "Geometry"),
537       SPV_ENV_VULKAN_1_1);
538   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
539   EXPECT_THAT(getDiagnosticString(),
540               HasSubstr("OpControlBarrier execution scope must be Subgroup for "
541                         "Fragment, Vertex, Geometry and TessellationEvaluation "
542                         "execution models"));
543 }
544 
TEST_F(ValidateBarriers,OpControlBarrierSubgroupExecutionGeometry1p0)545 TEST_F(ValidateBarriers, OpControlBarrierSubgroupExecutionGeometry1p0) {
546   const std::string body = R"(
547 OpControlBarrier %subgroup %workgroup %acquire_release
548 )";
549 
550   CompileSuccessfully(
551       GenerateShaderCode(body, "OpCapability Geometry\n", "Geometry"),
552       SPV_ENV_VULKAN_1_0);
553   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
554   EXPECT_THAT(
555       getDiagnosticString(),
556       HasSubstr("OpControlBarrier requires one of the following Execution "
557                 "Models: TessellationControl, GLCompute or Kernel"));
558 }
559 
TEST_F(ValidateBarriers,OpControlBarrierSubgroupExecutionTessellationEvaluation1p1)560 TEST_F(ValidateBarriers,
561        OpControlBarrierSubgroupExecutionTessellationEvaluation1p1) {
562   const std::string body = R"(
563 OpControlBarrier %subgroup %subgroup %acquire_release_subgroup
564 )";
565 
566   CompileSuccessfully(GenerateShaderCode(body, "OpCapability Tessellation\n",
567                                          "TessellationEvaluation"),
568                       SPV_ENV_VULKAN_1_1);
569   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
570 }
571 
TEST_F(ValidateBarriers,OpControlBarrierWorkgroupExecutionTessellationEvaluation1p1)572 TEST_F(ValidateBarriers,
573        OpControlBarrierWorkgroupExecutionTessellationEvaluation1p1) {
574   const std::string body = R"(
575 OpControlBarrier %workgroup %workgroup %acquire_release
576 )";
577 
578   CompileSuccessfully(GenerateShaderCode(body, "OpCapability Tessellation\n",
579                                          "TessellationEvaluation"),
580                       SPV_ENV_VULKAN_1_1);
581   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
582   EXPECT_THAT(getDiagnosticString(),
583               HasSubstr("OpControlBarrier execution scope must be Subgroup for "
584                         "Fragment, Vertex, Geometry and TessellationEvaluation "
585                         "execution models"));
586 }
587 
TEST_F(ValidateBarriers,OpControlBarrierSubgroupExecutionTessellationEvaluation1p0)588 TEST_F(ValidateBarriers,
589        OpControlBarrierSubgroupExecutionTessellationEvaluation1p0) {
590   const std::string body = R"(
591 OpControlBarrier %subgroup %workgroup %acquire_release
592 )";
593 
594   CompileSuccessfully(GenerateShaderCode(body, "OpCapability Tessellation\n",
595                                          "TessellationEvaluation"),
596                       SPV_ENV_VULKAN_1_0);
597   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
598   EXPECT_THAT(
599       getDiagnosticString(),
600       HasSubstr("OpControlBarrier requires one of the following Execution "
601                 "Models: TessellationControl, GLCompute or Kernel"));
602 }
603 
TEST_F(ValidateBarriers,OpMemoryBarrierSuccess)604 TEST_F(ValidateBarriers, OpMemoryBarrierSuccess) {
605   const std::string body = R"(
606 OpMemoryBarrier %cross_device %acquire_release_uniform_workgroup
607 OpMemoryBarrier %device %uniform
608 )";
609 
610   CompileSuccessfully(GenerateShaderCode(body));
611   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
612 }
613 
TEST_F(ValidateBarriers,OpMemoryBarrierKernelSuccess)614 TEST_F(ValidateBarriers, OpMemoryBarrierKernelSuccess) {
615   const std::string body = R"(
616 OpMemoryBarrier %cross_device %acquire_release_workgroup
617 OpMemoryBarrier %device %none
618 )";
619 
620   CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1);
621   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
622 }
623 
TEST_F(ValidateBarriers,OpMemoryBarrierVulkanSuccess)624 TEST_F(ValidateBarriers, OpMemoryBarrierVulkanSuccess) {
625   const std::string body = R"(
626 OpMemoryBarrier %workgroup %acquire_release_uniform_workgroup
627 )";
628 
629   CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
630   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
631 }
632 
TEST_F(ValidateBarriers,OpMemoryBarrierFloatMemoryScope)633 TEST_F(ValidateBarriers, OpMemoryBarrierFloatMemoryScope) {
634   const std::string body = R"(
635 OpMemoryBarrier %f32_1 %acquire_release_uniform_workgroup
636 )";
637 
638   CompileSuccessfully(GenerateShaderCode(body));
639   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
640   EXPECT_THAT(getDiagnosticString(),
641               HasSubstr("MemoryBarrier: expected scope to be a 32-bit int"));
642 }
643 
TEST_F(ValidateBarriers,OpMemoryBarrierU64MemoryScope)644 TEST_F(ValidateBarriers, OpMemoryBarrierU64MemoryScope) {
645   const std::string body = R"(
646 OpMemoryBarrier %u64_1 %acquire_release_uniform_workgroup
647 )";
648 
649   CompileSuccessfully(GenerateShaderCode(body));
650   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
651   EXPECT_THAT(getDiagnosticString(),
652               HasSubstr("MemoryBarrier: expected scope to be a 32-bit int"));
653 }
654 
TEST_F(ValidateBarriers,OpMemoryBarrierFloatMemorySemantics)655 TEST_F(ValidateBarriers, OpMemoryBarrierFloatMemorySemantics) {
656   const std::string body = R"(
657 OpMemoryBarrier %device %f32_0
658 )";
659 
660   CompileSuccessfully(GenerateShaderCode(body));
661   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
662   EXPECT_THAT(
663       getDiagnosticString(),
664       HasSubstr("MemoryBarrier: expected Memory Semantics to be a 32-bit int"));
665 }
666 
TEST_F(ValidateBarriers,OpMemoryBarrierU64MemorySemantics)667 TEST_F(ValidateBarriers, OpMemoryBarrierU64MemorySemantics) {
668   const std::string body = R"(
669 OpMemoryBarrier %device %u64_0
670 )";
671 
672   CompileSuccessfully(GenerateShaderCode(body));
673   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
674   EXPECT_THAT(
675       getDiagnosticString(),
676       HasSubstr("MemoryBarrier: expected Memory Semantics to be a 32-bit int"));
677 }
678 
TEST_F(ValidateBarriers,OpMemoryBarrierVulkanMemoryScopeSubgroup)679 TEST_F(ValidateBarriers, OpMemoryBarrierVulkanMemoryScopeSubgroup) {
680   const std::string body = R"(
681 OpMemoryBarrier %subgroup %acquire_release_uniform_workgroup
682 )";
683 
684   CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
685   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
686   EXPECT_THAT(getDiagnosticString(),
687               AnyVUID("VUID-StandaloneSpirv-None-04638"));
688   EXPECT_THAT(
689       getDiagnosticString(),
690       HasSubstr("MemoryBarrier: in Vulkan 1.0 environment Memory Scope is "
691                 "limited to Device, Workgroup and Invocation"));
692 }
693 
TEST_F(ValidateBarriers,OpMemoryBarrierVulkan1p1MemoryScopeSubgroup)694 TEST_F(ValidateBarriers, OpMemoryBarrierVulkan1p1MemoryScopeSubgroup) {
695   const std::string body = R"(
696 OpMemoryBarrier %subgroup %acquire_release_uniform_workgroup
697 )";
698 
699   CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_1);
700   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
701 }
702 
TEST_F(ValidateBarriers,OpMemoryBarrierAcquireAndRelease)703 TEST_F(ValidateBarriers, OpMemoryBarrierAcquireAndRelease) {
704   const std::string body = R"(
705 OpMemoryBarrier %device %acquire_and_release_uniform
706 )";
707 
708   CompileSuccessfully(GenerateShaderCode(body));
709   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
710   EXPECT_THAT(getDiagnosticString(),
711               HasSubstr("MemoryBarrier: Memory Semantics can have at most one "
712                         "of the following bits set: Acquire, Release, "
713                         "AcquireRelease or SequentiallyConsistent"));
714 }
715 
TEST_F(ValidateBarriers,OpMemoryBarrierVulkanMemorySemanticsNone)716 TEST_F(ValidateBarriers, OpMemoryBarrierVulkanMemorySemanticsNone) {
717   const std::string body = R"(
718 OpMemoryBarrier %device %none
719 )";
720 
721   CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
722   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
723   EXPECT_THAT(getDiagnosticString(),
724               AnyVUID("VUID-StandaloneSpirv-OpMemoryBarrier-04732"));
725   EXPECT_THAT(
726       getDiagnosticString(),
727       HasSubstr("MemoryBarrier: Vulkan specification requires Memory Semantics "
728                 "to have one of the following bits set: Acquire, Release, "
729                 "AcquireRelease or SequentiallyConsistent"));
730 }
731 
TEST_F(ValidateBarriers,OpMemoryBarrierVulkanMemorySemanticsAcquire)732 TEST_F(ValidateBarriers, OpMemoryBarrierVulkanMemorySemanticsAcquire) {
733   const std::string body = R"(
734 OpMemoryBarrier %device %acquire
735 )";
736 
737   CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
738   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
739   EXPECT_THAT(getDiagnosticString(),
740               AnyVUID("VUID-StandaloneSpirv-OpMemoryBarrier-04733"));
741   EXPECT_THAT(getDiagnosticString(),
742               HasSubstr("MemoryBarrier: expected Memory Semantics to include a "
743                         "Vulkan-supported storage class"));
744 }
745 
TEST_F(ValidateBarriers,OpMemoryBarrierVulkanSubgroupStorageClass)746 TEST_F(ValidateBarriers, OpMemoryBarrierVulkanSubgroupStorageClass) {
747   const std::string body = R"(
748 OpMemoryBarrier %device %acquire_release_subgroup
749 )";
750 
751   CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
752   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
753   EXPECT_THAT(getDiagnosticString(),
754               AnyVUID("VUID-StandaloneSpirv-OpMemoryBarrier-04733"));
755   EXPECT_THAT(getDiagnosticString(),
756               HasSubstr("MemoryBarrier: expected Memory Semantics to include a "
757                         "Vulkan-supported storage class"));
758 }
759 
TEST_F(ValidateBarriers,OpNamedBarrierInitializeSuccess)760 TEST_F(ValidateBarriers, OpNamedBarrierInitializeSuccess) {
761   const std::string body = R"(
762 %barrier = OpNamedBarrierInitialize %named_barrier %u32_4
763 )";
764 
765   CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1);
766   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
767 }
768 
TEST_F(ValidateBarriers,OpNamedBarrierInitializeWrongResultType)769 TEST_F(ValidateBarriers, OpNamedBarrierInitializeWrongResultType) {
770   const std::string body = R"(
771 %barrier = OpNamedBarrierInitialize %u32 %u32_4
772 )";
773 
774   CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1);
775   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
776             ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
777   EXPECT_THAT(getDiagnosticString(),
778               HasSubstr("NamedBarrierInitialize: expected Result Type to be "
779                         "OpTypeNamedBarrier"));
780 }
781 
TEST_F(ValidateBarriers,OpNamedBarrierInitializeFloatSubgroupCount)782 TEST_F(ValidateBarriers, OpNamedBarrierInitializeFloatSubgroupCount) {
783   const std::string body = R"(
784 %barrier = OpNamedBarrierInitialize %named_barrier %f32_4
785 )";
786 
787   CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1);
788   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
789             ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
790   EXPECT_THAT(getDiagnosticString(),
791               HasSubstr("NamedBarrierInitialize: expected Subgroup Count to be "
792                         "a 32-bit int"));
793 }
794 
TEST_F(ValidateBarriers,OpNamedBarrierInitializeU64SubgroupCount)795 TEST_F(ValidateBarriers, OpNamedBarrierInitializeU64SubgroupCount) {
796   const std::string body = R"(
797 %barrier = OpNamedBarrierInitialize %named_barrier %u64_4
798 )";
799 
800   CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1);
801   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
802             ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
803   EXPECT_THAT(getDiagnosticString(),
804               HasSubstr("NamedBarrierInitialize: expected Subgroup Count to be "
805                         "a 32-bit int"));
806 }
807 
TEST_F(ValidateBarriers,OpMemoryNamedBarrierSuccess)808 TEST_F(ValidateBarriers, OpMemoryNamedBarrierSuccess) {
809   const std::string body = R"(
810 %barrier = OpNamedBarrierInitialize %named_barrier %u32_4
811 OpMemoryNamedBarrier %barrier %workgroup %acquire_release_workgroup
812 )";
813 
814   CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1);
815   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
816 }
817 
TEST_F(ValidateBarriers,OpMemoryNamedBarrierNotNamedBarrier)818 TEST_F(ValidateBarriers, OpMemoryNamedBarrierNotNamedBarrier) {
819   const std::string body = R"(
820 OpMemoryNamedBarrier %u32_1 %workgroup %acquire_release_workgroup
821 )";
822 
823   CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1);
824   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
825             ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
826   EXPECT_THAT(getDiagnosticString(),
827               HasSubstr("MemoryNamedBarrier: expected Named Barrier to be of "
828                         "type OpTypeNamedBarrier"));
829 }
830 
TEST_F(ValidateBarriers,OpMemoryNamedBarrierFloatMemoryScope)831 TEST_F(ValidateBarriers, OpMemoryNamedBarrierFloatMemoryScope) {
832   const std::string body = R"(
833 %barrier = OpNamedBarrierInitialize %named_barrier %u32_4
834 OpMemoryNamedBarrier %barrier %f32_1 %acquire_release_workgroup
835 )";
836 
837   CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1);
838   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
839             ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
840   EXPECT_THAT(
841       getDiagnosticString(),
842       HasSubstr("MemoryNamedBarrier: expected scope to be a 32-bit int"));
843 }
844 
TEST_F(ValidateBarriers,OpMemoryNamedBarrierFloatMemorySemantics)845 TEST_F(ValidateBarriers, OpMemoryNamedBarrierFloatMemorySemantics) {
846   const std::string body = R"(
847 %barrier = OpNamedBarrierInitialize %named_barrier %u32_4
848 OpMemoryNamedBarrier %barrier %workgroup %f32_0
849 )";
850 
851   CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1);
852   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
853             ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
854   EXPECT_THAT(
855       getDiagnosticString(),
856       HasSubstr(
857           "MemoryNamedBarrier: expected Memory Semantics to be a 32-bit int"));
858 }
859 
TEST_F(ValidateBarriers,OpMemoryNamedBarrierAcquireAndRelease)860 TEST_F(ValidateBarriers, OpMemoryNamedBarrierAcquireAndRelease) {
861   const std::string body = R"(
862 %barrier = OpNamedBarrierInitialize %named_barrier %u32_4
863 OpMemoryNamedBarrier %barrier %workgroup %acquire_and_release
864 )";
865 
866   CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1);
867   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
868             ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
869   EXPECT_THAT(getDiagnosticString(),
870               HasSubstr("MemoryNamedBarrier: Memory Semantics can have at most "
871                         "one of the following bits set: Acquire, Release, "
872                         "AcquireRelease or SequentiallyConsistent"));
873 }
874 
TEST_F(ValidateBarriers,TypeAsMemoryScope)875 TEST_F(ValidateBarriers, TypeAsMemoryScope) {
876   const std::string body = R"(
877 OpMemoryBarrier %u32 %u32_0
878 )";
879 
880   CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1);
881   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
882   EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand 5[%uint] cannot be a "
883                                                "type"));
884 }
885 
TEST_F(ValidateBarriers,OpControlBarrierVulkanMemoryModelBanSequentiallyConsistent)886 TEST_F(ValidateBarriers,
887        OpControlBarrierVulkanMemoryModelBanSequentiallyConsistent) {
888   const std::string text = R"(
889 OpCapability Shader
890 OpCapability VulkanMemoryModelKHR
891 OpExtension "SPV_KHR_vulkan_memory_model"
892 OpMemoryModel Logical VulkanKHR
893 OpEntryPoint Fragment %1 "func"
894 OpExecutionMode %1 OriginUpperLeft
895 %2 = OpTypeVoid
896 %3 = OpTypeInt 32 0
897 %4 = OpConstant %3 16
898 %5 = OpTypeFunction %2
899 %6 = OpConstant %3 5
900 %1 = OpFunction %2 None %5
901 %7 = OpLabel
902 OpControlBarrier %6 %6 %4
903 OpReturn
904 OpFunctionEnd
905 )";
906 
907   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
908   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
909             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
910   EXPECT_THAT(getDiagnosticString(),
911               HasSubstr("SequentiallyConsistent memory semantics cannot be "
912                         "used with the VulkanKHR memory model."));
913 }
914 
TEST_F(ValidateBarriers,OpMemoryBarrierVulkanMemoryModelBanSequentiallyConsistent)915 TEST_F(ValidateBarriers,
916        OpMemoryBarrierVulkanMemoryModelBanSequentiallyConsistent) {
917   const std::string text = R"(
918 OpCapability Shader
919 OpCapability VulkanMemoryModelKHR
920 OpExtension "SPV_KHR_vulkan_memory_model"
921 OpMemoryModel Logical VulkanKHR
922 OpEntryPoint Fragment %1 "func"
923 OpExecutionMode %1 OriginUpperLeft
924 %2 = OpTypeVoid
925 %3 = OpTypeInt 32 0
926 %4 = OpConstant %3 16
927 %5 = OpTypeFunction %2
928 %6 = OpConstant %3 5
929 %1 = OpFunction %2 None %5
930 %7 = OpLabel
931 OpMemoryBarrier %6 %4
932 OpReturn
933 OpFunctionEnd
934 )";
935 
936   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
937   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
938             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
939   EXPECT_THAT(getDiagnosticString(),
940               HasSubstr("SequentiallyConsistent memory semantics cannot be "
941                         "used with the VulkanKHR memory model."));
942 }
943 
TEST_F(ValidateBarriers,OutputMemoryKHRRequireVulkanMemoryModelKHR)944 TEST_F(ValidateBarriers, OutputMemoryKHRRequireVulkanMemoryModelKHR) {
945   const std::string text = R"(
946 OpCapability Shader
947 OpMemoryModel Logical GLSL450
948 OpEntryPoint Fragment %1 "func"
949 OpExecutionMode %1 OriginUpperLeft
950 %2 = OpTypeVoid
951 %3 = OpTypeInt 32 0
952 %semantics = OpConstant %3 4104
953 %5 = OpTypeFunction %2
954 %device = OpConstant %3 1
955 %1 = OpFunction %2 None %5
956 %7 = OpLabel
957 OpControlBarrier %device %device %semantics
958 OpReturn
959 OpFunctionEnd
960 )";
961 
962   CompileSuccessfully(text);
963   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
964   EXPECT_THAT(getDiagnosticString(),
965               HasSubstr("ControlBarrier: Memory Semantics OutputMemoryKHR "
966                         "requires capability VulkanMemoryModelKHR"));
967 }
968 
TEST_F(ValidateBarriers,MakeAvailableKHRRequireVulkanMemoryModelKHR)969 TEST_F(ValidateBarriers, MakeAvailableKHRRequireVulkanMemoryModelKHR) {
970   const std::string text = R"(
971 OpCapability Shader
972 OpMemoryModel Logical GLSL450
973 OpEntryPoint Fragment %1 "func"
974 OpExecutionMode %1 OriginUpperLeft
975 %2 = OpTypeVoid
976 %3 = OpTypeInt 32 0
977 %semantics = OpConstant %3 8264
978 %5 = OpTypeFunction %2
979 %device = OpConstant %3 1
980 %1 = OpFunction %2 None %5
981 %7 = OpLabel
982 OpControlBarrier %device %device %semantics
983 OpReturn
984 OpFunctionEnd
985 )";
986 
987   CompileSuccessfully(text);
988   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
989   EXPECT_THAT(getDiagnosticString(),
990               HasSubstr("ControlBarrier: Memory Semantics MakeAvailableKHR "
991                         "requires capability VulkanMemoryModelKHR"));
992 }
993 
TEST_F(ValidateBarriers,MakeVisibleKHRRequireVulkanMemoryModelKHR)994 TEST_F(ValidateBarriers, MakeVisibleKHRRequireVulkanMemoryModelKHR) {
995   const std::string text = R"(
996 OpCapability Shader
997 OpMemoryModel Logical GLSL450
998 OpEntryPoint Fragment %1 "func"
999 OpExecutionMode %1 OriginUpperLeft
1000 %2 = OpTypeVoid
1001 %3 = OpTypeInt 32 0
1002 %semantics = OpConstant %3 16456
1003 %5 = OpTypeFunction %2
1004 %device = OpConstant %3 1
1005 %1 = OpFunction %2 None %5
1006 %7 = OpLabel
1007 OpControlBarrier %device %device %semantics
1008 OpReturn
1009 OpFunctionEnd
1010 )";
1011 
1012   CompileSuccessfully(text);
1013   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1014   EXPECT_THAT(getDiagnosticString(),
1015               HasSubstr("ControlBarrier: Memory Semantics MakeVisibleKHR "
1016                         "requires capability VulkanMemoryModelKHR"));
1017 }
1018 
TEST_F(ValidateBarriers,MakeAvailableKHRRequiresReleaseSemantics)1019 TEST_F(ValidateBarriers, MakeAvailableKHRRequiresReleaseSemantics) {
1020   const std::string text = R"(
1021 OpCapability Shader
1022 OpCapability VulkanMemoryModelKHR
1023 OpExtension "SPV_KHR_vulkan_memory_model"
1024 OpMemoryModel Logical VulkanKHR
1025 OpEntryPoint Fragment %func "func"
1026 OpExecutionMode %func OriginUpperLeft
1027 %void = OpTypeVoid
1028 %int = OpTypeInt 32 0
1029 %workgroup = OpConstant %int 2
1030 %semantics = OpConstant %int 8448
1031 %functy = OpTypeFunction %void
1032 %func = OpFunction %void None %functy
1033 %1 = OpLabel
1034 OpControlBarrier %workgroup %workgroup %semantics
1035 OpReturn
1036 OpFunctionEnd
1037 )";
1038 
1039   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
1040   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1041             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1042   EXPECT_THAT(
1043       getDiagnosticString(),
1044       HasSubstr("ControlBarrier: MakeAvailableKHR Memory Semantics also "
1045                 "requires either Release or AcquireRelease Memory Semantics"));
1046 }
1047 
TEST_F(ValidateBarriers,MakeVisibleKHRRequiresAcquireSemantics)1048 TEST_F(ValidateBarriers, MakeVisibleKHRRequiresAcquireSemantics) {
1049   const std::string text = R"(
1050 OpCapability Shader
1051 OpCapability VulkanMemoryModelKHR
1052 OpExtension "SPV_KHR_vulkan_memory_model"
1053 OpMemoryModel Logical VulkanKHR
1054 OpEntryPoint Fragment %func "func"
1055 OpExecutionMode %func OriginUpperLeft
1056 %void = OpTypeVoid
1057 %int = OpTypeInt 32 0
1058 %workgroup = OpConstant %int 2
1059 %semantics = OpConstant %int 16640
1060 %functy = OpTypeFunction %void
1061 %func = OpFunction %void None %functy
1062 %1 = OpLabel
1063 OpControlBarrier %workgroup %workgroup %semantics
1064 OpReturn
1065 OpFunctionEnd
1066 )";
1067 
1068   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
1069   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1070             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1071   EXPECT_THAT(
1072       getDiagnosticString(),
1073       HasSubstr("ControlBarrier: MakeVisibleKHR Memory Semantics also requires "
1074                 "either Acquire or AcquireRelease Memory Semantics"));
1075 }
1076 
TEST_F(ValidateBarriers,MakeAvailableKHRRequiresStorageSemantics)1077 TEST_F(ValidateBarriers, MakeAvailableKHRRequiresStorageSemantics) {
1078   const std::string text = R"(
1079 OpCapability Shader
1080 OpCapability VulkanMemoryModelKHR
1081 OpExtension "SPV_KHR_vulkan_memory_model"
1082 OpMemoryModel Logical VulkanKHR
1083 OpEntryPoint Fragment %func "func"
1084 OpExecutionMode %func OriginUpperLeft
1085 %void = OpTypeVoid
1086 %int = OpTypeInt 32 0
1087 %workgroup = OpConstant %int 2
1088 %semantics = OpConstant %int 8196
1089 %functy = OpTypeFunction %void
1090 %func = OpFunction %void None %functy
1091 %1 = OpLabel
1092 OpMemoryBarrier %workgroup %semantics
1093 OpReturn
1094 OpFunctionEnd
1095 )";
1096 
1097   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
1098   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1099             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1100   EXPECT_THAT(getDiagnosticString(),
1101               HasSubstr("MemoryBarrier: expected Memory Semantics to include a "
1102                         "storage class"));
1103 }
1104 
TEST_F(ValidateBarriers,MakeVisibleKHRRequiresStorageSemantics)1105 TEST_F(ValidateBarriers, MakeVisibleKHRRequiresStorageSemantics) {
1106   const std::string text = R"(
1107 OpCapability Shader
1108 OpCapability VulkanMemoryModelKHR
1109 OpExtension "SPV_KHR_vulkan_memory_model"
1110 OpMemoryModel Logical VulkanKHR
1111 OpEntryPoint Fragment %func "func"
1112 OpExecutionMode %func OriginUpperLeft
1113 %void = OpTypeVoid
1114 %int = OpTypeInt 32 0
1115 %workgroup = OpConstant %int 2
1116 %semantics = OpConstant %int 16386
1117 %functy = OpTypeFunction %void
1118 %func = OpFunction %void None %functy
1119 %1 = OpLabel
1120 OpMemoryBarrier %workgroup %semantics
1121 OpReturn
1122 OpFunctionEnd
1123 )";
1124 
1125   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
1126   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1127             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1128   EXPECT_THAT(getDiagnosticString(),
1129               HasSubstr("MemoryBarrier: expected Memory Semantics to include a "
1130                         "storage class"));
1131 }
1132 
TEST_F(ValidateBarriers,SemanticsSpecConstantShader)1133 TEST_F(ValidateBarriers, SemanticsSpecConstantShader) {
1134   const std::string spirv = R"(
1135 OpCapability Shader
1136 OpMemoryModel Logical GLSL450
1137 OpEntryPoint Fragment %func "func"
1138 OpExecutionMode %func OriginUpperLeft
1139 %void = OpTypeVoid
1140 %int = OpTypeInt 32 0
1141 %ptr_int_workgroup = OpTypePointer Workgroup %int
1142 %var = OpVariable %ptr_int_workgroup Workgroup
1143 %voidfn = OpTypeFunction %void
1144 %spec_const = OpSpecConstant %int 0
1145 %workgroup = OpConstant %int 2
1146 %func = OpFunction %void None %voidfn
1147 %entry = OpLabel
1148 OpMemoryBarrier %workgroup %spec_const
1149 OpReturn
1150 OpFunctionEnd
1151 )";
1152 
1153   CompileSuccessfully(spirv);
1154   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1155   EXPECT_THAT(getDiagnosticString(),
1156               HasSubstr("Memory Semantics ids must be OpConstant when Shader "
1157                         "capability is present"));
1158 }
1159 
TEST_F(ValidateBarriers,SemanticsSpecConstantKernel)1160 TEST_F(ValidateBarriers, SemanticsSpecConstantKernel) {
1161   const std::string spirv = R"(
1162 OpCapability Kernel
1163 OpCapability Linkage
1164 OpMemoryModel Logical OpenCL
1165 %void = OpTypeVoid
1166 %int = OpTypeInt 32 0
1167 %ptr_int_workgroup = OpTypePointer Workgroup %int
1168 %var = OpVariable %ptr_int_workgroup Workgroup
1169 %voidfn = OpTypeFunction %void
1170 %spec_const = OpSpecConstant %int 0
1171 %workgroup = OpConstant %int 2
1172 %func = OpFunction %void None %voidfn
1173 %entry = OpLabel
1174 OpMemoryBarrier %workgroup %spec_const
1175 OpReturn
1176 OpFunctionEnd
1177 )";
1178 
1179   CompileSuccessfully(spirv);
1180   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1181 }
1182 
TEST_F(ValidateBarriers,ScopeSpecConstantShader)1183 TEST_F(ValidateBarriers, ScopeSpecConstantShader) {
1184   const std::string spirv = R"(
1185 OpCapability Shader
1186 OpMemoryModel Logical GLSL450
1187 OpEntryPoint Fragment %func "func"
1188 OpExecutionMode %func OriginUpperLeft
1189 %void = OpTypeVoid
1190 %int = OpTypeInt 32 0
1191 %ptr_int_workgroup = OpTypePointer Workgroup %int
1192 %var = OpVariable %ptr_int_workgroup Workgroup
1193 %voidfn = OpTypeFunction %void
1194 %spec_const = OpSpecConstant %int 0
1195 %relaxed = OpConstant %int 0
1196 %func = OpFunction %void None %voidfn
1197 %entry = OpLabel
1198 OpMemoryBarrier %spec_const %relaxed
1199 OpReturn
1200 OpFunctionEnd
1201 )";
1202 
1203   CompileSuccessfully(spirv);
1204   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1205   EXPECT_THAT(getDiagnosticString(),
1206               HasSubstr("Scope ids must be OpConstant when Shader "
1207                         "capability is present"));
1208 }
1209 
TEST_F(ValidateBarriers,ScopeSpecConstantKernel)1210 TEST_F(ValidateBarriers, ScopeSpecConstantKernel) {
1211   const std::string spirv = R"(
1212 OpCapability Kernel
1213 OpCapability Linkage
1214 OpMemoryModel Logical OpenCL
1215 %void = OpTypeVoid
1216 %int = OpTypeInt 32 0
1217 %ptr_int_workgroup = OpTypePointer Workgroup %int
1218 %var = OpVariable %ptr_int_workgroup Workgroup
1219 %voidfn = OpTypeFunction %void
1220 %spec_const = OpSpecConstant %int 0
1221 %relaxed = OpConstant %int 0
1222 %func = OpFunction %void None %voidfn
1223 %entry = OpLabel
1224 OpMemoryBarrier %spec_const %relaxed
1225 OpReturn
1226 OpFunctionEnd
1227 )";
1228 
1229   CompileSuccessfully(spirv);
1230   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1231 }
1232 
TEST_F(ValidateBarriers,VulkanMemoryModelDeviceScopeBad)1233 TEST_F(ValidateBarriers, VulkanMemoryModelDeviceScopeBad) {
1234   const std::string text = R"(
1235 OpCapability Shader
1236 OpCapability VulkanMemoryModelKHR
1237 OpExtension "SPV_KHR_vulkan_memory_model"
1238 OpMemoryModel Logical VulkanKHR
1239 OpEntryPoint Fragment %func "func"
1240 OpExecutionMode %func OriginUpperLeft
1241 %void = OpTypeVoid
1242 %int = OpTypeInt 32 0
1243 %device = OpConstant %int 1
1244 %semantics = OpConstant %int 0
1245 %functy = OpTypeFunction %void
1246 %func = OpFunction %void None %functy
1247 %1 = OpLabel
1248 OpMemoryBarrier %device %semantics
1249 OpReturn
1250 OpFunctionEnd
1251 )";
1252 
1253   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
1254   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1255             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1256   EXPECT_THAT(
1257       getDiagnosticString(),
1258       HasSubstr("Use of device scope with VulkanKHR memory model requires the "
1259                 "VulkanMemoryModelDeviceScopeKHR capability"));
1260 }
1261 
TEST_F(ValidateBarriers,VulkanMemoryModelDeviceScopeGood)1262 TEST_F(ValidateBarriers, VulkanMemoryModelDeviceScopeGood) {
1263   const std::string text = R"(
1264 OpCapability Shader
1265 OpCapability VulkanMemoryModelKHR
1266 OpCapability VulkanMemoryModelDeviceScopeKHR
1267 OpExtension "SPV_KHR_vulkan_memory_model"
1268 OpMemoryModel Logical VulkanKHR
1269 OpEntryPoint Fragment %func "func"
1270 OpExecutionMode %func OriginUpperLeft
1271 %void = OpTypeVoid
1272 %int = OpTypeInt 32 0
1273 %device = OpConstant %int 1
1274 %semantics = OpConstant %int 0
1275 %functy = OpTypeFunction %void
1276 %func = OpFunction %void None %functy
1277 %1 = OpLabel
1278 OpMemoryBarrier %device %semantics
1279 OpReturn
1280 OpFunctionEnd
1281 )";
1282 
1283   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
1284   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1285 }
1286 
TEST_F(ValidateBarriers,VolatileMemoryBarrier)1287 TEST_F(ValidateBarriers, VolatileMemoryBarrier) {
1288   const std::string text = R"(
1289 OpCapability Shader
1290 OpCapability VulkanMemoryModelKHR
1291 OpCapability VulkanMemoryModelDeviceScopeKHR
1292 OpCapability Linkage
1293 OpExtension "SPV_KHR_vulkan_memory_model"
1294 OpMemoryModel Logical VulkanKHR
1295 %void = OpTypeVoid
1296 %int = OpTypeInt 32 0
1297 %device = OpConstant %int 1
1298 %semantics = OpConstant %int 32768
1299 %functy = OpTypeFunction %void
1300 %func = OpFunction %void None %functy
1301 %1 = OpLabel
1302 OpMemoryBarrier %device %semantics
1303 OpReturn
1304 OpFunctionEnd
1305 )";
1306 
1307   CompileSuccessfully(text);
1308   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1309   EXPECT_THAT(getDiagnosticString(),
1310               HasSubstr("Memory Semantics Volatile can only be used with "
1311                         "atomic instructions"));
1312 }
1313 
TEST_F(ValidateBarriers,VolatileControlBarrier)1314 TEST_F(ValidateBarriers, VolatileControlBarrier) {
1315   const std::string text = R"(
1316 OpCapability Shader
1317 OpCapability VulkanMemoryModelKHR
1318 OpCapability VulkanMemoryModelDeviceScopeKHR
1319 OpCapability Linkage
1320 OpExtension "SPV_KHR_vulkan_memory_model"
1321 OpMemoryModel Logical VulkanKHR
1322 %void = OpTypeVoid
1323 %int = OpTypeInt 32 0
1324 %device = OpConstant %int 1
1325 %semantics = OpConstant %int 32768
1326 %functy = OpTypeFunction %void
1327 %func = OpFunction %void None %functy
1328 %1 = OpLabel
1329 OpControlBarrier %device %device %semantics
1330 OpReturn
1331 OpFunctionEnd
1332 )";
1333 
1334   CompileSuccessfully(text);
1335   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1336   EXPECT_THAT(getDiagnosticString(),
1337               HasSubstr("Memory Semantics Volatile can only be used with "
1338                         "atomic instructions"));
1339 }
1340 
TEST_F(ValidateBarriers,CooperativeMatrixSpecConstantVolatile)1341 TEST_F(ValidateBarriers, CooperativeMatrixSpecConstantVolatile) {
1342   const std::string text = R"(
1343 OpCapability Shader
1344 OpCapability VulkanMemoryModelKHR
1345 OpCapability VulkanMemoryModelDeviceScopeKHR
1346 OpCapability CooperativeMatrixNV
1347 OpCapability Linkage
1348 OpExtension "SPV_KHR_vulkan_memory_model"
1349 OpExtension "SPV_NV_cooperative_matrix"
1350 OpMemoryModel Logical VulkanKHR
1351 %void = OpTypeVoid
1352 %int = OpTypeInt 32 0
1353 %device = OpConstant %int 1
1354 %semantics = OpSpecConstant %int 32768
1355 %functy = OpTypeFunction %void
1356 %func = OpFunction %void None %functy
1357 %1 = OpLabel
1358 OpControlBarrier %device %device %semantics
1359 OpReturn
1360 OpFunctionEnd
1361 )";
1362 
1363   CompileSuccessfully(text);
1364   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1365 }
1366 
TEST_F(ValidateBarriers,CooperativeMatrixNonConstantSemantics)1367 TEST_F(ValidateBarriers, CooperativeMatrixNonConstantSemantics) {
1368   const std::string text = R"(
1369 OpCapability Shader
1370 OpCapability VulkanMemoryModelKHR
1371 OpCapability VulkanMemoryModelDeviceScopeKHR
1372 OpCapability CooperativeMatrixNV
1373 OpCapability Linkage
1374 OpExtension "SPV_KHR_vulkan_memory_model"
1375 OpExtension "SPV_NV_cooperative_matrix"
1376 OpMemoryModel Logical VulkanKHR
1377 %void = OpTypeVoid
1378 %int = OpTypeInt 32 0
1379 %device = OpConstant %int 1
1380 %semantics = OpUndef %int
1381 %functy = OpTypeFunction %void
1382 %func = OpFunction %void None %functy
1383 %1 = OpLabel
1384 OpControlBarrier %device %device %semantics
1385 OpReturn
1386 OpFunctionEnd
1387 )";
1388 
1389   CompileSuccessfully(text);
1390   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1391   EXPECT_THAT(getDiagnosticString(),
1392               HasSubstr("Memory Semantics must be a constant instruction when "
1393                         "CooperativeMatrixNV capability is present"));
1394 }
1395 
TEST_F(ValidateBarriers,OpMemoryBarrierShaderCallRayGenSuccess)1396 TEST_F(ValidateBarriers, OpMemoryBarrierShaderCallRayGenSuccess) {
1397   const std::string body =
1398       "OpMemoryBarrier %shadercall %release_uniform_workgroup";
1399 
1400   CompileSuccessfully(GenerateShaderCodeImpl(body,
1401                                              // capabilities_and_extensions
1402                                              R"(
1403                                                OpCapability VulkanMemoryModelKHR
1404                                                OpCapability RayTracingKHR
1405                                                OpExtension "SPV_KHR_vulkan_memory_model"
1406                                                OpExtension "SPV_KHR_ray_tracing"
1407                                              )",
1408                                              // definitions
1409                                              "",
1410                                              // execution_model
1411                                              "RayGenerationKHR",
1412                                              // memory_model
1413                                              "OpMemoryModel Logical VulkanKHR"),
1414                       SPV_ENV_VULKAN_1_1);
1415 
1416   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
1417 }
1418 
TEST_F(ValidateBarriers,OpMemoryBarrierShaderCallComputeFailure)1419 TEST_F(ValidateBarriers, OpMemoryBarrierShaderCallComputeFailure) {
1420   const std::string body =
1421       "OpMemoryBarrier %shadercall %release_uniform_workgroup";
1422 
1423   CompileSuccessfully(GenerateShaderCodeImpl(body,
1424                                              // capabilities_and_extensions
1425                                              R"(
1426                                                OpCapability VulkanMemoryModelKHR
1427                                                OpExtension "SPV_KHR_vulkan_memory_model"
1428                                              )",
1429                                              // definitions
1430                                              "",
1431                                              // execution_model
1432                                              "GLCompute",
1433                                              // memory_model
1434                                              "OpMemoryModel Logical VulkanKHR"),
1435                       SPV_ENV_VULKAN_1_1);
1436 
1437   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
1438   EXPECT_THAT(getDiagnosticString(),
1439               AnyVUID("VUID-StandaloneSpirv-None-04640"));
1440   EXPECT_THAT(
1441       getDiagnosticString(),
1442       HasSubstr(
1443           "ShaderCallKHR Memory Scope requires a ray tracing execution model"));
1444 }
1445 
TEST_F(ValidateBarriers,OpControlBarrierShaderCallRayGenFailure)1446 TEST_F(ValidateBarriers, OpControlBarrierShaderCallRayGenFailure) {
1447   const std::string body = "OpControlBarrier %shadercall %shadercall %none";
1448 
1449   CompileSuccessfully(GenerateShaderCodeImpl(body,
1450                                              // capabilities_and_extensions
1451                                              R"(
1452                                                OpCapability VulkanMemoryModelKHR
1453                                                OpCapability RayTracingKHR
1454                                                OpExtension "SPV_KHR_vulkan_memory_model"
1455                                                OpExtension "SPV_KHR_ray_tracing"
1456                                              )",
1457                                              // definitions
1458                                              "",
1459                                              // execution_model
1460                                              "RayGenerationKHR",
1461                                              // memory_model
1462                                              "OpMemoryModel Logical VulkanKHR"),
1463                       SPV_ENV_VULKAN_1_1);
1464 
1465   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_1));
1466   EXPECT_THAT(getDiagnosticString(),
1467               HasSubstr("in Vulkan environment Execution Scope is limited to "
1468                         "Workgroup and Subgroup"));
1469 }
1470 
1471 }  // namespace
1472 }  // namespace val
1473 }  // namespace spvtools
1474