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