1 // Copyright (c) 2017 Google Inc.
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 ValidateAtomics = spvtest::ValidateBase<bool>;
30
GenerateShaderCodeImpl(const std::string & body,const std::string & capabilities_and_extensions,const std::string & definitions,const std::string & memory_model,const std::string & execution)31 std::string GenerateShaderCodeImpl(
32 const std::string& body, const std::string& capabilities_and_extensions,
33 const std::string& definitions, const std::string& memory_model,
34 const std::string& execution) {
35 std::ostringstream ss;
36 ss << R"(
37 OpCapability Shader
38 )";
39 ss << capabilities_and_extensions;
40 ss << "OpMemoryModel Logical " << memory_model << "\n";
41 ss << execution;
42 ss << R"(
43 %void = OpTypeVoid
44 %func = OpTypeFunction %void
45 %bool = OpTypeBool
46 %f32 = OpTypeFloat 32
47 %u32 = OpTypeInt 32 0
48 %f32vec4 = OpTypeVector %f32 4
49
50 %f32_0 = OpConstant %f32 0
51 %f32_1 = OpConstant %f32 1
52 %u32_0 = OpConstant %u32 0
53 %u32_1 = OpConstant %u32 1
54 %f32vec4_0000 = OpConstantComposite %f32vec4 %f32_0 %f32_0 %f32_0 %f32_0
55
56 %cross_device = OpConstant %u32 0
57 %device = OpConstant %u32 1
58 %workgroup = OpConstant %u32 2
59 %subgroup = OpConstant %u32 3
60 %invocation = OpConstant %u32 4
61 %queuefamily = OpConstant %u32 5
62
63 %relaxed = OpConstant %u32 0
64 %acquire = OpConstant %u32 2
65 %release = OpConstant %u32 4
66 %acquire_release = OpConstant %u32 8
67 %acquire_and_release = OpConstant %u32 6
68 %sequentially_consistent = OpConstant %u32 16
69 %acquire_release_uniform_workgroup = OpConstant %u32 328
70
71 %f32_ptr = OpTypePointer Workgroup %f32
72 %f32_var = OpVariable %f32_ptr Workgroup
73
74 %u32_ptr = OpTypePointer Workgroup %u32
75 %u32_var = OpVariable %u32_ptr Workgroup
76
77 %f32vec4_ptr = OpTypePointer Workgroup %f32vec4
78 %f32vec4_var = OpVariable %f32vec4_ptr Workgroup
79
80 %f32_ptr_function = OpTypePointer Function %f32
81 )";
82 ss << definitions;
83 ss << R"(
84 %main = OpFunction %void None %func
85 %main_entry = OpLabel
86 )";
87 ss << body;
88 ss << R"(
89 OpReturn
90 OpFunctionEnd)";
91
92 return ss.str();
93 }
94
GenerateShaderCode(const std::string & body,const std::string & capabilities_and_extensions="",const std::string & extra_defs="",const std::string & memory_model="GLSL450")95 std::string GenerateShaderCode(
96 const std::string& body,
97 const std::string& capabilities_and_extensions = "",
98 const std::string& extra_defs = "",
99 const std::string& memory_model = "GLSL450") {
100 const std::string execution = R"(
101 OpEntryPoint Fragment %main "main"
102 OpExecutionMode %main OriginUpperLeft
103 )";
104 const std::string definitions = R"(
105 %u64 = OpTypeInt 64 0
106 %s64 = OpTypeInt 64 1
107
108 %u64_1 = OpConstant %u64 1
109 %s64_1 = OpConstant %s64 1
110
111 %u64_ptr = OpTypePointer Workgroup %u64
112 %s64_ptr = OpTypePointer Workgroup %s64
113 %u64_var = OpVariable %u64_ptr Workgroup
114 %s64_var = OpVariable %s64_ptr Workgroup
115 )";
116 return GenerateShaderCodeImpl(
117 body, "OpCapability Int64\n" + capabilities_and_extensions,
118 definitions + extra_defs, memory_model, execution);
119 }
120
GenerateShaderComputeCode(const std::string & body,const std::string & capabilities_and_extensions="",const std::string & extra_defs="",const std::string & memory_model="GLSL450")121 std::string GenerateShaderComputeCode(
122 const std::string& body,
123 const std::string& capabilities_and_extensions = "",
124 const std::string& extra_defs = "",
125 const std::string& memory_model = "GLSL450") {
126 const std::string execution = R"(
127 OpEntryPoint GLCompute %main "main"
128 OpExecutionMode %main LocalSize 32 1 1
129 )";
130 const std::string definitions = R"(
131 %u64 = OpTypeInt 64 0
132 %s64 = OpTypeInt 64 1
133
134 %u64_1 = OpConstant %u64 1
135 %s64_1 = OpConstant %s64 1
136
137 %u64_ptr = OpTypePointer Workgroup %u64
138 %s64_ptr = OpTypePointer Workgroup %s64
139 %u64_var = OpVariable %u64_ptr Workgroup
140 %s64_var = OpVariable %s64_ptr Workgroup
141 )";
142 return GenerateShaderCodeImpl(
143 body, "OpCapability Int64\n" + capabilities_and_extensions,
144 definitions + extra_defs, memory_model, execution);
145 }
146
GenerateKernelCode(const std::string & body,const std::string & capabilities_and_extensions="")147 std::string GenerateKernelCode(
148 const std::string& body,
149 const std::string& capabilities_and_extensions = "") {
150 std::ostringstream ss;
151 ss << R"(
152 OpCapability Addresses
153 OpCapability Kernel
154 OpCapability Linkage
155 OpCapability Int64
156 )";
157
158 ss << capabilities_and_extensions;
159 ss << R"(
160 OpMemoryModel Physical32 OpenCL
161 %void = OpTypeVoid
162 %func = OpTypeFunction %void
163 %bool = OpTypeBool
164 %f32 = OpTypeFloat 32
165 %u32 = OpTypeInt 32 0
166 %u64 = OpTypeInt 64 0
167 %f32vec4 = OpTypeVector %f32 4
168
169 %f32_0 = OpConstant %f32 0
170 %f32_1 = OpConstant %f32 1
171 %u32_0 = OpConstant %u32 0
172 %u32_1 = OpConstant %u32 1
173 %u64_1 = OpConstant %u64 1
174 %f32vec4_0000 = OpConstantComposite %f32vec4 %f32_0 %f32_0 %f32_0 %f32_0
175
176 %cross_device = OpConstant %u32 0
177 %device = OpConstant %u32 1
178 %workgroup = OpConstant %u32 2
179 %subgroup = OpConstant %u32 3
180 %invocation = OpConstant %u32 4
181
182 %relaxed = OpConstant %u32 0
183 %acquire = OpConstant %u32 2
184 %release = OpConstant %u32 4
185 %acquire_release = OpConstant %u32 8
186 %acquire_and_release = OpConstant %u32 6
187 %sequentially_consistent = OpConstant %u32 16
188 %acquire_release_uniform_workgroup = OpConstant %u32 328
189 %acquire_release_atomic_counter_workgroup = OpConstant %u32 1288
190
191 %f32_ptr = OpTypePointer Workgroup %f32
192 %f32_var = OpVariable %f32_ptr Workgroup
193
194 %u32_ptr = OpTypePointer Workgroup %u32
195 %u32_var = OpVariable %u32_ptr Workgroup
196
197 %u64_ptr = OpTypePointer Workgroup %u64
198 %u64_var = OpVariable %u64_ptr Workgroup
199
200 %f32vec4_ptr = OpTypePointer Workgroup %f32vec4
201 %f32vec4_var = OpVariable %f32vec4_ptr Workgroup
202
203 %f32_ptr_function = OpTypePointer Function %f32
204 %f32_ptr_uniformconstant = OpTypePointer UniformConstant %f32
205 %f32_uc_var = OpVariable %f32_ptr_uniformconstant UniformConstant
206
207 %f32_ptr_image = OpTypePointer Image %f32
208 %f32_im_var = OpVariable %f32_ptr_image Image
209
210 %main = OpFunction %void None %func
211 %main_entry = OpLabel
212 )";
213
214 ss << body;
215
216 ss << R"(
217 OpReturn
218 OpFunctionEnd)";
219
220 return ss.str();
221 }
222
TEST_F(ValidateAtomics,AtomicLoadShaderSuccess)223 TEST_F(ValidateAtomics, AtomicLoadShaderSuccess) {
224 const std::string body = R"(
225 %val1 = OpAtomicLoad %u32 %u32_var %device %relaxed
226 %val2 = OpAtomicLoad %u32 %u32_var %workgroup %acquire
227 )";
228
229 CompileSuccessfully(GenerateShaderCode(body));
230 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
231 }
232
TEST_F(ValidateAtomics,AtomicLoadKernelSuccess)233 TEST_F(ValidateAtomics, AtomicLoadKernelSuccess) {
234 const std::string body = R"(
235 %val1 = OpAtomicLoad %f32 %f32_var %device %relaxed
236 %val2 = OpAtomicLoad %u32 %u32_var %workgroup %sequentially_consistent
237 )";
238
239 CompileSuccessfully(GenerateKernelCode(body));
240 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
241 }
242
TEST_F(ValidateAtomics,AtomicLoadInt64ShaderSuccess)243 TEST_F(ValidateAtomics, AtomicLoadInt64ShaderSuccess) {
244 const std::string body = R"(
245 %val1 = OpAtomicLoad %u64 %u64_var %subgroup %sequentially_consistent
246 )";
247
248 CompileSuccessfully(GenerateShaderCode(body, "OpCapability Int64Atomics\n"));
249 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
250 }
251
TEST_F(ValidateAtomics,AtomicLoadInt64KernelSuccess)252 TEST_F(ValidateAtomics, AtomicLoadInt64KernelSuccess) {
253 const std::string body = R"(
254 %val1 = OpAtomicLoad %u64 %u64_var %subgroup %acquire
255 )";
256
257 CompileSuccessfully(GenerateKernelCode(body, "OpCapability Int64Atomics\n"));
258 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
259 }
260
TEST_F(ValidateAtomics,AtomicLoadInt32VulkanSuccess)261 TEST_F(ValidateAtomics, AtomicLoadInt32VulkanSuccess) {
262 const std::string body = R"(
263 %val1 = OpAtomicLoad %u32 %u32_var %device %relaxed
264 %val2 = OpAtomicLoad %u32 %u32_var %workgroup %acquire
265 %val3 = OpAtomicLoad %u32 %u32_var %invocation %relaxed
266 )";
267
268 CompileSuccessfully(GenerateShaderComputeCode(body), SPV_ENV_VULKAN_1_0);
269 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
270 }
271
TEST_F(ValidateAtomics,AtomicLoadVulkanWrongStorageClass)272 TEST_F(ValidateAtomics, AtomicLoadVulkanWrongStorageClass) {
273 const std::string body = R"(
274 %val1 = OpAtomicLoad %u32 %u32_var %device %relaxed
275 )";
276
277 CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
278 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
279 EXPECT_THAT(getDiagnosticString(),
280 AnyVUID("VUID-StandaloneSpirv-None-04645"));
281 EXPECT_THAT(
282 getDiagnosticString(),
283 HasSubstr("in Vulkan evironment, Workgroup Storage Class is limited to "
284 "MeshNV, TaskNV, and GLCompute execution model"));
285 }
286
TEST_F(ValidateAtomics,AtomicAddIntVulkanWrongType1)287 TEST_F(ValidateAtomics, AtomicAddIntVulkanWrongType1) {
288 const std::string body = R"(
289 %val1 = OpAtomicIAdd %f32 %f32_var %device %relaxed %f32_1
290 )";
291
292 CompileSuccessfully(GenerateShaderCode(body));
293 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
294 EXPECT_THAT(getDiagnosticString(),
295 HasSubstr("AtomicIAdd: "
296 "expected Result Type to be integer scalar type"));
297 }
298
TEST_F(ValidateAtomics,AtomicAddIntVulkanWrongType2)299 TEST_F(ValidateAtomics, AtomicAddIntVulkanWrongType2) {
300 const std::string body = R"(
301 %val1 = OpAtomicIAdd %f32vec4 %f32vec4_var %device %relaxed %f32_1
302 )";
303
304 CompileSuccessfully(GenerateShaderCode(body));
305 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
306 EXPECT_THAT(getDiagnosticString(),
307 HasSubstr("AtomicIAdd: "
308 "expected Result Type to be integer scalar type"));
309 }
310
TEST_F(ValidateAtomics,AtomicAddFloatVulkan)311 TEST_F(ValidateAtomics, AtomicAddFloatVulkan) {
312 const std::string body = R"(
313 %val1 = OpAtomicFAddEXT %f32 %f32_var %device %relaxed %f32_1
314 )";
315
316 CompileSuccessfully(GenerateShaderCode(body));
317 ASSERT_EQ(SPV_ERROR_INVALID_CAPABILITY, ValidateInstructions());
318 EXPECT_THAT(
319 getDiagnosticString(),
320 HasSubstr("Opcode AtomicFAddEXT requires one of these capabilities: "
321 "AtomicFloat32AddEXT AtomicFloat64AddEXT AtomicFloat16AddEXT"));
322 }
323
TEST_F(ValidateAtomics,AtomicMinFloatVulkan)324 TEST_F(ValidateAtomics, AtomicMinFloatVulkan) {
325 const std::string body = R"(
326 %val1 = OpAtomicFMinEXT %f32 %f32_var %device %relaxed %f32_1
327 )";
328
329 CompileSuccessfully(GenerateShaderCode(body));
330 ASSERT_EQ(SPV_ERROR_INVALID_CAPABILITY, ValidateInstructions());
331 EXPECT_THAT(
332 getDiagnosticString(),
333 HasSubstr("Opcode AtomicFMinEXT requires one of these capabilities: "
334 "AtomicFloat32MinMaxEXT AtomicFloat64MinMaxEXT AtomicFloat16MinMaxEXT"));
335 }
336
TEST_F(ValidateAtomics,AtomicMaxFloatVulkan)337 TEST_F(ValidateAtomics, AtomicMaxFloatVulkan) {
338 const std::string body = R"(
339 %val1 = OpAtomicFMaxEXT %f32 %f32_var %device %relaxed %f32_1
340 )";
341
342 CompileSuccessfully(GenerateShaderCode(body));
343 ASSERT_EQ(SPV_ERROR_INVALID_CAPABILITY, ValidateInstructions());
344 EXPECT_THAT(
345 getDiagnosticString(),
346 HasSubstr("Opcode AtomicFMaxEXT requires one of these capabilities: "
347 "AtomicFloat32MinMaxEXT AtomicFloat64MinMaxEXT AtomicFloat16MinMaxEXT"));
348 }
349
TEST_F(ValidateAtomics,AtomicAddFloatVulkanWrongType1)350 TEST_F(ValidateAtomics, AtomicAddFloatVulkanWrongType1) {
351 const std::string body = R"(
352 %val1 = OpAtomicFAddEXT %f32vec4 %f32vec4_var %device %relaxed %f32_1
353 )";
354 const std::string extra = R"(
355 OpCapability AtomicFloat32AddEXT
356 OpExtension "SPV_EXT_shader_atomic_float_add"
357 )";
358
359 CompileSuccessfully(GenerateShaderCode(body, extra), SPV_ENV_VULKAN_1_0);
360 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
361 EXPECT_THAT(getDiagnosticString(),
362 HasSubstr("AtomicFAddEXT: "
363 "expected Result Type to be float scalar type"));
364 }
365
TEST_F(ValidateAtomics,AtomicMinFloatVulkanWrongType1)366 TEST_F(ValidateAtomics, AtomicMinFloatVulkanWrongType1) {
367 const std::string body = R"(
368 %val1 = OpAtomicFMinEXT %f32vec4 %f32vec4_var %device %relaxed %f32_1
369 )";
370 const std::string extra = R"(
371 OpCapability AtomicFloat32MinMaxEXT
372 OpExtension "SPV_EXT_shader_atomic_float_min_max"
373 )";
374
375 CompileSuccessfully(GenerateShaderCode(body, extra), SPV_ENV_VULKAN_1_0);
376 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
377 EXPECT_THAT(getDiagnosticString(),
378 HasSubstr("AtomicFMinEXT: "
379 "expected Result Type to be float scalar type"));
380 }
381
TEST_F(ValidateAtomics,AtomicMaxFloatVulkanWrongType1)382 TEST_F(ValidateAtomics, AtomicMaxFloatVulkanWrongType1) {
383 const std::string body = R"(
384 %val1 = OpAtomicFMaxEXT %f32vec4 %f32vec4_var %device %relaxed %f32_1
385 )";
386 const std::string extra = R"(
387 OpCapability AtomicFloat32MinMaxEXT
388 OpExtension "SPV_EXT_shader_atomic_float_min_max"
389 )";
390
391 CompileSuccessfully(GenerateShaderCode(body, extra), SPV_ENV_VULKAN_1_0);
392 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
393 EXPECT_THAT(getDiagnosticString(),
394 HasSubstr("AtomicFMaxEXT: "
395 "expected Result Type to be float scalar type"));
396 }
397
TEST_F(ValidateAtomics,AtomicAddFloatVulkanWrongType2)398 TEST_F(ValidateAtomics, AtomicAddFloatVulkanWrongType2) {
399 const std::string body = R"(
400 %val1 = OpAtomicFAddEXT %u32 %u32_var %device %relaxed %u32_1
401 )";
402 const std::string extra = R"(
403 OpCapability AtomicFloat32AddEXT
404 OpExtension "SPV_EXT_shader_atomic_float_add"
405 )";
406
407 CompileSuccessfully(GenerateShaderCode(body, extra), SPV_ENV_VULKAN_1_0);
408 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
409 EXPECT_THAT(getDiagnosticString(),
410 HasSubstr("AtomicFAddEXT: "
411 "expected Result Type to be float scalar type"));
412 }
413
TEST_F(ValidateAtomics,AtomicMinFloatVulkanWrongType2)414 TEST_F(ValidateAtomics, AtomicMinFloatVulkanWrongType2) {
415 const std::string body = R"(
416 %val1 = OpAtomicFMinEXT %u32 %u32_var %device %relaxed %u32_1
417 )";
418 const std::string extra = R"(
419 OpCapability AtomicFloat32MinMaxEXT
420 OpExtension "SPV_EXT_shader_atomic_float_min_max"
421 )";
422
423 CompileSuccessfully(GenerateShaderCode(body, extra), SPV_ENV_VULKAN_1_0);
424 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
425 EXPECT_THAT(getDiagnosticString(),
426 HasSubstr("AtomicFMinEXT: "
427 "expected Result Type to be float scalar type"));
428 }
429
TEST_F(ValidateAtomics,AtomicMaxFloatVulkanWrongType2)430 TEST_F(ValidateAtomics, AtomicMaxFloatVulkanWrongType2) {
431 const std::string body = R"(
432 %val1 = OpAtomicFMaxEXT %u32 %u32_var %device %relaxed %u32_1
433 )";
434 const std::string extra = R"(
435 OpCapability AtomicFloat32MinMaxEXT
436 OpExtension "SPV_EXT_shader_atomic_float_min_max"
437 )";
438
439 CompileSuccessfully(GenerateShaderCode(body, extra), SPV_ENV_VULKAN_1_0);
440 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
441 EXPECT_THAT(getDiagnosticString(),
442 HasSubstr("AtomicFMaxEXT: "
443 "expected Result Type to be float scalar type"));
444 }
445
TEST_F(ValidateAtomics,AtomicAddFloatVulkanWrongType3)446 TEST_F(ValidateAtomics, AtomicAddFloatVulkanWrongType3) {
447 const std::string body = R"(
448 %val1 = OpAtomicFAddEXT %u64 %u64_var %device %relaxed %u64_1
449 )";
450 const std::string extra = R"(
451 OpCapability AtomicFloat32AddEXT
452 OpExtension "SPV_EXT_shader_atomic_float_add"
453 )";
454
455 CompileSuccessfully(GenerateShaderCode(body, extra), SPV_ENV_VULKAN_1_0);
456 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
457 EXPECT_THAT(getDiagnosticString(),
458 HasSubstr("AtomicFAddEXT: "
459 "expected Result Type to be float scalar type"));
460 }
461
TEST_F(ValidateAtomics,AtomicMinFloatVulkanWrongType3)462 TEST_F(ValidateAtomics, AtomicMinFloatVulkanWrongType3) {
463 const std::string body = R"(
464 %val1 = OpAtomicFMinEXT %u64 %u64_var %device %relaxed %u64_1
465 )";
466 const std::string extra = R"(
467 OpCapability AtomicFloat32MinMaxEXT
468 OpExtension "SPV_EXT_shader_atomic_float_min_max"
469 )";
470
471 CompileSuccessfully(GenerateShaderCode(body, extra), SPV_ENV_VULKAN_1_0);
472 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
473 EXPECT_THAT(getDiagnosticString(),
474 HasSubstr("AtomicFMinEXT: "
475 "expected Result Type to be float scalar type"));
476 }
477
TEST_F(ValidateAtomics,AtomicMaxFloatVulkanWrongType3)478 TEST_F(ValidateAtomics, AtomicMaxFloatVulkanWrongType3) {
479 const std::string body = R"(
480 %val1 = OpAtomicFMaxEXT %u64 %u64_var %device %relaxed %u64_1
481 )";
482 const std::string extra = R"(
483 OpCapability AtomicFloat32MinMaxEXT
484 OpExtension "SPV_EXT_shader_atomic_float_min_max"
485 )";
486
487 CompileSuccessfully(GenerateShaderCode(body, extra), SPV_ENV_VULKAN_1_0);
488 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
489 EXPECT_THAT(getDiagnosticString(),
490 HasSubstr("AtomicFMaxEXT: "
491 "expected Result Type to be float scalar type"));
492 }
493
TEST_F(ValidateAtomics,AtomicAddFloatVulkanWrongCapability)494 TEST_F(ValidateAtomics, AtomicAddFloatVulkanWrongCapability) {
495 const std::string body = R"(
496 %val1 = OpAtomicFAddEXT %f32 %f32_var %device %relaxed %f32_1
497 )";
498 const std::string extra = R"(
499 OpCapability AtomicFloat64AddEXT
500 OpExtension "SPV_EXT_shader_atomic_float_add"
501 )";
502
503 CompileSuccessfully(GenerateShaderCode(body, extra), SPV_ENV_VULKAN_1_0);
504 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
505 EXPECT_THAT(getDiagnosticString(),
506 HasSubstr("AtomicFAddEXT: float add atomics "
507 "require the AtomicFloat32AddEXT capability"));
508 }
509
TEST_F(ValidateAtomics,AtomicMinFloatVulkanWrongCapability)510 TEST_F(ValidateAtomics, AtomicMinFloatVulkanWrongCapability) {
511 const std::string body = R"(
512 %val1 = OpAtomicFMinEXT %f32 %f32_var %device %relaxed %f32_1
513 )";
514 const std::string extra = R"(
515 OpCapability AtomicFloat64MinMaxEXT
516 OpExtension "SPV_EXT_shader_atomic_float_min_max"
517 )";
518
519 CompileSuccessfully(GenerateShaderCode(body, extra), SPV_ENV_VULKAN_1_0);
520 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
521 EXPECT_THAT(getDiagnosticString(),
522 HasSubstr("AtomicFMinEXT: float min/max atomics "
523 "require the AtomicFloat32MinMaxEXT capability"));
524 }
525
TEST_F(ValidateAtomics,AtomicMaxFloatVulkanWrongCapability)526 TEST_F(ValidateAtomics, AtomicMaxFloatVulkanWrongCapability) {
527 const std::string body = R"(
528 %val1 = OpAtomicFMaxEXT %f32 %f32_var %device %relaxed %f32_1
529 )";
530 const std::string extra = R"(
531 OpCapability AtomicFloat64MinMaxEXT
532 OpExtension "SPV_EXT_shader_atomic_float_min_max"
533 )";
534
535 CompileSuccessfully(GenerateShaderCode(body, extra), SPV_ENV_VULKAN_1_0);
536 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
537 EXPECT_THAT(getDiagnosticString(),
538 HasSubstr("AtomicFMaxEXT: float min/max atomics "
539 "require the AtomicFloat32MinMaxEXT capability"));
540 }
541
TEST_F(ValidateAtomics,AtomicAddFloat16VulkanSuccess)542 TEST_F(ValidateAtomics, AtomicAddFloat16VulkanSuccess) {
543 const std::string defs = R"(
544 %f16 = OpTypeFloat 16
545 %f16_1 = OpConstant %f16 1
546 %f16_ptr = OpTypePointer Workgroup %f16
547 %f16_var = OpVariable %f16_ptr Workgroup
548 )";
549 const std::string body = R"(
550 %val1 = OpAtomicFAddEXT %f16 %f16_var %device %relaxed %f16_1
551 )";
552 const std::string extra = R"(
553 OpCapability Float16
554 OpCapability AtomicFloat16AddEXT
555 OpExtension "SPV_EXT_shader_atomic_float16_add"
556 )";
557
558 CompileSuccessfully(GenerateShaderComputeCode(body, extra, defs),
559 SPV_ENV_VULKAN_1_0);
560 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
561 }
562
TEST_F(ValidateAtomics,AtomicAddFloatVulkanSuccess)563 TEST_F(ValidateAtomics, AtomicAddFloatVulkanSuccess) {
564 const std::string body = R"(
565 %val1 = OpAtomicFAddEXT %f32 %f32_var %device %relaxed %f32_1
566 %val2 = OpAtomicFAddEXT %f32 %f32_var %invocation %relaxed %f32_1
567 )";
568 const std::string extra = R"(
569 OpCapability AtomicFloat32AddEXT
570 OpExtension "SPV_EXT_shader_atomic_float_add"
571 )";
572
573 CompileSuccessfully(GenerateShaderComputeCode(body, extra),
574 SPV_ENV_VULKAN_1_0);
575 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
576 }
577
TEST_F(ValidateAtomics,AtomicMinFloat16VulkanSuccess)578 TEST_F(ValidateAtomics, AtomicMinFloat16VulkanSuccess) {
579 const std::string defs = R"(
580 %f16 = OpTypeFloat 16
581 %f16_1 = OpConstant %f16 1
582 %f16_ptr = OpTypePointer Workgroup %f16
583 %f16_var = OpVariable %f16_ptr Workgroup
584 )";
585 const std::string body = R"(
586 %val1 = OpAtomicFMinEXT %f16 %f16_var %device %relaxed %f16_1
587 )";
588 const std::string extra = R"(
589 OpCapability Float16
590 OpCapability AtomicFloat16MinMaxEXT
591 OpExtension "SPV_EXT_shader_atomic_float_min_max"
592 )";
593
594 CompileSuccessfully(GenerateShaderComputeCode(body, extra, defs),
595 SPV_ENV_VULKAN_1_0);
596 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
597 }
598
TEST_F(ValidateAtomics,AtomicMaxFloat16VulkanSuccess)599 TEST_F(ValidateAtomics, AtomicMaxFloat16VulkanSuccess) {
600 const std::string defs = R"(
601 %f16 = OpTypeFloat 16
602 %f16_1 = OpConstant %f16 1
603 %f16_ptr = OpTypePointer Workgroup %f16
604 %f16_var = OpVariable %f16_ptr Workgroup
605 )";
606 const std::string body = R"(
607 %val1 = OpAtomicFMaxEXT %f16 %f16_var %device %relaxed %f16_1
608 )";
609 const std::string extra = R"(
610 OpCapability Float16
611 OpCapability AtomicFloat16MinMaxEXT
612 OpExtension "SPV_EXT_shader_atomic_float_min_max"
613 )";
614
615 CompileSuccessfully(GenerateShaderComputeCode(body, extra, defs),
616 SPV_ENV_VULKAN_1_0);
617 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
618 }
619
TEST_F(ValidateAtomics,AtomicMinFloat32VulkanSuccess)620 TEST_F(ValidateAtomics, AtomicMinFloat32VulkanSuccess) {
621 const std::string body = R"(
622 %val1 = OpAtomicFMinEXT %f32 %f32_var %device %relaxed %f32_1
623 )";
624 const std::string extra = R"(
625 OpCapability AtomicFloat32MinMaxEXT
626 OpExtension "SPV_EXT_shader_atomic_float_min_max"
627 )";
628
629 CompileSuccessfully(GenerateShaderComputeCode(body, extra),
630 SPV_ENV_VULKAN_1_0);
631 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
632 }
633
TEST_F(ValidateAtomics,AtomicMaxFloat32VulkanSuccess)634 TEST_F(ValidateAtomics, AtomicMaxFloat32VulkanSuccess) {
635 const std::string body = R"(
636 %val1 = OpAtomicFMaxEXT %f32 %f32_var %device %relaxed %f32_1
637 )";
638 const std::string extra = R"(
639 OpCapability AtomicFloat32MinMaxEXT
640 OpExtension "SPV_EXT_shader_atomic_float_min_max"
641 )";
642
643 CompileSuccessfully(GenerateShaderComputeCode(body, extra),
644 SPV_ENV_VULKAN_1_0);
645 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
646 }
647
TEST_F(ValidateAtomics,AtomicMinFloat64VulkanSuccess)648 TEST_F(ValidateAtomics, AtomicMinFloat64VulkanSuccess) {
649 const std::string defs = R"(
650 %f64 = OpTypeFloat 64
651 %f64_1 = OpConstant %f64 1
652 %f64_ptr = OpTypePointer Workgroup %f64
653 %f64_var = OpVariable %f64_ptr Workgroup
654 )";
655 const std::string body = R"(
656 %val1 = OpAtomicFMinEXT %f64 %f64_var %device %relaxed %f64_1
657 )";
658 const std::string extra = R"(
659 OpCapability Float64
660 OpCapability AtomicFloat64MinMaxEXT
661 OpExtension "SPV_EXT_shader_atomic_float_min_max"
662 )";
663
664 CompileSuccessfully(GenerateShaderComputeCode(body, extra, defs),
665 SPV_ENV_VULKAN_1_0);
666 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
667 }
668
TEST_F(ValidateAtomics,AtomicMaxFloat64VulkanSuccess)669 TEST_F(ValidateAtomics, AtomicMaxFloat64VulkanSuccess) {
670 const std::string defs = R"(
671 %f64 = OpTypeFloat 64
672 %f64_1 = OpConstant %f64 1
673 %f64_ptr = OpTypePointer Workgroup %f64
674 %f64_var = OpVariable %f64_ptr Workgroup
675 )";
676 const std::string body = R"(
677 %val1 = OpAtomicFMaxEXT %f64 %f64_var %device %relaxed %f64_1
678 )";
679 const std::string extra = R"(
680 OpCapability Float64
681 OpCapability AtomicFloat64MinMaxEXT
682 OpExtension "SPV_EXT_shader_atomic_float_min_max"
683 )";
684
685 CompileSuccessfully(GenerateShaderComputeCode(body, extra, defs),
686 SPV_ENV_VULKAN_1_0);
687 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
688 }
689
TEST_F(ValidateAtomics,AtomicLoadFloatVulkan)690 TEST_F(ValidateAtomics, AtomicLoadFloatVulkan) {
691 const std::string body = R"(
692 %val1 = OpAtomicLoad %f32 %f32_var %device %relaxed
693 %val2 = OpAtomicLoad %f32 %f32_var %workgroup %acquire
694 )";
695
696 CompileSuccessfully(GenerateShaderComputeCode(body), SPV_ENV_VULKAN_1_0);
697 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
698 }
699
TEST_F(ValidateAtomics,AtomicStoreVulkanWrongStorageClass)700 TEST_F(ValidateAtomics, AtomicStoreVulkanWrongStorageClass) {
701 const std::string body = R"(
702 OpAtomicStore %f32_var %device %relaxed %f32_1
703 )";
704
705 CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
706 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
707 EXPECT_THAT(getDiagnosticString(),
708 AnyVUID("VUID-StandaloneSpirv-None-04645"));
709 EXPECT_THAT(
710 getDiagnosticString(),
711 HasSubstr("in Vulkan evironment, Workgroup Storage Class is limited to "
712 "MeshNV, TaskNV, and GLCompute execution model"));
713 }
714
TEST_F(ValidateAtomics,AtomicStoreFloatVulkan)715 TEST_F(ValidateAtomics, AtomicStoreFloatVulkan) {
716 const std::string body = R"(
717 OpAtomicStore %f32_var %device %relaxed %f32_1
718 )";
719
720 CompileSuccessfully(GenerateShaderComputeCode(body), SPV_ENV_VULKAN_1_0);
721 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
722 }
723
TEST_F(ValidateAtomics,AtomicExchangeFloatVulkan)724 TEST_F(ValidateAtomics, AtomicExchangeFloatVulkan) {
725 const std::string body = R"(
726 %val2 = OpAtomicExchange %f32 %f32_var %device %relaxed %f32_0
727 )";
728
729 CompileSuccessfully(GenerateShaderComputeCode(body), SPV_ENV_VULKAN_1_0);
730 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
731 }
732
TEST_F(ValidateAtomics,AtomicLoadInt64WithCapabilityVulkanSuccess)733 TEST_F(ValidateAtomics, AtomicLoadInt64WithCapabilityVulkanSuccess) {
734 const std::string body = R"(
735 %val1 = OpAtomicLoad %u64 %u64_var %device %relaxed
736 %val2 = OpAtomicLoad %u64 %u64_var %workgroup %acquire
737 %val3 = OpAtomicLoad %u64 %u64_var %invocation %relaxed
738 )";
739
740 CompileSuccessfully(
741 GenerateShaderComputeCode(body, "OpCapability Int64Atomics\n"),
742 SPV_ENV_VULKAN_1_0);
743 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
744 }
745
TEST_F(ValidateAtomics,AtomicLoadInt64WithoutCapabilityVulkan)746 TEST_F(ValidateAtomics, AtomicLoadInt64WithoutCapabilityVulkan) {
747 const std::string body = R"(
748 %val1 = OpAtomicLoad %u64 %u64_var %device %relaxed
749 %val2 = OpAtomicLoad %u64 %u64_var %workgroup %acquire
750 )";
751
752 CompileSuccessfully(GenerateShaderComputeCode(body), SPV_ENV_VULKAN_1_0);
753 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
754 EXPECT_THAT(getDiagnosticString(),
755 HasSubstr("64-bit atomics require the Int64Atomics capability"));
756 }
757
TEST_F(ValidateAtomics,AtomicStoreOpenCLFunctionPointerStorageTypeSuccess)758 TEST_F(ValidateAtomics, AtomicStoreOpenCLFunctionPointerStorageTypeSuccess) {
759 const std::string body = R"(
760 %f32_var_function = OpVariable %f32_ptr_function Function
761 OpAtomicStore %f32_var_function %device %relaxed %f32_1
762 )";
763
764 CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_OPENCL_1_2);
765 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_OPENCL_1_2));
766 }
767
TEST_F(ValidateAtomics,AtomicStoreVulkanFunctionPointerStorageType)768 TEST_F(ValidateAtomics, AtomicStoreVulkanFunctionPointerStorageType) {
769 const std::string body = R"(
770 %f32_var_function = OpVariable %f32_ptr_function Function
771 OpAtomicStore %f32_var_function %device %relaxed %f32_1
772 )";
773
774 CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
775 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
776 EXPECT_THAT(getDiagnosticString(),
777 AnyVUID("VUID-StandaloneSpirv-None-04686"));
778 EXPECT_THAT(
779 getDiagnosticString(),
780 HasSubstr("AtomicStore: Vulkan spec only allows storage classes for "
781 "atomic to be: Uniform, Workgroup, Image, StorageBuffer, or "
782 "PhysicalStorageBuffer."));
783 }
784
TEST_F(ValidateAtomics,AtomicStoreFunctionPointerStorageType)785 TEST_F(ValidateAtomics, AtomicStoreFunctionPointerStorageType) {
786 const std::string body = R"(
787 %f32_var_function = OpVariable %f32_ptr_function Function
788 OpAtomicStore %f32_var_function %device %relaxed %f32_1
789 )";
790
791 CompileSuccessfully(GenerateShaderCode(body));
792 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
793 EXPECT_THAT(getDiagnosticString(),
794 HasSubstr("AtomicStore: Function storage class forbidden when "
795 "the Shader capability is declared."));
796 }
797
798 // TODO(atgoo@github.com): the corresponding check fails Vulkan CTS,
799 // reenable once fixed.
TEST_F(ValidateAtomics,DISABLED_AtomicLoadVulkanSubgroup)800 TEST_F(ValidateAtomics, DISABLED_AtomicLoadVulkanSubgroup) {
801 const std::string body = R"(
802 %val1 = OpAtomicLoad %u32 %u32_var %subgroup %acquire
803 )";
804
805 CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
806 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
807 EXPECT_THAT(getDiagnosticString(),
808 HasSubstr("AtomicLoad: in Vulkan environment memory scope is "
809 "limited to Device, Workgroup and Invocation"));
810 }
811
TEST_F(ValidateAtomics,AtomicLoadVulkanRelease)812 TEST_F(ValidateAtomics, AtomicLoadVulkanRelease) {
813 const std::string body = R"(
814 %val1 = OpAtomicLoad %u32 %u32_var %workgroup %release
815 )";
816
817 CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
818 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
819 EXPECT_THAT(getDiagnosticString(),
820 AnyVUID("VUID-StandaloneSpirv-OpAtomicLoad-04731"));
821 EXPECT_THAT(
822 getDiagnosticString(),
823 HasSubstr("Vulkan spec disallows OpAtomicLoad with Memory Semantics "
824 "Release, AcquireRelease and SequentiallyConsistent"));
825 }
826
TEST_F(ValidateAtomics,AtomicLoadVulkanAcquireRelease)827 TEST_F(ValidateAtomics, AtomicLoadVulkanAcquireRelease) {
828 const std::string body = R"(
829 %val1 = OpAtomicLoad %u32 %u32_var %workgroup %acquire_release
830 )";
831
832 CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
833 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
834 EXPECT_THAT(getDiagnosticString(),
835 AnyVUID("VUID-StandaloneSpirv-OpAtomicLoad-04731"));
836 EXPECT_THAT(
837 getDiagnosticString(),
838 HasSubstr("Vulkan spec disallows OpAtomicLoad with Memory Semantics "
839 "Release, AcquireRelease and SequentiallyConsistent"));
840 }
841
TEST_F(ValidateAtomics,AtomicLoadVulkanSequentiallyConsistent)842 TEST_F(ValidateAtomics, AtomicLoadVulkanSequentiallyConsistent) {
843 const std::string body = R"(
844 %val1 = OpAtomicLoad %u32 %u32_var %workgroup %sequentially_consistent
845 )";
846
847 CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
848 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
849 EXPECT_THAT(getDiagnosticString(),
850 AnyVUID("VUID-StandaloneSpirv-OpAtomicLoad-04731"));
851 EXPECT_THAT(
852 getDiagnosticString(),
853 HasSubstr("Vulkan spec disallows OpAtomicLoad with Memory Semantics "
854 "Release, AcquireRelease and SequentiallyConsistent"));
855 }
856
TEST_F(ValidateAtomics,AtomicLoadVulkanInvocationSemantics)857 TEST_F(ValidateAtomics, AtomicLoadVulkanInvocationSemantics) {
858 const std::string body = R"(
859 %val1 = OpAtomicLoad %u32 %u32_var %invocation %acquire
860 )";
861
862 CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
863 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
864 EXPECT_THAT(getDiagnosticString(),
865 AnyVUID("VUID-StandaloneSpirv-None-04641"));
866 EXPECT_THAT(
867 getDiagnosticString(),
868 HasSubstr("AtomicLoad: Vulkan specification requires Memory Semantics to "
869 "be None if used with Invocation Memory Scope"));
870 }
871
TEST_F(ValidateAtomics,AtomicLoadShaderFloat)872 TEST_F(ValidateAtomics, AtomicLoadShaderFloat) {
873 const std::string body = R"(
874 %val1 = OpAtomicLoad %f32 %f32_var %device %relaxed
875 )";
876
877 CompileSuccessfully(GenerateShaderCode(body));
878 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
879 }
880
TEST_F(ValidateAtomics,AtomicLoadVulkanInt64)881 TEST_F(ValidateAtomics, AtomicLoadVulkanInt64) {
882 const std::string body = R"(
883 %val1 = OpAtomicLoad %u64 %u64_var %device %relaxed
884 )";
885
886 CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
887 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
888 EXPECT_THAT(
889 getDiagnosticString(),
890 HasSubstr(
891 "AtomicLoad: 64-bit atomics require the Int64Atomics capability"));
892 }
893
TEST_F(ValidateAtomics,AtomicLoadKernelInt64)894 TEST_F(ValidateAtomics, AtomicLoadKernelInt64) {
895 const std::string body = R"(
896 %val1 = OpAtomicLoad %u64 %u64_var %device %relaxed
897 )";
898
899 CompileSuccessfully(GenerateKernelCode(body));
900 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
901 EXPECT_THAT(
902 getDiagnosticString(),
903 HasSubstr(
904 "AtomicLoad: 64-bit atomics require the Int64Atomics capability"));
905 }
906
TEST_F(ValidateAtomics,AtomicStoreVulkanInt64)907 TEST_F(ValidateAtomics, AtomicStoreVulkanInt64) {
908 const std::string body = R"(
909 OpAtomicStore %u64_var %device %relaxed %u64_1
910 )";
911
912 CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
913 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
914 EXPECT_THAT(
915 getDiagnosticString(),
916 HasSubstr(
917 "AtomicStore: 64-bit atomics require the Int64Atomics capability"));
918 }
919
TEST_F(ValidateAtomics,AtomicStoreKernelInt64)920 TEST_F(ValidateAtomics, AtomicStoreKernelInt64) {
921 const std::string body = R"(
922 OpAtomicStore %u64_var %device %relaxed %u64_1
923 )";
924
925 CompileSuccessfully(GenerateKernelCode(body));
926 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
927 EXPECT_THAT(
928 getDiagnosticString(),
929 HasSubstr(
930 "AtomicStore: 64-bit atomics require the Int64Atomics capability"));
931 }
932
TEST_F(ValidateAtomics,VK_KHR_shader_atomic_int64Success)933 TEST_F(ValidateAtomics, VK_KHR_shader_atomic_int64Success) {
934 const std::string body = R"(
935 %val1 = OpAtomicUMin %u64 %u64_var %device %relaxed %u64_1
936 %val2 = OpAtomicUMax %u64 %u64_var %device %relaxed %u64_1
937 %val3 = OpAtomicSMin %u64 %u64_var %device %relaxed %u64_1
938 %val4 = OpAtomicSMax %u64 %u64_var %device %relaxed %u64_1
939 %val5 = OpAtomicAnd %u64 %u64_var %device %relaxed %u64_1
940 %val6 = OpAtomicOr %u64 %u64_var %device %relaxed %u64_1
941 %val7 = OpAtomicXor %u64 %u64_var %device %relaxed %u64_1
942 %val8 = OpAtomicIAdd %u64 %u64_var %device %relaxed %u64_1
943 %val9 = OpAtomicExchange %u64 %u64_var %device %relaxed %u64_1
944 %val10 = OpAtomicCompareExchange %u64 %u64_var %device %relaxed %relaxed %u64_1 %u64_1
945
946 %val11 = OpAtomicUMin %s64 %s64_var %device %relaxed %s64_1
947 %val12 = OpAtomicUMax %s64 %s64_var %device %relaxed %s64_1
948 %val13 = OpAtomicSMin %s64 %s64_var %device %relaxed %s64_1
949 %val14 = OpAtomicSMax %s64 %s64_var %device %relaxed %s64_1
950 %val15 = OpAtomicAnd %s64 %s64_var %device %relaxed %s64_1
951 %val16 = OpAtomicOr %s64 %s64_var %device %relaxed %s64_1
952 %val17 = OpAtomicXor %s64 %s64_var %device %relaxed %s64_1
953 %val18 = OpAtomicIAdd %s64 %s64_var %device %relaxed %s64_1
954 %val19 = OpAtomicExchange %s64 %s64_var %device %relaxed %s64_1
955 %val20 = OpAtomicCompareExchange %s64 %s64_var %device %relaxed %relaxed %s64_1 %s64_1
956
957 %val21 = OpAtomicLoad %u64 %u64_var %device %relaxed
958 %val22 = OpAtomicLoad %s64 %s64_var %device %relaxed
959
960 OpAtomicStore %u64_var %device %relaxed %u64_1
961 OpAtomicStore %s64_var %device %relaxed %s64_1
962 )";
963
964 CompileSuccessfully(
965 GenerateShaderComputeCode(body, "OpCapability Int64Atomics\n"),
966 SPV_ENV_VULKAN_1_0);
967 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
968 }
969
TEST_F(ValidateAtomics,VK_KHR_shader_atomic_int64MissingCapability)970 TEST_F(ValidateAtomics, VK_KHR_shader_atomic_int64MissingCapability) {
971 const std::string body = R"(
972 %val1 = OpAtomicUMin %u64 %u64_var %device %relaxed %u64_1
973 )";
974
975 CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
976 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
977 EXPECT_THAT(
978 getDiagnosticString(),
979 HasSubstr(
980 "AtomicUMin: 64-bit atomics require the Int64Atomics capability"));
981 }
982
TEST_F(ValidateAtomics,AtomicLoadWrongResultType)983 TEST_F(ValidateAtomics, AtomicLoadWrongResultType) {
984 const std::string body = R"(
985 %val1 = OpAtomicLoad %f32vec4 %f32vec4_var %device %relaxed
986 )";
987
988 CompileSuccessfully(GenerateKernelCode(body));
989 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
990 EXPECT_THAT(
991 getDiagnosticString(),
992 HasSubstr("AtomicLoad: "
993 "expected Result Type to be integer or float scalar type"));
994 }
995
TEST_F(ValidateAtomics,AtomicLoadWrongPointerType)996 TEST_F(ValidateAtomics, AtomicLoadWrongPointerType) {
997 const std::string body = R"(
998 %val1 = OpAtomicLoad %f32 %f32_ptr %device %relaxed
999 )";
1000
1001 CompileSuccessfully(GenerateKernelCode(body));
1002 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1003 EXPECT_THAT(getDiagnosticString(),
1004 HasSubstr("Operand 27[%_ptr_Workgroup_float] cannot be a type"));
1005 }
1006
TEST_F(ValidateAtomics,AtomicLoadWrongPointerDataType)1007 TEST_F(ValidateAtomics, AtomicLoadWrongPointerDataType) {
1008 const std::string body = R"(
1009 %val1 = OpAtomicLoad %u32 %f32_var %device %relaxed
1010 )";
1011
1012 CompileSuccessfully(GenerateKernelCode(body));
1013 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1014 EXPECT_THAT(
1015 getDiagnosticString(),
1016 HasSubstr("AtomicLoad: "
1017 "expected Pointer to point to a value of type Result Type"));
1018 }
1019
TEST_F(ValidateAtomics,AtomicLoadWrongScopeType)1020 TEST_F(ValidateAtomics, AtomicLoadWrongScopeType) {
1021 const std::string body = R"(
1022 %val1 = OpAtomicLoad %f32 %f32_var %f32_1 %relaxed
1023 )";
1024
1025 CompileSuccessfully(GenerateKernelCode(body));
1026 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1027 EXPECT_THAT(getDiagnosticString(),
1028 HasSubstr("AtomicLoad: expected scope to be a 32-bit int"));
1029 }
1030
TEST_F(ValidateAtomics,AtomicLoadWrongMemorySemanticsType)1031 TEST_F(ValidateAtomics, AtomicLoadWrongMemorySemanticsType) {
1032 const std::string body = R"(
1033 %val1 = OpAtomicLoad %f32 %f32_var %device %u64_1
1034 )";
1035
1036 CompileSuccessfully(GenerateKernelCode(body));
1037 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1038 EXPECT_THAT(
1039 getDiagnosticString(),
1040 HasSubstr("AtomicLoad: expected Memory Semantics to be a 32-bit int"));
1041 }
1042
TEST_F(ValidateAtomics,AtomicStoreKernelSuccess)1043 TEST_F(ValidateAtomics, AtomicStoreKernelSuccess) {
1044 const std::string body = R"(
1045 OpAtomicStore %f32_var %device %relaxed %f32_1
1046 OpAtomicStore %u32_var %subgroup %release %u32_1
1047 )";
1048
1049 CompileSuccessfully(GenerateKernelCode(body));
1050 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1051 }
1052
TEST_F(ValidateAtomics,AtomicStoreShaderSuccess)1053 TEST_F(ValidateAtomics, AtomicStoreShaderSuccess) {
1054 const std::string body = R"(
1055 OpAtomicStore %u32_var %device %release %u32_1
1056 OpAtomicStore %u32_var %subgroup %sequentially_consistent %u32_1
1057 )";
1058
1059 CompileSuccessfully(GenerateShaderCode(body));
1060 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1061 }
1062
TEST_F(ValidateAtomics,AtomicStoreVulkanSuccess)1063 TEST_F(ValidateAtomics, AtomicStoreVulkanSuccess) {
1064 const std::string body = R"(
1065 OpAtomicStore %u32_var %device %release %u32_1
1066 OpAtomicStore %u32_var %invocation %relaxed %u32_1
1067 )";
1068
1069 CompileSuccessfully(GenerateShaderComputeCode(body), SPV_ENV_VULKAN_1_0);
1070 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1071 }
1072
TEST_F(ValidateAtomics,AtomicStoreVulkanAcquire)1073 TEST_F(ValidateAtomics, AtomicStoreVulkanAcquire) {
1074 const std::string body = R"(
1075 OpAtomicStore %u32_var %device %acquire %u32_1
1076 )";
1077
1078 CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
1079 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1080 EXPECT_THAT(getDiagnosticString(),
1081 AnyVUID("VUID-StandaloneSpirv-OpAtomicStore-04730"));
1082 EXPECT_THAT(
1083 getDiagnosticString(),
1084 HasSubstr("Vulkan spec disallows OpAtomicStore with Memory Semantics "
1085 "Acquire, AcquireRelease and SequentiallyConsistent"));
1086 }
1087
TEST_F(ValidateAtomics,AtomicStoreVulkanAcquireRelease)1088 TEST_F(ValidateAtomics, AtomicStoreVulkanAcquireRelease) {
1089 const std::string body = R"(
1090 OpAtomicStore %u32_var %device %acquire_release %u32_1
1091 )";
1092
1093 CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
1094 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1095 EXPECT_THAT(getDiagnosticString(),
1096 AnyVUID("VUID-StandaloneSpirv-OpAtomicStore-04730"));
1097 EXPECT_THAT(
1098 getDiagnosticString(),
1099 HasSubstr("Vulkan spec disallows OpAtomicStore with Memory Semantics "
1100 "Acquire, AcquireRelease and SequentiallyConsistent"));
1101 }
1102
TEST_F(ValidateAtomics,AtomicStoreVulkanSequentiallyConsistent)1103 TEST_F(ValidateAtomics, AtomicStoreVulkanSequentiallyConsistent) {
1104 const std::string body = R"(
1105 OpAtomicStore %u32_var %device %sequentially_consistent %u32_1
1106 )";
1107
1108 CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
1109 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1110 EXPECT_THAT(getDiagnosticString(),
1111 AnyVUID("VUID-StandaloneSpirv-OpAtomicStore-04730"));
1112 EXPECT_THAT(
1113 getDiagnosticString(),
1114 HasSubstr("Vulkan spec disallows OpAtomicStore with Memory Semantics "
1115 "Acquire, AcquireRelease and SequentiallyConsistent"));
1116 }
1117
TEST_F(ValidateAtomics,AtomicStoreVulkanInvocationSemantics)1118 TEST_F(ValidateAtomics, AtomicStoreVulkanInvocationSemantics) {
1119 const std::string body = R"(
1120 OpAtomicStore %u32_var %invocation %acquire %u32_1
1121 )";
1122
1123 CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
1124 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1125 EXPECT_THAT(getDiagnosticString(),
1126 AnyVUID("VUID-StandaloneSpirv-None-04641"));
1127 EXPECT_THAT(
1128 getDiagnosticString(),
1129 HasSubstr("AtomicStore: Vulkan specification requires Memory Semantics "
1130 "to be None if used with Invocation Memory Scope"));
1131 }
1132
TEST_F(ValidateAtomics,AtomicStoreWrongPointerType)1133 TEST_F(ValidateAtomics, AtomicStoreWrongPointerType) {
1134 const std::string body = R"(
1135 OpAtomicStore %f32_1 %device %relaxed %f32_1
1136 )";
1137
1138 CompileSuccessfully(GenerateKernelCode(body));
1139 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1140 EXPECT_THAT(
1141 getDiagnosticString(),
1142 HasSubstr("AtomicStore: expected Pointer to be of type OpTypePointer"));
1143 }
1144
TEST_F(ValidateAtomics,AtomicStoreWrongPointerDataType)1145 TEST_F(ValidateAtomics, AtomicStoreWrongPointerDataType) {
1146 const std::string body = R"(
1147 OpAtomicStore %f32vec4_var %device %relaxed %f32_1
1148 )";
1149
1150 CompileSuccessfully(GenerateKernelCode(body));
1151 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1152 EXPECT_THAT(
1153 getDiagnosticString(),
1154 HasSubstr(
1155 "AtomicStore: "
1156 "expected Pointer to be a pointer to integer or float scalar type"));
1157 }
1158
TEST_F(ValidateAtomics,AtomicStoreWrongPointerStorageTypeForOpenCL)1159 TEST_F(ValidateAtomics, AtomicStoreWrongPointerStorageTypeForOpenCL) {
1160 const std::string body = R"(
1161 OpAtomicStore %f32_im_var %device %relaxed %f32_1
1162 )";
1163
1164 CompileSuccessfully(GenerateKernelCode(body));
1165 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_1_2));
1166 EXPECT_THAT(
1167 getDiagnosticString(),
1168 HasSubstr("AtomicStore: storage class must be Function, Workgroup, "
1169 "CrossWorkGroup or Generic in the OpenCL environment."));
1170 }
1171
TEST_F(ValidateAtomics,AtomicStoreWrongPointerStorageType)1172 TEST_F(ValidateAtomics, AtomicStoreWrongPointerStorageType) {
1173 const std::string body = R"(
1174 OpAtomicStore %f32_uc_var %device %relaxed %f32_1
1175 )";
1176
1177 CompileSuccessfully(GenerateKernelCode(body));
1178 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1179 EXPECT_THAT(getDiagnosticString(),
1180 HasSubstr("AtomicStore: storage class forbidden by universal "
1181 "validation rules."));
1182 }
1183
TEST_F(ValidateAtomics,AtomicStoreWrongScopeType)1184 TEST_F(ValidateAtomics, AtomicStoreWrongScopeType) {
1185 const std::string body = R"(
1186 OpAtomicStore %f32_var %f32_1 %relaxed %f32_1
1187 )";
1188
1189 CompileSuccessfully(GenerateKernelCode(body));
1190 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1191 EXPECT_THAT(getDiagnosticString(),
1192 HasSubstr("AtomicStore: expected scope to be a 32-bit int\n "
1193 "OpAtomicStore %28 %float_1 %uint_0_1 %float_1\n"));
1194 }
1195
TEST_F(ValidateAtomics,AtomicStoreWrongMemorySemanticsType)1196 TEST_F(ValidateAtomics, AtomicStoreWrongMemorySemanticsType) {
1197 const std::string body = R"(
1198 OpAtomicStore %f32_var %device %f32_1 %f32_1
1199 )";
1200
1201 CompileSuccessfully(GenerateKernelCode(body));
1202 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1203 EXPECT_THAT(
1204 getDiagnosticString(),
1205 HasSubstr("AtomicStore: expected Memory Semantics to be a 32-bit int"));
1206 }
1207
TEST_F(ValidateAtomics,AtomicStoreWrongValueType)1208 TEST_F(ValidateAtomics, AtomicStoreWrongValueType) {
1209 const std::string body = R"(
1210 OpAtomicStore %f32_var %device %relaxed %u32_1
1211 )";
1212
1213 CompileSuccessfully(GenerateKernelCode(body));
1214 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1215 EXPECT_THAT(
1216 getDiagnosticString(),
1217 HasSubstr("AtomicStore: "
1218 "expected Value type and the type pointed to by Pointer to "
1219 "be the same"));
1220 }
1221
TEST_F(ValidateAtomics,AtomicExchangeShaderSuccess)1222 TEST_F(ValidateAtomics, AtomicExchangeShaderSuccess) {
1223 const std::string body = R"(
1224 OpAtomicStore %u32_var %device %relaxed %u32_1
1225 %val2 = OpAtomicExchange %u32 %u32_var %device %relaxed %u32_0
1226 )";
1227
1228 CompileSuccessfully(GenerateShaderCode(body));
1229 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1230 }
1231
TEST_F(ValidateAtomics,AtomicExchangeKernelSuccess)1232 TEST_F(ValidateAtomics, AtomicExchangeKernelSuccess) {
1233 const std::string body = R"(
1234 OpAtomicStore %f32_var %device %relaxed %f32_1
1235 %val2 = OpAtomicExchange %f32 %f32_var %device %relaxed %f32_0
1236 OpAtomicStore %u32_var %device %relaxed %u32_1
1237 %val4 = OpAtomicExchange %u32 %u32_var %device %relaxed %u32_0
1238 )";
1239
1240 CompileSuccessfully(GenerateKernelCode(body));
1241 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1242 }
1243
TEST_F(ValidateAtomics,AtomicExchangeShaderFloat)1244 TEST_F(ValidateAtomics, AtomicExchangeShaderFloat) {
1245 const std::string body = R"(
1246 OpAtomicStore %f32_var %device %relaxed %f32_1
1247 %val2 = OpAtomicExchange %f32 %f32_var %device %relaxed %f32_0
1248 )";
1249
1250 CompileSuccessfully(GenerateShaderCode(body));
1251 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1252 }
1253
TEST_F(ValidateAtomics,AtomicExchangeWrongResultType)1254 TEST_F(ValidateAtomics, AtomicExchangeWrongResultType) {
1255 const std::string body = R"(
1256 OpStore %f32vec4_var %f32vec4_0000
1257 %val2 = OpAtomicExchange %f32vec4 %f32vec4_var %device %relaxed %f32vec4_0000
1258 )";
1259
1260 CompileSuccessfully(GenerateKernelCode(body));
1261 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1262 EXPECT_THAT(
1263 getDiagnosticString(),
1264 HasSubstr("AtomicExchange: "
1265 "expected Result Type to be integer or float scalar type"));
1266 }
1267
TEST_F(ValidateAtomics,AtomicExchangeWrongPointerType)1268 TEST_F(ValidateAtomics, AtomicExchangeWrongPointerType) {
1269 const std::string body = R"(
1270 %val2 = OpAtomicExchange %f32 %f32vec4_ptr %device %relaxed %f32vec4_0000
1271 )";
1272
1273 CompileSuccessfully(GenerateKernelCode(body));
1274 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1275 EXPECT_THAT(getDiagnosticString(),
1276 HasSubstr("Operand 33[%_ptr_Workgroup_v4float] cannot be a "
1277 "type"));
1278 }
1279
TEST_F(ValidateAtomics,AtomicExchangeWrongPointerDataType)1280 TEST_F(ValidateAtomics, AtomicExchangeWrongPointerDataType) {
1281 const std::string body = R"(
1282 OpStore %f32vec4_var %f32vec4_0000
1283 %val2 = OpAtomicExchange %f32 %f32vec4_var %device %relaxed %f32vec4_0000
1284 )";
1285
1286 CompileSuccessfully(GenerateKernelCode(body));
1287 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1288 EXPECT_THAT(
1289 getDiagnosticString(),
1290 HasSubstr("AtomicExchange: "
1291 "expected Pointer to point to a value of type Result Type"));
1292 }
1293
TEST_F(ValidateAtomics,AtomicExchangeWrongScopeType)1294 TEST_F(ValidateAtomics, AtomicExchangeWrongScopeType) {
1295 const std::string body = R"(
1296 OpAtomicStore %f32_var %device %relaxed %f32_1
1297 %val2 = OpAtomicExchange %f32 %f32_var %f32_1 %relaxed %f32_0
1298 )";
1299
1300 CompileSuccessfully(GenerateKernelCode(body));
1301 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1302 EXPECT_THAT(getDiagnosticString(),
1303 HasSubstr("AtomicExchange: expected scope to be a 32-bit int"));
1304 }
1305
TEST_F(ValidateAtomics,AtomicExchangeWrongMemorySemanticsType)1306 TEST_F(ValidateAtomics, AtomicExchangeWrongMemorySemanticsType) {
1307 const std::string body = R"(
1308 OpAtomicStore %f32_var %device %relaxed %f32_1
1309 %val2 = OpAtomicExchange %f32 %f32_var %device %f32_1 %f32_0
1310 )";
1311
1312 CompileSuccessfully(GenerateKernelCode(body));
1313 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1314 EXPECT_THAT(
1315 getDiagnosticString(),
1316 HasSubstr(
1317 "AtomicExchange: expected Memory Semantics to be a 32-bit int"));
1318 }
1319
TEST_F(ValidateAtomics,AtomicExchangeWrongValueType)1320 TEST_F(ValidateAtomics, AtomicExchangeWrongValueType) {
1321 const std::string body = R"(
1322 OpAtomicStore %f32_var %device %relaxed %f32_1
1323 %val2 = OpAtomicExchange %f32 %f32_var %device %relaxed %u32_0
1324 )";
1325
1326 CompileSuccessfully(GenerateKernelCode(body));
1327 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1328 EXPECT_THAT(getDiagnosticString(),
1329 HasSubstr("AtomicExchange: "
1330 "expected Value to be of type Result Type"));
1331 }
1332
TEST_F(ValidateAtomics,AtomicExchangeVulkanInvocationSemantics)1333 TEST_F(ValidateAtomics, AtomicExchangeVulkanInvocationSemantics) {
1334 const std::string body = R"(
1335 OpAtomicStore %u32_var %invocation %relaxed %u32_1
1336 %val2 = OpAtomicExchange %u32 %u32_var %invocation %acquire %u32_0
1337 )";
1338
1339 CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
1340 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1341 EXPECT_THAT(getDiagnosticString(),
1342 AnyVUID("VUID-StandaloneSpirv-None-04641"));
1343 EXPECT_THAT(
1344 getDiagnosticString(),
1345 HasSubstr("AtomicExchange: Vulkan specification requires Memory "
1346 "Semantics to be None if used with Invocation Memory Scope"));
1347 }
1348
TEST_F(ValidateAtomics,AtomicCompareExchangeShaderSuccess)1349 TEST_F(ValidateAtomics, AtomicCompareExchangeShaderSuccess) {
1350 const std::string body = R"(
1351 OpAtomicStore %u32_var %device %relaxed %u32_1
1352 %val2 = OpAtomicCompareExchange %u32 %u32_var %device %relaxed %relaxed %u32_0 %u32_0
1353 )";
1354
1355 CompileSuccessfully(GenerateShaderCode(body));
1356 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1357 }
1358
TEST_F(ValidateAtomics,AtomicCompareExchangeKernelSuccess)1359 TEST_F(ValidateAtomics, AtomicCompareExchangeKernelSuccess) {
1360 const std::string body = R"(
1361 OpAtomicStore %u32_var %device %relaxed %u32_1
1362 %val2 = OpAtomicCompareExchange %u32 %u32_var %device %relaxed %relaxed %u32_0 %u32_0
1363 )";
1364
1365 CompileSuccessfully(GenerateKernelCode(body));
1366 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1367 }
1368
TEST_F(ValidateAtomics,AtomicCompareExchangeShaderFloat)1369 TEST_F(ValidateAtomics, AtomicCompareExchangeShaderFloat) {
1370 const std::string body = R"(
1371 OpAtomicStore %f32_var %device %relaxed %f32_1
1372 %val1 = OpAtomicCompareExchange %f32 %f32_var %device %relaxed %relaxed %f32_0 %f32_1
1373 )";
1374
1375 CompileSuccessfully(GenerateShaderCode(body));
1376 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1377 EXPECT_THAT(getDiagnosticString(),
1378 HasSubstr("AtomicCompareExchange: "
1379 "expected Result Type to be integer scalar type"));
1380 }
1381
TEST_F(ValidateAtomics,AtomicCompareExchangeWrongResultType)1382 TEST_F(ValidateAtomics, AtomicCompareExchangeWrongResultType) {
1383 const std::string body = R"(
1384 OpStore %f32vec4_var %f32vec4_0000
1385 %val2 = OpAtomicCompareExchange %f32vec4 %f32vec4_var %device %relaxed %relaxed %f32vec4_0000 %f32vec4_0000
1386 )";
1387
1388 CompileSuccessfully(GenerateKernelCode(body));
1389 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1390 EXPECT_THAT(getDiagnosticString(),
1391 HasSubstr("AtomicCompareExchange: "
1392 "expected Result Type to be integer scalar type"));
1393 }
1394
TEST_F(ValidateAtomics,AtomicCompareExchangeWrongPointerType)1395 TEST_F(ValidateAtomics, AtomicCompareExchangeWrongPointerType) {
1396 const std::string body = R"(
1397 %val2 = OpAtomicCompareExchange %f32 %f32vec4_ptr %device %relaxed %relaxed %f32vec4_0000 %f32vec4_0000
1398 )";
1399
1400 CompileSuccessfully(GenerateKernelCode(body));
1401 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1402 EXPECT_THAT(getDiagnosticString(),
1403 HasSubstr("Operand 33[%_ptr_Workgroup_v4float] cannot be a "
1404 "type"));
1405 }
1406
TEST_F(ValidateAtomics,AtomicCompareExchangeWrongPointerDataType)1407 TEST_F(ValidateAtomics, AtomicCompareExchangeWrongPointerDataType) {
1408 const std::string body = R"(
1409 OpStore %f32vec4_var %f32vec4_0000
1410 %val2 = OpAtomicCompareExchange %u32 %f32vec4_var %device %relaxed %relaxed %u32_0 %u32_0
1411 )";
1412
1413 CompileSuccessfully(GenerateKernelCode(body));
1414 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1415 EXPECT_THAT(
1416 getDiagnosticString(),
1417 HasSubstr("AtomicCompareExchange: "
1418 "expected Pointer to point to a value of type Result Type"));
1419 }
1420
TEST_F(ValidateAtomics,AtomicCompareExchangeWrongScopeType)1421 TEST_F(ValidateAtomics, AtomicCompareExchangeWrongScopeType) {
1422 const std::string body = R"(
1423 OpAtomicStore %u64_var %device %relaxed %u64_1
1424 %val2 = OpAtomicCompareExchange %u64 %u64_var %u64_1 %relaxed %relaxed %u32_0 %u32_0
1425 )";
1426
1427 CompileSuccessfully(GenerateKernelCode(body, "OpCapability Int64Atomics\n"));
1428 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1429 EXPECT_THAT(getDiagnosticString(),
1430 HasSubstr("AtomicCompareExchange: expected scope to be a 32-bit "
1431 "int"));
1432 }
1433
TEST_F(ValidateAtomics,AtomicCompareExchangeWrongMemorySemanticsType1)1434 TEST_F(ValidateAtomics, AtomicCompareExchangeWrongMemorySemanticsType1) {
1435 const std::string body = R"(
1436 OpAtomicStore %u32_var %device %relaxed %u32_1
1437 %val2 = OpAtomicCompareExchange %u32 %u32_var %device %f32_1 %relaxed %u32_0 %u32_0
1438 )";
1439
1440 CompileSuccessfully(GenerateKernelCode(body));
1441 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1442 EXPECT_THAT(getDiagnosticString(),
1443 HasSubstr("AtomicCompareExchange: expected Memory Semantics to "
1444 "be a 32-bit int"));
1445 }
1446
TEST_F(ValidateAtomics,AtomicCompareExchangeWrongMemorySemanticsType2)1447 TEST_F(ValidateAtomics, AtomicCompareExchangeWrongMemorySemanticsType2) {
1448 const std::string body = R"(
1449 OpAtomicStore %u32_var %device %relaxed %u32_1
1450 %val2 = OpAtomicCompareExchange %u32 %u32_var %device %relaxed %f32_1 %u32_0 %u32_0
1451 )";
1452
1453 CompileSuccessfully(GenerateKernelCode(body));
1454 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1455 EXPECT_THAT(getDiagnosticString(),
1456 HasSubstr("AtomicCompareExchange: expected Memory Semantics to "
1457 "be a 32-bit int"));
1458 }
1459
TEST_F(ValidateAtomics,AtomicCompareExchangeUnequalRelease)1460 TEST_F(ValidateAtomics, AtomicCompareExchangeUnequalRelease) {
1461 const std::string body = R"(
1462 OpAtomicStore %u32_var %device %relaxed %u32_1
1463 %val2 = OpAtomicCompareExchange %u32 %u32_var %device %relaxed %release %u32_0 %u32_0
1464 )";
1465
1466 CompileSuccessfully(GenerateKernelCode(body));
1467 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1468 EXPECT_THAT(getDiagnosticString(),
1469 HasSubstr("AtomicCompareExchange: Memory Semantics Release and "
1470 "AcquireRelease cannot be used for operand Unequal"));
1471 }
1472
TEST_F(ValidateAtomics,AtomicCompareExchangeWrongValueType)1473 TEST_F(ValidateAtomics, AtomicCompareExchangeWrongValueType) {
1474 const std::string body = R"(
1475 OpAtomicStore %u32_var %device %relaxed %u32_1
1476 %val2 = OpAtomicCompareExchange %u32 %u32_var %device %relaxed %relaxed %f32_1 %u32_0
1477 )";
1478
1479 CompileSuccessfully(GenerateKernelCode(body));
1480 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1481 EXPECT_THAT(getDiagnosticString(),
1482 HasSubstr("AtomicCompareExchange: "
1483 "expected Value to be of type Result Type"));
1484 }
1485
TEST_F(ValidateAtomics,AtomicCompareExchangeWrongComparatorType)1486 TEST_F(ValidateAtomics, AtomicCompareExchangeWrongComparatorType) {
1487 const std::string body = R"(
1488 OpAtomicStore %u32_var %device %relaxed %u32_1
1489 %val2 = OpAtomicCompareExchange %u32 %u32_var %device %relaxed %relaxed %u32_0 %f32_0
1490 )";
1491
1492 CompileSuccessfully(GenerateKernelCode(body));
1493 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1494 EXPECT_THAT(getDiagnosticString(),
1495 HasSubstr("AtomicCompareExchange: "
1496 "expected Comparator to be of type Result Type"));
1497 }
1498
TEST_F(ValidateAtomics,AtomicCompareExchangeWeakSuccess)1499 TEST_F(ValidateAtomics, AtomicCompareExchangeWeakSuccess) {
1500 const std::string body = R"(
1501 OpAtomicStore %u32_var %device %relaxed %u32_1
1502 %val4 = OpAtomicCompareExchangeWeak %u32 %u32_var %device %relaxed %relaxed %u32_0 %u32_0
1503 )";
1504
1505 CompileSuccessfully(GenerateKernelCode(body));
1506 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1507 }
1508
TEST_F(ValidateAtomics,AtomicCompareExchangeWeakWrongResultType)1509 TEST_F(ValidateAtomics, AtomicCompareExchangeWeakWrongResultType) {
1510 const std::string body = R"(
1511 OpAtomicStore %f32_var %device %relaxed %f32_1
1512 %val2 = OpAtomicCompareExchangeWeak %f32 %f32_var %device %relaxed %relaxed %f32_0 %f32_1
1513 )";
1514
1515 CompileSuccessfully(GenerateKernelCode(body));
1516 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1517 EXPECT_THAT(getDiagnosticString(),
1518 HasSubstr("AtomicCompareExchangeWeak: "
1519 "expected Result Type to be integer scalar type"));
1520 }
1521
TEST_F(ValidateAtomics,AtomicCompareExchangeVulkanInvocationSemanticsEqual)1522 TEST_F(ValidateAtomics, AtomicCompareExchangeVulkanInvocationSemanticsEqual) {
1523 const std::string body = R"(
1524 OpAtomicStore %u32_var %device %relaxed %u32_1
1525 %val2 = OpAtomicCompareExchange %u32 %u32_var %invocation %release %relaxed %u32_0 %u32_0
1526 )";
1527
1528 CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
1529 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1530 EXPECT_THAT(getDiagnosticString(),
1531 AnyVUID("VUID-StandaloneSpirv-None-04641"));
1532 EXPECT_THAT(
1533 getDiagnosticString(),
1534 HasSubstr("AtomicCompareExchange: Vulkan specification requires Memory "
1535 "Semantics to be None if used with Invocation Memory Scope"));
1536 }
1537
TEST_F(ValidateAtomics,AtomicCompareExchangeVulkanInvocationSemanticsUnequal)1538 TEST_F(ValidateAtomics, AtomicCompareExchangeVulkanInvocationSemanticsUnequal) {
1539 const std::string body = R"(
1540 OpAtomicStore %u32_var %device %relaxed %u32_1
1541 %val2 = OpAtomicCompareExchange %u32 %u32_var %invocation %relaxed %acquire %u32_0 %u32_0
1542 )";
1543
1544 CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
1545 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1546 EXPECT_THAT(getDiagnosticString(),
1547 AnyVUID("VUID-StandaloneSpirv-None-04641"));
1548 EXPECT_THAT(
1549 getDiagnosticString(),
1550 HasSubstr("AtomicCompareExchange: Vulkan specification requires Memory "
1551 "Semantics to be None if used with Invocation Memory Scope"));
1552 }
1553
TEST_F(ValidateAtomics,AtomicArithmeticsSuccess)1554 TEST_F(ValidateAtomics, AtomicArithmeticsSuccess) {
1555 const std::string body = R"(
1556 OpAtomicStore %u32_var %device %relaxed %u32_1
1557 %val1 = OpAtomicIIncrement %u32 %u32_var %device %acquire_release
1558 %val2 = OpAtomicIDecrement %u32 %u32_var %device %acquire_release
1559 %val3 = OpAtomicIAdd %u32 %u32_var %device %acquire_release %u32_1
1560 %val4 = OpAtomicISub %u32 %u32_var %device %acquire_release %u32_1
1561 %val5 = OpAtomicUMin %u32 %u32_var %device %acquire_release %u32_1
1562 %val6 = OpAtomicUMax %u32 %u32_var %device %acquire_release %u32_1
1563 %val7 = OpAtomicSMin %u32 %u32_var %device %sequentially_consistent %u32_1
1564 %val8 = OpAtomicSMax %u32 %u32_var %device %sequentially_consistent %u32_1
1565 %val9 = OpAtomicAnd %u32 %u32_var %device %sequentially_consistent %u32_1
1566 %val10 = OpAtomicOr %u32 %u32_var %device %sequentially_consistent %u32_1
1567 %val11 = OpAtomicXor %u32 %u32_var %device %sequentially_consistent %u32_1
1568 )";
1569
1570 CompileSuccessfully(GenerateKernelCode(body));
1571 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1572 }
1573
TEST_F(ValidateAtomics,AtomicFlagsSuccess)1574 TEST_F(ValidateAtomics, AtomicFlagsSuccess) {
1575 const std::string body = R"(
1576 OpAtomicFlagClear %u32_var %device %release
1577 %val1 = OpAtomicFlagTestAndSet %bool %u32_var %device %relaxed
1578 )";
1579
1580 CompileSuccessfully(GenerateKernelCode(body));
1581 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1582 }
1583
TEST_F(ValidateAtomics,AtomicFlagTestAndSetWrongResultType)1584 TEST_F(ValidateAtomics, AtomicFlagTestAndSetWrongResultType) {
1585 const std::string body = R"(
1586 %val1 = OpAtomicFlagTestAndSet %u32 %u32_var %device %relaxed
1587 )";
1588
1589 CompileSuccessfully(GenerateKernelCode(body));
1590 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1591 EXPECT_THAT(getDiagnosticString(),
1592 HasSubstr("AtomicFlagTestAndSet: "
1593 "expected Result Type to be bool scalar type"));
1594 }
1595
TEST_F(ValidateAtomics,AtomicFlagTestAndSetNotPointer)1596 TEST_F(ValidateAtomics, AtomicFlagTestAndSetNotPointer) {
1597 const std::string body = R"(
1598 %val1 = OpAtomicFlagTestAndSet %bool %u32_1 %device %relaxed
1599 )";
1600
1601 CompileSuccessfully(GenerateKernelCode(body));
1602 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1603 EXPECT_THAT(getDiagnosticString(),
1604 HasSubstr("AtomicFlagTestAndSet: "
1605 "expected Pointer to be of type OpTypePointer"));
1606 }
1607
TEST_F(ValidateAtomics,AtomicFlagTestAndSetNotIntPointer)1608 TEST_F(ValidateAtomics, AtomicFlagTestAndSetNotIntPointer) {
1609 const std::string body = R"(
1610 %val1 = OpAtomicFlagTestAndSet %bool %f32_var %device %relaxed
1611 )";
1612
1613 CompileSuccessfully(GenerateKernelCode(body));
1614 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1615 EXPECT_THAT(
1616 getDiagnosticString(),
1617 HasSubstr("AtomicFlagTestAndSet: "
1618 "expected Pointer to point to a value of 32-bit integer type"));
1619 }
1620
TEST_F(ValidateAtomics,AtomicFlagTestAndSetNotInt32Pointer)1621 TEST_F(ValidateAtomics, AtomicFlagTestAndSetNotInt32Pointer) {
1622 const std::string body = R"(
1623 %val1 = OpAtomicFlagTestAndSet %bool %u64_var %device %relaxed
1624 )";
1625
1626 CompileSuccessfully(GenerateKernelCode(body, "OpCapability Int64Atomics\n"));
1627 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1628 EXPECT_THAT(
1629 getDiagnosticString(),
1630 HasSubstr("AtomicFlagTestAndSet: "
1631 "expected Pointer to point to a value of 32-bit integer type"));
1632 }
1633
TEST_F(ValidateAtomics,AtomicFlagTestAndSetWrongScopeType)1634 TEST_F(ValidateAtomics, AtomicFlagTestAndSetWrongScopeType) {
1635 const std::string body = R"(
1636 %val1 = OpAtomicFlagTestAndSet %bool %u32_var %u64_1 %relaxed
1637 )";
1638
1639 CompileSuccessfully(GenerateKernelCode(body));
1640 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1641 EXPECT_THAT(
1642 getDiagnosticString(),
1643 HasSubstr("AtomicFlagTestAndSet: expected scope to be a 32-bit int"));
1644 }
1645
TEST_F(ValidateAtomics,AtomicFlagTestAndSetWrongMemorySemanticsType)1646 TEST_F(ValidateAtomics, AtomicFlagTestAndSetWrongMemorySemanticsType) {
1647 const std::string body = R"(
1648 %val1 = OpAtomicFlagTestAndSet %bool %u32_var %device %u64_1
1649 )";
1650
1651 CompileSuccessfully(GenerateKernelCode(body));
1652 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1653 EXPECT_THAT(getDiagnosticString(),
1654 HasSubstr("AtomicFlagTestAndSet: "
1655 "expected Memory Semantics to be a 32-bit int"));
1656 }
1657
TEST_F(ValidateAtomics,AtomicFlagClearAcquire)1658 TEST_F(ValidateAtomics, AtomicFlagClearAcquire) {
1659 const std::string body = R"(
1660 OpAtomicFlagClear %u32_var %device %acquire
1661 )";
1662
1663 CompileSuccessfully(GenerateKernelCode(body));
1664 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1665 EXPECT_THAT(getDiagnosticString(),
1666 HasSubstr("Memory Semantics Acquire and AcquireRelease cannot be "
1667 "used with AtomicFlagClear"));
1668 }
1669
TEST_F(ValidateAtomics,AtomicFlagClearNotPointer)1670 TEST_F(ValidateAtomics, AtomicFlagClearNotPointer) {
1671 const std::string body = R"(
1672 OpAtomicFlagClear %u32_1 %device %relaxed
1673 )";
1674
1675 CompileSuccessfully(GenerateKernelCode(body));
1676 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1677 EXPECT_THAT(getDiagnosticString(),
1678 HasSubstr("AtomicFlagClear: "
1679 "expected Pointer to be of type OpTypePointer"));
1680 }
1681
TEST_F(ValidateAtomics,AtomicFlagClearNotIntPointer)1682 TEST_F(ValidateAtomics, AtomicFlagClearNotIntPointer) {
1683 const std::string body = R"(
1684 OpAtomicFlagClear %f32_var %device %relaxed
1685 )";
1686
1687 CompileSuccessfully(GenerateKernelCode(body));
1688 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1689 EXPECT_THAT(
1690 getDiagnosticString(),
1691 HasSubstr("AtomicFlagClear: "
1692 "expected Pointer to point to a value of 32-bit integer type"));
1693 }
1694
TEST_F(ValidateAtomics,AtomicFlagClearNotInt32Pointer)1695 TEST_F(ValidateAtomics, AtomicFlagClearNotInt32Pointer) {
1696 const std::string body = R"(
1697 OpAtomicFlagClear %u64_var %device %relaxed
1698 )";
1699
1700 CompileSuccessfully(GenerateKernelCode(body, "OpCapability Int64Atomics\n"));
1701 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1702 EXPECT_THAT(
1703 getDiagnosticString(),
1704 HasSubstr("AtomicFlagClear: "
1705 "expected Pointer to point to a value of 32-bit integer type"));
1706 }
1707
TEST_F(ValidateAtomics,AtomicFlagClearWrongScopeType)1708 TEST_F(ValidateAtomics, AtomicFlagClearWrongScopeType) {
1709 const std::string body = R"(
1710 OpAtomicFlagClear %u32_var %u64_1 %relaxed
1711 )";
1712
1713 CompileSuccessfully(GenerateKernelCode(body));
1714 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1715 EXPECT_THAT(getDiagnosticString(),
1716 HasSubstr("AtomicFlagClear: expected scope to be a 32-bit "
1717 "int\n OpAtomicFlagClear %30 %ulong_1 %uint_0_1\n"));
1718 }
1719
TEST_F(ValidateAtomics,AtomicFlagClearWrongMemorySemanticsType)1720 TEST_F(ValidateAtomics, AtomicFlagClearWrongMemorySemanticsType) {
1721 const std::string body = R"(
1722 OpAtomicFlagClear %u32_var %device %u64_1
1723 )";
1724
1725 CompileSuccessfully(GenerateKernelCode(body));
1726 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1727 EXPECT_THAT(
1728 getDiagnosticString(),
1729 HasSubstr(
1730 "AtomicFlagClear: expected Memory Semantics to be a 32-bit int"));
1731 }
1732
TEST_F(ValidateAtomics,AtomicIIncrementAcquireAndRelease)1733 TEST_F(ValidateAtomics, AtomicIIncrementAcquireAndRelease) {
1734 const std::string body = R"(
1735 OpAtomicStore %u32_var %device %relaxed %u32_1
1736 %val1 = OpAtomicIIncrement %u32 %u32_var %device %acquire_and_release
1737 )";
1738
1739 CompileSuccessfully(GenerateKernelCode(body));
1740 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1741 EXPECT_THAT(getDiagnosticString(),
1742 HasSubstr("AtomicIIncrement: Memory Semantics can have at most "
1743 "one of the following bits set: Acquire, Release, "
1744 "AcquireRelease or SequentiallyConsistent"));
1745 }
1746
TEST_F(ValidateAtomics,AtomicUniformMemorySemanticsShader)1747 TEST_F(ValidateAtomics, AtomicUniformMemorySemanticsShader) {
1748 const std::string body = R"(
1749 OpAtomicStore %u32_var %device %relaxed %u32_1
1750 %val1 = OpAtomicIIncrement %u32 %u32_var %device %acquire_release_uniform_workgroup
1751 )";
1752
1753 CompileSuccessfully(GenerateShaderCode(body));
1754 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1755 }
1756
TEST_F(ValidateAtomics,AtomicUniformMemorySemanticsKernel)1757 TEST_F(ValidateAtomics, AtomicUniformMemorySemanticsKernel) {
1758 const std::string body = R"(
1759 OpAtomicStore %u32_var %device %relaxed %u32_1
1760 %val1 = OpAtomicIIncrement %u32 %u32_var %device %acquire_release_uniform_workgroup
1761 )";
1762
1763 CompileSuccessfully(GenerateKernelCode(body));
1764 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1765 EXPECT_THAT(getDiagnosticString(),
1766 HasSubstr("AtomicIIncrement: Memory Semantics UniformMemory "
1767 "requires capability Shader"));
1768 }
1769
1770 // Lack of the AtomicStorage capability is intentionally ignored, see
1771 // https://github.com/KhronosGroup/glslang/issues/1618 for the reasoning why.
TEST_F(ValidateAtomics,AtomicCounterMemorySemanticsNoCapability)1772 TEST_F(ValidateAtomics, AtomicCounterMemorySemanticsNoCapability) {
1773 const std::string body = R"(
1774 OpAtomicStore %u32_var %device %relaxed %u32_1
1775 %val1 = OpAtomicIIncrement %u32 %u32_var %device
1776 %acquire_release_atomic_counter_workgroup
1777 )";
1778
1779 CompileSuccessfully(GenerateKernelCode(body));
1780 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1781 }
1782
TEST_F(ValidateAtomics,AtomicCounterMemorySemanticsWithCapability)1783 TEST_F(ValidateAtomics, AtomicCounterMemorySemanticsWithCapability) {
1784 const std::string body = R"(
1785 OpAtomicStore %u32_var %device %relaxed %u32_1
1786 %val1 = OpAtomicIIncrement %u32 %u32_var %device %acquire_release_atomic_counter_workgroup
1787 )";
1788
1789 CompileSuccessfully(GenerateKernelCode(body, "OpCapability AtomicStorage\n"));
1790 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1791 }
1792
TEST_F(ValidateAtomics,VulkanMemoryModelBanSequentiallyConsistentAtomicLoad)1793 TEST_F(ValidateAtomics, VulkanMemoryModelBanSequentiallyConsistentAtomicLoad) {
1794 const std::string body = R"(
1795 %ld = OpAtomicLoad %u32 %u32_var %workgroup %sequentially_consistent
1796 )";
1797
1798 const std::string extra = R"(
1799 OpCapability VulkanMemoryModelKHR
1800 OpExtension "SPV_KHR_vulkan_memory_model"
1801 )";
1802
1803 CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
1804 SPV_ENV_UNIVERSAL_1_3);
1805 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1806 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1807 EXPECT_THAT(getDiagnosticString(),
1808 HasSubstr("SequentiallyConsistent memory semantics cannot be "
1809 "used with the VulkanKHR memory model."));
1810 }
1811
TEST_F(ValidateAtomics,VulkanMemoryModelBanSequentiallyConsistentAtomicStore)1812 TEST_F(ValidateAtomics, VulkanMemoryModelBanSequentiallyConsistentAtomicStore) {
1813 const std::string body = R"(
1814 OpAtomicStore %u32_var %workgroup %sequentially_consistent %u32_0
1815 )";
1816
1817 const std::string extra = R"(
1818 OpCapability VulkanMemoryModelKHR
1819 OpExtension "SPV_KHR_vulkan_memory_model"
1820 )";
1821
1822 CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
1823 SPV_ENV_UNIVERSAL_1_3);
1824 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1825 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1826 EXPECT_THAT(getDiagnosticString(),
1827 HasSubstr("SequentiallyConsistent memory semantics cannot be "
1828 "used with the VulkanKHR memory model."));
1829 }
1830
TEST_F(ValidateAtomics,VulkanMemoryModelBanSequentiallyConsistentAtomicExchange)1831 TEST_F(ValidateAtomics,
1832 VulkanMemoryModelBanSequentiallyConsistentAtomicExchange) {
1833 const std::string body = R"(
1834 %ex = OpAtomicExchange %u32 %u32_var %workgroup %sequentially_consistent %u32_0
1835 )";
1836
1837 const std::string extra = R"(
1838 OpCapability VulkanMemoryModelKHR
1839 OpExtension "SPV_KHR_vulkan_memory_model"
1840 )";
1841
1842 CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
1843 SPV_ENV_UNIVERSAL_1_3);
1844 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1845 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1846 EXPECT_THAT(getDiagnosticString(),
1847 HasSubstr("SequentiallyConsistent memory semantics cannot be "
1848 "used with the VulkanKHR memory model."));
1849 }
1850
TEST_F(ValidateAtomics,VulkanMemoryModelBanSequentiallyConsistentAtomicCompareExchangeEqual)1851 TEST_F(ValidateAtomics,
1852 VulkanMemoryModelBanSequentiallyConsistentAtomicCompareExchangeEqual) {
1853 const std::string body = R"(
1854 %ex = OpAtomicCompareExchange %u32 %u32_var %workgroup %sequentially_consistent %relaxed %u32_0 %u32_0
1855 )";
1856
1857 const std::string extra = R"(
1858 OpCapability VulkanMemoryModelKHR
1859 OpExtension "SPV_KHR_vulkan_memory_model"
1860 )";
1861
1862 CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
1863 SPV_ENV_UNIVERSAL_1_3);
1864 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1865 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1866 EXPECT_THAT(getDiagnosticString(),
1867 HasSubstr("SequentiallyConsistent memory semantics cannot be "
1868 "used with the VulkanKHR memory model."));
1869 }
1870
TEST_F(ValidateAtomics,VulkanMemoryModelBanSequentiallyConsistentAtomicCompareExchangeUnequal)1871 TEST_F(ValidateAtomics,
1872 VulkanMemoryModelBanSequentiallyConsistentAtomicCompareExchangeUnequal) {
1873 const std::string body = R"(
1874 %ex = OpAtomicCompareExchange %u32 %u32_var %workgroup %relaxed %sequentially_consistent %u32_0 %u32_0
1875 )";
1876
1877 const std::string extra = R"(
1878 OpCapability VulkanMemoryModelKHR
1879 OpExtension "SPV_KHR_vulkan_memory_model"
1880 )";
1881
1882 CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
1883 SPV_ENV_UNIVERSAL_1_3);
1884 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1885 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1886 EXPECT_THAT(getDiagnosticString(),
1887 HasSubstr("SequentiallyConsistent memory semantics cannot be "
1888 "used with the VulkanKHR memory model."));
1889 }
1890
TEST_F(ValidateAtomics,VulkanMemoryModelBanSequentiallyConsistentAtomicIIncrement)1891 TEST_F(ValidateAtomics,
1892 VulkanMemoryModelBanSequentiallyConsistentAtomicIIncrement) {
1893 const std::string body = R"(
1894 %inc = OpAtomicIIncrement %u32 %u32_var %workgroup %sequentially_consistent
1895 )";
1896
1897 const std::string extra = R"(
1898 OpCapability VulkanMemoryModelKHR
1899 OpExtension "SPV_KHR_vulkan_memory_model"
1900 )";
1901
1902 CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
1903 SPV_ENV_UNIVERSAL_1_3);
1904 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1905 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1906 EXPECT_THAT(getDiagnosticString(),
1907 HasSubstr("SequentiallyConsistent memory semantics cannot be "
1908 "used with the VulkanKHR memory model."));
1909 }
1910
TEST_F(ValidateAtomics,VulkanMemoryModelBanSequentiallyConsistentAtomicIDecrement)1911 TEST_F(ValidateAtomics,
1912 VulkanMemoryModelBanSequentiallyConsistentAtomicIDecrement) {
1913 const std::string body = R"(
1914 %dec = OpAtomicIDecrement %u32 %u32_var %workgroup %sequentially_consistent
1915 )";
1916
1917 const std::string extra = R"(
1918 OpCapability VulkanMemoryModelKHR
1919 OpExtension "SPV_KHR_vulkan_memory_model"
1920 )";
1921
1922 CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
1923 SPV_ENV_UNIVERSAL_1_3);
1924 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1925 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1926 EXPECT_THAT(getDiagnosticString(),
1927 HasSubstr("SequentiallyConsistent memory semantics cannot be "
1928 "used with the VulkanKHR memory model."));
1929 }
1930
TEST_F(ValidateAtomics,VulkanMemoryModelBanSequentiallyConsistentAtomicIAdd)1931 TEST_F(ValidateAtomics, VulkanMemoryModelBanSequentiallyConsistentAtomicIAdd) {
1932 const std::string body = R"(
1933 %add = OpAtomicIAdd %u32 %u32_var %workgroup %sequentially_consistent %u32_0
1934 )";
1935
1936 const std::string extra = R"(
1937 OpCapability VulkanMemoryModelKHR
1938 OpExtension "SPV_KHR_vulkan_memory_model"
1939 )";
1940
1941 CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
1942 SPV_ENV_UNIVERSAL_1_3);
1943 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1944 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1945 EXPECT_THAT(getDiagnosticString(),
1946 HasSubstr("SequentiallyConsistent memory semantics cannot be "
1947 "used with the VulkanKHR memory model."));
1948 }
1949
TEST_F(ValidateAtomics,VulkanMemoryModelBanSequentiallyConsistentAtomicISub)1950 TEST_F(ValidateAtomics, VulkanMemoryModelBanSequentiallyConsistentAtomicISub) {
1951 const std::string body = R"(
1952 %sub = OpAtomicISub %u32 %u32_var %workgroup %sequentially_consistent %u32_0
1953 )";
1954
1955 const std::string extra = R"(
1956 OpCapability VulkanMemoryModelKHR
1957 OpExtension "SPV_KHR_vulkan_memory_model"
1958 )";
1959
1960 CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
1961 SPV_ENV_UNIVERSAL_1_3);
1962 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1963 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1964 EXPECT_THAT(getDiagnosticString(),
1965 HasSubstr("SequentiallyConsistent memory semantics cannot be "
1966 "used with the VulkanKHR memory model."));
1967 }
1968
TEST_F(ValidateAtomics,VulkanMemoryModelBanSequentiallyConsistentAtomicSMin)1969 TEST_F(ValidateAtomics, VulkanMemoryModelBanSequentiallyConsistentAtomicSMin) {
1970 const std::string body = R"(
1971 %min = OpAtomicSMin %u32 %u32_var %workgroup %sequentially_consistent %u32_0
1972 )";
1973
1974 const std::string extra = R"(
1975 OpCapability VulkanMemoryModelKHR
1976 OpExtension "SPV_KHR_vulkan_memory_model"
1977 )";
1978
1979 CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
1980 SPV_ENV_UNIVERSAL_1_3);
1981 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1982 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1983 EXPECT_THAT(getDiagnosticString(),
1984 HasSubstr("SequentiallyConsistent memory semantics cannot be "
1985 "used with the VulkanKHR memory model."));
1986 }
1987
TEST_F(ValidateAtomics,VulkanMemoryModelBanSequentiallyConsistentAtomicUMin)1988 TEST_F(ValidateAtomics, VulkanMemoryModelBanSequentiallyConsistentAtomicUMin) {
1989 const std::string body = R"(
1990 %min = OpAtomicUMin %u32 %u32_var %workgroup %sequentially_consistent %u32_0
1991 )";
1992
1993 const std::string extra = R"(
1994 OpCapability VulkanMemoryModelKHR
1995 OpExtension "SPV_KHR_vulkan_memory_model"
1996 )";
1997
1998 CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
1999 SPV_ENV_UNIVERSAL_1_3);
2000 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
2001 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2002 EXPECT_THAT(getDiagnosticString(),
2003 HasSubstr("SequentiallyConsistent memory semantics cannot be "
2004 "used with the VulkanKHR memory model."));
2005 }
2006
TEST_F(ValidateAtomics,VulkanMemoryModelBanSequentiallyConsistentAtomicFMinEXT)2007 TEST_F(ValidateAtomics, VulkanMemoryModelBanSequentiallyConsistentAtomicFMinEXT) {
2008 const std::string body = R"(
2009 %max = OpAtomicFMinEXT %f32 %f32_var %workgroup %sequentially_consistent %f32_0
2010 )";
2011
2012 const std::string extra = R"(
2013 OpCapability VulkanMemoryModelKHR
2014 OpCapability AtomicFloat32MinMaxEXT
2015 OpExtension "SPV_KHR_vulkan_memory_model"
2016 OpExtension "SPV_EXT_shader_atomic_float_min_max"
2017 )";
2018
2019 CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
2020 SPV_ENV_UNIVERSAL_1_3);
2021 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
2022 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2023 EXPECT_THAT(getDiagnosticString(),
2024 HasSubstr("SequentiallyConsistent memory semantics cannot be "
2025 "used with the VulkanKHR memory model."));
2026 }
2027
TEST_F(ValidateAtomics,VulkanMemoryModelBanSequentiallyConsistentAtomicSMax)2028 TEST_F(ValidateAtomics, VulkanMemoryModelBanSequentiallyConsistentAtomicSMax) {
2029 const std::string body = R"(
2030 %max = OpAtomicSMax %u32 %u32_var %workgroup %sequentially_consistent %u32_0
2031 )";
2032
2033 const std::string extra = R"(
2034 OpCapability VulkanMemoryModelKHR
2035 OpExtension "SPV_KHR_vulkan_memory_model"
2036 )";
2037
2038 CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
2039 SPV_ENV_UNIVERSAL_1_3);
2040 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
2041 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2042 EXPECT_THAT(getDiagnosticString(),
2043 HasSubstr("SequentiallyConsistent memory semantics cannot be "
2044 "used with the VulkanKHR memory model."));
2045 }
2046
TEST_F(ValidateAtomics,VulkanMemoryModelBanSequentiallyConsistentAtomicUMax)2047 TEST_F(ValidateAtomics, VulkanMemoryModelBanSequentiallyConsistentAtomicUMax) {
2048 const std::string body = R"(
2049 %max = OpAtomicUMax %u32 %u32_var %workgroup %sequentially_consistent %u32_0
2050 )";
2051
2052 const std::string extra = R"(
2053 OpCapability VulkanMemoryModelKHR
2054 OpExtension "SPV_KHR_vulkan_memory_model"
2055 )";
2056
2057 CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
2058 SPV_ENV_UNIVERSAL_1_3);
2059 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
2060 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2061 EXPECT_THAT(getDiagnosticString(),
2062 HasSubstr("SequentiallyConsistent memory semantics cannot be "
2063 "used with the VulkanKHR memory model."));
2064 }
2065
TEST_F(ValidateAtomics,VulkanMemoryModelBanSequentiallyConsistentAtomicFMaxEXT)2066 TEST_F(ValidateAtomics, VulkanMemoryModelBanSequentiallyConsistentAtomicFMaxEXT) {
2067 const std::string body = R"(
2068 %max = OpAtomicFMaxEXT %f32 %f32_var %workgroup %sequentially_consistent %f32_0
2069 )";
2070
2071 const std::string extra = R"(
2072 OpCapability VulkanMemoryModelKHR
2073 OpCapability AtomicFloat32MinMaxEXT
2074 OpExtension "SPV_KHR_vulkan_memory_model"
2075 OpExtension "SPV_EXT_shader_atomic_float_min_max"
2076 )";
2077
2078 CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
2079 SPV_ENV_UNIVERSAL_1_3);
2080 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
2081 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2082 EXPECT_THAT(getDiagnosticString(),
2083 HasSubstr("SequentiallyConsistent memory semantics cannot be "
2084 "used with the VulkanKHR memory model."));
2085 }
2086
TEST_F(ValidateAtomics,VulkanMemoryModelBanSequentiallyConsistentAtomicAnd)2087 TEST_F(ValidateAtomics, VulkanMemoryModelBanSequentiallyConsistentAtomicAnd) {
2088 const std::string body = R"(
2089 %and = OpAtomicAnd %u32 %u32_var %workgroup %sequentially_consistent %u32_0
2090 )";
2091
2092 const std::string extra = R"(
2093 OpCapability VulkanMemoryModelKHR
2094 OpExtension "SPV_KHR_vulkan_memory_model"
2095 )";
2096
2097 CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
2098 SPV_ENV_UNIVERSAL_1_3);
2099 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
2100 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2101 EXPECT_THAT(getDiagnosticString(),
2102 HasSubstr("SequentiallyConsistent memory semantics cannot be "
2103 "used with the VulkanKHR memory model."));
2104 }
2105
TEST_F(ValidateAtomics,VulkanMemoryModelBanSequentiallyConsistentAtomicOr)2106 TEST_F(ValidateAtomics, VulkanMemoryModelBanSequentiallyConsistentAtomicOr) {
2107 const std::string body = R"(
2108 %or = OpAtomicOr %u32 %u32_var %workgroup %sequentially_consistent %u32_0
2109 )";
2110
2111 const std::string extra = R"(
2112 OpCapability VulkanMemoryModelKHR
2113 OpExtension "SPV_KHR_vulkan_memory_model"
2114 )";
2115
2116 CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
2117 SPV_ENV_UNIVERSAL_1_3);
2118 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
2119 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2120 EXPECT_THAT(getDiagnosticString(),
2121 HasSubstr("SequentiallyConsistent memory semantics cannot be "
2122 "used with the VulkanKHR memory model."));
2123 }
2124
TEST_F(ValidateAtomics,VulkanMemoryModelBanSequentiallyConsistentAtomicXor)2125 TEST_F(ValidateAtomics, VulkanMemoryModelBanSequentiallyConsistentAtomicXor) {
2126 const std::string body = R"(
2127 %xor = OpAtomicXor %u32 %u32_var %workgroup %sequentially_consistent %u32_0
2128 )";
2129
2130 const std::string extra = R"(
2131 OpCapability VulkanMemoryModelKHR
2132 OpExtension "SPV_KHR_vulkan_memory_model"
2133 )";
2134
2135 CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
2136 SPV_ENV_UNIVERSAL_1_3);
2137 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
2138 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2139 EXPECT_THAT(getDiagnosticString(),
2140 HasSubstr("SequentiallyConsistent memory semantics cannot be "
2141 "used with the VulkanKHR memory model."));
2142 }
2143
TEST_F(ValidateAtomics,OutputMemoryKHRRequiresVulkanMemoryModelKHR)2144 TEST_F(ValidateAtomics, OutputMemoryKHRRequiresVulkanMemoryModelKHR) {
2145 const std::string text = R"(
2146 OpCapability Shader
2147 OpMemoryModel Logical GLSL450
2148 OpEntryPoint Fragment %1 "func"
2149 OpExecutionMode %1 OriginUpperLeft
2150 %2 = OpTypeVoid
2151 %3 = OpTypeInt 32 0
2152 %semantics = OpConstant %3 4100
2153 %5 = OpTypeFunction %2
2154 %workgroup = OpConstant %3 2
2155 %ptr = OpTypePointer Workgroup %3
2156 %var = OpVariable %ptr Workgroup
2157 %1 = OpFunction %2 None %5
2158 %7 = OpLabel
2159 OpAtomicStore %var %workgroup %semantics %workgroup
2160 OpReturn
2161 OpFunctionEnd
2162 )";
2163
2164 CompileSuccessfully(text);
2165 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2166 EXPECT_THAT(getDiagnosticString(),
2167 HasSubstr("AtomicStore: Memory Semantics OutputMemoryKHR "
2168 "requires capability VulkanMemoryModelKHR"));
2169 }
2170
TEST_F(ValidateAtomics,MakeAvailableKHRRequiresVulkanMemoryModelKHR)2171 TEST_F(ValidateAtomics, MakeAvailableKHRRequiresVulkanMemoryModelKHR) {
2172 const std::string text = R"(
2173 OpCapability Shader
2174 OpMemoryModel Logical GLSL450
2175 OpEntryPoint Fragment %1 "func"
2176 OpExecutionMode %1 OriginUpperLeft
2177 %2 = OpTypeVoid
2178 %3 = OpTypeInt 32 0
2179 %semantics = OpConstant %3 8196
2180 %5 = OpTypeFunction %2
2181 %workgroup = OpConstant %3 2
2182 %ptr = OpTypePointer Workgroup %3
2183 %var = OpVariable %ptr Workgroup
2184 %1 = OpFunction %2 None %5
2185 %7 = OpLabel
2186 OpAtomicStore %var %workgroup %semantics %workgroup
2187 OpReturn
2188 OpFunctionEnd
2189 )";
2190
2191 CompileSuccessfully(text);
2192 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2193 EXPECT_THAT(getDiagnosticString(),
2194 HasSubstr("AtomicStore: Memory Semantics MakeAvailableKHR "
2195 "requires capability VulkanMemoryModelKHR"));
2196 }
2197
TEST_F(ValidateAtomics,MakeVisibleKHRRequiresVulkanMemoryModelKHR)2198 TEST_F(ValidateAtomics, MakeVisibleKHRRequiresVulkanMemoryModelKHR) {
2199 const std::string text = R"(
2200 OpCapability Shader
2201 OpMemoryModel Logical GLSL450
2202 OpEntryPoint Fragment %1 "func"
2203 OpExecutionMode %1 OriginUpperLeft
2204 %2 = OpTypeVoid
2205 %3 = OpTypeInt 32 0
2206 %semantics = OpConstant %3 16386
2207 %5 = OpTypeFunction %2
2208 %workgroup = OpConstant %3 2
2209 %ptr = OpTypePointer Workgroup %3
2210 %var = OpVariable %ptr Workgroup
2211 %1 = OpFunction %2 None %5
2212 %7 = OpLabel
2213 %ld = OpAtomicLoad %3 %var %workgroup %semantics
2214 OpReturn
2215 OpFunctionEnd
2216 )";
2217
2218 CompileSuccessfully(text);
2219 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2220 EXPECT_THAT(getDiagnosticString(),
2221 HasSubstr("AtomicLoad: Memory Semantics MakeVisibleKHR requires "
2222 "capability VulkanMemoryModelKHR"));
2223 }
2224
TEST_F(ValidateAtomics,MakeAvailableKHRRequiresReleaseSemantics)2225 TEST_F(ValidateAtomics, MakeAvailableKHRRequiresReleaseSemantics) {
2226 const std::string text = R"(
2227 OpCapability Shader
2228 OpCapability VulkanMemoryModelKHR
2229 OpExtension "SPV_KHR_vulkan_memory_model"
2230 OpMemoryModel Logical VulkanKHR
2231 OpEntryPoint Fragment %1 "func"
2232 OpExecutionMode %1 OriginUpperLeft
2233 %2 = OpTypeVoid
2234 %3 = OpTypeInt 32 0
2235 %semantics = OpConstant %3 8448
2236 %5 = OpTypeFunction %2
2237 %workgroup = OpConstant %3 2
2238 %ptr = OpTypePointer Workgroup %3
2239 %var = OpVariable %ptr Workgroup
2240 %1 = OpFunction %2 None %5
2241 %7 = OpLabel
2242 OpAtomicStore %var %workgroup %semantics %workgroup
2243 OpReturn
2244 OpFunctionEnd
2245 )";
2246
2247 CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
2248 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
2249 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2250 EXPECT_THAT(
2251 getDiagnosticString(),
2252 HasSubstr("AtomicStore: MakeAvailableKHR Memory Semantics also requires "
2253 "either Release or AcquireRelease Memory Semantics"));
2254 }
2255
TEST_F(ValidateAtomics,MakeVisibleKHRRequiresAcquireSemantics)2256 TEST_F(ValidateAtomics, MakeVisibleKHRRequiresAcquireSemantics) {
2257 const std::string text = R"(
2258 OpCapability Shader
2259 OpCapability VulkanMemoryModelKHR
2260 OpExtension "SPV_KHR_vulkan_memory_model"
2261 OpMemoryModel Logical VulkanKHR
2262 OpEntryPoint Fragment %1 "func"
2263 OpExecutionMode %1 OriginUpperLeft
2264 %2 = OpTypeVoid
2265 %3 = OpTypeInt 32 0
2266 %semantics = OpConstant %3 16640
2267 %5 = OpTypeFunction %2
2268 %workgroup = OpConstant %3 2
2269 %ptr = OpTypePointer Workgroup %3
2270 %var = OpVariable %ptr Workgroup
2271 %1 = OpFunction %2 None %5
2272 %7 = OpLabel
2273 %ld = OpAtomicLoad %3 %var %workgroup %semantics
2274 OpReturn
2275 OpFunctionEnd
2276 )";
2277
2278 CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
2279 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
2280 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2281 EXPECT_THAT(
2282 getDiagnosticString(),
2283 HasSubstr("AtomicLoad: MakeVisibleKHR Memory Semantics also requires "
2284 "either Acquire or AcquireRelease Memory Semantics"));
2285 }
2286
TEST_F(ValidateAtomics,MakeAvailableKHRRequiresStorageSemantics)2287 TEST_F(ValidateAtomics, MakeAvailableKHRRequiresStorageSemantics) {
2288 const std::string text = R"(
2289 OpCapability Shader
2290 OpCapability VulkanMemoryModelKHR
2291 OpExtension "SPV_KHR_vulkan_memory_model"
2292 OpMemoryModel Logical VulkanKHR
2293 OpEntryPoint Fragment %1 "func"
2294 OpExecutionMode %1 OriginUpperLeft
2295 %2 = OpTypeVoid
2296 %3 = OpTypeInt 32 0
2297 %semantics = OpConstant %3 8196
2298 %5 = OpTypeFunction %2
2299 %workgroup = OpConstant %3 2
2300 %ptr = OpTypePointer Workgroup %3
2301 %var = OpVariable %ptr Workgroup
2302 %1 = OpFunction %2 None %5
2303 %7 = OpLabel
2304 OpAtomicStore %var %workgroup %semantics %workgroup
2305 OpReturn
2306 OpFunctionEnd
2307 )";
2308
2309 CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
2310 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
2311 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2312 EXPECT_THAT(
2313 getDiagnosticString(),
2314 HasSubstr(
2315 "AtomicStore: expected Memory Semantics to include a storage class"));
2316 }
2317
TEST_F(ValidateAtomics,MakeVisibleKHRRequiresStorageSemantics)2318 TEST_F(ValidateAtomics, MakeVisibleKHRRequiresStorageSemantics) {
2319 const std::string text = R"(
2320 OpCapability Shader
2321 OpCapability VulkanMemoryModelKHR
2322 OpExtension "SPV_KHR_vulkan_memory_model"
2323 OpMemoryModel Logical VulkanKHR
2324 OpEntryPoint Fragment %1 "func"
2325 OpExecutionMode %1 OriginUpperLeft
2326 %2 = OpTypeVoid
2327 %3 = OpTypeInt 32 0
2328 %semantics = OpConstant %3 16386
2329 %5 = OpTypeFunction %2
2330 %workgroup = OpConstant %3 2
2331 %ptr = OpTypePointer Workgroup %3
2332 %var = OpVariable %ptr Workgroup
2333 %1 = OpFunction %2 None %5
2334 %7 = OpLabel
2335 %ld = OpAtomicLoad %3 %var %workgroup %semantics
2336 OpReturn
2337 OpFunctionEnd
2338 )";
2339
2340 CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
2341 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
2342 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2343 EXPECT_THAT(
2344 getDiagnosticString(),
2345 HasSubstr(
2346 "AtomicLoad: expected Memory Semantics to include a storage class"));
2347 }
2348
TEST_F(ValidateAtomics,VulkanMemoryModelAllowsQueueFamilyKHR)2349 TEST_F(ValidateAtomics, VulkanMemoryModelAllowsQueueFamilyKHR) {
2350 const std::string body = R"(
2351 %val = OpAtomicAnd %u32 %u32_var %queuefamily %relaxed %u32_1
2352 )";
2353
2354 const std::string extra = R"(
2355 OpCapability VulkanMemoryModelKHR
2356 OpExtension "SPV_KHR_vulkan_memory_model"
2357 )";
2358
2359 CompileSuccessfully(GenerateShaderComputeCode(body, extra, "", "VulkanKHR"),
2360 SPV_ENV_VULKAN_1_1);
2361 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
2362 }
2363
TEST_F(ValidateAtomics,NonVulkanMemoryModelDisallowsQueueFamilyKHR)2364 TEST_F(ValidateAtomics, NonVulkanMemoryModelDisallowsQueueFamilyKHR) {
2365 const std::string body = R"(
2366 %val = OpAtomicAnd %u32 %u32_var %queuefamily %relaxed %u32_1
2367 )";
2368
2369 CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_1);
2370 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_1));
2371 EXPECT_THAT(getDiagnosticString(),
2372 HasSubstr("AtomicAnd: Memory Scope QueueFamilyKHR requires "
2373 "capability VulkanMemoryModelKHR\n %42 = OpAtomicAnd "
2374 "%uint %29 %uint_5 %uint_0_1 %uint_1\n"));
2375 }
2376
TEST_F(ValidateAtomics,SemanticsSpecConstantShader)2377 TEST_F(ValidateAtomics, SemanticsSpecConstantShader) {
2378 const std::string spirv = R"(
2379 OpCapability Shader
2380 OpMemoryModel Logical GLSL450
2381 OpEntryPoint Fragment %func "func"
2382 OpExecutionMode %func OriginUpperLeft
2383 %void = OpTypeVoid
2384 %int = OpTypeInt 32 0
2385 %spec_const = OpSpecConstant %int 0
2386 %workgroup = OpConstant %int 2
2387 %ptr_int_workgroup = OpTypePointer Workgroup %int
2388 %var = OpVariable %ptr_int_workgroup Workgroup
2389 %voidfn = OpTypeFunction %void
2390 %func = OpFunction %void None %voidfn
2391 %entry = OpLabel
2392 %ld = OpAtomicLoad %int %var %workgroup %spec_const
2393 OpReturn
2394 OpFunctionEnd
2395 )";
2396
2397 CompileSuccessfully(spirv);
2398 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2399 EXPECT_THAT(getDiagnosticString(),
2400 HasSubstr("Memory Semantics ids must be OpConstant when Shader "
2401 "capability is present"));
2402 }
2403
TEST_F(ValidateAtomics,SemanticsSpecConstantKernel)2404 TEST_F(ValidateAtomics, SemanticsSpecConstantKernel) {
2405 const std::string spirv = R"(
2406 OpCapability Kernel
2407 OpCapability Linkage
2408 OpMemoryModel Logical OpenCL
2409 %void = OpTypeVoid
2410 %int = OpTypeInt 32 0
2411 %spec_const = OpSpecConstant %int 0
2412 %workgroup = OpConstant %int 2
2413 %ptr_int_workgroup = OpTypePointer Workgroup %int
2414 %var = OpVariable %ptr_int_workgroup Workgroup
2415 %voidfn = OpTypeFunction %void
2416 %func = OpFunction %void None %voidfn
2417 %entry = OpLabel
2418 %ld = OpAtomicLoad %int %var %workgroup %spec_const
2419 OpReturn
2420 OpFunctionEnd
2421 )";
2422
2423 CompileSuccessfully(spirv);
2424 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2425 }
2426
TEST_F(ValidateAtomics,ScopeSpecConstantShader)2427 TEST_F(ValidateAtomics, ScopeSpecConstantShader) {
2428 const std::string spirv = R"(
2429 OpCapability Shader
2430 OpMemoryModel Logical GLSL450
2431 OpEntryPoint Fragment %func "func"
2432 OpExecutionMode %func OriginUpperLeft
2433 %void = OpTypeVoid
2434 %int = OpTypeInt 32 0
2435 %spec_const = OpSpecConstant %int 0
2436 %relaxed = OpConstant %int 0
2437 %ptr_int_workgroup = OpTypePointer Workgroup %int
2438 %var = OpVariable %ptr_int_workgroup Workgroup
2439 %voidfn = OpTypeFunction %void
2440 %func = OpFunction %void None %voidfn
2441 %entry = OpLabel
2442 %ld = OpAtomicLoad %int %var %spec_const %relaxed
2443 OpReturn
2444 OpFunctionEnd
2445 )";
2446
2447 CompileSuccessfully(spirv);
2448 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2449 EXPECT_THAT(
2450 getDiagnosticString(),
2451 HasSubstr(
2452 "Scope ids must be OpConstant when Shader capability is present"));
2453 }
2454
TEST_F(ValidateAtomics,ScopeSpecConstantKernel)2455 TEST_F(ValidateAtomics, ScopeSpecConstantKernel) {
2456 const std::string spirv = R"(
2457 OpCapability Kernel
2458 OpCapability Linkage
2459 OpMemoryModel Logical OpenCL
2460 %void = OpTypeVoid
2461 %int = OpTypeInt 32 0
2462 %spec_const = OpSpecConstant %int 0
2463 %relaxed = OpConstant %int 0
2464 %ptr_int_workgroup = OpTypePointer Workgroup %int
2465 %var = OpVariable %ptr_int_workgroup Workgroup
2466 %voidfn = OpTypeFunction %void
2467 %func = OpFunction %void None %voidfn
2468 %entry = OpLabel
2469 %ld = OpAtomicLoad %int %var %spec_const %relaxed
2470 OpReturn
2471 OpFunctionEnd
2472 )";
2473
2474 CompileSuccessfully(spirv);
2475 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2476 }
2477
TEST_F(ValidateAtomics,VulkanMemoryModelDeviceScopeBad)2478 TEST_F(ValidateAtomics, VulkanMemoryModelDeviceScopeBad) {
2479 const std::string body = R"(
2480 %val = OpAtomicAnd %u32 %u32_var %device %relaxed %u32_1
2481 )";
2482
2483 const std::string extra = R"(OpCapability VulkanMemoryModelKHR
2484 OpExtension "SPV_KHR_vulkan_memory_model"
2485 )";
2486
2487 CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
2488 SPV_ENV_UNIVERSAL_1_3);
2489 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
2490 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2491 EXPECT_THAT(
2492 getDiagnosticString(),
2493 HasSubstr("Use of device scope with VulkanKHR memory model requires the "
2494 "VulkanMemoryModelDeviceScopeKHR capability"));
2495 }
2496
TEST_F(ValidateAtomics,VulkanMemoryModelDeviceScopeGood)2497 TEST_F(ValidateAtomics, VulkanMemoryModelDeviceScopeGood) {
2498 const std::string body = R"(
2499 %val = OpAtomicAnd %u32 %u32_var %device %relaxed %u32_1
2500 )";
2501
2502 const std::string extra = R"(OpCapability VulkanMemoryModelKHR
2503 OpCapability VulkanMemoryModelDeviceScopeKHR
2504 OpExtension "SPV_KHR_vulkan_memory_model"
2505 )";
2506
2507 CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
2508 SPV_ENV_UNIVERSAL_1_3);
2509 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2510 }
2511
TEST_F(ValidateAtomics,CompareExchangeWeakV13ValV14Good)2512 TEST_F(ValidateAtomics, CompareExchangeWeakV13ValV14Good) {
2513 const std::string body = R"(
2514 %val1 = OpAtomicCompareExchangeWeak %u32 %u32_var %device %relaxed %relaxed %u32_0 %u32_0
2515 )";
2516
2517 CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_3);
2518 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
2519 }
2520
TEST_F(ValidateAtomics,CompareExchangeWeakV14Bad)2521 TEST_F(ValidateAtomics, CompareExchangeWeakV14Bad) {
2522 const std::string body = R"(
2523 %val1 = OpAtomicCompareExchangeWeak %u32 %u32_var %device %relaxed %relaxed %u32_0 %u32_0
2524 )";
2525
2526 CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_4);
2527 EXPECT_EQ(SPV_ERROR_WRONG_VERSION,
2528 ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
2529 EXPECT_THAT(
2530 getDiagnosticString(),
2531 HasSubstr(
2532 "AtomicCompareExchangeWeak requires SPIR-V version 1.3 or earlier"));
2533 }
2534
TEST_F(ValidateAtomics,CompareExchangeVolatileMatch)2535 TEST_F(ValidateAtomics, CompareExchangeVolatileMatch) {
2536 const std::string spirv = R"(
2537 OpCapability Shader
2538 OpCapability VulkanMemoryModelKHR
2539 OpCapability Linkage
2540 OpExtension "SPV_KHR_vulkan_memory_model"
2541 OpMemoryModel Logical VulkanKHR
2542 %void = OpTypeVoid
2543 %int = OpTypeInt 32 0
2544 %int_0 = OpConstant %int 0
2545 %int_1 = OpConstant %int 1
2546 %workgroup = OpConstant %int 2
2547 %volatile = OpConstant %int 32768
2548 %ptr_wg_int = OpTypePointer Workgroup %int
2549 %wg_var = OpVariable %ptr_wg_int Workgroup
2550 %void_fn = OpTypeFunction %void
2551 %func = OpFunction %void None %void_fn
2552 %entry = OpLabel
2553 %cmp_ex = OpAtomicCompareExchange %int %wg_var %workgroup %volatile %volatile %int_0 %int_1
2554 OpReturn
2555 OpFunctionEnd
2556 )";
2557
2558 CompileSuccessfully(spirv);
2559 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2560 }
2561
TEST_F(ValidateAtomics,CompareExchangeVolatileMismatch)2562 TEST_F(ValidateAtomics, CompareExchangeVolatileMismatch) {
2563 const std::string spirv = R"(
2564 OpCapability Shader
2565 OpCapability VulkanMemoryModelKHR
2566 OpCapability Linkage
2567 OpExtension "SPV_KHR_vulkan_memory_model"
2568 OpMemoryModel Logical VulkanKHR
2569 %void = OpTypeVoid
2570 %int = OpTypeInt 32 0
2571 %int_0 = OpConstant %int 0
2572 %int_1 = OpConstant %int 1
2573 %workgroup = OpConstant %int 2
2574 %volatile = OpConstant %int 32768
2575 %non_volatile = OpConstant %int 0
2576 %ptr_wg_int = OpTypePointer Workgroup %int
2577 %wg_var = OpVariable %ptr_wg_int Workgroup
2578 %void_fn = OpTypeFunction %void
2579 %func = OpFunction %void None %void_fn
2580 %entry = OpLabel
2581 %cmp_ex = OpAtomicCompareExchange %int %wg_var %workgroup %non_volatile %volatile %int_0 %int_1
2582 OpReturn
2583 OpFunctionEnd
2584 )";
2585
2586 CompileSuccessfully(spirv);
2587 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2588 EXPECT_THAT(getDiagnosticString(),
2589 HasSubstr("Volatile mask setting must match for Equal and "
2590 "Unequal memory semantics"));
2591 }
2592
TEST_F(ValidateAtomics,CompareExchangeVolatileMismatchCooperativeMatrix)2593 TEST_F(ValidateAtomics, CompareExchangeVolatileMismatchCooperativeMatrix) {
2594 const std::string spirv = R"(
2595 OpCapability Shader
2596 OpCapability VulkanMemoryModelKHR
2597 OpCapability Linkage
2598 OpCapability CooperativeMatrixNV
2599 OpExtension "SPV_KHR_vulkan_memory_model"
2600 OpExtension "SPV_NV_cooperative_matrix"
2601 OpMemoryModel Logical VulkanKHR
2602 %void = OpTypeVoid
2603 %int = OpTypeInt 32 0
2604 %int_0 = OpConstant %int 0
2605 %int_1 = OpConstant %int 1
2606 %workgroup = OpConstant %int 2
2607 %volatile = OpSpecConstant %int 32768
2608 %non_volatile = OpSpecConstant %int 32768
2609 %ptr_wg_int = OpTypePointer Workgroup %int
2610 %wg_var = OpVariable %ptr_wg_int Workgroup
2611 %void_fn = OpTypeFunction %void
2612 %func = OpFunction %void None %void_fn
2613 %entry = OpLabel
2614 %cmp_ex = OpAtomicCompareExchange %int %wg_var %workgroup %volatile %non_volatile %int_0 %int_1
2615 OpReturn
2616 OpFunctionEnd
2617 )";
2618
2619 // This is ok because we cannot evaluate the spec constant defaults.
2620 CompileSuccessfully(spirv);
2621 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2622 }
2623
TEST_F(ValidateAtomics,VolatileRequiresVulkanMemoryModel)2624 TEST_F(ValidateAtomics, VolatileRequiresVulkanMemoryModel) {
2625 const std::string spirv = R"(
2626 OpCapability Shader
2627 OpCapability Linkage
2628 OpMemoryModel Logical GLSL450
2629 %void = OpTypeVoid
2630 %int = OpTypeInt 32 0
2631 %int_0 = OpConstant %int 0
2632 %int_1 = OpConstant %int 1
2633 %workgroup = OpConstant %int 2
2634 %volatile = OpConstant %int 32768
2635 %ptr_wg_int = OpTypePointer Workgroup %int
2636 %wg_var = OpVariable %ptr_wg_int Workgroup
2637 %void_fn = OpTypeFunction %void
2638 %func = OpFunction %void None %void_fn
2639 %entry = OpLabel
2640 %ld = OpAtomicLoad %int %wg_var %workgroup %volatile
2641 OpReturn
2642 OpFunctionEnd
2643 )";
2644
2645 CompileSuccessfully(spirv);
2646 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2647 EXPECT_THAT(getDiagnosticString(),
2648 HasSubstr("Memory Semantics Volatile requires capability "
2649 "VulkanMemoryModelKHR"));
2650 }
2651
TEST_F(ValidateAtomics,CooperativeMatrixSemanticsMustBeConstant)2652 TEST_F(ValidateAtomics, CooperativeMatrixSemanticsMustBeConstant) {
2653 const std::string spirv = R"(
2654 OpCapability Shader
2655 OpCapability Linkage
2656 OpCapability CooperativeMatrixNV
2657 OpExtension "SPV_NV_cooperative_matrix"
2658 OpMemoryModel Logical GLSL450
2659 %void = OpTypeVoid
2660 %int = OpTypeInt 32 0
2661 %int_0 = OpConstant %int 0
2662 %int_1 = OpConstant %int 1
2663 %workgroup = OpConstant %int 2
2664 %undef = OpUndef %int
2665 %ptr_wg_int = OpTypePointer Workgroup %int
2666 %wg_var = OpVariable %ptr_wg_int Workgroup
2667 %void_fn = OpTypeFunction %void
2668 %func = OpFunction %void None %void_fn
2669 %entry = OpLabel
2670 %ld = OpAtomicLoad %int %wg_var %workgroup %undef
2671 OpReturn
2672 OpFunctionEnd
2673 )";
2674
2675 CompileSuccessfully(spirv);
2676 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2677 EXPECT_THAT(getDiagnosticString(),
2678 HasSubstr("Memory Semantics must be a constant instruction when "
2679 "CooperativeMatrixNV capability is present"));
2680 }
2681
TEST_F(ValidateAtomics,IIncrementBadPointerDataType)2682 TEST_F(ValidateAtomics, IIncrementBadPointerDataType) {
2683 const std::string spirv = R"(
2684 OpCapability Shader
2685 OpMemoryModel Logical GLSL450
2686 %uint = OpTypeInt 32 0
2687 %_ptr_Input_uint = OpTypePointer Input %uint
2688 %v3uint = OpTypeVector %uint 3
2689 %_ptr_Input_v3uint = OpTypePointer Input %v3uint
2690 %void = OpTypeVoid
2691 %16 = OpTypeFunction %void
2692 %uint_538976288 = OpConstant %uint 538976288
2693 %int = OpTypeInt 32 1
2694 %_runtimearr_int = OpTypeRuntimeArray %int
2695 %_struct_5 = OpTypeStruct %_runtimearr_int
2696 %_ptr_Uniform__struct_5 = OpTypePointer Uniform %_struct_5
2697 %3 = OpVariable %_ptr_Input_v3uint Input
2698 %7 = OpVariable %_ptr_Uniform__struct_5 Uniform
2699 %8224 = OpFunction %void None %16
2700 %65312 = OpLabel
2701 %25 = OpAccessChain %_ptr_Input_uint %3 %uint_538976288
2702 %26 = OpLoad %uint %25
2703 %2097184 = OpAtomicIIncrement %int %7 %uint_538976288 %26
2704 OpUnreachable
2705 OpFunctionEnd
2706 )";
2707
2708 CompileSuccessfully(spirv);
2709 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2710 EXPECT_THAT(getDiagnosticString(),
2711 HasSubstr("AtomicIIncrement: expected Pointer to point to a "
2712 "value of type Result Type"));
2713 }
2714
2715 } // namespace
2716 } // namespace val
2717 } // namespace spvtools
2718