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