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