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 environment, 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 environment, 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, "
782 "PhysicalStorageBuffer or TaskPayloadWorkgroupEXT."));
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([email protected]): 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(
1004 getDiagnosticString(),
1005 HasSubstr("Operand '27[%_ptr_Workgroup_float]' cannot be a type"));
1006 }
1007
TEST_F(ValidateAtomics,AtomicLoadWrongPointerDataType)1008 TEST_F(ValidateAtomics, AtomicLoadWrongPointerDataType) {
1009 const std::string body = R"(
1010 %val1 = OpAtomicLoad %u32 %f32_var %device %relaxed
1011 )";
1012
1013 CompileSuccessfully(GenerateKernelCode(body));
1014 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1015 EXPECT_THAT(
1016 getDiagnosticString(),
1017 HasSubstr("AtomicLoad: "
1018 "expected Pointer to point to a value of type Result Type"));
1019 }
1020
TEST_F(ValidateAtomics,AtomicLoadWrongScopeType)1021 TEST_F(ValidateAtomics, AtomicLoadWrongScopeType) {
1022 const std::string body = R"(
1023 %val1 = OpAtomicLoad %f32 %f32_var %f32_1 %relaxed
1024 )";
1025
1026 CompileSuccessfully(GenerateKernelCode(body));
1027 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1028 EXPECT_THAT(getDiagnosticString(),
1029 HasSubstr("AtomicLoad: expected scope to be a 32-bit int"));
1030 }
1031
TEST_F(ValidateAtomics,AtomicLoadWrongMemorySemanticsType)1032 TEST_F(ValidateAtomics, AtomicLoadWrongMemorySemanticsType) {
1033 const std::string body = R"(
1034 %val1 = OpAtomicLoad %f32 %f32_var %device %u64_1
1035 )";
1036
1037 CompileSuccessfully(GenerateKernelCode(body));
1038 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1039 EXPECT_THAT(
1040 getDiagnosticString(),
1041 HasSubstr("AtomicLoad: expected Memory Semantics to be a 32-bit int"));
1042 }
1043
TEST_F(ValidateAtomics,AtomicStoreKernelSuccess)1044 TEST_F(ValidateAtomics, AtomicStoreKernelSuccess) {
1045 const std::string body = R"(
1046 OpAtomicStore %f32_var %device %relaxed %f32_1
1047 OpAtomicStore %u32_var %subgroup %release %u32_1
1048 )";
1049
1050 CompileSuccessfully(GenerateKernelCode(body));
1051 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1052 }
1053
TEST_F(ValidateAtomics,AtomicStoreShaderSuccess)1054 TEST_F(ValidateAtomics, AtomicStoreShaderSuccess) {
1055 const std::string body = R"(
1056 OpAtomicStore %u32_var %device %release %u32_1
1057 OpAtomicStore %u32_var %subgroup %sequentially_consistent %u32_1
1058 )";
1059
1060 CompileSuccessfully(GenerateShaderCode(body));
1061 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1062 }
1063
TEST_F(ValidateAtomics,AtomicStoreVulkanSuccess)1064 TEST_F(ValidateAtomics, AtomicStoreVulkanSuccess) {
1065 const std::string body = R"(
1066 OpAtomicStore %u32_var %device %release %u32_1
1067 OpAtomicStore %u32_var %invocation %relaxed %u32_1
1068 )";
1069
1070 CompileSuccessfully(GenerateShaderComputeCode(body), SPV_ENV_VULKAN_1_0);
1071 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1072 }
1073
TEST_F(ValidateAtomics,AtomicStoreVulkanAcquire)1074 TEST_F(ValidateAtomics, AtomicStoreVulkanAcquire) {
1075 const std::string body = R"(
1076 OpAtomicStore %u32_var %device %acquire %u32_1
1077 )";
1078
1079 CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
1080 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1081 EXPECT_THAT(getDiagnosticString(),
1082 AnyVUID("VUID-StandaloneSpirv-OpAtomicStore-04730"));
1083 EXPECT_THAT(
1084 getDiagnosticString(),
1085 HasSubstr("Vulkan spec disallows OpAtomicStore with Memory Semantics "
1086 "Acquire, AcquireRelease and SequentiallyConsistent"));
1087 }
1088
TEST_F(ValidateAtomics,AtomicStoreVulkanAcquireRelease)1089 TEST_F(ValidateAtomics, AtomicStoreVulkanAcquireRelease) {
1090 const std::string body = R"(
1091 OpAtomicStore %u32_var %device %acquire_release %u32_1
1092 )";
1093
1094 CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
1095 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1096 EXPECT_THAT(getDiagnosticString(),
1097 AnyVUID("VUID-StandaloneSpirv-OpAtomicStore-04730"));
1098 EXPECT_THAT(
1099 getDiagnosticString(),
1100 HasSubstr("Vulkan spec disallows OpAtomicStore with Memory Semantics "
1101 "Acquire, AcquireRelease and SequentiallyConsistent"));
1102 }
1103
TEST_F(ValidateAtomics,AtomicStoreVulkanSequentiallyConsistent)1104 TEST_F(ValidateAtomics, AtomicStoreVulkanSequentiallyConsistent) {
1105 const std::string body = R"(
1106 OpAtomicStore %u32_var %device %sequentially_consistent %u32_1
1107 )";
1108
1109 CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
1110 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1111 EXPECT_THAT(getDiagnosticString(),
1112 AnyVUID("VUID-StandaloneSpirv-OpAtomicStore-04730"));
1113 EXPECT_THAT(
1114 getDiagnosticString(),
1115 HasSubstr("Vulkan spec disallows OpAtomicStore with Memory Semantics "
1116 "Acquire, AcquireRelease and SequentiallyConsistent"));
1117 }
1118
TEST_F(ValidateAtomics,AtomicStoreVulkanInvocationSemantics)1119 TEST_F(ValidateAtomics, AtomicStoreVulkanInvocationSemantics) {
1120 const std::string body = R"(
1121 OpAtomicStore %u32_var %invocation %acquire %u32_1
1122 )";
1123
1124 CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
1125 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1126 EXPECT_THAT(getDiagnosticString(),
1127 AnyVUID("VUID-StandaloneSpirv-None-04641"));
1128 EXPECT_THAT(
1129 getDiagnosticString(),
1130 HasSubstr("AtomicStore: Vulkan specification requires Memory Semantics "
1131 "to be None if used with Invocation Memory Scope"));
1132 }
1133
TEST_F(ValidateAtomics,AtomicStoreWrongPointerType)1134 TEST_F(ValidateAtomics, AtomicStoreWrongPointerType) {
1135 const std::string body = R"(
1136 OpAtomicStore %f32_1 %device %relaxed %f32_1
1137 )";
1138
1139 CompileSuccessfully(GenerateKernelCode(body));
1140 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1141 EXPECT_THAT(
1142 getDiagnosticString(),
1143 HasSubstr("AtomicStore: expected Pointer to be of type OpTypePointer"));
1144 }
1145
TEST_F(ValidateAtomics,AtomicStoreWrongPointerDataType)1146 TEST_F(ValidateAtomics, AtomicStoreWrongPointerDataType) {
1147 const std::string body = R"(
1148 OpAtomicStore %f32vec4_var %device %relaxed %f32_1
1149 )";
1150
1151 CompileSuccessfully(GenerateKernelCode(body));
1152 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1153 EXPECT_THAT(
1154 getDiagnosticString(),
1155 HasSubstr(
1156 "AtomicStore: "
1157 "expected Pointer to be a pointer to integer or float scalar type"));
1158 }
1159
TEST_F(ValidateAtomics,AtomicStoreWrongPointerStorageTypeForOpenCL)1160 TEST_F(ValidateAtomics, AtomicStoreWrongPointerStorageTypeForOpenCL) {
1161 const std::string body = R"(
1162 OpAtomicStore %f32_im_var %device %relaxed %f32_1
1163 )";
1164
1165 CompileSuccessfully(GenerateKernelCode(body));
1166 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_1_2));
1167 EXPECT_THAT(
1168 getDiagnosticString(),
1169 HasSubstr("AtomicStore: storage class must be Function, Workgroup, "
1170 "CrossWorkGroup or Generic in the OpenCL environment."));
1171 }
1172
TEST_F(ValidateAtomics,AtomicStoreWrongPointerStorageType)1173 TEST_F(ValidateAtomics, AtomicStoreWrongPointerStorageType) {
1174 const std::string body = R"(
1175 OpAtomicStore %f32_uc_var %device %relaxed %f32_1
1176 )";
1177
1178 CompileSuccessfully(GenerateKernelCode(body));
1179 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1180 EXPECT_THAT(getDiagnosticString(),
1181 HasSubstr("AtomicStore: storage class forbidden by universal "
1182 "validation rules."));
1183 }
1184
TEST_F(ValidateAtomics,AtomicStoreWrongScopeType)1185 TEST_F(ValidateAtomics, AtomicStoreWrongScopeType) {
1186 const std::string body = R"(
1187 OpAtomicStore %f32_var %f32_1 %relaxed %f32_1
1188 )";
1189
1190 CompileSuccessfully(GenerateKernelCode(body));
1191 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1192 EXPECT_THAT(getDiagnosticString(),
1193 HasSubstr("AtomicStore: expected scope to be a 32-bit int\n "
1194 "OpAtomicStore %28 %float_1 %uint_0_1 %float_1\n"));
1195 }
1196
TEST_F(ValidateAtomics,AtomicStoreWrongMemorySemanticsType)1197 TEST_F(ValidateAtomics, AtomicStoreWrongMemorySemanticsType) {
1198 const std::string body = R"(
1199 OpAtomicStore %f32_var %device %f32_1 %f32_1
1200 )";
1201
1202 CompileSuccessfully(GenerateKernelCode(body));
1203 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1204 EXPECT_THAT(
1205 getDiagnosticString(),
1206 HasSubstr("AtomicStore: expected Memory Semantics to be a 32-bit int"));
1207 }
1208
TEST_F(ValidateAtomics,AtomicStoreWrongValueType)1209 TEST_F(ValidateAtomics, AtomicStoreWrongValueType) {
1210 const std::string body = R"(
1211 OpAtomicStore %f32_var %device %relaxed %u32_1
1212 )";
1213
1214 CompileSuccessfully(GenerateKernelCode(body));
1215 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1216 EXPECT_THAT(
1217 getDiagnosticString(),
1218 HasSubstr("AtomicStore: "
1219 "expected Value type and the type pointed to by Pointer to "
1220 "be the same"));
1221 }
1222
TEST_F(ValidateAtomics,AtomicExchangeShaderSuccess)1223 TEST_F(ValidateAtomics, AtomicExchangeShaderSuccess) {
1224 const std::string body = R"(
1225 OpAtomicStore %u32_var %device %relaxed %u32_1
1226 %val2 = OpAtomicExchange %u32 %u32_var %device %relaxed %u32_0
1227 )";
1228
1229 CompileSuccessfully(GenerateShaderCode(body));
1230 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1231 }
1232
TEST_F(ValidateAtomics,AtomicExchangeKernelSuccess)1233 TEST_F(ValidateAtomics, AtomicExchangeKernelSuccess) {
1234 const std::string body = R"(
1235 OpAtomicStore %f32_var %device %relaxed %f32_1
1236 %val2 = OpAtomicExchange %f32 %f32_var %device %relaxed %f32_0
1237 OpAtomicStore %u32_var %device %relaxed %u32_1
1238 %val4 = OpAtomicExchange %u32 %u32_var %device %relaxed %u32_0
1239 )";
1240
1241 CompileSuccessfully(GenerateKernelCode(body));
1242 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1243 }
1244
TEST_F(ValidateAtomics,AtomicExchangeShaderFloat)1245 TEST_F(ValidateAtomics, AtomicExchangeShaderFloat) {
1246 const std::string body = R"(
1247 OpAtomicStore %f32_var %device %relaxed %f32_1
1248 %val2 = OpAtomicExchange %f32 %f32_var %device %relaxed %f32_0
1249 )";
1250
1251 CompileSuccessfully(GenerateShaderCode(body));
1252 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1253 }
1254
TEST_F(ValidateAtomics,AtomicExchangeWrongResultType)1255 TEST_F(ValidateAtomics, AtomicExchangeWrongResultType) {
1256 const std::string body = R"(
1257 OpStore %f32vec4_var %f32vec4_0000
1258 %val2 = OpAtomicExchange %f32vec4 %f32vec4_var %device %relaxed %f32vec4_0000
1259 )";
1260
1261 CompileSuccessfully(GenerateKernelCode(body));
1262 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1263 EXPECT_THAT(
1264 getDiagnosticString(),
1265 HasSubstr("AtomicExchange: "
1266 "expected Result Type to be integer or float scalar type"));
1267 }
1268
TEST_F(ValidateAtomics,AtomicExchangeWrongPointerType)1269 TEST_F(ValidateAtomics, AtomicExchangeWrongPointerType) {
1270 const std::string body = R"(
1271 %val2 = OpAtomicExchange %f32 %f32vec4_ptr %device %relaxed %f32vec4_0000
1272 )";
1273
1274 CompileSuccessfully(GenerateKernelCode(body));
1275 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1276 EXPECT_THAT(getDiagnosticString(),
1277 HasSubstr("Operand '33[%_ptr_Workgroup_v4float]' cannot be a "
1278 "type"));
1279 }
1280
TEST_F(ValidateAtomics,AtomicExchangeWrongPointerDataType)1281 TEST_F(ValidateAtomics, AtomicExchangeWrongPointerDataType) {
1282 const std::string body = R"(
1283 OpStore %f32vec4_var %f32vec4_0000
1284 %val2 = OpAtomicExchange %f32 %f32vec4_var %device %relaxed %f32vec4_0000
1285 )";
1286
1287 CompileSuccessfully(GenerateKernelCode(body));
1288 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1289 EXPECT_THAT(
1290 getDiagnosticString(),
1291 HasSubstr("AtomicExchange: "
1292 "expected Pointer to point to a value of type Result Type"));
1293 }
1294
TEST_F(ValidateAtomics,AtomicExchangeWrongScopeType)1295 TEST_F(ValidateAtomics, AtomicExchangeWrongScopeType) {
1296 const std::string body = R"(
1297 OpAtomicStore %f32_var %device %relaxed %f32_1
1298 %val2 = OpAtomicExchange %f32 %f32_var %f32_1 %relaxed %f32_0
1299 )";
1300
1301 CompileSuccessfully(GenerateKernelCode(body));
1302 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1303 EXPECT_THAT(getDiagnosticString(),
1304 HasSubstr("AtomicExchange: expected scope to be a 32-bit int"));
1305 }
1306
TEST_F(ValidateAtomics,AtomicExchangeWrongMemorySemanticsType)1307 TEST_F(ValidateAtomics, AtomicExchangeWrongMemorySemanticsType) {
1308 const std::string body = R"(
1309 OpAtomicStore %f32_var %device %relaxed %f32_1
1310 %val2 = OpAtomicExchange %f32 %f32_var %device %f32_1 %f32_0
1311 )";
1312
1313 CompileSuccessfully(GenerateKernelCode(body));
1314 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1315 EXPECT_THAT(
1316 getDiagnosticString(),
1317 HasSubstr(
1318 "AtomicExchange: expected Memory Semantics to be a 32-bit int"));
1319 }
1320
TEST_F(ValidateAtomics,AtomicExchangeWrongValueType)1321 TEST_F(ValidateAtomics, AtomicExchangeWrongValueType) {
1322 const std::string body = R"(
1323 OpAtomicStore %f32_var %device %relaxed %f32_1
1324 %val2 = OpAtomicExchange %f32 %f32_var %device %relaxed %u32_0
1325 )";
1326
1327 CompileSuccessfully(GenerateKernelCode(body));
1328 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1329 EXPECT_THAT(getDiagnosticString(),
1330 HasSubstr("AtomicExchange: "
1331 "expected Value to be of type Result Type"));
1332 }
1333
TEST_F(ValidateAtomics,AtomicExchangeVulkanInvocationSemantics)1334 TEST_F(ValidateAtomics, AtomicExchangeVulkanInvocationSemantics) {
1335 const std::string body = R"(
1336 OpAtomicStore %u32_var %invocation %relaxed %u32_1
1337 %val2 = OpAtomicExchange %u32 %u32_var %invocation %acquire %u32_0
1338 )";
1339
1340 CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
1341 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1342 EXPECT_THAT(getDiagnosticString(),
1343 AnyVUID("VUID-StandaloneSpirv-None-04641"));
1344 EXPECT_THAT(
1345 getDiagnosticString(),
1346 HasSubstr("AtomicExchange: Vulkan specification requires Memory "
1347 "Semantics to be None if used with Invocation Memory Scope"));
1348 }
1349
TEST_F(ValidateAtomics,AtomicCompareExchangeShaderSuccess)1350 TEST_F(ValidateAtomics, AtomicCompareExchangeShaderSuccess) {
1351 const std::string body = R"(
1352 OpAtomicStore %u32_var %device %relaxed %u32_1
1353 %val2 = OpAtomicCompareExchange %u32 %u32_var %device %relaxed %relaxed %u32_0 %u32_0
1354 )";
1355
1356 CompileSuccessfully(GenerateShaderCode(body));
1357 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1358 }
1359
TEST_F(ValidateAtomics,AtomicCompareExchangeKernelSuccess)1360 TEST_F(ValidateAtomics, AtomicCompareExchangeKernelSuccess) {
1361 const std::string body = R"(
1362 OpAtomicStore %u32_var %device %relaxed %u32_1
1363 %val2 = OpAtomicCompareExchange %u32 %u32_var %device %relaxed %relaxed %u32_0 %u32_0
1364 )";
1365
1366 CompileSuccessfully(GenerateKernelCode(body));
1367 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1368 }
1369
TEST_F(ValidateAtomics,AtomicCompareExchangeShaderFloat)1370 TEST_F(ValidateAtomics, AtomicCompareExchangeShaderFloat) {
1371 const std::string body = R"(
1372 OpAtomicStore %f32_var %device %relaxed %f32_1
1373 %val1 = OpAtomicCompareExchange %f32 %f32_var %device %relaxed %relaxed %f32_0 %f32_1
1374 )";
1375
1376 CompileSuccessfully(GenerateShaderCode(body));
1377 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1378 EXPECT_THAT(getDiagnosticString(),
1379 HasSubstr("AtomicCompareExchange: "
1380 "expected Result Type to be integer scalar type"));
1381 }
1382
TEST_F(ValidateAtomics,AtomicCompareExchangeWrongResultType)1383 TEST_F(ValidateAtomics, AtomicCompareExchangeWrongResultType) {
1384 const std::string body = R"(
1385 OpStore %f32vec4_var %f32vec4_0000
1386 %val2 = OpAtomicCompareExchange %f32vec4 %f32vec4_var %device %relaxed %relaxed %f32vec4_0000 %f32vec4_0000
1387 )";
1388
1389 CompileSuccessfully(GenerateKernelCode(body));
1390 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1391 EXPECT_THAT(getDiagnosticString(),
1392 HasSubstr("AtomicCompareExchange: "
1393 "expected Result Type to be integer scalar type"));
1394 }
1395
TEST_F(ValidateAtomics,AtomicCompareExchangeWrongPointerType)1396 TEST_F(ValidateAtomics, AtomicCompareExchangeWrongPointerType) {
1397 const std::string body = R"(
1398 %val2 = OpAtomicCompareExchange %f32 %f32vec4_ptr %device %relaxed %relaxed %f32vec4_0000 %f32vec4_0000
1399 )";
1400
1401 CompileSuccessfully(GenerateKernelCode(body));
1402 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1403 EXPECT_THAT(getDiagnosticString(),
1404 HasSubstr("Operand '33[%_ptr_Workgroup_v4float]' cannot be a "
1405 "type"));
1406 }
1407
TEST_F(ValidateAtomics,AtomicCompareExchangeWrongPointerDataType)1408 TEST_F(ValidateAtomics, AtomicCompareExchangeWrongPointerDataType) {
1409 const std::string body = R"(
1410 OpStore %f32vec4_var %f32vec4_0000
1411 %val2 = OpAtomicCompareExchange %u32 %f32vec4_var %device %relaxed %relaxed %u32_0 %u32_0
1412 )";
1413
1414 CompileSuccessfully(GenerateKernelCode(body));
1415 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1416 EXPECT_THAT(
1417 getDiagnosticString(),
1418 HasSubstr("AtomicCompareExchange: "
1419 "expected Pointer to point to a value of type Result Type"));
1420 }
1421
TEST_F(ValidateAtomics,AtomicCompareExchangeWrongScopeType)1422 TEST_F(ValidateAtomics, AtomicCompareExchangeWrongScopeType) {
1423 const std::string body = R"(
1424 OpAtomicStore %u64_var %device %relaxed %u64_1
1425 %val2 = OpAtomicCompareExchange %u64 %u64_var %u64_1 %relaxed %relaxed %u32_0 %u32_0
1426 )";
1427
1428 CompileSuccessfully(GenerateKernelCode(body, "OpCapability Int64Atomics\n"));
1429 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1430 EXPECT_THAT(getDiagnosticString(),
1431 HasSubstr("AtomicCompareExchange: expected scope to be a 32-bit "
1432 "int"));
1433 }
1434
TEST_F(ValidateAtomics,AtomicCompareExchangeWrongMemorySemanticsType1)1435 TEST_F(ValidateAtomics, AtomicCompareExchangeWrongMemorySemanticsType1) {
1436 const std::string body = R"(
1437 OpAtomicStore %u32_var %device %relaxed %u32_1
1438 %val2 = OpAtomicCompareExchange %u32 %u32_var %device %f32_1 %relaxed %u32_0 %u32_0
1439 )";
1440
1441 CompileSuccessfully(GenerateKernelCode(body));
1442 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1443 EXPECT_THAT(getDiagnosticString(),
1444 HasSubstr("AtomicCompareExchange: expected Memory Semantics to "
1445 "be a 32-bit int"));
1446 }
1447
TEST_F(ValidateAtomics,AtomicCompareExchangeWrongMemorySemanticsType2)1448 TEST_F(ValidateAtomics, AtomicCompareExchangeWrongMemorySemanticsType2) {
1449 const std::string body = R"(
1450 OpAtomicStore %u32_var %device %relaxed %u32_1
1451 %val2 = OpAtomicCompareExchange %u32 %u32_var %device %relaxed %f32_1 %u32_0 %u32_0
1452 )";
1453
1454 CompileSuccessfully(GenerateKernelCode(body));
1455 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1456 EXPECT_THAT(getDiagnosticString(),
1457 HasSubstr("AtomicCompareExchange: expected Memory Semantics to "
1458 "be a 32-bit int"));
1459 }
1460
TEST_F(ValidateAtomics,AtomicCompareExchangeUnequalRelease)1461 TEST_F(ValidateAtomics, AtomicCompareExchangeUnequalRelease) {
1462 const std::string body = R"(
1463 OpAtomicStore %u32_var %device %relaxed %u32_1
1464 %val2 = OpAtomicCompareExchange %u32 %u32_var %device %relaxed %release %u32_0 %u32_0
1465 )";
1466
1467 CompileSuccessfully(GenerateKernelCode(body));
1468 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1469 EXPECT_THAT(getDiagnosticString(),
1470 HasSubstr("AtomicCompareExchange: Memory Semantics Release and "
1471 "AcquireRelease cannot be used for operand Unequal"));
1472 }
1473
TEST_F(ValidateAtomics,AtomicCompareExchangeWrongValueType)1474 TEST_F(ValidateAtomics, AtomicCompareExchangeWrongValueType) {
1475 const std::string body = R"(
1476 OpAtomicStore %u32_var %device %relaxed %u32_1
1477 %val2 = OpAtomicCompareExchange %u32 %u32_var %device %relaxed %relaxed %f32_1 %u32_0
1478 )";
1479
1480 CompileSuccessfully(GenerateKernelCode(body));
1481 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1482 EXPECT_THAT(getDiagnosticString(),
1483 HasSubstr("AtomicCompareExchange: "
1484 "expected Value to be of type Result Type"));
1485 }
1486
TEST_F(ValidateAtomics,AtomicCompareExchangeWrongComparatorType)1487 TEST_F(ValidateAtomics, AtomicCompareExchangeWrongComparatorType) {
1488 const std::string body = R"(
1489 OpAtomicStore %u32_var %device %relaxed %u32_1
1490 %val2 = OpAtomicCompareExchange %u32 %u32_var %device %relaxed %relaxed %u32_0 %f32_0
1491 )";
1492
1493 CompileSuccessfully(GenerateKernelCode(body));
1494 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1495 EXPECT_THAT(getDiagnosticString(),
1496 HasSubstr("AtomicCompareExchange: "
1497 "expected Comparator to be of type Result Type"));
1498 }
1499
TEST_F(ValidateAtomics,AtomicCompareExchangeWeakSuccess)1500 TEST_F(ValidateAtomics, AtomicCompareExchangeWeakSuccess) {
1501 const std::string body = R"(
1502 OpAtomicStore %u32_var %device %relaxed %u32_1
1503 %val4 = OpAtomicCompareExchangeWeak %u32 %u32_var %device %relaxed %relaxed %u32_0 %u32_0
1504 )";
1505
1506 CompileSuccessfully(GenerateKernelCode(body));
1507 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1508 }
1509
TEST_F(ValidateAtomics,AtomicCompareExchangeWeakWrongResultType)1510 TEST_F(ValidateAtomics, AtomicCompareExchangeWeakWrongResultType) {
1511 const std::string body = R"(
1512 OpAtomicStore %f32_var %device %relaxed %f32_1
1513 %val2 = OpAtomicCompareExchangeWeak %f32 %f32_var %device %relaxed %relaxed %f32_0 %f32_1
1514 )";
1515
1516 CompileSuccessfully(GenerateKernelCode(body));
1517 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1518 EXPECT_THAT(getDiagnosticString(),
1519 HasSubstr("AtomicCompareExchangeWeak: "
1520 "expected Result Type to be integer scalar type"));
1521 }
1522
TEST_F(ValidateAtomics,AtomicCompareExchangeVulkanInvocationSemanticsEqual)1523 TEST_F(ValidateAtomics, AtomicCompareExchangeVulkanInvocationSemanticsEqual) {
1524 const std::string body = R"(
1525 OpAtomicStore %u32_var %device %relaxed %u32_1
1526 %val2 = OpAtomicCompareExchange %u32 %u32_var %invocation %release %relaxed %u32_0 %u32_0
1527 )";
1528
1529 CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
1530 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1531 EXPECT_THAT(getDiagnosticString(),
1532 AnyVUID("VUID-StandaloneSpirv-None-04641"));
1533 EXPECT_THAT(
1534 getDiagnosticString(),
1535 HasSubstr("AtomicCompareExchange: Vulkan specification requires Memory "
1536 "Semantics to be None if used with Invocation Memory Scope"));
1537 }
1538
TEST_F(ValidateAtomics,AtomicCompareExchangeVulkanInvocationSemanticsUnequal)1539 TEST_F(ValidateAtomics, AtomicCompareExchangeVulkanInvocationSemanticsUnequal) {
1540 const std::string body = R"(
1541 OpAtomicStore %u32_var %device %relaxed %u32_1
1542 %val2 = OpAtomicCompareExchange %u32 %u32_var %invocation %relaxed %acquire %u32_0 %u32_0
1543 )";
1544
1545 CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
1546 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1547 EXPECT_THAT(getDiagnosticString(),
1548 AnyVUID("VUID-StandaloneSpirv-None-04641"));
1549 EXPECT_THAT(
1550 getDiagnosticString(),
1551 HasSubstr("AtomicCompareExchange: Vulkan specification requires Memory "
1552 "Semantics to be None if used with Invocation Memory Scope"));
1553 }
1554
TEST_F(ValidateAtomics,AtomicArithmeticsSuccess)1555 TEST_F(ValidateAtomics, AtomicArithmeticsSuccess) {
1556 const std::string body = R"(
1557 OpAtomicStore %u32_var %device %relaxed %u32_1
1558 %val1 = OpAtomicIIncrement %u32 %u32_var %device %acquire_release
1559 %val2 = OpAtomicIDecrement %u32 %u32_var %device %acquire_release
1560 %val3 = OpAtomicIAdd %u32 %u32_var %device %acquire_release %u32_1
1561 %val4 = OpAtomicISub %u32 %u32_var %device %acquire_release %u32_1
1562 %val5 = OpAtomicUMin %u32 %u32_var %device %acquire_release %u32_1
1563 %val6 = OpAtomicUMax %u32 %u32_var %device %acquire_release %u32_1
1564 %val7 = OpAtomicSMin %u32 %u32_var %device %sequentially_consistent %u32_1
1565 %val8 = OpAtomicSMax %u32 %u32_var %device %sequentially_consistent %u32_1
1566 %val9 = OpAtomicAnd %u32 %u32_var %device %sequentially_consistent %u32_1
1567 %val10 = OpAtomicOr %u32 %u32_var %device %sequentially_consistent %u32_1
1568 %val11 = OpAtomicXor %u32 %u32_var %device %sequentially_consistent %u32_1
1569 )";
1570
1571 CompileSuccessfully(GenerateKernelCode(body));
1572 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1573 }
1574
TEST_F(ValidateAtomics,AtomicFlagsSuccess)1575 TEST_F(ValidateAtomics, AtomicFlagsSuccess) {
1576 const std::string body = R"(
1577 OpAtomicFlagClear %u32_var %device %release
1578 %val1 = OpAtomicFlagTestAndSet %bool %u32_var %device %relaxed
1579 )";
1580
1581 CompileSuccessfully(GenerateKernelCode(body));
1582 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1583 }
1584
TEST_F(ValidateAtomics,AtomicFlagTestAndSetWrongResultType)1585 TEST_F(ValidateAtomics, AtomicFlagTestAndSetWrongResultType) {
1586 const std::string body = R"(
1587 %val1 = OpAtomicFlagTestAndSet %u32 %u32_var %device %relaxed
1588 )";
1589
1590 CompileSuccessfully(GenerateKernelCode(body));
1591 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1592 EXPECT_THAT(getDiagnosticString(),
1593 HasSubstr("AtomicFlagTestAndSet: "
1594 "expected Result Type to be bool scalar type"));
1595 }
1596
TEST_F(ValidateAtomics,AtomicFlagTestAndSetNotPointer)1597 TEST_F(ValidateAtomics, AtomicFlagTestAndSetNotPointer) {
1598 const std::string body = R"(
1599 %val1 = OpAtomicFlagTestAndSet %bool %u32_1 %device %relaxed
1600 )";
1601
1602 CompileSuccessfully(GenerateKernelCode(body));
1603 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1604 EXPECT_THAT(getDiagnosticString(),
1605 HasSubstr("AtomicFlagTestAndSet: "
1606 "expected Pointer to be of type OpTypePointer"));
1607 }
1608
TEST_F(ValidateAtomics,AtomicFlagTestAndSetNotIntPointer)1609 TEST_F(ValidateAtomics, AtomicFlagTestAndSetNotIntPointer) {
1610 const std::string body = R"(
1611 %val1 = OpAtomicFlagTestAndSet %bool %f32_var %device %relaxed
1612 )";
1613
1614 CompileSuccessfully(GenerateKernelCode(body));
1615 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1616 EXPECT_THAT(
1617 getDiagnosticString(),
1618 HasSubstr("AtomicFlagTestAndSet: "
1619 "expected Pointer to point to a value of 32-bit integer type"));
1620 }
1621
TEST_F(ValidateAtomics,AtomicFlagTestAndSetNotInt32Pointer)1622 TEST_F(ValidateAtomics, AtomicFlagTestAndSetNotInt32Pointer) {
1623 const std::string body = R"(
1624 %val1 = OpAtomicFlagTestAndSet %bool %u64_var %device %relaxed
1625 )";
1626
1627 CompileSuccessfully(GenerateKernelCode(body, "OpCapability Int64Atomics\n"));
1628 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1629 EXPECT_THAT(
1630 getDiagnosticString(),
1631 HasSubstr("AtomicFlagTestAndSet: "
1632 "expected Pointer to point to a value of 32-bit integer type"));
1633 }
1634
TEST_F(ValidateAtomics,AtomicFlagTestAndSetWrongScopeType)1635 TEST_F(ValidateAtomics, AtomicFlagTestAndSetWrongScopeType) {
1636 const std::string body = R"(
1637 %val1 = OpAtomicFlagTestAndSet %bool %u32_var %u64_1 %relaxed
1638 )";
1639
1640 CompileSuccessfully(GenerateKernelCode(body));
1641 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1642 EXPECT_THAT(
1643 getDiagnosticString(),
1644 HasSubstr("AtomicFlagTestAndSet: expected scope to be a 32-bit int"));
1645 }
1646
TEST_F(ValidateAtomics,AtomicFlagTestAndSetWrongMemorySemanticsType)1647 TEST_F(ValidateAtomics, AtomicFlagTestAndSetWrongMemorySemanticsType) {
1648 const std::string body = R"(
1649 %val1 = OpAtomicFlagTestAndSet %bool %u32_var %device %u64_1
1650 )";
1651
1652 CompileSuccessfully(GenerateKernelCode(body));
1653 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1654 EXPECT_THAT(getDiagnosticString(),
1655 HasSubstr("AtomicFlagTestAndSet: "
1656 "expected Memory Semantics to be a 32-bit int"));
1657 }
1658
TEST_F(ValidateAtomics,AtomicFlagClearAcquire)1659 TEST_F(ValidateAtomics, AtomicFlagClearAcquire) {
1660 const std::string body = R"(
1661 OpAtomicFlagClear %u32_var %device %acquire
1662 )";
1663
1664 CompileSuccessfully(GenerateKernelCode(body));
1665 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1666 EXPECT_THAT(getDiagnosticString(),
1667 HasSubstr("Memory Semantics Acquire and AcquireRelease cannot be "
1668 "used with AtomicFlagClear"));
1669 }
1670
TEST_F(ValidateAtomics,AtomicFlagClearNotPointer)1671 TEST_F(ValidateAtomics, AtomicFlagClearNotPointer) {
1672 const std::string body = R"(
1673 OpAtomicFlagClear %u32_1 %device %relaxed
1674 )";
1675
1676 CompileSuccessfully(GenerateKernelCode(body));
1677 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1678 EXPECT_THAT(getDiagnosticString(),
1679 HasSubstr("AtomicFlagClear: "
1680 "expected Pointer to be of type OpTypePointer"));
1681 }
1682
TEST_F(ValidateAtomics,AtomicFlagClearNotIntPointer)1683 TEST_F(ValidateAtomics, AtomicFlagClearNotIntPointer) {
1684 const std::string body = R"(
1685 OpAtomicFlagClear %f32_var %device %relaxed
1686 )";
1687
1688 CompileSuccessfully(GenerateKernelCode(body));
1689 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1690 EXPECT_THAT(
1691 getDiagnosticString(),
1692 HasSubstr("AtomicFlagClear: "
1693 "expected Pointer to point to a value of 32-bit integer type"));
1694 }
1695
TEST_F(ValidateAtomics,AtomicFlagClearNotInt32Pointer)1696 TEST_F(ValidateAtomics, AtomicFlagClearNotInt32Pointer) {
1697 const std::string body = R"(
1698 OpAtomicFlagClear %u64_var %device %relaxed
1699 )";
1700
1701 CompileSuccessfully(GenerateKernelCode(body, "OpCapability Int64Atomics\n"));
1702 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1703 EXPECT_THAT(
1704 getDiagnosticString(),
1705 HasSubstr("AtomicFlagClear: "
1706 "expected Pointer to point to a value of 32-bit integer type"));
1707 }
1708
TEST_F(ValidateAtomics,AtomicFlagClearWrongScopeType)1709 TEST_F(ValidateAtomics, AtomicFlagClearWrongScopeType) {
1710 const std::string body = R"(
1711 OpAtomicFlagClear %u32_var %u64_1 %relaxed
1712 )";
1713
1714 CompileSuccessfully(GenerateKernelCode(body));
1715 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1716 EXPECT_THAT(getDiagnosticString(),
1717 HasSubstr("AtomicFlagClear: expected scope to be a 32-bit "
1718 "int\n OpAtomicFlagClear %30 %ulong_1 %uint_0_1\n"));
1719 }
1720
TEST_F(ValidateAtomics,AtomicFlagClearWrongMemorySemanticsType)1721 TEST_F(ValidateAtomics, AtomicFlagClearWrongMemorySemanticsType) {
1722 const std::string body = R"(
1723 OpAtomicFlagClear %u32_var %device %u64_1
1724 )";
1725
1726 CompileSuccessfully(GenerateKernelCode(body));
1727 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1728 EXPECT_THAT(
1729 getDiagnosticString(),
1730 HasSubstr(
1731 "AtomicFlagClear: expected Memory Semantics to be a 32-bit int"));
1732 }
1733
TEST_F(ValidateAtomics,AtomicIIncrementAcquireAndRelease)1734 TEST_F(ValidateAtomics, AtomicIIncrementAcquireAndRelease) {
1735 const std::string body = R"(
1736 OpAtomicStore %u32_var %device %relaxed %u32_1
1737 %val1 = OpAtomicIIncrement %u32 %u32_var %device %acquire_and_release
1738 )";
1739
1740 CompileSuccessfully(GenerateKernelCode(body));
1741 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1742 EXPECT_THAT(getDiagnosticString(),
1743 HasSubstr("AtomicIIncrement: Memory Semantics can have at most "
1744 "one of the following bits set: Acquire, Release, "
1745 "AcquireRelease or SequentiallyConsistent"));
1746 }
1747
TEST_F(ValidateAtomics,AtomicUniformMemorySemanticsShader)1748 TEST_F(ValidateAtomics, AtomicUniformMemorySemanticsShader) {
1749 const std::string body = R"(
1750 OpAtomicStore %u32_var %device %relaxed %u32_1
1751 %val1 = OpAtomicIIncrement %u32 %u32_var %device %acquire_release_uniform_workgroup
1752 )";
1753
1754 CompileSuccessfully(GenerateShaderCode(body));
1755 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1756 }
1757
TEST_F(ValidateAtomics,AtomicUniformMemorySemanticsKernel)1758 TEST_F(ValidateAtomics, AtomicUniformMemorySemanticsKernel) {
1759 const std::string body = R"(
1760 OpAtomicStore %u32_var %device %relaxed %u32_1
1761 %val1 = OpAtomicIIncrement %u32 %u32_var %device %acquire_release_uniform_workgroup
1762 )";
1763
1764 CompileSuccessfully(GenerateKernelCode(body));
1765 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1766 EXPECT_THAT(getDiagnosticString(),
1767 HasSubstr("AtomicIIncrement: Memory Semantics UniformMemory "
1768 "requires capability Shader"));
1769 }
1770
1771 // Lack of the AtomicStorage capability is intentionally ignored, see
1772 // https://github.com/KhronosGroup/glslang/issues/1618 for the reasoning why.
TEST_F(ValidateAtomics,AtomicCounterMemorySemanticsNoCapability)1773 TEST_F(ValidateAtomics, AtomicCounterMemorySemanticsNoCapability) {
1774 const std::string body = R"(
1775 OpAtomicStore %u32_var %device %relaxed %u32_1
1776 %val1 = OpAtomicIIncrement %u32 %u32_var %device
1777 %acquire_release_atomic_counter_workgroup
1778 )";
1779
1780 CompileSuccessfully(GenerateKernelCode(body));
1781 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1782 }
1783
TEST_F(ValidateAtomics,AtomicCounterMemorySemanticsWithCapability)1784 TEST_F(ValidateAtomics, AtomicCounterMemorySemanticsWithCapability) {
1785 const std::string body = R"(
1786 OpAtomicStore %u32_var %device %relaxed %u32_1
1787 %val1 = OpAtomicIIncrement %u32 %u32_var %device %acquire_release_atomic_counter_workgroup
1788 )";
1789
1790 CompileSuccessfully(GenerateKernelCode(body, "OpCapability AtomicStorage\n"));
1791 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1792 }
1793
TEST_F(ValidateAtomics,VulkanMemoryModelBanSequentiallyConsistentAtomicLoad)1794 TEST_F(ValidateAtomics, VulkanMemoryModelBanSequentiallyConsistentAtomicLoad) {
1795 const std::string body = R"(
1796 %ld = OpAtomicLoad %u32 %u32_var %workgroup %sequentially_consistent
1797 )";
1798
1799 const std::string extra = R"(
1800 OpCapability VulkanMemoryModelKHR
1801 OpExtension "SPV_KHR_vulkan_memory_model"
1802 )";
1803
1804 CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
1805 SPV_ENV_UNIVERSAL_1_3);
1806 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1807 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1808 EXPECT_THAT(getDiagnosticString(),
1809 HasSubstr("SequentiallyConsistent memory semantics cannot be "
1810 "used with the VulkanKHR memory model."));
1811 }
1812
TEST_F(ValidateAtomics,VulkanMemoryModelBanSequentiallyConsistentAtomicStore)1813 TEST_F(ValidateAtomics, VulkanMemoryModelBanSequentiallyConsistentAtomicStore) {
1814 const std::string body = R"(
1815 OpAtomicStore %u32_var %workgroup %sequentially_consistent %u32_0
1816 )";
1817
1818 const std::string extra = R"(
1819 OpCapability VulkanMemoryModelKHR
1820 OpExtension "SPV_KHR_vulkan_memory_model"
1821 )";
1822
1823 CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
1824 SPV_ENV_UNIVERSAL_1_3);
1825 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1826 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1827 EXPECT_THAT(getDiagnosticString(),
1828 HasSubstr("SequentiallyConsistent memory semantics cannot be "
1829 "used with the VulkanKHR memory model."));
1830 }
1831
TEST_F(ValidateAtomics,VulkanMemoryModelBanSequentiallyConsistentAtomicExchange)1832 TEST_F(ValidateAtomics,
1833 VulkanMemoryModelBanSequentiallyConsistentAtomicExchange) {
1834 const std::string body = R"(
1835 %ex = OpAtomicExchange %u32 %u32_var %workgroup %sequentially_consistent %u32_0
1836 )";
1837
1838 const std::string extra = R"(
1839 OpCapability VulkanMemoryModelKHR
1840 OpExtension "SPV_KHR_vulkan_memory_model"
1841 )";
1842
1843 CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
1844 SPV_ENV_UNIVERSAL_1_3);
1845 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1846 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1847 EXPECT_THAT(getDiagnosticString(),
1848 HasSubstr("SequentiallyConsistent memory semantics cannot be "
1849 "used with the VulkanKHR memory model."));
1850 }
1851
TEST_F(ValidateAtomics,VulkanMemoryModelBanSequentiallyConsistentAtomicCompareExchangeEqual)1852 TEST_F(ValidateAtomics,
1853 VulkanMemoryModelBanSequentiallyConsistentAtomicCompareExchangeEqual) {
1854 const std::string body = R"(
1855 %ex = OpAtomicCompareExchange %u32 %u32_var %workgroup %sequentially_consistent %relaxed %u32_0 %u32_0
1856 )";
1857
1858 const std::string extra = R"(
1859 OpCapability VulkanMemoryModelKHR
1860 OpExtension "SPV_KHR_vulkan_memory_model"
1861 )";
1862
1863 CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
1864 SPV_ENV_UNIVERSAL_1_3);
1865 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1866 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1867 EXPECT_THAT(getDiagnosticString(),
1868 HasSubstr("SequentiallyConsistent memory semantics cannot be "
1869 "used with the VulkanKHR memory model."));
1870 }
1871
TEST_F(ValidateAtomics,VulkanMemoryModelBanSequentiallyConsistentAtomicCompareExchangeUnequal)1872 TEST_F(ValidateAtomics,
1873 VulkanMemoryModelBanSequentiallyConsistentAtomicCompareExchangeUnequal) {
1874 const std::string body = R"(
1875 %ex = OpAtomicCompareExchange %u32 %u32_var %workgroup %relaxed %sequentially_consistent %u32_0 %u32_0
1876 )";
1877
1878 const std::string extra = R"(
1879 OpCapability VulkanMemoryModelKHR
1880 OpExtension "SPV_KHR_vulkan_memory_model"
1881 )";
1882
1883 CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
1884 SPV_ENV_UNIVERSAL_1_3);
1885 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1886 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1887 EXPECT_THAT(getDiagnosticString(),
1888 HasSubstr("SequentiallyConsistent memory semantics cannot be "
1889 "used with the VulkanKHR memory model."));
1890 }
1891
TEST_F(ValidateAtomics,VulkanMemoryModelBanSequentiallyConsistentAtomicIIncrement)1892 TEST_F(ValidateAtomics,
1893 VulkanMemoryModelBanSequentiallyConsistentAtomicIIncrement) {
1894 const std::string body = R"(
1895 %inc = OpAtomicIIncrement %u32 %u32_var %workgroup %sequentially_consistent
1896 )";
1897
1898 const std::string extra = R"(
1899 OpCapability VulkanMemoryModelKHR
1900 OpExtension "SPV_KHR_vulkan_memory_model"
1901 )";
1902
1903 CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
1904 SPV_ENV_UNIVERSAL_1_3);
1905 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1906 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1907 EXPECT_THAT(getDiagnosticString(),
1908 HasSubstr("SequentiallyConsistent memory semantics cannot be "
1909 "used with the VulkanKHR memory model."));
1910 }
1911
TEST_F(ValidateAtomics,VulkanMemoryModelBanSequentiallyConsistentAtomicIDecrement)1912 TEST_F(ValidateAtomics,
1913 VulkanMemoryModelBanSequentiallyConsistentAtomicIDecrement) {
1914 const std::string body = R"(
1915 %dec = OpAtomicIDecrement %u32 %u32_var %workgroup %sequentially_consistent
1916 )";
1917
1918 const std::string extra = R"(
1919 OpCapability VulkanMemoryModelKHR
1920 OpExtension "SPV_KHR_vulkan_memory_model"
1921 )";
1922
1923 CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
1924 SPV_ENV_UNIVERSAL_1_3);
1925 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1926 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1927 EXPECT_THAT(getDiagnosticString(),
1928 HasSubstr("SequentiallyConsistent memory semantics cannot be "
1929 "used with the VulkanKHR memory model."));
1930 }
1931
TEST_F(ValidateAtomics,VulkanMemoryModelBanSequentiallyConsistentAtomicIAdd)1932 TEST_F(ValidateAtomics, VulkanMemoryModelBanSequentiallyConsistentAtomicIAdd) {
1933 const std::string body = R"(
1934 %add = OpAtomicIAdd %u32 %u32_var %workgroup %sequentially_consistent %u32_0
1935 )";
1936
1937 const std::string extra = R"(
1938 OpCapability VulkanMemoryModelKHR
1939 OpExtension "SPV_KHR_vulkan_memory_model"
1940 )";
1941
1942 CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
1943 SPV_ENV_UNIVERSAL_1_3);
1944 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1945 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1946 EXPECT_THAT(getDiagnosticString(),
1947 HasSubstr("SequentiallyConsistent memory semantics cannot be "
1948 "used with the VulkanKHR memory model."));
1949 }
1950
TEST_F(ValidateAtomics,VulkanMemoryModelBanSequentiallyConsistentAtomicISub)1951 TEST_F(ValidateAtomics, VulkanMemoryModelBanSequentiallyConsistentAtomicISub) {
1952 const std::string body = R"(
1953 %sub = OpAtomicISub %u32 %u32_var %workgroup %sequentially_consistent %u32_0
1954 )";
1955
1956 const std::string extra = R"(
1957 OpCapability VulkanMemoryModelKHR
1958 OpExtension "SPV_KHR_vulkan_memory_model"
1959 )";
1960
1961 CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
1962 SPV_ENV_UNIVERSAL_1_3);
1963 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1964 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1965 EXPECT_THAT(getDiagnosticString(),
1966 HasSubstr("SequentiallyConsistent memory semantics cannot be "
1967 "used with the VulkanKHR memory model."));
1968 }
1969
TEST_F(ValidateAtomics,VulkanMemoryModelBanSequentiallyConsistentAtomicSMin)1970 TEST_F(ValidateAtomics, VulkanMemoryModelBanSequentiallyConsistentAtomicSMin) {
1971 const std::string body = R"(
1972 %min = OpAtomicSMin %u32 %u32_var %workgroup %sequentially_consistent %u32_0
1973 )";
1974
1975 const std::string extra = R"(
1976 OpCapability VulkanMemoryModelKHR
1977 OpExtension "SPV_KHR_vulkan_memory_model"
1978 )";
1979
1980 CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
1981 SPV_ENV_UNIVERSAL_1_3);
1982 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1983 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1984 EXPECT_THAT(getDiagnosticString(),
1985 HasSubstr("SequentiallyConsistent memory semantics cannot be "
1986 "used with the VulkanKHR memory model."));
1987 }
1988
TEST_F(ValidateAtomics,VulkanMemoryModelBanSequentiallyConsistentAtomicUMin)1989 TEST_F(ValidateAtomics, VulkanMemoryModelBanSequentiallyConsistentAtomicUMin) {
1990 const std::string body = R"(
1991 %min = OpAtomicUMin %u32 %u32_var %workgroup %sequentially_consistent %u32_0
1992 )";
1993
1994 const std::string extra = R"(
1995 OpCapability VulkanMemoryModelKHR
1996 OpExtension "SPV_KHR_vulkan_memory_model"
1997 )";
1998
1999 CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
2000 SPV_ENV_UNIVERSAL_1_3);
2001 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
2002 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2003 EXPECT_THAT(getDiagnosticString(),
2004 HasSubstr("SequentiallyConsistent memory semantics cannot be "
2005 "used with the VulkanKHR memory model."));
2006 }
2007
TEST_F(ValidateAtomics,VulkanMemoryModelBanSequentiallyConsistentAtomicFMinEXT)2008 TEST_F(ValidateAtomics, VulkanMemoryModelBanSequentiallyConsistentAtomicFMinEXT) {
2009 const std::string body = R"(
2010 %max = OpAtomicFMinEXT %f32 %f32_var %workgroup %sequentially_consistent %f32_0
2011 )";
2012
2013 const std::string extra = R"(
2014 OpCapability VulkanMemoryModelKHR
2015 OpCapability AtomicFloat32MinMaxEXT
2016 OpExtension "SPV_KHR_vulkan_memory_model"
2017 OpExtension "SPV_EXT_shader_atomic_float_min_max"
2018 )";
2019
2020 CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
2021 SPV_ENV_UNIVERSAL_1_3);
2022 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
2023 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2024 EXPECT_THAT(getDiagnosticString(),
2025 HasSubstr("SequentiallyConsistent memory semantics cannot be "
2026 "used with the VulkanKHR memory model."));
2027 }
2028
TEST_F(ValidateAtomics,VulkanMemoryModelBanSequentiallyConsistentAtomicSMax)2029 TEST_F(ValidateAtomics, VulkanMemoryModelBanSequentiallyConsistentAtomicSMax) {
2030 const std::string body = R"(
2031 %max = OpAtomicSMax %u32 %u32_var %workgroup %sequentially_consistent %u32_0
2032 )";
2033
2034 const std::string extra = R"(
2035 OpCapability VulkanMemoryModelKHR
2036 OpExtension "SPV_KHR_vulkan_memory_model"
2037 )";
2038
2039 CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
2040 SPV_ENV_UNIVERSAL_1_3);
2041 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
2042 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2043 EXPECT_THAT(getDiagnosticString(),
2044 HasSubstr("SequentiallyConsistent memory semantics cannot be "
2045 "used with the VulkanKHR memory model."));
2046 }
2047
TEST_F(ValidateAtomics,VulkanMemoryModelBanSequentiallyConsistentAtomicUMax)2048 TEST_F(ValidateAtomics, VulkanMemoryModelBanSequentiallyConsistentAtomicUMax) {
2049 const std::string body = R"(
2050 %max = OpAtomicUMax %u32 %u32_var %workgroup %sequentially_consistent %u32_0
2051 )";
2052
2053 const std::string extra = R"(
2054 OpCapability VulkanMemoryModelKHR
2055 OpExtension "SPV_KHR_vulkan_memory_model"
2056 )";
2057
2058 CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
2059 SPV_ENV_UNIVERSAL_1_3);
2060 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
2061 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2062 EXPECT_THAT(getDiagnosticString(),
2063 HasSubstr("SequentiallyConsistent memory semantics cannot be "
2064 "used with the VulkanKHR memory model."));
2065 }
2066
TEST_F(ValidateAtomics,VulkanMemoryModelBanSequentiallyConsistentAtomicFMaxEXT)2067 TEST_F(ValidateAtomics, VulkanMemoryModelBanSequentiallyConsistentAtomicFMaxEXT) {
2068 const std::string body = R"(
2069 %max = OpAtomicFMaxEXT %f32 %f32_var %workgroup %sequentially_consistent %f32_0
2070 )";
2071
2072 const std::string extra = R"(
2073 OpCapability VulkanMemoryModelKHR
2074 OpCapability AtomicFloat32MinMaxEXT
2075 OpExtension "SPV_KHR_vulkan_memory_model"
2076 OpExtension "SPV_EXT_shader_atomic_float_min_max"
2077 )";
2078
2079 CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
2080 SPV_ENV_UNIVERSAL_1_3);
2081 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
2082 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2083 EXPECT_THAT(getDiagnosticString(),
2084 HasSubstr("SequentiallyConsistent memory semantics cannot be "
2085 "used with the VulkanKHR memory model."));
2086 }
2087
TEST_F(ValidateAtomics,VulkanMemoryModelBanSequentiallyConsistentAtomicAnd)2088 TEST_F(ValidateAtomics, VulkanMemoryModelBanSequentiallyConsistentAtomicAnd) {
2089 const std::string body = R"(
2090 %and = OpAtomicAnd %u32 %u32_var %workgroup %sequentially_consistent %u32_0
2091 )";
2092
2093 const std::string extra = R"(
2094 OpCapability VulkanMemoryModelKHR
2095 OpExtension "SPV_KHR_vulkan_memory_model"
2096 )";
2097
2098 CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
2099 SPV_ENV_UNIVERSAL_1_3);
2100 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
2101 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2102 EXPECT_THAT(getDiagnosticString(),
2103 HasSubstr("SequentiallyConsistent memory semantics cannot be "
2104 "used with the VulkanKHR memory model."));
2105 }
2106
TEST_F(ValidateAtomics,VulkanMemoryModelBanSequentiallyConsistentAtomicOr)2107 TEST_F(ValidateAtomics, VulkanMemoryModelBanSequentiallyConsistentAtomicOr) {
2108 const std::string body = R"(
2109 %or = OpAtomicOr %u32 %u32_var %workgroup %sequentially_consistent %u32_0
2110 )";
2111
2112 const std::string extra = R"(
2113 OpCapability VulkanMemoryModelKHR
2114 OpExtension "SPV_KHR_vulkan_memory_model"
2115 )";
2116
2117 CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
2118 SPV_ENV_UNIVERSAL_1_3);
2119 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
2120 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2121 EXPECT_THAT(getDiagnosticString(),
2122 HasSubstr("SequentiallyConsistent memory semantics cannot be "
2123 "used with the VulkanKHR memory model."));
2124 }
2125
TEST_F(ValidateAtomics,VulkanMemoryModelBanSequentiallyConsistentAtomicXor)2126 TEST_F(ValidateAtomics, VulkanMemoryModelBanSequentiallyConsistentAtomicXor) {
2127 const std::string body = R"(
2128 %xor = OpAtomicXor %u32 %u32_var %workgroup %sequentially_consistent %u32_0
2129 )";
2130
2131 const std::string extra = R"(
2132 OpCapability VulkanMemoryModelKHR
2133 OpExtension "SPV_KHR_vulkan_memory_model"
2134 )";
2135
2136 CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
2137 SPV_ENV_UNIVERSAL_1_3);
2138 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
2139 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2140 EXPECT_THAT(getDiagnosticString(),
2141 HasSubstr("SequentiallyConsistent memory semantics cannot be "
2142 "used with the VulkanKHR memory model."));
2143 }
2144
TEST_F(ValidateAtomics,OutputMemoryKHRRequiresVulkanMemoryModelKHR)2145 TEST_F(ValidateAtomics, OutputMemoryKHRRequiresVulkanMemoryModelKHR) {
2146 const std::string text = R"(
2147 OpCapability Shader
2148 OpMemoryModel Logical GLSL450
2149 OpEntryPoint Fragment %1 "func"
2150 OpExecutionMode %1 OriginUpperLeft
2151 %2 = OpTypeVoid
2152 %3 = OpTypeInt 32 0
2153 %semantics = OpConstant %3 4100
2154 %5 = OpTypeFunction %2
2155 %workgroup = OpConstant %3 2
2156 %ptr = OpTypePointer Workgroup %3
2157 %var = OpVariable %ptr Workgroup
2158 %1 = OpFunction %2 None %5
2159 %7 = OpLabel
2160 OpAtomicStore %var %workgroup %semantics %workgroup
2161 OpReturn
2162 OpFunctionEnd
2163 )";
2164
2165 CompileSuccessfully(text);
2166 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2167 EXPECT_THAT(getDiagnosticString(),
2168 HasSubstr("AtomicStore: Memory Semantics OutputMemoryKHR "
2169 "requires capability VulkanMemoryModelKHR"));
2170 }
2171
TEST_F(ValidateAtomics,MakeAvailableKHRRequiresVulkanMemoryModelKHR)2172 TEST_F(ValidateAtomics, MakeAvailableKHRRequiresVulkanMemoryModelKHR) {
2173 const std::string text = R"(
2174 OpCapability Shader
2175 OpMemoryModel Logical GLSL450
2176 OpEntryPoint Fragment %1 "func"
2177 OpExecutionMode %1 OriginUpperLeft
2178 %2 = OpTypeVoid
2179 %3 = OpTypeInt 32 0
2180 %semantics = OpConstant %3 8196
2181 %5 = OpTypeFunction %2
2182 %workgroup = OpConstant %3 2
2183 %ptr = OpTypePointer Workgroup %3
2184 %var = OpVariable %ptr Workgroup
2185 %1 = OpFunction %2 None %5
2186 %7 = OpLabel
2187 OpAtomicStore %var %workgroup %semantics %workgroup
2188 OpReturn
2189 OpFunctionEnd
2190 )";
2191
2192 CompileSuccessfully(text);
2193 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2194 EXPECT_THAT(getDiagnosticString(),
2195 HasSubstr("AtomicStore: Memory Semantics MakeAvailableKHR "
2196 "requires capability VulkanMemoryModelKHR"));
2197 }
2198
TEST_F(ValidateAtomics,MakeVisibleKHRRequiresVulkanMemoryModelKHR)2199 TEST_F(ValidateAtomics, MakeVisibleKHRRequiresVulkanMemoryModelKHR) {
2200 const std::string text = R"(
2201 OpCapability Shader
2202 OpMemoryModel Logical GLSL450
2203 OpEntryPoint Fragment %1 "func"
2204 OpExecutionMode %1 OriginUpperLeft
2205 %2 = OpTypeVoid
2206 %3 = OpTypeInt 32 0
2207 %semantics = OpConstant %3 16386
2208 %5 = OpTypeFunction %2
2209 %workgroup = OpConstant %3 2
2210 %ptr = OpTypePointer Workgroup %3
2211 %var = OpVariable %ptr Workgroup
2212 %1 = OpFunction %2 None %5
2213 %7 = OpLabel
2214 %ld = OpAtomicLoad %3 %var %workgroup %semantics
2215 OpReturn
2216 OpFunctionEnd
2217 )";
2218
2219 CompileSuccessfully(text);
2220 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2221 EXPECT_THAT(getDiagnosticString(),
2222 HasSubstr("AtomicLoad: Memory Semantics MakeVisibleKHR requires "
2223 "capability VulkanMemoryModelKHR"));
2224 }
2225
TEST_F(ValidateAtomics,MakeAvailableKHRRequiresReleaseSemantics)2226 TEST_F(ValidateAtomics, MakeAvailableKHRRequiresReleaseSemantics) {
2227 const std::string text = R"(
2228 OpCapability Shader
2229 OpCapability VulkanMemoryModelKHR
2230 OpExtension "SPV_KHR_vulkan_memory_model"
2231 OpMemoryModel Logical VulkanKHR
2232 OpEntryPoint Fragment %1 "func"
2233 OpExecutionMode %1 OriginUpperLeft
2234 %2 = OpTypeVoid
2235 %3 = OpTypeInt 32 0
2236 %semantics = OpConstant %3 8448
2237 %5 = OpTypeFunction %2
2238 %workgroup = OpConstant %3 2
2239 %ptr = OpTypePointer Workgroup %3
2240 %var = OpVariable %ptr Workgroup
2241 %1 = OpFunction %2 None %5
2242 %7 = OpLabel
2243 OpAtomicStore %var %workgroup %semantics %workgroup
2244 OpReturn
2245 OpFunctionEnd
2246 )";
2247
2248 CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
2249 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
2250 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2251 EXPECT_THAT(
2252 getDiagnosticString(),
2253 HasSubstr("AtomicStore: MakeAvailableKHR Memory Semantics also requires "
2254 "either Release or AcquireRelease Memory Semantics"));
2255 }
2256
TEST_F(ValidateAtomics,MakeVisibleKHRRequiresAcquireSemantics)2257 TEST_F(ValidateAtomics, MakeVisibleKHRRequiresAcquireSemantics) {
2258 const std::string text = R"(
2259 OpCapability Shader
2260 OpCapability VulkanMemoryModelKHR
2261 OpExtension "SPV_KHR_vulkan_memory_model"
2262 OpMemoryModel Logical VulkanKHR
2263 OpEntryPoint Fragment %1 "func"
2264 OpExecutionMode %1 OriginUpperLeft
2265 %2 = OpTypeVoid
2266 %3 = OpTypeInt 32 0
2267 %semantics = OpConstant %3 16640
2268 %5 = OpTypeFunction %2
2269 %workgroup = OpConstant %3 2
2270 %ptr = OpTypePointer Workgroup %3
2271 %var = OpVariable %ptr Workgroup
2272 %1 = OpFunction %2 None %5
2273 %7 = OpLabel
2274 %ld = OpAtomicLoad %3 %var %workgroup %semantics
2275 OpReturn
2276 OpFunctionEnd
2277 )";
2278
2279 CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
2280 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
2281 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2282 EXPECT_THAT(
2283 getDiagnosticString(),
2284 HasSubstr("AtomicLoad: MakeVisibleKHR Memory Semantics also requires "
2285 "either Acquire or AcquireRelease Memory Semantics"));
2286 }
2287
TEST_F(ValidateAtomics,MakeAvailableKHRRequiresStorageSemantics)2288 TEST_F(ValidateAtomics, MakeAvailableKHRRequiresStorageSemantics) {
2289 const std::string text = R"(
2290 OpCapability Shader
2291 OpCapability VulkanMemoryModelKHR
2292 OpExtension "SPV_KHR_vulkan_memory_model"
2293 OpMemoryModel Logical VulkanKHR
2294 OpEntryPoint Fragment %1 "func"
2295 OpExecutionMode %1 OriginUpperLeft
2296 %2 = OpTypeVoid
2297 %3 = OpTypeInt 32 0
2298 %semantics = OpConstant %3 8196
2299 %5 = OpTypeFunction %2
2300 %workgroup = OpConstant %3 2
2301 %ptr = OpTypePointer Workgroup %3
2302 %var = OpVariable %ptr Workgroup
2303 %1 = OpFunction %2 None %5
2304 %7 = OpLabel
2305 OpAtomicStore %var %workgroup %semantics %workgroup
2306 OpReturn
2307 OpFunctionEnd
2308 )";
2309
2310 CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
2311 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
2312 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2313 EXPECT_THAT(
2314 getDiagnosticString(),
2315 HasSubstr(
2316 "AtomicStore: expected Memory Semantics to include a storage class"));
2317 }
2318
TEST_F(ValidateAtomics,MakeVisibleKHRRequiresStorageSemantics)2319 TEST_F(ValidateAtomics, MakeVisibleKHRRequiresStorageSemantics) {
2320 const std::string text = R"(
2321 OpCapability Shader
2322 OpCapability VulkanMemoryModelKHR
2323 OpExtension "SPV_KHR_vulkan_memory_model"
2324 OpMemoryModel Logical VulkanKHR
2325 OpEntryPoint Fragment %1 "func"
2326 OpExecutionMode %1 OriginUpperLeft
2327 %2 = OpTypeVoid
2328 %3 = OpTypeInt 32 0
2329 %semantics = OpConstant %3 16386
2330 %5 = OpTypeFunction %2
2331 %workgroup = OpConstant %3 2
2332 %ptr = OpTypePointer Workgroup %3
2333 %var = OpVariable %ptr Workgroup
2334 %1 = OpFunction %2 None %5
2335 %7 = OpLabel
2336 %ld = OpAtomicLoad %3 %var %workgroup %semantics
2337 OpReturn
2338 OpFunctionEnd
2339 )";
2340
2341 CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
2342 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
2343 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2344 EXPECT_THAT(
2345 getDiagnosticString(),
2346 HasSubstr(
2347 "AtomicLoad: expected Memory Semantics to include a storage class"));
2348 }
2349
TEST_F(ValidateAtomics,VulkanMemoryModelAllowsQueueFamilyKHR)2350 TEST_F(ValidateAtomics, VulkanMemoryModelAllowsQueueFamilyKHR) {
2351 const std::string body = R"(
2352 %val = OpAtomicAnd %u32 %u32_var %queuefamily %relaxed %u32_1
2353 )";
2354
2355 const std::string extra = R"(
2356 OpCapability VulkanMemoryModelKHR
2357 OpExtension "SPV_KHR_vulkan_memory_model"
2358 )";
2359
2360 CompileSuccessfully(GenerateShaderComputeCode(body, extra, "", "VulkanKHR"),
2361 SPV_ENV_VULKAN_1_1);
2362 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
2363 }
2364
TEST_F(ValidateAtomics,NonVulkanMemoryModelDisallowsQueueFamilyKHR)2365 TEST_F(ValidateAtomics, NonVulkanMemoryModelDisallowsQueueFamilyKHR) {
2366 const std::string body = R"(
2367 %val = OpAtomicAnd %u32 %u32_var %queuefamily %relaxed %u32_1
2368 )";
2369
2370 CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_1);
2371 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_1));
2372 EXPECT_THAT(getDiagnosticString(),
2373 HasSubstr("AtomicAnd: Memory Scope QueueFamilyKHR requires "
2374 "capability VulkanMemoryModelKHR\n %42 = OpAtomicAnd "
2375 "%uint %29 %uint_5 %uint_0_1 %uint_1\n"));
2376 }
2377
TEST_F(ValidateAtomics,SemanticsSpecConstantShader)2378 TEST_F(ValidateAtomics, SemanticsSpecConstantShader) {
2379 const std::string spirv = R"(
2380 OpCapability Shader
2381 OpMemoryModel Logical GLSL450
2382 OpEntryPoint Fragment %func "func"
2383 OpExecutionMode %func OriginUpperLeft
2384 %void = OpTypeVoid
2385 %int = OpTypeInt 32 0
2386 %spec_const = OpSpecConstant %int 0
2387 %workgroup = OpConstant %int 2
2388 %ptr_int_workgroup = OpTypePointer Workgroup %int
2389 %var = OpVariable %ptr_int_workgroup Workgroup
2390 %voidfn = OpTypeFunction %void
2391 %func = OpFunction %void None %voidfn
2392 %entry = OpLabel
2393 %ld = OpAtomicLoad %int %var %workgroup %spec_const
2394 OpReturn
2395 OpFunctionEnd
2396 )";
2397
2398 CompileSuccessfully(spirv);
2399 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2400 EXPECT_THAT(getDiagnosticString(),
2401 HasSubstr("Memory Semantics ids must be OpConstant when Shader "
2402 "capability is present"));
2403 }
2404
TEST_F(ValidateAtomics,SemanticsSpecConstantKernel)2405 TEST_F(ValidateAtomics, SemanticsSpecConstantKernel) {
2406 const std::string spirv = R"(
2407 OpCapability Kernel
2408 OpCapability Linkage
2409 OpMemoryModel Logical OpenCL
2410 %void = OpTypeVoid
2411 %int = OpTypeInt 32 0
2412 %spec_const = OpSpecConstant %int 0
2413 %workgroup = OpConstant %int 2
2414 %ptr_int_workgroup = OpTypePointer Workgroup %int
2415 %var = OpVariable %ptr_int_workgroup Workgroup
2416 %voidfn = OpTypeFunction %void
2417 %func = OpFunction %void None %voidfn
2418 %entry = OpLabel
2419 %ld = OpAtomicLoad %int %var %workgroup %spec_const
2420 OpReturn
2421 OpFunctionEnd
2422 )";
2423
2424 CompileSuccessfully(spirv);
2425 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2426 }
2427
TEST_F(ValidateAtomics,ScopeSpecConstantShader)2428 TEST_F(ValidateAtomics, ScopeSpecConstantShader) {
2429 const std::string spirv = R"(
2430 OpCapability Shader
2431 OpMemoryModel Logical GLSL450
2432 OpEntryPoint Fragment %func "func"
2433 OpExecutionMode %func OriginUpperLeft
2434 %void = OpTypeVoid
2435 %int = OpTypeInt 32 0
2436 %spec_const = OpSpecConstant %int 0
2437 %relaxed = OpConstant %int 0
2438 %ptr_int_workgroup = OpTypePointer Workgroup %int
2439 %var = OpVariable %ptr_int_workgroup Workgroup
2440 %voidfn = OpTypeFunction %void
2441 %func = OpFunction %void None %voidfn
2442 %entry = OpLabel
2443 %ld = OpAtomicLoad %int %var %spec_const %relaxed
2444 OpReturn
2445 OpFunctionEnd
2446 )";
2447
2448 CompileSuccessfully(spirv);
2449 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2450 EXPECT_THAT(
2451 getDiagnosticString(),
2452 HasSubstr(
2453 "Scope ids must be OpConstant when Shader capability is present"));
2454 }
2455
TEST_F(ValidateAtomics,ScopeSpecConstantKernel)2456 TEST_F(ValidateAtomics, ScopeSpecConstantKernel) {
2457 const std::string spirv = R"(
2458 OpCapability Kernel
2459 OpCapability Linkage
2460 OpMemoryModel Logical OpenCL
2461 %void = OpTypeVoid
2462 %int = OpTypeInt 32 0
2463 %spec_const = OpSpecConstant %int 0
2464 %relaxed = OpConstant %int 0
2465 %ptr_int_workgroup = OpTypePointer Workgroup %int
2466 %var = OpVariable %ptr_int_workgroup Workgroup
2467 %voidfn = OpTypeFunction %void
2468 %func = OpFunction %void None %voidfn
2469 %entry = OpLabel
2470 %ld = OpAtomicLoad %int %var %spec_const %relaxed
2471 OpReturn
2472 OpFunctionEnd
2473 )";
2474
2475 CompileSuccessfully(spirv);
2476 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2477 }
2478
TEST_F(ValidateAtomics,VulkanMemoryModelDeviceScopeBad)2479 TEST_F(ValidateAtomics, VulkanMemoryModelDeviceScopeBad) {
2480 const std::string body = R"(
2481 %val = OpAtomicAnd %u32 %u32_var %device %relaxed %u32_1
2482 )";
2483
2484 const std::string extra = R"(OpCapability VulkanMemoryModelKHR
2485 OpExtension "SPV_KHR_vulkan_memory_model"
2486 )";
2487
2488 CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
2489 SPV_ENV_UNIVERSAL_1_3);
2490 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
2491 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2492 EXPECT_THAT(
2493 getDiagnosticString(),
2494 HasSubstr("Use of device scope with VulkanKHR memory model requires the "
2495 "VulkanMemoryModelDeviceScopeKHR capability"));
2496 }
2497
TEST_F(ValidateAtomics,VulkanMemoryModelDeviceScopeGood)2498 TEST_F(ValidateAtomics, VulkanMemoryModelDeviceScopeGood) {
2499 const std::string body = R"(
2500 %val = OpAtomicAnd %u32 %u32_var %device %relaxed %u32_1
2501 )";
2502
2503 const std::string extra = R"(OpCapability VulkanMemoryModelKHR
2504 OpCapability VulkanMemoryModelDeviceScopeKHR
2505 OpExtension "SPV_KHR_vulkan_memory_model"
2506 )";
2507
2508 CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
2509 SPV_ENV_UNIVERSAL_1_3);
2510 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2511 }
2512
TEST_F(ValidateAtomics,CompareExchangeWeakV13ValV14Good)2513 TEST_F(ValidateAtomics, CompareExchangeWeakV13ValV14Good) {
2514 const std::string body = R"(
2515 %val1 = OpAtomicCompareExchangeWeak %u32 %u32_var %device %relaxed %relaxed %u32_0 %u32_0
2516 )";
2517
2518 CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_3);
2519 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
2520 }
2521
TEST_F(ValidateAtomics,CompareExchangeWeakV14Bad)2522 TEST_F(ValidateAtomics, CompareExchangeWeakV14Bad) {
2523 const std::string body = R"(
2524 %val1 = OpAtomicCompareExchangeWeak %u32 %u32_var %device %relaxed %relaxed %u32_0 %u32_0
2525 )";
2526
2527 CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_4);
2528 EXPECT_EQ(SPV_ERROR_WRONG_VERSION,
2529 ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
2530 EXPECT_THAT(
2531 getDiagnosticString(),
2532 HasSubstr(
2533 "AtomicCompareExchangeWeak requires SPIR-V version 1.3 or earlier"));
2534 }
2535
TEST_F(ValidateAtomics,CompareExchangeVolatileMatch)2536 TEST_F(ValidateAtomics, CompareExchangeVolatileMatch) {
2537 const std::string spirv = R"(
2538 OpCapability Shader
2539 OpCapability VulkanMemoryModelKHR
2540 OpCapability Linkage
2541 OpExtension "SPV_KHR_vulkan_memory_model"
2542 OpMemoryModel Logical VulkanKHR
2543 %void = OpTypeVoid
2544 %int = OpTypeInt 32 0
2545 %int_0 = OpConstant %int 0
2546 %int_1 = OpConstant %int 1
2547 %workgroup = OpConstant %int 2
2548 %volatile = OpConstant %int 32768
2549 %ptr_wg_int = OpTypePointer Workgroup %int
2550 %wg_var = OpVariable %ptr_wg_int Workgroup
2551 %void_fn = OpTypeFunction %void
2552 %func = OpFunction %void None %void_fn
2553 %entry = OpLabel
2554 %cmp_ex = OpAtomicCompareExchange %int %wg_var %workgroup %volatile %volatile %int_0 %int_1
2555 OpReturn
2556 OpFunctionEnd
2557 )";
2558
2559 CompileSuccessfully(spirv);
2560 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2561 }
2562
TEST_F(ValidateAtomics,CompareExchangeVolatileMismatch)2563 TEST_F(ValidateAtomics, CompareExchangeVolatileMismatch) {
2564 const std::string spirv = R"(
2565 OpCapability Shader
2566 OpCapability VulkanMemoryModelKHR
2567 OpCapability Linkage
2568 OpExtension "SPV_KHR_vulkan_memory_model"
2569 OpMemoryModel Logical VulkanKHR
2570 %void = OpTypeVoid
2571 %int = OpTypeInt 32 0
2572 %int_0 = OpConstant %int 0
2573 %int_1 = OpConstant %int 1
2574 %workgroup = OpConstant %int 2
2575 %volatile = OpConstant %int 32768
2576 %non_volatile = OpConstant %int 0
2577 %ptr_wg_int = OpTypePointer Workgroup %int
2578 %wg_var = OpVariable %ptr_wg_int Workgroup
2579 %void_fn = OpTypeFunction %void
2580 %func = OpFunction %void None %void_fn
2581 %entry = OpLabel
2582 %cmp_ex = OpAtomicCompareExchange %int %wg_var %workgroup %non_volatile %volatile %int_0 %int_1
2583 OpReturn
2584 OpFunctionEnd
2585 )";
2586
2587 CompileSuccessfully(spirv);
2588 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2589 EXPECT_THAT(getDiagnosticString(),
2590 HasSubstr("Volatile mask setting must match for Equal and "
2591 "Unequal memory semantics"));
2592 }
2593
TEST_F(ValidateAtomics,CompareExchangeVolatileMismatchCooperativeMatrix)2594 TEST_F(ValidateAtomics, CompareExchangeVolatileMismatchCooperativeMatrix) {
2595 const std::string spirv = R"(
2596 OpCapability Shader
2597 OpCapability VulkanMemoryModelKHR
2598 OpCapability Linkage
2599 OpCapability CooperativeMatrixNV
2600 OpExtension "SPV_KHR_vulkan_memory_model"
2601 OpExtension "SPV_NV_cooperative_matrix"
2602 OpMemoryModel Logical VulkanKHR
2603 %void = OpTypeVoid
2604 %int = OpTypeInt 32 0
2605 %int_0 = OpConstant %int 0
2606 %int_1 = OpConstant %int 1
2607 %workgroup = OpConstant %int 2
2608 %volatile = OpSpecConstant %int 32768
2609 %non_volatile = OpSpecConstant %int 32768
2610 %ptr_wg_int = OpTypePointer Workgroup %int
2611 %wg_var = OpVariable %ptr_wg_int Workgroup
2612 %void_fn = OpTypeFunction %void
2613 %func = OpFunction %void None %void_fn
2614 %entry = OpLabel
2615 %cmp_ex = OpAtomicCompareExchange %int %wg_var %workgroup %volatile %non_volatile %int_0 %int_1
2616 OpReturn
2617 OpFunctionEnd
2618 )";
2619
2620 // This is ok because we cannot evaluate the spec constant defaults.
2621 CompileSuccessfully(spirv);
2622 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2623 }
2624
TEST_F(ValidateAtomics,VolatileRequiresVulkanMemoryModel)2625 TEST_F(ValidateAtomics, VolatileRequiresVulkanMemoryModel) {
2626 const std::string spirv = R"(
2627 OpCapability Shader
2628 OpCapability Linkage
2629 OpMemoryModel Logical GLSL450
2630 %void = OpTypeVoid
2631 %int = OpTypeInt 32 0
2632 %int_0 = OpConstant %int 0
2633 %int_1 = OpConstant %int 1
2634 %workgroup = OpConstant %int 2
2635 %volatile = OpConstant %int 32768
2636 %ptr_wg_int = OpTypePointer Workgroup %int
2637 %wg_var = OpVariable %ptr_wg_int Workgroup
2638 %void_fn = OpTypeFunction %void
2639 %func = OpFunction %void None %void_fn
2640 %entry = OpLabel
2641 %ld = OpAtomicLoad %int %wg_var %workgroup %volatile
2642 OpReturn
2643 OpFunctionEnd
2644 )";
2645
2646 CompileSuccessfully(spirv);
2647 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2648 EXPECT_THAT(getDiagnosticString(),
2649 HasSubstr("Memory Semantics Volatile requires capability "
2650 "VulkanMemoryModelKHR"));
2651 }
2652
TEST_F(ValidateAtomics,CooperativeMatrixSemanticsMustBeConstant)2653 TEST_F(ValidateAtomics, CooperativeMatrixSemanticsMustBeConstant) {
2654 const std::string spirv = R"(
2655 OpCapability Shader
2656 OpCapability Linkage
2657 OpCapability CooperativeMatrixNV
2658 OpExtension "SPV_NV_cooperative_matrix"
2659 OpMemoryModel Logical GLSL450
2660 %void = OpTypeVoid
2661 %int = OpTypeInt 32 0
2662 %int_0 = OpConstant %int 0
2663 %int_1 = OpConstant %int 1
2664 %workgroup = OpConstant %int 2
2665 %undef = OpUndef %int
2666 %ptr_wg_int = OpTypePointer Workgroup %int
2667 %wg_var = OpVariable %ptr_wg_int Workgroup
2668 %void_fn = OpTypeFunction %void
2669 %func = OpFunction %void None %void_fn
2670 %entry = OpLabel
2671 %ld = OpAtomicLoad %int %wg_var %workgroup %undef
2672 OpReturn
2673 OpFunctionEnd
2674 )";
2675
2676 CompileSuccessfully(spirv);
2677 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2678 EXPECT_THAT(getDiagnosticString(),
2679 HasSubstr("Memory Semantics must be a constant instruction when "
2680 "CooperativeMatrixNV capability is present"));
2681 }
2682
TEST_F(ValidateAtomics,IIncrementBadPointerDataType)2683 TEST_F(ValidateAtomics, IIncrementBadPointerDataType) {
2684 const std::string spirv = R"(
2685 OpCapability Shader
2686 OpMemoryModel Logical GLSL450
2687 %uint = OpTypeInt 32 0
2688 %_ptr_Input_uint = OpTypePointer Input %uint
2689 %v3uint = OpTypeVector %uint 3
2690 %_ptr_Input_v3uint = OpTypePointer Input %v3uint
2691 %void = OpTypeVoid
2692 %16 = OpTypeFunction %void
2693 %uint_538976288 = OpConstant %uint 538976288
2694 %int = OpTypeInt 32 1
2695 %_runtimearr_int = OpTypeRuntimeArray %int
2696 %_struct_5 = OpTypeStruct %_runtimearr_int
2697 %_ptr_Uniform__struct_5 = OpTypePointer Uniform %_struct_5
2698 %3 = OpVariable %_ptr_Input_v3uint Input
2699 %7 = OpVariable %_ptr_Uniform__struct_5 Uniform
2700 %8224 = OpFunction %void None %16
2701 %65312 = OpLabel
2702 %25 = OpAccessChain %_ptr_Input_uint %3 %uint_538976288
2703 %26 = OpLoad %uint %25
2704 %2097184 = OpAtomicIIncrement %int %7 %uint_538976288 %26
2705 OpUnreachable
2706 OpFunctionEnd
2707 )";
2708
2709 CompileSuccessfully(spirv);
2710 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2711 EXPECT_THAT(getDiagnosticString(),
2712 HasSubstr("AtomicIIncrement: expected Pointer to point to a "
2713 "value of type Result Type"));
2714 }
2715
2716 } // namespace
2717 } // namespace val
2718 } // namespace spvtools
2719