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