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