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