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