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