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