1 // Copyright (c) 2017 Google Inc.
2 // Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights
3 // reserved.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 
17 // Tests for unique type declaration rules validator.
18 
19 #include <sstream>
20 #include <string>
21 
22 #include "gmock/gmock.h"
23 #include "test/unit_spirv.h"
24 #include "test/val/val_fixtures.h"
25 
26 namespace spvtools {
27 namespace val {
28 namespace {
29 
30 using ::testing::Eq;
31 using ::testing::HasSubstr;
32 using ::testing::Not;
33 
34 using ValidateImage = spvtest::ValidateBase<bool>;
35 
GenerateShaderCode(const std::string & body,const std::string & capabilities_and_extensions="",const std::string & execution_model="Fragment",const std::string & execution_mode="",const spv_target_env env=SPV_ENV_UNIVERSAL_1_0,const std::string & memory_model="GLSL450",const std::string & declarations="")36 std::string GenerateShaderCode(
37     const std::string& body,
38     const std::string& capabilities_and_extensions = "",
39     const std::string& execution_model = "Fragment",
40     const std::string& execution_mode = "",
41     const spv_target_env env = SPV_ENV_UNIVERSAL_1_0,
42     const std::string& memory_model = "GLSL450",
43     const std::string& declarations = "") {
44   std::ostringstream ss;
45   ss << R"(
46 OpCapability Shader
47 OpCapability InputAttachment
48 OpCapability ImageGatherExtended
49 OpCapability MinLod
50 OpCapability Sampled1D
51 OpCapability ImageQuery
52 OpCapability Int64
53 OpCapability Float64
54 OpCapability SparseResidency
55 OpCapability ImageBuffer
56 )";
57 
58   if (env == SPV_ENV_UNIVERSAL_1_0) {
59     ss << "OpCapability SampledRect\n";
60   }
61 
62   // In 1.4, the entry point must list all module-scope variables used.  Just
63   // list all of them.
64   std::string interface_vars = (env != SPV_ENV_UNIVERSAL_1_4) ? "" :
65                                                               R"(
66 %uniform_image_f32_1d_0001
67 %uniform_image_f32_1d_0002_rgba32f
68 %uniform_image_f32_2d_0001
69 %uniform_image_f32_2d_0010
70 %uniform_image_u32_2d_0001
71 %uniform_image_u32_2d_0000
72 %uniform_image_s32_3d_0001
73 %uniform_image_f32_2d_0002
74 %uniform_image_s32_2d_0002
75 %uniform_image_f32_spd_0002
76 %uniform_image_f32_3d_0111
77 %uniform_image_f32_cube_0101
78 %uniform_image_f32_cube_0102_rgba32f
79 %uniform_sampler
80 %private_image_u32_buffer_0002_r32ui
81 %private_image_u32_spd_0002
82 %private_image_f32_buffer_0002_r32ui
83 )";
84 
85   ss << capabilities_and_extensions;
86   ss << "OpMemoryModel Logical " << memory_model << "\n";
87   ss << "OpEntryPoint " << execution_model
88      << " %main \"main\" " + interface_vars + "\n";
89   if (execution_model == "Fragment") {
90     ss << "OpExecutionMode %main OriginUpperLeft\n";
91   }
92   ss << execution_mode;
93 
94   if (env == SPV_ENV_VULKAN_1_0) {
95     ss << R"(
96 OpDecorate %uniform_image_f32_1d_0001 DescriptorSet 0
97 OpDecorate %uniform_image_f32_1d_0001 Binding 0
98 OpDecorate %uniform_image_f32_1d_0002_rgba32f DescriptorSet 0
99 OpDecorate %uniform_image_f32_1d_0002_rgba32f Binding 1
100 OpDecorate %uniform_image_f32_2d_0001 DescriptorSet 0
101 OpDecorate %uniform_image_f32_2d_0001 Binding 2
102 OpDecorate %uniform_image_f32_2d_0010 DescriptorSet 0
103 OpDecorate %uniform_image_f32_2d_0010 Binding 3
104 OpDecorate %uniform_image_u32_2d_0001 DescriptorSet 1
105 OpDecorate %uniform_image_u32_2d_0001 Binding 0
106 OpDecorate %uniform_image_u32_2d_0000 DescriptorSet 1
107 OpDecorate %uniform_image_u32_2d_0000 Binding 1
108 OpDecorate %uniform_image_s32_3d_0001 DescriptorSet 1
109 OpDecorate %uniform_image_s32_3d_0001 Binding 2
110 OpDecorate %uniform_image_f32_2d_0002 DescriptorSet 1
111 OpDecorate %uniform_image_f32_2d_0002 Binding 3
112 OpDecorate %uniform_image_s32_2d_0002 DescriptorSet 1
113 OpDecorate %uniform_image_s32_2d_0002 Binding 4
114 OpDecorate %uniform_image_f32_spd_0002 DescriptorSet 2
115 OpDecorate %uniform_image_f32_spd_0002 Binding 0
116 OpDecorate %uniform_image_f32_3d_0111 DescriptorSet 2
117 OpDecorate %uniform_image_f32_3d_0111 Binding 1
118 OpDecorate %uniform_image_f32_cube_0101 DescriptorSet 2
119 OpDecorate %uniform_image_f32_cube_0101 Binding 2
120 OpDecorate %uniform_image_f32_cube_0102_rgba32f DescriptorSet 2
121 OpDecorate %uniform_image_f32_cube_0102_rgba32f Binding 3
122 OpDecorate %uniform_sampler DescriptorSet 3
123 OpDecorate %uniform_sampler Binding 0
124 )";
125   }
126 
127   ss << R"(
128 %void = OpTypeVoid
129 %func = OpTypeFunction %void
130 %bool = OpTypeBool
131 %f32 = OpTypeFloat 32
132 %f64 = OpTypeFloat 64
133 %u32 = OpTypeInt 32 0
134 %s32 = OpTypeInt 32 1
135 %u64 = OpTypeInt 64 0
136 %s32vec2 = OpTypeVector %s32 2
137 %u32vec2 = OpTypeVector %u32 2
138 %f32vec2 = OpTypeVector %f32 2
139 %u32vec3 = OpTypeVector %u32 3
140 %s32vec3 = OpTypeVector %s32 3
141 %f32vec3 = OpTypeVector %f32 3
142 %u32vec4 = OpTypeVector %u32 4
143 %s32vec4 = OpTypeVector %s32 4
144 %f32vec4 = OpTypeVector %f32 4
145 
146 %f32_0 = OpConstant %f32 0
147 %f32_1 = OpConstant %f32 1
148 %f32_0_5 = OpConstant %f32 0.5
149 %f32_0_25 = OpConstant %f32 0.25
150 %f32_0_75 = OpConstant %f32 0.75
151 
152 %f64_0 = OpConstant %f64 0
153 %f64_1 = OpConstant %f64 1
154 
155 %s32_0 = OpConstant %s32 0
156 %s32_1 = OpConstant %s32 1
157 %s32_2 = OpConstant %s32 2
158 %s32_3 = OpConstant %s32 3
159 %s32_4 = OpConstant %s32 4
160 %s32_m1 = OpConstant %s32 -1
161 
162 %u32_0 = OpConstant %u32 0
163 %u32_1 = OpConstant %u32 1
164 %u32_2 = OpConstant %u32 2
165 %u32_3 = OpConstant %u32 3
166 %u32_4 = OpConstant %u32 4
167 
168 %u64_0 = OpConstant %u64 0
169 %u64_1 = OpConstant %u64 1
170 
171 %u32vec2arr4 = OpTypeArray %u32vec2 %u32_4
172 %u32vec2arr3 = OpTypeArray %u32vec2 %u32_3
173 %u32arr4 = OpTypeArray %u32 %u32_4
174 %u32vec3arr4 = OpTypeArray %u32vec3 %u32_4
175 
176 %struct_u32_f32vec4 = OpTypeStruct %u32 %f32vec4
177 %struct_u64_f32vec4 = OpTypeStruct %u64 %f32vec4
178 %struct_u32_u32vec4 = OpTypeStruct %u32 %u32vec4
179 %struct_u32_f32vec3 = OpTypeStruct %u32 %f32vec3
180 %struct_f32_f32vec4 = OpTypeStruct %f32 %f32vec4
181 %struct_u32_u32 = OpTypeStruct %u32 %u32
182 %struct_f32_f32 = OpTypeStruct %f32 %f32
183 %struct_u32 = OpTypeStruct %u32
184 %struct_u32_f32_u32 = OpTypeStruct %u32 %f32 %u32
185 %struct_u32_f32vec4_u32 = OpTypeStruct %u32 %f32vec4 %u32
186 %struct_u32_u32arr4 = OpTypeStruct %u32 %u32arr4
187 
188 %u32vec2_01 = OpConstantComposite %u32vec2 %u32_0 %u32_1
189 %u32vec2_12 = OpConstantComposite %u32vec2 %u32_1 %u32_2
190 %u32vec3_012 = OpConstantComposite %u32vec3 %u32_0 %u32_1 %u32_2
191 %u32vec3_123 = OpConstantComposite %u32vec3 %u32_1 %u32_2 %u32_3
192 %u32vec4_0123 = OpConstantComposite %u32vec4 %u32_0 %u32_1 %u32_2 %u32_3
193 %u32vec4_1234 = OpConstantComposite %u32vec4 %u32_1 %u32_2 %u32_3 %u32_4
194 
195 %s32vec2_01 = OpConstantComposite %s32vec2 %s32_0 %s32_1
196 %s32vec2_12 = OpConstantComposite %s32vec2 %s32_1 %s32_2
197 %s32vec3_012 = OpConstantComposite %s32vec3 %s32_0 %s32_1 %s32_2
198 %s32vec3_123 = OpConstantComposite %s32vec3 %s32_1 %s32_2 %s32_3
199 %s32vec4_0123 = OpConstantComposite %s32vec4 %s32_0 %s32_1 %s32_2 %s32_3
200 %s32vec4_1234 = OpConstantComposite %s32vec4 %s32_1 %s32_2 %s32_3 %s32_4
201 
202 %f32vec2_00 = OpConstantComposite %f32vec2 %f32_0 %f32_0
203 %f32vec2_01 = OpConstantComposite %f32vec2 %f32_0 %f32_1
204 %f32vec2_10 = OpConstantComposite %f32vec2 %f32_1 %f32_0
205 %f32vec2_11 = OpConstantComposite %f32vec2 %f32_1 %f32_1
206 %f32vec2_hh = OpConstantComposite %f32vec2 %f32_0_5 %f32_0_5
207 
208 %f32vec3_000 = OpConstantComposite %f32vec3 %f32_0 %f32_0 %f32_0
209 %f32vec3_hhh = OpConstantComposite %f32vec3 %f32_0_5 %f32_0_5 %f32_0_5
210 
211 %f32vec4_0000 = OpConstantComposite %f32vec4 %f32_0 %f32_0 %f32_0 %f32_0
212 
213 %const_offsets = OpConstantComposite %u32vec2arr4 %u32vec2_01 %u32vec2_12 %u32vec2_01 %u32vec2_12
214 %const_offsets3x2 = OpConstantComposite %u32vec2arr3 %u32vec2_01 %u32vec2_12 %u32vec2_01
215 %const_offsets4xu = OpConstantComposite %u32arr4 %u32_0 %u32_0 %u32_0 %u32_0
216 %const_offsets4x3 = OpConstantComposite %u32vec3arr4 %u32vec3_012 %u32vec3_012 %u32vec3_012 %u32vec3_012
217 
218 %type_image_f32_1d_0001 = OpTypeImage %f32 1D 0 0 0 1 Unknown
219 %ptr_image_f32_1d_0001 = OpTypePointer UniformConstant %type_image_f32_1d_0001
220 %uniform_image_f32_1d_0001 = OpVariable %ptr_image_f32_1d_0001 UniformConstant
221 %type_sampled_image_f32_1d_0001 = OpTypeSampledImage %type_image_f32_1d_0001
222 
223 %type_image_f32_1d_0002_rgba32f = OpTypeImage %f32 1D 0 0 0 2 Rgba32f
224 %ptr_image_f32_1d_0002_rgba32f = OpTypePointer UniformConstant %type_image_f32_1d_0002_rgba32f
225 %uniform_image_f32_1d_0002_rgba32f = OpVariable %ptr_image_f32_1d_0002_rgba32f UniformConstant
226 %type_sampled_image_f32_1d_0002_rgba32f = OpTypeSampledImage %type_image_f32_1d_0002_rgba32f
227 
228 %type_image_f32_2d_0001 = OpTypeImage %f32 2D 0 0 0 1 Unknown
229 %ptr_image_f32_2d_0001 = OpTypePointer UniformConstant %type_image_f32_2d_0001
230 %uniform_image_f32_2d_0001 = OpVariable %ptr_image_f32_2d_0001 UniformConstant
231 %type_sampled_image_f32_2d_0001 = OpTypeSampledImage %type_image_f32_2d_0001
232 
233 %type_image_f32_2d_0010 = OpTypeImage %f32 2D 0 0 1 0 Unknown
234 %ptr_image_f32_2d_0010 = OpTypePointer UniformConstant %type_image_f32_2d_0010
235 %uniform_image_f32_2d_0010 = OpVariable %ptr_image_f32_2d_0010 UniformConstant
236 %type_sampled_image_f32_2d_0010 = OpTypeSampledImage %type_image_f32_2d_0010
237 
238 %type_image_u32_2d_0001 = OpTypeImage %u32 2D 0 0 0 1 Unknown
239 %ptr_image_u32_2d_0001 = OpTypePointer UniformConstant %type_image_u32_2d_0001
240 %uniform_image_u32_2d_0001 = OpVariable %ptr_image_u32_2d_0001 UniformConstant
241 %type_sampled_image_u32_2d_0001 = OpTypeSampledImage %type_image_u32_2d_0001
242 
243 %type_image_u32_2d_0000 = OpTypeImage %u32 2D 0 0 0 0 Unknown
244 %ptr_image_u32_2d_0000 = OpTypePointer UniformConstant %type_image_u32_2d_0000
245 %uniform_image_u32_2d_0000 = OpVariable %ptr_image_u32_2d_0000 UniformConstant
246 %type_sampled_image_u32_2d_0000 = OpTypeSampledImage %type_image_u32_2d_0000
247 
248 %type_image_s32_3d_0001 = OpTypeImage %s32 3D 0 0 0 1 Unknown
249 %ptr_image_s32_3d_0001 = OpTypePointer UniformConstant %type_image_s32_3d_0001
250 %uniform_image_s32_3d_0001 = OpVariable %ptr_image_s32_3d_0001 UniformConstant
251 %type_sampled_image_s32_3d_0001 = OpTypeSampledImage %type_image_s32_3d_0001
252 
253 %type_image_f32_2d_0002 = OpTypeImage %f32 2D 0 0 0 2 Unknown
254 %ptr_image_f32_2d_0002 = OpTypePointer UniformConstant %type_image_f32_2d_0002
255 %uniform_image_f32_2d_0002 = OpVariable %ptr_image_f32_2d_0002 UniformConstant
256 %type_sampled_image_f32_2d_0002 = OpTypeSampledImage %type_image_f32_2d_0002
257 
258 %type_image_s32_2d_0002 = OpTypeImage %s32 2D 0 0 0 2 Unknown
259 %ptr_image_s32_2d_0002 = OpTypePointer UniformConstant %type_image_s32_2d_0002
260 %uniform_image_s32_2d_0002 = OpVariable %ptr_image_s32_2d_0002 UniformConstant
261 %type_sampled_image_s32_2d_0002 = OpTypeSampledImage %type_image_s32_2d_0002
262 
263 %type_image_f32_spd_0002 = OpTypeImage %f32 SubpassData 0 0 0 2 Unknown
264 %ptr_image_f32_spd_0002 = OpTypePointer UniformConstant %type_image_f32_spd_0002
265 %uniform_image_f32_spd_0002 = OpVariable %ptr_image_f32_spd_0002 UniformConstant
266 %type_sampled_image_f32_spd_0002 = OpTypeSampledImage %type_image_f32_spd_0002
267 
268 %type_image_f32_3d_0111 = OpTypeImage %f32 3D 0 1 1 1 Unknown
269 %ptr_image_f32_3d_0111 = OpTypePointer UniformConstant %type_image_f32_3d_0111
270 %uniform_image_f32_3d_0111 = OpVariable %ptr_image_f32_3d_0111 UniformConstant
271 %type_sampled_image_f32_3d_0111 = OpTypeSampledImage %type_image_f32_3d_0111
272 
273 %type_image_f32_cube_0101 = OpTypeImage %f32 Cube 0 1 0 1 Unknown
274 %ptr_image_f32_cube_0101 = OpTypePointer UniformConstant %type_image_f32_cube_0101
275 %uniform_image_f32_cube_0101 = OpVariable %ptr_image_f32_cube_0101 UniformConstant
276 %type_sampled_image_f32_cube_0101 = OpTypeSampledImage %type_image_f32_cube_0101
277 
278 %type_image_f32_cube_0102_rgba32f = OpTypeImage %f32 Cube 0 1 0 2 Rgba32f
279 %ptr_image_f32_cube_0102_rgba32f = OpTypePointer UniformConstant %type_image_f32_cube_0102_rgba32f
280 %uniform_image_f32_cube_0102_rgba32f = OpVariable %ptr_image_f32_cube_0102_rgba32f UniformConstant
281 %type_sampled_image_f32_cube_0102_rgba32f = OpTypeSampledImage %type_image_f32_cube_0102_rgba32f
282 
283 %type_sampler = OpTypeSampler
284 %ptr_sampler = OpTypePointer UniformConstant %type_sampler
285 %uniform_sampler = OpVariable %ptr_sampler UniformConstant
286 
287 %type_image_u32_buffer_0002_r32ui = OpTypeImage %u32 Buffer 0 0 0 2 R32ui
288 %ptr_Image_u32 = OpTypePointer Image %u32
289 %ptr_image_u32_buffer_0002_r32ui = OpTypePointer Private %type_image_u32_buffer_0002_r32ui
290 %private_image_u32_buffer_0002_r32ui = OpVariable %ptr_image_u32_buffer_0002_r32ui Private
291 
292 %ptr_Image_u32arr4 = OpTypePointer Image %u32arr4
293 
294 %type_image_u32_spd_0002 = OpTypeImage %u32 SubpassData 0 0 0 2 Unknown
295 %ptr_image_u32_spd_0002 = OpTypePointer Private %type_image_u32_spd_0002
296 %private_image_u32_spd_0002 = OpVariable %ptr_image_u32_spd_0002 Private
297 
298 %type_image_f32_buffer_0002_r32ui = OpTypeImage %f32 Buffer 0 0 0 2 R32ui
299 %ptr_Image_f32 = OpTypePointer Image %f32
300 %ptr_image_f32_buffer_0002_r32ui = OpTypePointer Private %type_image_f32_buffer_0002_r32ui
301 %private_image_f32_buffer_0002_r32ui = OpVariable %ptr_image_f32_buffer_0002_r32ui Private
302 )";
303 
304   if (env == SPV_ENV_UNIVERSAL_1_0) {
305     ss << R"(
306 %type_image_void_2d_0001 = OpTypeImage %void 2D 0 0 0 1 Unknown
307 %ptr_image_void_2d_0001 = OpTypePointer UniformConstant %type_image_void_2d_0001
308 %uniform_image_void_2d_0001 = OpVariable %ptr_image_void_2d_0001 UniformConstant
309 %type_sampled_image_void_2d_0001 = OpTypeSampledImage %type_image_void_2d_0001
310 
311 %type_image_void_2d_0002 = OpTypeImage %void 2D 0 0 0 2 Unknown
312 %ptr_image_void_2d_0002 = OpTypePointer UniformConstant %type_image_void_2d_0002
313 %uniform_image_void_2d_0002 = OpVariable %ptr_image_void_2d_0002 UniformConstant
314 %type_sampled_image_void_2d_0002 = OpTypeSampledImage %type_image_void_2d_0002
315 
316 %type_image_f32_rect_0001 = OpTypeImage %f32 Rect 0 0 0 1 Unknown
317 %ptr_image_f32_rect_0001 = OpTypePointer UniformConstant %type_image_f32_rect_0001
318 %uniform_image_f32_rect_0001 = OpVariable %ptr_image_f32_rect_0001 UniformConstant
319 %type_sampled_image_f32_rect_0001 = OpTypeSampledImage %type_image_f32_rect_0001
320 )";
321   }
322 
323   ss << declarations;
324 
325   ss << R"(
326 %main = OpFunction %void None %func
327 %main_entry = OpLabel
328 )";
329 
330   ss << body;
331 
332   ss << R"(
333 OpReturn
334 OpFunctionEnd)";
335 
336   return ss.str();
337 }
338 
GenerateKernelCode(const std::string & body,const std::string & capabilities_and_extensions="")339 std::string GenerateKernelCode(
340     const std::string& body,
341     const std::string& capabilities_and_extensions = "") {
342   std::ostringstream ss;
343   ss << R"(
344 OpCapability Addresses
345 OpCapability Kernel
346 OpCapability Linkage
347 OpCapability ImageQuery
348 OpCapability ImageGatherExtended
349 OpCapability InputAttachment
350 OpCapability SampledRect
351 )";
352 
353   ss << capabilities_and_extensions;
354   ss << R"(
355 OpMemoryModel Physical32 OpenCL
356 %void = OpTypeVoid
357 %func = OpTypeFunction %void
358 %bool = OpTypeBool
359 %f32 = OpTypeFloat 32
360 %u32 = OpTypeInt 32 0
361 %u32vec2 = OpTypeVector %u32 2
362 %f32vec2 = OpTypeVector %f32 2
363 %u32vec3 = OpTypeVector %u32 3
364 %f32vec3 = OpTypeVector %f32 3
365 %u32vec4 = OpTypeVector %u32 4
366 %f32vec4 = OpTypeVector %f32 4
367 
368 %f32_0 = OpConstant %f32 0
369 %f32_1 = OpConstant %f32 1
370 %f32_0_5 = OpConstant %f32 0.5
371 %f32_0_25 = OpConstant %f32 0.25
372 %f32_0_75 = OpConstant %f32 0.75
373 
374 %u32_0 = OpConstant %u32 0
375 %u32_1 = OpConstant %u32 1
376 %u32_2 = OpConstant %u32 2
377 %u32_3 = OpConstant %u32 3
378 %u32_4 = OpConstant %u32 4
379 
380 %u32vec2_01 = OpConstantComposite %u32vec2 %u32_0 %u32_1
381 %u32vec2_12 = OpConstantComposite %u32vec2 %u32_1 %u32_2
382 %u32vec3_012 = OpConstantComposite %u32vec3 %u32_0 %u32_1 %u32_2
383 %u32vec3_123 = OpConstantComposite %u32vec3 %u32_1 %u32_2 %u32_3
384 %u32vec4_0123 = OpConstantComposite %u32vec4 %u32_0 %u32_1 %u32_2 %u32_3
385 %u32vec4_1234 = OpConstantComposite %u32vec4 %u32_1 %u32_2 %u32_3 %u32_4
386 
387 %f32vec2_00 = OpConstantComposite %f32vec2 %f32_0 %f32_0
388 %f32vec2_01 = OpConstantComposite %f32vec2 %f32_0 %f32_1
389 %f32vec2_10 = OpConstantComposite %f32vec2 %f32_1 %f32_0
390 %f32vec2_11 = OpConstantComposite %f32vec2 %f32_1 %f32_1
391 %f32vec2_hh = OpConstantComposite %f32vec2 %f32_0_5 %f32_0_5
392 
393 %f32vec3_000 = OpConstantComposite %f32vec3 %f32_0 %f32_0 %f32_0
394 %f32vec3_hhh = OpConstantComposite %f32vec3 %f32_0_5 %f32_0_5 %f32_0_5
395 
396 %f32vec4_0000 = OpConstantComposite %f32vec4 %f32_0 %f32_0 %f32_0 %f32_0
397 
398 %type_image_f32_2d_0001 = OpTypeImage %f32 2D 0 0 0 1 Unknown
399 %ptr_image_f32_2d_0001 = OpTypePointer UniformConstant %type_image_f32_2d_0001
400 %uniform_image_f32_2d_0001 = OpVariable %ptr_image_f32_2d_0001 UniformConstant
401 %type_sampled_image_f32_2d_0001 = OpTypeSampledImage %type_image_f32_2d_0001
402 
403 %type_image_f32_2d_0010 = OpTypeImage %f32 2D 0 0 1 0 Unknown
404 %ptr_image_f32_2d_0010 = OpTypePointer UniformConstant %type_image_f32_2d_0010
405 %uniform_image_f32_2d_0010 = OpVariable %ptr_image_f32_2d_0010 UniformConstant
406 %type_sampled_image_f32_2d_0010 = OpTypeSampledImage %type_image_f32_2d_0010
407 
408 %type_image_f32_3d_0010 = OpTypeImage %f32 3D 0 0 1 0 Unknown
409 %ptr_image_f32_3d_0010 = OpTypePointer UniformConstant %type_image_f32_3d_0010
410 %uniform_image_f32_3d_0010 = OpVariable %ptr_image_f32_3d_0010 UniformConstant
411 %type_sampled_image_f32_3d_0010 = OpTypeSampledImage %type_image_f32_3d_0010
412 
413 %type_image_f32_rect_0001 = OpTypeImage %f32 Rect 0 0 0 1 Unknown
414 %ptr_image_f32_rect_0001 = OpTypePointer UniformConstant %type_image_f32_rect_0001
415 %uniform_image_f32_rect_0001 = OpVariable %ptr_image_f32_rect_0001 UniformConstant
416 %type_sampled_image_f32_rect_0001 = OpTypeSampledImage %type_image_f32_rect_0001
417 
418 %type_sampler = OpTypeSampler
419 %ptr_sampler = OpTypePointer UniformConstant %type_sampler
420 %uniform_sampler = OpVariable %ptr_sampler UniformConstant
421 
422 %main = OpFunction %void None %func
423 %main_entry = OpLabel
424 )";
425 
426   ss << body;
427   ss << R"(
428 OpReturn
429 OpFunctionEnd)";
430 
431   return ss.str();
432 }
433 
GetShaderHeader(const std::string & capabilities_and_extensions="",bool include_entry_point=true)434 std::string GetShaderHeader(const std::string& capabilities_and_extensions = "",
435                             bool include_entry_point = true) {
436   std::ostringstream ss;
437   ss << R"(
438 OpCapability Shader
439 OpCapability Int64
440 )";
441 
442   ss << capabilities_and_extensions;
443   if (!include_entry_point) {
444     ss << "OpCapability Linkage";
445   }
446 
447   ss << R"(
448 OpMemoryModel Logical GLSL450
449 )";
450 
451   if (include_entry_point) {
452     ss << "OpEntryPoint Fragment %main \"main\"\n";
453     ss << "OpExecutionMode %main OriginUpperLeft";
454   }
455   ss << R"(
456 %void = OpTypeVoid
457 %func = OpTypeFunction %void
458 %bool = OpTypeBool
459 %f32 = OpTypeFloat 32
460 %u32 = OpTypeInt 32 0
461 %u64 = OpTypeInt 64 0
462 %s32 = OpTypeInt 32 1
463 )";
464 
465   return ss.str();
466 }
467 
TEST_F(ValidateImage,TypeImageWrongSampledType)468 TEST_F(ValidateImage, TypeImageWrongSampledType) {
469   const std::string code = GetShaderHeader("", false) + R"(
470 %img_type = OpTypeImage %bool 2D 0 0 0 1 Unknown
471 )";
472 
473   CompileSuccessfully(code.c_str());
474   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
475   EXPECT_THAT(getDiagnosticString(),
476               HasSubstr("Expected Sampled Type to be either void or "
477                         "numerical scalar "
478                         "type"));
479 }
480 
TEST_F(ValidateImage,TypeImageVoidSampledTypeVulkan)481 TEST_F(ValidateImage, TypeImageVoidSampledTypeVulkan) {
482   const std::string code = GetShaderHeader() + R"(
483 %img_type = OpTypeImage %void 2D 0 0 0 1 Unknown
484 %void_func = OpTypeFunction %void
485 %main = OpFunction %void None %void_func
486 %main_lab = OpLabel
487 OpReturn
488 OpFunctionEnd
489 )";
490 
491   const spv_target_env env = SPV_ENV_VULKAN_1_0;
492   CompileSuccessfully(code, env);
493   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
494   EXPECT_THAT(getDiagnosticString(),
495               HasSubstr("Expected Sampled Type to be a 32-bit int "
496                         "or float scalar type for Vulkan environment"));
497 }
498 
TEST_F(ValidateImage,TypeImageU64SampledTypeVulkan)499 TEST_F(ValidateImage, TypeImageU64SampledTypeVulkan) {
500   const std::string code = GetShaderHeader() + R"(
501 %img_type = OpTypeImage %u64 2D 0 0 0 1 Unknown
502 %void_func = OpTypeFunction %void
503 %main = OpFunction %void None %void_func
504 %main_lab = OpLabel
505 OpReturn
506 OpFunctionEnd
507 )";
508 
509   const spv_target_env env = SPV_ENV_VULKAN_1_0;
510   CompileSuccessfully(code, env);
511   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
512   EXPECT_THAT(getDiagnosticString(),
513               HasSubstr("Expected Sampled Type to be a 32-bit int "
514                         "or float scalar type for Vulkan environment"));
515 }
516 
TEST_F(ValidateImage,TypeImageWrongDepth)517 TEST_F(ValidateImage, TypeImageWrongDepth) {
518   const std::string code = GetShaderHeader("", false) + R"(
519 %img_type = OpTypeImage %f32 2D 3 0 0 1 Unknown
520 )";
521 
522   CompileSuccessfully(code.c_str());
523   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
524   EXPECT_THAT(getDiagnosticString(),
525               HasSubstr("Invalid Depth 3 (must be 0, 1 or 2)"));
526 }
527 
TEST_F(ValidateImage,TypeImageWrongArrayed)528 TEST_F(ValidateImage, TypeImageWrongArrayed) {
529   const std::string code = GetShaderHeader("", false) + R"(
530 %img_type = OpTypeImage %f32 2D 0 2 0 1 Unknown
531 )";
532 
533   CompileSuccessfully(code.c_str());
534   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
535   EXPECT_THAT(getDiagnosticString(),
536               HasSubstr("Invalid Arrayed 2 (must be 0 or 1)"));
537 }
538 
TEST_F(ValidateImage,TypeImageWrongMS)539 TEST_F(ValidateImage, TypeImageWrongMS) {
540   const std::string code = GetShaderHeader("", false) + R"(
541 %img_type = OpTypeImage %f32 2D 0 0 2 1 Unknown
542 )";
543 
544   CompileSuccessfully(code.c_str());
545   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
546   EXPECT_THAT(getDiagnosticString(),
547               HasSubstr("Invalid MS 2 (must be 0 or 1)"));
548 }
549 
TEST_F(ValidateImage,TypeImageWrongSampled)550 TEST_F(ValidateImage, TypeImageWrongSampled) {
551   const std::string code = GetShaderHeader("", false) + R"(
552 %img_type = OpTypeImage %f32 2D 0 0 0 3 Unknown
553 )";
554 
555   CompileSuccessfully(code.c_str());
556   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
557   EXPECT_THAT(getDiagnosticString(),
558               HasSubstr("Invalid Sampled 3 (must be 0, 1 or 2)"));
559 }
560 
TEST_F(ValidateImage,TypeImageWrongSampledForSubpassData)561 TEST_F(ValidateImage, TypeImageWrongSampledForSubpassData) {
562   const std::string code =
563       GetShaderHeader("OpCapability InputAttachment\n", false) +
564       R"(
565 %img_type = OpTypeImage %f32 SubpassData 0 0 0 1 Unknown
566 )";
567 
568   CompileSuccessfully(code.c_str());
569   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
570   EXPECT_THAT(getDiagnosticString(),
571               HasSubstr("Dim SubpassData requires Sampled to be 2"));
572 }
573 
TEST_F(ValidateImage,TypeImageWrongFormatForSubpassData)574 TEST_F(ValidateImage, TypeImageWrongFormatForSubpassData) {
575   const std::string code =
576       GetShaderHeader("OpCapability InputAttachment\n", false) +
577       R"(
578 %img_type = OpTypeImage %f32 SubpassData 0 0 0 2 Rgba32f
579 )";
580 
581   CompileSuccessfully(code.c_str());
582   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
583   EXPECT_THAT(getDiagnosticString(),
584               HasSubstr("Dim SubpassData requires format Unknown"));
585 }
586 
TEST_F(ValidateImage,TypeSampledImageNotImage)587 TEST_F(ValidateImage, TypeSampledImageNotImage) {
588   const std::string code = GetShaderHeader("", false) + R"(
589 %simg_type = OpTypeSampledImage %f32
590 )";
591 
592   CompileSuccessfully(code.c_str());
593   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
594   EXPECT_THAT(getDiagnosticString(),
595               HasSubstr("Expected Image to be of type OpTypeImage"));
596 }
597 
TEST_F(ValidateImage,SampledImageSuccess)598 TEST_F(ValidateImage, SampledImageSuccess) {
599   const std::string body = R"(
600 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
601 %sampler = OpLoad %type_sampler %uniform_sampler
602 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
603 )";
604 
605   CompileSuccessfully(GenerateShaderCode(body).c_str());
606   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
607 }
608 
TEST_F(ValidateImage,SampledImageVulkanSuccess)609 TEST_F(ValidateImage, SampledImageVulkanSuccess) {
610   const std::string body = R"(
611 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
612 %sampler = OpLoad %type_sampler %uniform_sampler
613 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
614 )";
615 
616   const spv_target_env env = SPV_ENV_VULKAN_1_0;
617   CompileSuccessfully(GenerateShaderCode(body, "", "Fragment", "", env), env);
618   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(env));
619 }
620 
TEST_F(ValidateImage,SampledImageWrongResultType)621 TEST_F(ValidateImage, SampledImageWrongResultType) {
622   const std::string body = R"(
623 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
624 %sampler = OpLoad %type_sampler %uniform_sampler
625 %simg = OpSampledImage %type_image_f32_2d_0001 %img %sampler
626 )";
627 
628   CompileSuccessfully(GenerateShaderCode(body).c_str());
629   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
630   EXPECT_THAT(getDiagnosticString(),
631               HasSubstr("Expected Result Type to be OpTypeSampledImage"));
632 }
633 
TEST_F(ValidateImage,SampledImageNotImage)634 TEST_F(ValidateImage, SampledImageNotImage) {
635   const std::string body = R"(
636 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
637 %sampler = OpLoad %type_sampler %uniform_sampler
638 %simg1 = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
639 %simg2 = OpSampledImage %type_sampled_image_f32_2d_0001 %simg1 %sampler
640 )";
641 
642   CompileSuccessfully(GenerateShaderCode(body).c_str());
643   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
644   EXPECT_THAT(getDiagnosticString(),
645               HasSubstr("Expected Image to be of type OpTypeImage"));
646 }
647 
TEST_F(ValidateImage,SampledImageImageNotForSampling)648 TEST_F(ValidateImage, SampledImageImageNotForSampling) {
649   const std::string body = R"(
650 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
651 %sampler = OpLoad %type_sampler %uniform_sampler
652 %simg = OpSampledImage %type_sampled_image_f32_2d_0002 %img %sampler
653 )";
654 
655   CompileSuccessfully(GenerateShaderCode(body).c_str());
656   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
657   EXPECT_THAT(getDiagnosticString(),
658               HasSubstr("Expected Image 'Sampled' parameter to be 0 or 1"));
659 }
660 
TEST_F(ValidateImage,SampledImageVulkanUnknownSampled)661 TEST_F(ValidateImage, SampledImageVulkanUnknownSampled) {
662   const std::string body = R"(
663 %img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
664 %sampler = OpLoad %type_sampler %uniform_sampler
665 %simg = OpSampledImage %type_sampled_image_u32_2d_0000 %img %sampler
666 )";
667 
668   const spv_target_env env = SPV_ENV_VULKAN_1_0;
669   CompileSuccessfully(GenerateShaderCode(body, "", "Fragment", "", env), env);
670   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
671   EXPECT_THAT(getDiagnosticString(),
672               HasSubstr("Expected Image 'Sampled' parameter to "
673                         "be 1 for Vulkan environment."));
674 }
675 
TEST_F(ValidateImage,SampledImageNotSampler)676 TEST_F(ValidateImage, SampledImageNotSampler) {
677   const std::string body = R"(
678 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
679 %sampler = OpLoad %type_sampler %uniform_sampler
680 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %img
681 )";
682 
683   CompileSuccessfully(GenerateShaderCode(body).c_str());
684   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
685   EXPECT_THAT(getDiagnosticString(),
686               HasSubstr("Expected Sampler to be of type OpTypeSampler"));
687 }
688 
TEST_F(ValidateImage,ImageTexelPointerSuccess)689 TEST_F(ValidateImage, ImageTexelPointerSuccess) {
690   const std::string body = R"(
691 %texel_ptr = OpImageTexelPointer %ptr_Image_u32 %private_image_u32_buffer_0002_r32ui %u32_0 %u32_0
692 %sum = OpAtomicIAdd %u32 %texel_ptr %u32_1 %u32_0 %u32_1
693 )";
694 
695   CompileSuccessfully(GenerateShaderCode(body).c_str());
696   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
697 }
698 
TEST_F(ValidateImage,ImageTexelPointerResultTypeNotPointer)699 TEST_F(ValidateImage, ImageTexelPointerResultTypeNotPointer) {
700   const std::string body = R"(
701 %texel_ptr = OpImageTexelPointer %type_image_u32_buffer_0002_r32ui %private_image_u32_buffer_0002_r32ui %u32_0 %u32_0
702 %sum = OpAtomicIAdd %u32 %texel_ptr %u32_1 %u32_0 %u32_1
703 )";
704 
705   CompileSuccessfully(GenerateShaderCode(body).c_str());
706   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
707   EXPECT_THAT(getDiagnosticString(),
708               HasSubstr("Expected Result Type to be OpTypePointer"));
709 }
710 
TEST_F(ValidateImage,ImageTexelPointerResultTypeNotImageClass)711 TEST_F(ValidateImage, ImageTexelPointerResultTypeNotImageClass) {
712   const std::string body = R"(
713 %texel_ptr = OpImageTexelPointer %ptr_image_f32_cube_0101 %private_image_u32_buffer_0002_r32ui %u32_0 %u32_0
714 %sum = OpAtomicIAdd %u32 %texel_ptr %u32_1 %u32_0 %u32_1
715 )";
716 
717   CompileSuccessfully(GenerateShaderCode(body).c_str());
718   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
719   EXPECT_THAT(getDiagnosticString(),
720               HasSubstr("Expected Result Type to be OpTypePointer whose "
721                         "Storage Class operand is Image"));
722 }
723 
TEST_F(ValidateImage,ImageTexelPointerResultTypeNotNumericNorVoid)724 TEST_F(ValidateImage, ImageTexelPointerResultTypeNotNumericNorVoid) {
725   const std::string body = R"(
726 %texel_ptr = OpImageTexelPointer %ptr_Image_u32arr4 %private_image_u32_buffer_0002_r32ui %u32_0 %u32_0
727 %sum = OpAtomicIAdd %u32 %texel_ptr %u32_1 %u32_0 %u32_1
728 )";
729 
730   CompileSuccessfully(GenerateShaderCode(body).c_str());
731   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
732   EXPECT_THAT(
733       getDiagnosticString(),
734       HasSubstr("Expected Result Type to be OpTypePointer whose Type operand "
735                 "must be a scalar numerical type or OpTypeVoid"));
736 }
737 
TEST_F(ValidateImage,ImageTexelPointerImageNotResultTypePointer)738 TEST_F(ValidateImage, ImageTexelPointerImageNotResultTypePointer) {
739   const std::string body = R"(
740 %texel_ptr = OpImageTexelPointer %ptr_Image_u32 %type_image_f32_buffer_0002_r32ui %u32_0 %u32_0
741 %sum = OpAtomicIAdd %u32 %texel_ptr %u32_1 %u32_0 %u32_1
742 )";
743 
744   CompileSuccessfully(GenerateShaderCode(body).c_str());
745   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
746   EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand 141[%141] cannot be a "
747                                                "type"));
748 }
749 
TEST_F(ValidateImage,ImageTexelPointerImageNotImage)750 TEST_F(ValidateImage, ImageTexelPointerImageNotImage) {
751   const std::string body = R"(
752 %texel_ptr = OpImageTexelPointer %ptr_Image_u32 %uniform_sampler %u32_0 %u32_0
753 %sum = OpAtomicIAdd %u32 %texel_ptr %u32_1 %u32_0 %u32_1
754 )";
755 
756   CompileSuccessfully(GenerateShaderCode(body).c_str());
757   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
758   EXPECT_THAT(
759       getDiagnosticString(),
760       HasSubstr("Expected Image to be OpTypePointer with Type OpTypeImage"));
761 }
762 
TEST_F(ValidateImage,ImageTexelPointerImageSampledNotResultType)763 TEST_F(ValidateImage, ImageTexelPointerImageSampledNotResultType) {
764   const std::string body = R"(
765 %texel_ptr = OpImageTexelPointer %ptr_Image_u32 %uniform_image_f32_cube_0101 %u32_0 %u32_0
766 %sum = OpAtomicIAdd %u32 %texel_ptr %u32_1 %u32_0 %u32_1
767 )";
768 
769   CompileSuccessfully(GenerateShaderCode(body).c_str());
770   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
771   EXPECT_THAT(getDiagnosticString(),
772               HasSubstr("Expected Image 'Sampled Type' to be the same as the "
773                         "Type pointed to by Result Type"));
774 }
775 
TEST_F(ValidateImage,ImageTexelPointerImageDimSubpassDataBad)776 TEST_F(ValidateImage, ImageTexelPointerImageDimSubpassDataBad) {
777   const std::string body = R"(
778 %texel_ptr = OpImageTexelPointer %ptr_Image_u32 %private_image_u32_spd_0002 %u32_0 %u32_0
779 %sum = OpAtomicIAdd %u32 %texel_ptr %u32_1 %u32_0 %u32_1
780 )";
781 
782   CompileSuccessfully(GenerateShaderCode(body).c_str());
783   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
784   EXPECT_THAT(
785       getDiagnosticString(),
786       HasSubstr(
787           "Image Dim SubpassData cannot be used with OpImageTexelPointer"));
788 }
789 
TEST_F(ValidateImage,ImageTexelPointerImageCoordTypeBad)790 TEST_F(ValidateImage, ImageTexelPointerImageCoordTypeBad) {
791   const std::string body = R"(
792 %texel_ptr = OpImageTexelPointer %ptr_Image_f32 %private_image_f32_buffer_0002_r32ui %f32_0 %f32_0
793 %sum = OpAtomicIAdd %f32 %texel_ptr %f32_1 %f32_0 %f32_1
794 )";
795 
796   CompileSuccessfully(GenerateShaderCode(body).c_str());
797   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
798   EXPECT_THAT(getDiagnosticString(),
799               HasSubstr("Expected Coordinate to be integer scalar or vector"));
800 }
801 
TEST_F(ValidateImage,ImageTexelPointerImageCoordSizeBad)802 TEST_F(ValidateImage, ImageTexelPointerImageCoordSizeBad) {
803   const std::string body = R"(
804 %texel_ptr = OpImageTexelPointer %ptr_Image_u32 %uniform_image_u32_2d_0000 %u32vec3_012 %u32_0
805 %sum = OpAtomicIAdd %u32 %texel_ptr %u32_1 %u32_0 %u32_1
806 )";
807 
808   CompileSuccessfully(GenerateShaderCode(body).c_str());
809   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
810   EXPECT_THAT(
811       getDiagnosticString(),
812       HasSubstr("Expected Coordinate to have 2 components, but given 3"));
813 }
814 
TEST_F(ValidateImage,ImageTexelPointerSampleNotIntScalar)815 TEST_F(ValidateImage, ImageTexelPointerSampleNotIntScalar) {
816   const std::string body = R"(
817 %texel_ptr = OpImageTexelPointer %ptr_Image_u32 %private_image_u32_buffer_0002_r32ui %u32_0 %f32_0
818 %sum = OpAtomicIAdd %u32 %texel_ptr %u32_1 %u32_0 %u32_1
819 )";
820 
821   CompileSuccessfully(GenerateShaderCode(body).c_str());
822   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
823   EXPECT_THAT(getDiagnosticString(),
824               HasSubstr("Expected Sample to be integer scalar"));
825 }
826 
TEST_F(ValidateImage,ImageTexelPointerSampleNotZeroForImageWithMSZero)827 TEST_F(ValidateImage, ImageTexelPointerSampleNotZeroForImageWithMSZero) {
828   const std::string body = R"(
829 %texel_ptr = OpImageTexelPointer %ptr_Image_u32 %private_image_u32_buffer_0002_r32ui %u32_0 %u32_1
830 %sum = OpAtomicIAdd %u32 %texel_ptr %u32_1 %u32_0 %u32_1
831 )";
832 
833   CompileSuccessfully(GenerateShaderCode(body).c_str());
834   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
835   EXPECT_THAT(getDiagnosticString(),
836               HasSubstr("Expected Sample for Image with MS 0 to be a valid "
837                         "<id> for the value 0"));
838 }
839 
TEST_F(ValidateImage,SampleImplicitLodSuccess)840 TEST_F(ValidateImage, SampleImplicitLodSuccess) {
841   const std::string body = R"(
842 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
843 %sampler = OpLoad %type_sampler %uniform_sampler
844 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
845 %res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh
846 %res2 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh Bias %f32_0_25
847 %res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh ConstOffset %s32vec2_01
848 %res5 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh Offset %s32vec2_01
849 %res6 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh MinLod %f32_0_5
850 %res7 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh Bias|Offset|MinLod %f32_0_25 %s32vec2_01 %f32_0_5
851 %res8 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh NonPrivateTexelKHR
852 )";
853 
854   const std::string extra = R"(
855 OpCapability VulkanMemoryModelKHR
856 OpExtension "SPV_KHR_vulkan_memory_model"
857 )";
858   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
859                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
860                           .c_str());
861   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
862 }
863 
TEST_F(ValidateImage,SampleImplicitLodWrongResultType)864 TEST_F(ValidateImage, SampleImplicitLodWrongResultType) {
865   const std::string body = R"(
866 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
867 %sampler = OpLoad %type_sampler %uniform_sampler
868 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
869 %res1 = OpImageSampleImplicitLod %f32 %simg %f32vec2_hh
870 )";
871 
872   CompileSuccessfully(GenerateShaderCode(body).c_str());
873   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
874   EXPECT_THAT(getDiagnosticString(),
875               HasSubstr("Expected Result Type to be int or float vector type"));
876 }
877 
TEST_F(ValidateImage,SampleImplicitLodWrongNumComponentsResultType)878 TEST_F(ValidateImage, SampleImplicitLodWrongNumComponentsResultType) {
879   const std::string body = R"(
880 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
881 %sampler = OpLoad %type_sampler %uniform_sampler
882 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
883 %res1 = OpImageSampleImplicitLod %f32vec3 %simg %f32vec2_hh
884 )";
885 
886   CompileSuccessfully(GenerateShaderCode(body).c_str());
887   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
888   EXPECT_THAT(getDiagnosticString(),
889               HasSubstr("Expected Result Type to have 4 components"));
890 }
891 
TEST_F(ValidateImage,SampleImplicitLodNotSampledImage)892 TEST_F(ValidateImage, SampleImplicitLodNotSampledImage) {
893   const std::string body = R"(
894 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
895 %res1 = OpImageSampleImplicitLod %f32vec4 %img %f32vec2_hh
896 )";
897 
898   CompileSuccessfully(GenerateShaderCode(body).c_str());
899   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
900   EXPECT_THAT(
901       getDiagnosticString(),
902       HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage"));
903 }
904 
TEST_F(ValidateImage,SampleImplicitLodWrongSampledType)905 TEST_F(ValidateImage, SampleImplicitLodWrongSampledType) {
906   const std::string body = R"(
907 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
908 %sampler = OpLoad %type_sampler %uniform_sampler
909 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
910 %res1 = OpImageSampleImplicitLod %u32vec4 %simg %f32vec2_00
911 )";
912 
913   CompileSuccessfully(GenerateShaderCode(body).c_str());
914   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
915   EXPECT_THAT(getDiagnosticString(),
916               HasSubstr("Expected Image 'Sampled Type' to be the same as "
917                         "Result Type components"));
918 }
919 
TEST_F(ValidateImage,SampleImplicitLodVoidSampledType)920 TEST_F(ValidateImage, SampleImplicitLodVoidSampledType) {
921   const std::string body = R"(
922 %img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001
923 %sampler = OpLoad %type_sampler %uniform_sampler
924 %simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler
925 %res1 = OpImageSampleImplicitLod %u32vec4 %simg %f32vec2_00
926 )";
927 
928   CompileSuccessfully(GenerateShaderCode(body).c_str());
929   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
930 }
931 
TEST_F(ValidateImage,SampleImplicitLodWrongCoordinateType)932 TEST_F(ValidateImage, SampleImplicitLodWrongCoordinateType) {
933   const std::string body = R"(
934 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
935 %sampler = OpLoad %type_sampler %uniform_sampler
936 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
937 %res1 = OpImageSampleImplicitLod %f32vec4 %simg %img
938 )";
939 
940   CompileSuccessfully(GenerateShaderCode(body).c_str());
941   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
942   EXPECT_THAT(getDiagnosticString(),
943               HasSubstr("Expected Coordinate to be float scalar or vector"));
944 }
945 
TEST_F(ValidateImage,SampleImplicitLodCoordinateSizeTooSmall)946 TEST_F(ValidateImage, SampleImplicitLodCoordinateSizeTooSmall) {
947   const std::string body = R"(
948 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
949 %sampler = OpLoad %type_sampler %uniform_sampler
950 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
951 %res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32_0_5
952 )";
953 
954   CompileSuccessfully(GenerateShaderCode(body).c_str());
955   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
956   EXPECT_THAT(getDiagnosticString(),
957               HasSubstr("Expected Coordinate to have at least 2 components, "
958                         "but given only 1"));
959 }
960 
TEST_F(ValidateImage,SampleExplicitLodSuccessShader)961 TEST_F(ValidateImage, SampleExplicitLodSuccessShader) {
962   const std::string body = R"(
963 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
964 %sampler = OpLoad %type_sampler %uniform_sampler
965 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
966 %res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec4_0000 Lod %f32_1
967 %res2 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_hh Grad %f32vec2_10 %f32vec2_01
968 %res3 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_hh ConstOffset %s32vec2_01
969 %res4 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec3_hhh Offset %s32vec2_01
970 %res5 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_hh Grad|Offset|MinLod %f32vec2_10 %f32vec2_01 %s32vec2_01 %f32_0_5
971 %res6 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec4_0000 Lod|NonPrivateTexelKHR %f32_1
972 )";
973 
974   const std::string extra = R"(
975 OpCapability VulkanMemoryModelKHR
976 OpExtension "SPV_KHR_vulkan_memory_model"
977 )";
978   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
979                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
980                           .c_str());
981   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
982 }
983 
TEST_F(ValidateImage,SampleExplicitLodSuccessKernel)984 TEST_F(ValidateImage, SampleExplicitLodSuccessKernel) {
985   const std::string body = R"(
986 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
987 %sampler = OpLoad %type_sampler %uniform_sampler
988 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
989 %res1 = OpImageSampleExplicitLod %f32vec4 %simg %u32vec4_0123 Lod %f32_1
990 %res2 = OpImageSampleExplicitLod %f32vec4 %simg %u32vec2_01 Grad %f32vec2_10 %f32vec2_01
991 %res3 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_hh ConstOffset %u32vec2_01
992 %res4 = OpImageSampleExplicitLod %f32vec4 %simg %u32vec2_01 Offset %u32vec2_01
993 %res5 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_hh Grad|Offset %f32vec2_10 %f32vec2_01 %u32vec2_01
994 )";
995 
996   CompileSuccessfully(GenerateKernelCode(body).c_str());
997   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
998 }
999 
TEST_F(ValidateImage,SampleExplicitLodSuccessCubeArrayed)1000 TEST_F(ValidateImage, SampleExplicitLodSuccessCubeArrayed) {
1001   const std::string body = R"(
1002 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
1003 %sampler = OpLoad %type_sampler %uniform_sampler
1004 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
1005 %res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec4_0000 Grad %f32vec3_hhh %f32vec3_hhh
1006 )";
1007 
1008   CompileSuccessfully(GenerateShaderCode(body).c_str());
1009   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1010 }
1011 
TEST_F(ValidateImage,SampleExplicitLodWrongResultType)1012 TEST_F(ValidateImage, SampleExplicitLodWrongResultType) {
1013   const std::string body = R"(
1014 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1015 %sampler = OpLoad %type_sampler %uniform_sampler
1016 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1017 %res1 = OpImageSampleExplicitLod %f32 %simg %f32vec2_hh Lod %f32_1
1018 )";
1019 
1020   CompileSuccessfully(GenerateShaderCode(body).c_str());
1021   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1022   EXPECT_THAT(getDiagnosticString(),
1023               HasSubstr("Expected Result Type to be int or float vector type"));
1024 }
1025 
TEST_F(ValidateImage,SampleExplicitLodWrongNumComponentsResultType)1026 TEST_F(ValidateImage, SampleExplicitLodWrongNumComponentsResultType) {
1027   const std::string body = R"(
1028 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1029 %sampler = OpLoad %type_sampler %uniform_sampler
1030 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1031 %res1 = OpImageSampleExplicitLod %f32vec3 %simg %f32vec2_hh Lod %f32_1
1032 )";
1033 
1034   CompileSuccessfully(GenerateShaderCode(body).c_str());
1035   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1036   EXPECT_THAT(getDiagnosticString(),
1037               HasSubstr("Expected Result Type to have 4 components"));
1038 }
1039 
TEST_F(ValidateImage,SampleExplicitLodNotSampledImage)1040 TEST_F(ValidateImage, SampleExplicitLodNotSampledImage) {
1041   const std::string body = R"(
1042 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1043 %res1 = OpImageSampleExplicitLod %f32vec4 %img %f32vec2_hh Lod %f32_1
1044 )";
1045 
1046   CompileSuccessfully(GenerateShaderCode(body).c_str());
1047   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1048   EXPECT_THAT(
1049       getDiagnosticString(),
1050       HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage"));
1051 }
1052 
TEST_F(ValidateImage,SampleExplicitLodWrongSampledType)1053 TEST_F(ValidateImage, SampleExplicitLodWrongSampledType) {
1054   const std::string body = R"(
1055 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1056 %sampler = OpLoad %type_sampler %uniform_sampler
1057 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1058 %res1 = OpImageSampleExplicitLod %u32vec4 %simg %f32vec2_00 Lod %f32_1
1059 )";
1060 
1061   CompileSuccessfully(GenerateShaderCode(body).c_str());
1062   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1063   EXPECT_THAT(getDiagnosticString(),
1064               HasSubstr("Expected Image 'Sampled Type' to be the same as "
1065                         "Result Type components"));
1066 }
1067 
TEST_F(ValidateImage,SampleExplicitLodVoidSampledType)1068 TEST_F(ValidateImage, SampleExplicitLodVoidSampledType) {
1069   const std::string body = R"(
1070 %img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001
1071 %sampler = OpLoad %type_sampler %uniform_sampler
1072 %simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler
1073 %res1 = OpImageSampleExplicitLod %u32vec4 %simg %f32vec2_00 Lod %f32_1
1074 )";
1075 
1076   CompileSuccessfully(GenerateShaderCode(body).c_str());
1077   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1078 }
1079 
TEST_F(ValidateImage,SampleExplicitLodWrongCoordinateType)1080 TEST_F(ValidateImage, SampleExplicitLodWrongCoordinateType) {
1081   const std::string body = R"(
1082 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1083 %sampler = OpLoad %type_sampler %uniform_sampler
1084 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1085 %res1 = OpImageSampleExplicitLod %f32vec4 %simg %img Lod %f32_1
1086 )";
1087 
1088   CompileSuccessfully(GenerateShaderCode(body).c_str());
1089   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1090   EXPECT_THAT(getDiagnosticString(),
1091               HasSubstr("Expected Coordinate to be float scalar or vector"));
1092 }
1093 
TEST_F(ValidateImage,SampleExplicitLodCoordinateSizeTooSmall)1094 TEST_F(ValidateImage, SampleExplicitLodCoordinateSizeTooSmall) {
1095   const std::string body = R"(
1096 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1097 %sampler = OpLoad %type_sampler %uniform_sampler
1098 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1099 %res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32_0_5 Lod %f32_1
1100 )";
1101 
1102   CompileSuccessfully(GenerateShaderCode(body).c_str());
1103   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1104   EXPECT_THAT(getDiagnosticString(),
1105               HasSubstr("Expected Coordinate to have at least 2 components, "
1106                         "but given only 1"));
1107 }
1108 
TEST_F(ValidateImage,SampleExplicitLodBias)1109 TEST_F(ValidateImage, SampleExplicitLodBias) {
1110   const std::string body = R"(
1111 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1112 %sampler = OpLoad %type_sampler %uniform_sampler
1113 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1114 %res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_00 Bias|Lod %f32_1 %f32_1
1115 )";
1116 
1117   CompileSuccessfully(GenerateShaderCode(body).c_str());
1118   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1119   EXPECT_THAT(
1120       getDiagnosticString(),
1121       HasSubstr(
1122           "Image Operand Bias can only be used with ImplicitLod opcodes"));
1123 }
1124 
TEST_F(ValidateImage,LodAndGrad)1125 TEST_F(ValidateImage, LodAndGrad) {
1126   const std::string body = R"(
1127 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1128 %sampler = OpLoad %type_sampler %uniform_sampler
1129 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1130 %res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_00 Lod|Grad %f32_1 %f32vec2_hh %f32vec2_hh
1131 )";
1132 
1133   CompileSuccessfully(GenerateShaderCode(body).c_str());
1134   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1135   EXPECT_THAT(
1136       getDiagnosticString(),
1137       HasSubstr(
1138           "Image Operand bits Lod and Grad cannot be set at the same time"));
1139 }
1140 
TEST_F(ValidateImage,ImplicitLodWithLod)1141 TEST_F(ValidateImage, ImplicitLodWithLod) {
1142   const std::string body = R"(
1143 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1144 %sampler = OpLoad %type_sampler %uniform_sampler
1145 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1146 %res2 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh Lod %f32_0_5
1147 )";
1148 
1149   CompileSuccessfully(GenerateShaderCode(body).c_str());
1150   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1151   EXPECT_THAT(
1152       getDiagnosticString(),
1153       HasSubstr("Image Operand Lod can only be used with ExplicitLod opcodes "
1154                 "and OpImageFetch"));
1155 }
1156 
TEST_F(ValidateImage,LodWrongType)1157 TEST_F(ValidateImage, LodWrongType) {
1158   const std::string body = R"(
1159 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1160 %sampler = OpLoad %type_sampler %uniform_sampler
1161 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1162 %res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_00 Lod %f32vec2_hh)";
1163 
1164   CompileSuccessfully(GenerateShaderCode(body).c_str());
1165   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1166   EXPECT_THAT(getDiagnosticString(),
1167               HasSubstr("Expected Image Operand Lod to be float scalar when "
1168                         "used with ExplicitLod"));
1169 }
1170 
TEST_F(ValidateImage,LodWrongDim)1171 TEST_F(ValidateImage, LodWrongDim) {
1172   const std::string body = R"(
1173 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
1174 %sampler = OpLoad %type_sampler %uniform_sampler
1175 %simg = OpSampledImage %type_sampled_image_f32_rect_0001 %img %sampler
1176 %res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_00 Lod %f32_0)";
1177 
1178   CompileSuccessfully(GenerateShaderCode(body).c_str());
1179   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1180   EXPECT_THAT(getDiagnosticString(),
1181               HasSubstr("Image Operand Lod requires 'Dim' parameter to be 1D, "
1182                         "2D, 3D or Cube"));
1183 }
1184 
TEST_F(ValidateImage,LodMultisampled)1185 TEST_F(ValidateImage, LodMultisampled) {
1186   const std::string body = R"(
1187 %img = OpLoad %type_image_f32_2d_0010 %uniform_image_f32_2d_0010
1188 %sampler = OpLoad %type_sampler %uniform_sampler
1189 %simg = OpSampledImage %type_sampled_image_f32_2d_0010 %img %sampler
1190 %res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_00 Lod %f32_0)";
1191 
1192   CompileSuccessfully(GenerateShaderCode(body).c_str());
1193   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1194   EXPECT_THAT(getDiagnosticString(),
1195               HasSubstr("Image Operand Lod requires 'MS' parameter to be 0"));
1196 }
1197 
TEST_F(ValidateImage,MinLodIncompatible)1198 TEST_F(ValidateImage, MinLodIncompatible) {
1199   const std::string body = R"(
1200 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1201 %sampler = OpLoad %type_sampler %uniform_sampler
1202 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1203 %res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_00 Lod|MinLod %f32_0 %f32_0)";
1204 
1205   CompileSuccessfully(GenerateShaderCode(body).c_str());
1206   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1207   EXPECT_THAT(
1208       getDiagnosticString(),
1209       HasSubstr(
1210           "Image Operand MinLod can only be used with ImplicitLod opcodes or "
1211           "together with Image Operand Grad"));
1212 }
1213 
TEST_F(ValidateImage,ImplicitLodWithGrad)1214 TEST_F(ValidateImage, ImplicitLodWithGrad) {
1215   const std::string body = R"(
1216 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1217 %sampler = OpLoad %type_sampler %uniform_sampler
1218 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1219 %res2 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh Grad %f32vec2_hh %f32vec2_hh
1220 )";
1221 
1222   CompileSuccessfully(GenerateShaderCode(body).c_str());
1223   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1224   EXPECT_THAT(
1225       getDiagnosticString(),
1226       HasSubstr(
1227           "Image Operand Grad can only be used with ExplicitLod opcodes"));
1228 }
1229 
TEST_F(ValidateImage,SampleImplicitLod3DArrayedMultisampledSuccess)1230 TEST_F(ValidateImage, SampleImplicitLod3DArrayedMultisampledSuccess) {
1231   const std::string body = R"(
1232 %img = OpLoad %type_image_f32_3d_0111 %uniform_image_f32_3d_0111
1233 %sampler = OpLoad %type_sampler %uniform_sampler
1234 %simg = OpSampledImage %type_sampled_image_f32_3d_0111 %img %sampler
1235 %res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000
1236 %res2 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 ConstOffset %s32vec3_012
1237 %res3 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 Offset %s32vec3_012
1238 )";
1239 
1240   CompileSuccessfully(GenerateShaderCode(body).c_str());
1241   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1242 }
1243 
TEST_F(ValidateImage,SampleImplicitLodCubeArrayedSuccess)1244 TEST_F(ValidateImage, SampleImplicitLodCubeArrayedSuccess) {
1245   const std::string body = R"(
1246 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
1247 %sampler = OpLoad %type_sampler %uniform_sampler
1248 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
1249 %res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000
1250 %res2 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 Bias %f32_0_25
1251 %res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 MinLod %f32_0_5
1252 %res5 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 Bias|MinLod %f32_0_25 %f32_0_5
1253 )";
1254 
1255   CompileSuccessfully(GenerateShaderCode(body).c_str());
1256   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1257 }
1258 
TEST_F(ValidateImage,SampleImplicitLodBiasWrongType)1259 TEST_F(ValidateImage, SampleImplicitLodBiasWrongType) {
1260   const std::string body = R"(
1261 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1262 %sampler = OpLoad %type_sampler %uniform_sampler
1263 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1264 %res2 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh Bias %u32_0
1265 )";
1266 
1267   CompileSuccessfully(GenerateShaderCode(body).c_str());
1268   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1269   EXPECT_THAT(getDiagnosticString(),
1270               HasSubstr("Expected Image Operand Bias to be float scalar"));
1271 }
1272 
TEST_F(ValidateImage,SampleImplicitLodBiasWrongDim)1273 TEST_F(ValidateImage, SampleImplicitLodBiasWrongDim) {
1274   const std::string body = R"(
1275 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
1276 %sampler = OpLoad %type_sampler %uniform_sampler
1277 %simg = OpSampledImage %type_sampled_image_f32_rect_0001 %img %sampler
1278 %res2 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh Bias %f32_0
1279 )";
1280 
1281   CompileSuccessfully(GenerateShaderCode(body).c_str());
1282   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1283   EXPECT_THAT(getDiagnosticString(),
1284               HasSubstr("Image Operand Bias requires 'Dim' parameter to be 1D, "
1285                         "2D, 3D or Cube"));
1286 }
1287 
TEST_F(ValidateImage,SampleImplicitLodBiasMultisampled)1288 TEST_F(ValidateImage, SampleImplicitLodBiasMultisampled) {
1289   const std::string body = R"(
1290 %img = OpLoad %type_image_f32_3d_0111 %uniform_image_f32_3d_0111
1291 %sampler = OpLoad %type_sampler %uniform_sampler
1292 %simg = OpSampledImage %type_sampled_image_f32_3d_0111 %img %sampler
1293 %res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 Bias %f32_0_25
1294 )";
1295 
1296   CompileSuccessfully(GenerateShaderCode(body).c_str());
1297   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1298   EXPECT_THAT(getDiagnosticString(),
1299               HasSubstr("Image Operand Bias requires 'MS' parameter to be 0"));
1300 }
1301 
TEST_F(ValidateImage,SampleExplicitLodGradDxWrongType)1302 TEST_F(ValidateImage, SampleExplicitLodGradDxWrongType) {
1303   const std::string body = R"(
1304 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
1305 %sampler = OpLoad %type_sampler %uniform_sampler
1306 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
1307 %res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec4_0000 Grad %s32vec3_012 %f32vec3_hhh
1308 )";
1309 
1310   CompileSuccessfully(GenerateShaderCode(body).c_str());
1311   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1312   EXPECT_THAT(getDiagnosticString(),
1313               HasSubstr("Expected both Image Operand Grad ids to be float "
1314                         "scalars or vectors"));
1315 }
1316 
TEST_F(ValidateImage,SampleExplicitLodGradDyWrongType)1317 TEST_F(ValidateImage, SampleExplicitLodGradDyWrongType) {
1318   const std::string body = R"(
1319 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
1320 %sampler = OpLoad %type_sampler %uniform_sampler
1321 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
1322 %res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec4_0000 Grad  %f32vec3_hhh %s32vec3_012
1323 )";
1324 
1325   CompileSuccessfully(GenerateShaderCode(body).c_str());
1326   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1327   EXPECT_THAT(getDiagnosticString(),
1328               HasSubstr("Expected both Image Operand Grad ids to be float "
1329                         "scalars or vectors"));
1330 }
1331 
TEST_F(ValidateImage,SampleExplicitLodGradDxWrongSize)1332 TEST_F(ValidateImage, SampleExplicitLodGradDxWrongSize) {
1333   const std::string body = R"(
1334 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
1335 %sampler = OpLoad %type_sampler %uniform_sampler
1336 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
1337 %res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec4_0000 Grad %f32vec2_00 %f32vec3_hhh
1338 )";
1339 
1340   CompileSuccessfully(GenerateShaderCode(body).c_str());
1341   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1342   EXPECT_THAT(
1343       getDiagnosticString(),
1344       HasSubstr(
1345           "Expected Image Operand Grad dx to have 3 components, but given 2"));
1346 }
1347 
TEST_F(ValidateImage,SampleExplicitLodGradDyWrongSize)1348 TEST_F(ValidateImage, SampleExplicitLodGradDyWrongSize) {
1349   const std::string body = R"(
1350 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
1351 %sampler = OpLoad %type_sampler %uniform_sampler
1352 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
1353 %res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec4_0000 Grad %f32vec3_hhh %f32vec2_00
1354 )";
1355 
1356   CompileSuccessfully(GenerateShaderCode(body).c_str());
1357   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1358   EXPECT_THAT(
1359       getDiagnosticString(),
1360       HasSubstr(
1361           "Expected Image Operand Grad dy to have 3 components, but given 2"));
1362 }
1363 
TEST_F(ValidateImage,SampleExplicitLodGradMultisampled)1364 TEST_F(ValidateImage, SampleExplicitLodGradMultisampled) {
1365   const std::string body = R"(
1366 %img = OpLoad %type_image_f32_3d_0111 %uniform_image_f32_3d_0111
1367 %sampler = OpLoad %type_sampler %uniform_sampler
1368 %simg = OpSampledImage %type_sampled_image_f32_3d_0111 %img %sampler
1369 %res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec4_0000 Grad %f32vec3_000 %f32vec3_000
1370 )";
1371 
1372   CompileSuccessfully(GenerateShaderCode(body).c_str());
1373   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1374   EXPECT_THAT(getDiagnosticString(),
1375               HasSubstr("Image Operand Grad requires 'MS' parameter to be 0"));
1376 }
1377 
TEST_F(ValidateImage,SampleImplicitLodConstOffsetCubeDim)1378 TEST_F(ValidateImage, SampleImplicitLodConstOffsetCubeDim) {
1379   const std::string body = R"(
1380 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
1381 %sampler = OpLoad %type_sampler %uniform_sampler
1382 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
1383 %res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 ConstOffset %s32vec3_012
1384 )";
1385 
1386   CompileSuccessfully(GenerateShaderCode(body).c_str());
1387   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1388   EXPECT_THAT(
1389       getDiagnosticString(),
1390       HasSubstr(
1391           "Image Operand ConstOffset cannot be used with Cube Image 'Dim'"));
1392 }
1393 
TEST_F(ValidateImage,SampleImplicitLodConstOffsetWrongType)1394 TEST_F(ValidateImage, SampleImplicitLodConstOffsetWrongType) {
1395   const std::string body = R"(
1396 %img = OpLoad %type_image_f32_3d_0111 %uniform_image_f32_3d_0111
1397 %sampler = OpLoad %type_sampler %uniform_sampler
1398 %simg = OpSampledImage %type_sampled_image_f32_3d_0111 %img %sampler
1399 %res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 ConstOffset %f32vec3_000
1400 )";
1401 
1402   CompileSuccessfully(GenerateShaderCode(body).c_str());
1403   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1404   EXPECT_THAT(
1405       getDiagnosticString(),
1406       HasSubstr(
1407           "Expected Image Operand ConstOffset to be int scalar or vector"));
1408 }
1409 
TEST_F(ValidateImage,SampleImplicitLodConstOffsetWrongSize)1410 TEST_F(ValidateImage, SampleImplicitLodConstOffsetWrongSize) {
1411   const std::string body = R"(
1412 %img = OpLoad %type_image_f32_3d_0111 %uniform_image_f32_3d_0111
1413 %sampler = OpLoad %type_sampler %uniform_sampler
1414 %simg = OpSampledImage %type_sampled_image_f32_3d_0111 %img %sampler
1415 %res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 ConstOffset %s32vec2_01
1416 )";
1417 
1418   CompileSuccessfully(GenerateShaderCode(body).c_str());
1419   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1420   EXPECT_THAT(getDiagnosticString(),
1421               HasSubstr("Expected Image Operand ConstOffset to have 3 "
1422                         "components, but given 2"));
1423 }
1424 
TEST_F(ValidateImage,SampleImplicitLodConstOffsetNotConst)1425 TEST_F(ValidateImage, SampleImplicitLodConstOffsetNotConst) {
1426   const std::string body = R"(
1427 %img = OpLoad %type_image_f32_3d_0111 %uniform_image_f32_3d_0111
1428 %sampler = OpLoad %type_sampler %uniform_sampler
1429 %simg = OpSampledImage %type_sampled_image_f32_3d_0111 %img %sampler
1430 %offset = OpSNegate %s32vec3 %s32vec3_012
1431 %res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 ConstOffset %offset
1432 )";
1433 
1434   CompileSuccessfully(GenerateShaderCode(body).c_str());
1435   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1436   EXPECT_THAT(
1437       getDiagnosticString(),
1438       HasSubstr("Expected Image Operand ConstOffset to be a const object"));
1439 }
1440 
TEST_F(ValidateImage,SampleImplicitLodOffsetCubeDim)1441 TEST_F(ValidateImage, SampleImplicitLodOffsetCubeDim) {
1442   const std::string body = R"(
1443 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
1444 %sampler = OpLoad %type_sampler %uniform_sampler
1445 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
1446 %res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 Offset %s32vec3_012
1447 )";
1448 
1449   CompileSuccessfully(GenerateShaderCode(body).c_str());
1450   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1451   EXPECT_THAT(
1452       getDiagnosticString(),
1453       HasSubstr("Image Operand Offset cannot be used with Cube Image 'Dim'"));
1454 }
1455 
TEST_F(ValidateImage,SampleImplicitLodOffsetWrongType)1456 TEST_F(ValidateImage, SampleImplicitLodOffsetWrongType) {
1457   const std::string body = R"(
1458 %img = OpLoad %type_image_f32_3d_0111 %uniform_image_f32_3d_0111
1459 %sampler = OpLoad %type_sampler %uniform_sampler
1460 %simg = OpSampledImage %type_sampled_image_f32_3d_0111 %img %sampler
1461 %res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 Offset %f32vec3_000
1462 )";
1463 
1464   CompileSuccessfully(GenerateShaderCode(body).c_str());
1465   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1466   EXPECT_THAT(
1467       getDiagnosticString(),
1468       HasSubstr("Expected Image Operand Offset to be int scalar or vector"));
1469 }
1470 
TEST_F(ValidateImage,SampleImplicitLodOffsetWrongSize)1471 TEST_F(ValidateImage, SampleImplicitLodOffsetWrongSize) {
1472   const std::string body = R"(
1473 %img = OpLoad %type_image_f32_3d_0111 %uniform_image_f32_3d_0111
1474 %sampler = OpLoad %type_sampler %uniform_sampler
1475 %simg = OpSampledImage %type_sampled_image_f32_3d_0111 %img %sampler
1476 %res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 Offset %s32vec2_01
1477 )";
1478 
1479   CompileSuccessfully(GenerateShaderCode(body).c_str());
1480   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1481   EXPECT_THAT(
1482       getDiagnosticString(),
1483       HasSubstr(
1484           "Expected Image Operand Offset to have 3 components, but given 2"));
1485 }
1486 
TEST_F(ValidateImage,SampleImplicitLodMoreThanOneOffset)1487 TEST_F(ValidateImage, SampleImplicitLodMoreThanOneOffset) {
1488   const std::string body = R"(
1489 %img = OpLoad %type_image_f32_3d_0111 %uniform_image_f32_3d_0111
1490 %sampler = OpLoad %type_sampler %uniform_sampler
1491 %simg = OpSampledImage %type_sampled_image_f32_3d_0111 %img %sampler
1492 %res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 ConstOffset|Offset %s32vec3_012 %s32vec3_012
1493 )";
1494 
1495   CompileSuccessfully(GenerateShaderCode(body).c_str());
1496   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1497   EXPECT_THAT(getDiagnosticString(),
1498               HasSubstr("Image Operands Offset, ConstOffset, ConstOffsets "
1499                         "cannot be used together"));
1500 }
1501 
TEST_F(ValidateImage,SampleImplicitLodMinLodWrongType)1502 TEST_F(ValidateImage, SampleImplicitLodMinLodWrongType) {
1503   const std::string body = R"(
1504 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
1505 %sampler = OpLoad %type_sampler %uniform_sampler
1506 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
1507 %res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 MinLod %s32_0
1508 )";
1509 
1510   CompileSuccessfully(GenerateShaderCode(body).c_str());
1511   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1512   EXPECT_THAT(getDiagnosticString(),
1513               HasSubstr("Expected Image Operand MinLod to be float scalar"));
1514 }
1515 
TEST_F(ValidateImage,SampleImplicitLodMinLodWrongDim)1516 TEST_F(ValidateImage, SampleImplicitLodMinLodWrongDim) {
1517   const std::string body = R"(
1518 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
1519 %sampler = OpLoad %type_sampler %uniform_sampler
1520 %simg = OpSampledImage %type_sampled_image_f32_rect_0001 %img %sampler
1521 %res2 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh MinLod %f32_0_25
1522 )";
1523 
1524   CompileSuccessfully(GenerateShaderCode(body).c_str());
1525   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1526   EXPECT_THAT(getDiagnosticString(),
1527               HasSubstr("Image Operand MinLod requires 'Dim' parameter to be "
1528                         "1D, 2D, 3D or Cube"));
1529 }
1530 
TEST_F(ValidateImage,SampleImplicitLodMinLodMultisampled)1531 TEST_F(ValidateImage, SampleImplicitLodMinLodMultisampled) {
1532   const std::string body = R"(
1533 %img = OpLoad %type_image_f32_3d_0111 %uniform_image_f32_3d_0111
1534 %sampler = OpLoad %type_sampler %uniform_sampler
1535 %simg = OpSampledImage %type_sampled_image_f32_3d_0111 %img %sampler
1536 %res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 MinLod %f32_0_25
1537 )";
1538 
1539   CompileSuccessfully(GenerateShaderCode(body).c_str());
1540   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1541   EXPECT_THAT(
1542       getDiagnosticString(),
1543       HasSubstr("Image Operand MinLod requires 'MS' parameter to be 0"));
1544 }
1545 
TEST_F(ValidateImage,SampleProjExplicitLodSuccess2D)1546 TEST_F(ValidateImage, SampleProjExplicitLodSuccess2D) {
1547   const std::string body = R"(
1548 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1549 %sampler = OpLoad %type_sampler %uniform_sampler
1550 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1551 %res1 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec3_hhh Lod %f32_1
1552 %res3 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec3_hhh Grad %f32vec2_10 %f32vec2_01
1553 %res4 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec3_hhh ConstOffset %s32vec2_01
1554 %res5 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec3_hhh Offset %s32vec2_01
1555 %res7 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec3_hhh Grad|Offset %f32vec2_10 %f32vec2_01 %s32vec2_01
1556 %res8 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec3_hhh Lod|NonPrivateTexelKHR %f32_1
1557 )";
1558 
1559   const std::string extra = R"(
1560 OpCapability VulkanMemoryModelKHR
1561 OpExtension "SPV_KHR_vulkan_memory_model"
1562 )";
1563   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
1564                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
1565                           .c_str());
1566   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1567 }
1568 
TEST_F(ValidateImage,SampleProjExplicitLodSuccessRect)1569 TEST_F(ValidateImage, SampleProjExplicitLodSuccessRect) {
1570   const std::string body = R"(
1571 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
1572 %sampler = OpLoad %type_sampler %uniform_sampler
1573 %simg = OpSampledImage %type_sampled_image_f32_rect_0001 %img %sampler
1574 %res1 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec3_hhh Grad %f32vec2_10 %f32vec2_01
1575 %res2 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec3_hhh Grad|Offset %f32vec2_10 %f32vec2_01 %s32vec2_01
1576 )";
1577 
1578   CompileSuccessfully(GenerateShaderCode(body).c_str());
1579   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1580 }
1581 
TEST_F(ValidateImage,SampleProjExplicitLodWrongResultType)1582 TEST_F(ValidateImage, SampleProjExplicitLodWrongResultType) {
1583   const std::string body = R"(
1584 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1585 %sampler = OpLoad %type_sampler %uniform_sampler
1586 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1587 %res1 = OpImageSampleProjExplicitLod %f32 %simg %f32vec3_hhh Lod %f32_1
1588 )";
1589 
1590   CompileSuccessfully(GenerateShaderCode(body).c_str());
1591   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1592   EXPECT_THAT(getDiagnosticString(),
1593               HasSubstr("Expected Result Type to be int or float vector type"));
1594 }
1595 
TEST_F(ValidateImage,SampleProjExplicitLodWrongNumComponentsResultType)1596 TEST_F(ValidateImage, SampleProjExplicitLodWrongNumComponentsResultType) {
1597   const std::string body = R"(
1598 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1599 %sampler = OpLoad %type_sampler %uniform_sampler
1600 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1601 %res1 = OpImageSampleProjExplicitLod %f32vec3 %simg %f32vec3_hhh Lod %f32_1
1602 )";
1603 
1604   CompileSuccessfully(GenerateShaderCode(body).c_str());
1605   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1606   EXPECT_THAT(getDiagnosticString(),
1607               HasSubstr("Expected Result Type to have 4 components"));
1608 }
1609 
TEST_F(ValidateImage,SampleProjExplicitLodNotSampledImage)1610 TEST_F(ValidateImage, SampleProjExplicitLodNotSampledImage) {
1611   const std::string body = R"(
1612 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1613 %res1 = OpImageSampleProjExplicitLod %f32vec4 %img %f32vec3_hhh Lod %f32_1
1614 )";
1615 
1616   CompileSuccessfully(GenerateShaderCode(body).c_str());
1617   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1618   EXPECT_THAT(
1619       getDiagnosticString(),
1620       HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage"));
1621 }
1622 
TEST_F(ValidateImage,SampleProjExplicitLodWrongSampledType)1623 TEST_F(ValidateImage, SampleProjExplicitLodWrongSampledType) {
1624   const std::string body = R"(
1625 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1626 %sampler = OpLoad %type_sampler %uniform_sampler
1627 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1628 %res1 = OpImageSampleProjExplicitLod %u32vec4 %simg %f32vec3_hhh Lod %f32_1
1629 )";
1630 
1631   CompileSuccessfully(GenerateShaderCode(body).c_str());
1632   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1633   EXPECT_THAT(getDiagnosticString(),
1634               HasSubstr("Expected Image 'Sampled Type' to be the same as "
1635                         "Result Type components"));
1636 }
1637 
TEST_F(ValidateImage,SampleProjExplicitLodVoidSampledType)1638 TEST_F(ValidateImage, SampleProjExplicitLodVoidSampledType) {
1639   const std::string body = R"(
1640 %img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001
1641 %sampler = OpLoad %type_sampler %uniform_sampler
1642 %simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler
1643 %res1 = OpImageSampleProjExplicitLod %u32vec4 %simg %f32vec3_hhh Lod %f32_1
1644 )";
1645 
1646   CompileSuccessfully(GenerateShaderCode(body).c_str());
1647   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1648 }
1649 
TEST_F(ValidateImage,SampleProjExplicitLodWrongCoordinateType)1650 TEST_F(ValidateImage, SampleProjExplicitLodWrongCoordinateType) {
1651   const std::string body = R"(
1652 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1653 %sampler = OpLoad %type_sampler %uniform_sampler
1654 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1655 %res1 = OpImageSampleProjExplicitLod %f32vec4 %simg %img Lod %f32_1
1656 )";
1657 
1658   CompileSuccessfully(GenerateShaderCode(body).c_str());
1659   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1660   EXPECT_THAT(getDiagnosticString(),
1661               HasSubstr("Expected Coordinate to be float scalar or vector"));
1662 }
1663 
TEST_F(ValidateImage,SampleProjExplicitLodCoordinateSizeTooSmall)1664 TEST_F(ValidateImage, SampleProjExplicitLodCoordinateSizeTooSmall) {
1665   const std::string body = R"(
1666 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1667 %sampler = OpLoad %type_sampler %uniform_sampler
1668 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1669 %res1 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec2_hh Lod %f32_1
1670 )";
1671 
1672   CompileSuccessfully(GenerateShaderCode(body).c_str());
1673   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1674   EXPECT_THAT(getDiagnosticString(),
1675               HasSubstr("Expected Coordinate to have at least 3 components, "
1676                         "but given only 2"));
1677 }
1678 
TEST_F(ValidateImage,SampleProjImplicitLodSuccess)1679 TEST_F(ValidateImage, SampleProjImplicitLodSuccess) {
1680   const std::string body = R"(
1681 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1682 %sampler = OpLoad %type_sampler %uniform_sampler
1683 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1684 %res1 = OpImageSampleProjImplicitLod %f32vec4 %simg %f32vec3_hhh
1685 %res2 = OpImageSampleProjImplicitLod %f32vec4 %simg %f32vec3_hhh Bias %f32_0_25
1686 %res4 = OpImageSampleProjImplicitLod %f32vec4 %simg %f32vec3_hhh ConstOffset %s32vec2_01
1687 %res5 = OpImageSampleProjImplicitLod %f32vec4 %simg %f32vec3_hhh Offset %s32vec2_01
1688 %res6 = OpImageSampleProjImplicitLod %f32vec4 %simg %f32vec3_hhh MinLod %f32_0_5
1689 %res7 = OpImageSampleProjImplicitLod %f32vec4 %simg %f32vec3_hhh Bias|Offset|MinLod %f32_0_25 %s32vec2_01 %f32_0_5
1690 %res8 = OpImageSampleProjImplicitLod %f32vec4 %simg %f32vec3_hhh NonPrivateTexelKHR
1691 )";
1692 
1693   const std::string extra = R"(
1694 OpCapability VulkanMemoryModelKHR
1695 OpExtension "SPV_KHR_vulkan_memory_model"
1696 )";
1697   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
1698                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
1699                           .c_str());
1700   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1701 }
1702 
TEST_F(ValidateImage,SampleProjImplicitLodWrongResultType)1703 TEST_F(ValidateImage, SampleProjImplicitLodWrongResultType) {
1704   const std::string body = R"(
1705 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1706 %sampler = OpLoad %type_sampler %uniform_sampler
1707 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1708 %res1 = OpImageSampleProjImplicitLod %f32 %simg %f32vec3_hhh
1709 )";
1710 
1711   CompileSuccessfully(GenerateShaderCode(body).c_str());
1712   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1713   EXPECT_THAT(getDiagnosticString(),
1714               HasSubstr("Expected Result Type to be int or float vector type"));
1715 }
1716 
TEST_F(ValidateImage,SampleProjImplicitLodWrongNumComponentsResultType)1717 TEST_F(ValidateImage, SampleProjImplicitLodWrongNumComponentsResultType) {
1718   const std::string body = R"(
1719 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1720 %sampler = OpLoad %type_sampler %uniform_sampler
1721 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1722 %res1 = OpImageSampleProjImplicitLod %f32vec3 %simg %f32vec3_hhh
1723 )";
1724 
1725   CompileSuccessfully(GenerateShaderCode(body).c_str());
1726   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1727   EXPECT_THAT(getDiagnosticString(),
1728               HasSubstr("Expected Result Type to have 4 components"));
1729 }
1730 
TEST_F(ValidateImage,SampleProjImplicitLodNotSampledImage)1731 TEST_F(ValidateImage, SampleProjImplicitLodNotSampledImage) {
1732   const std::string body = R"(
1733 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1734 %res1 = OpImageSampleProjImplicitLod %f32vec4 %img %f32vec3_hhh
1735 )";
1736 
1737   CompileSuccessfully(GenerateShaderCode(body).c_str());
1738   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1739   EXPECT_THAT(
1740       getDiagnosticString(),
1741       HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage"));
1742 }
1743 
TEST_F(ValidateImage,SampleProjImplicitLodWrongSampledType)1744 TEST_F(ValidateImage, SampleProjImplicitLodWrongSampledType) {
1745   const std::string body = R"(
1746 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1747 %sampler = OpLoad %type_sampler %uniform_sampler
1748 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1749 %res1 = OpImageSampleProjImplicitLod %u32vec4 %simg %f32vec3_hhh
1750 )";
1751 
1752   CompileSuccessfully(GenerateShaderCode(body).c_str());
1753   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1754   EXPECT_THAT(getDiagnosticString(),
1755               HasSubstr("Expected Image 'Sampled Type' to be the same as "
1756                         "Result Type components"));
1757 }
1758 
TEST_F(ValidateImage,SampleProjImplicitLodVoidSampledType)1759 TEST_F(ValidateImage, SampleProjImplicitLodVoidSampledType) {
1760   const std::string body = R"(
1761 %img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001
1762 %sampler = OpLoad %type_sampler %uniform_sampler
1763 %simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler
1764 %res1 = OpImageSampleProjImplicitLod %u32vec4 %simg %f32vec3_hhh
1765 )";
1766 
1767   CompileSuccessfully(GenerateShaderCode(body).c_str());
1768   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1769 }
1770 
TEST_F(ValidateImage,SampleProjImplicitLodWrongCoordinateType)1771 TEST_F(ValidateImage, SampleProjImplicitLodWrongCoordinateType) {
1772   const std::string body = R"(
1773 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1774 %sampler = OpLoad %type_sampler %uniform_sampler
1775 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1776 %res1 = OpImageSampleProjImplicitLod %f32vec4 %simg %img
1777 )";
1778 
1779   CompileSuccessfully(GenerateShaderCode(body).c_str());
1780   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1781   EXPECT_THAT(getDiagnosticString(),
1782               HasSubstr("Expected Coordinate to be float scalar or vector"));
1783 }
1784 
TEST_F(ValidateImage,SampleProjImplicitLodCoordinateSizeTooSmall)1785 TEST_F(ValidateImage, SampleProjImplicitLodCoordinateSizeTooSmall) {
1786   const std::string body = R"(
1787 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1788 %sampler = OpLoad %type_sampler %uniform_sampler
1789 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1790 %res1 = OpImageSampleProjImplicitLod %f32vec4 %simg %f32vec2_hh
1791 )";
1792 
1793   CompileSuccessfully(GenerateShaderCode(body).c_str());
1794   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1795   EXPECT_THAT(getDiagnosticString(),
1796               HasSubstr("Expected Coordinate to have at least 3 components, "
1797                         "but given only 2"));
1798 }
1799 
TEST_F(ValidateImage,SampleDrefImplicitLodSuccess)1800 TEST_F(ValidateImage, SampleDrefImplicitLodSuccess) {
1801   const std::string body = R"(
1802 %img = OpLoad %type_image_u32_2d_0001 %uniform_image_u32_2d_0001
1803 %sampler = OpLoad %type_sampler %uniform_sampler
1804 %simg = OpSampledImage %type_sampled_image_u32_2d_0001 %img %sampler
1805 %res1 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec2_hh %f32_1
1806 %res2 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec2_hh %f32_1 Bias %f32_0_25
1807 %res4 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec2_hh %f32_1 ConstOffset %s32vec2_01
1808 %res5 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec2_hh %f32_1 Offset %s32vec2_01
1809 %res6 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec2_hh %f32_1 MinLod %f32_0_5
1810 %res7 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec2_hh %f32_1 Bias|Offset|MinLod %f32_0_25 %s32vec2_01 %f32_0_5
1811 %res8 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec2_hh %f32_1 NonPrivateTexelKHR
1812 )";
1813 
1814   const std::string extra = R"(
1815 OpCapability VulkanMemoryModelKHR
1816 OpExtension "SPV_KHR_vulkan_memory_model"
1817 )";
1818   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
1819                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
1820                           .c_str());
1821   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1822 }
1823 
TEST_F(ValidateImage,SampleDrefImplicitLodWrongResultType)1824 TEST_F(ValidateImage, SampleDrefImplicitLodWrongResultType) {
1825   const std::string body = R"(
1826 %img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001
1827 %sampler = OpLoad %type_sampler %uniform_sampler
1828 %simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler
1829 %res1 = OpImageSampleDrefImplicitLod %void %simg %f32vec2_hh %u32_1
1830 )";
1831 
1832   CompileSuccessfully(GenerateShaderCode(body).c_str());
1833   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1834   EXPECT_THAT(getDiagnosticString(),
1835               HasSubstr("Expected Result Type to be int or float scalar type"));
1836 }
1837 
TEST_F(ValidateImage,SampleDrefImplicitLodNotSampledImage)1838 TEST_F(ValidateImage, SampleDrefImplicitLodNotSampledImage) {
1839   const std::string body = R"(
1840 %img = OpLoad %type_image_u32_2d_0001 %uniform_image_u32_2d_0001
1841 %res1 = OpImageSampleDrefImplicitLod %u32 %img %f32vec2_hh %u32_1
1842 )";
1843 
1844   CompileSuccessfully(GenerateShaderCode(body).c_str());
1845   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1846   EXPECT_THAT(
1847       getDiagnosticString(),
1848       HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage"));
1849 }
1850 
TEST_F(ValidateImage,SampleDrefImplicitLodWrongSampledType)1851 TEST_F(ValidateImage, SampleDrefImplicitLodWrongSampledType) {
1852   const std::string body = R"(
1853 %img = OpLoad %type_image_u32_2d_0001 %uniform_image_u32_2d_0001
1854 %sampler = OpLoad %type_sampler %uniform_sampler
1855 %simg = OpSampledImage %type_sampled_image_u32_2d_0001 %img %sampler
1856 %res1 = OpImageSampleDrefImplicitLod %f32 %simg %f32vec2_00 %u32_1
1857 )";
1858 
1859   CompileSuccessfully(GenerateShaderCode(body).c_str());
1860   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1861   EXPECT_THAT(
1862       getDiagnosticString(),
1863       HasSubstr("Expected Image 'Sampled Type' to be the same as Result Type"));
1864 }
1865 
TEST_F(ValidateImage,SampleDrefImplicitLodVoidSampledType)1866 TEST_F(ValidateImage, SampleDrefImplicitLodVoidSampledType) {
1867   const std::string body = R"(
1868 %img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001
1869 %sampler = OpLoad %type_sampler %uniform_sampler
1870 %simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler
1871 %res1 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec2_00 %u32_1
1872 )";
1873 
1874   CompileSuccessfully(GenerateShaderCode(body).c_str());
1875   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1876   EXPECT_THAT(
1877       getDiagnosticString(),
1878       HasSubstr("Expected Image 'Sampled Type' to be the same as Result Type"));
1879 }
1880 
TEST_F(ValidateImage,SampleDrefImplicitLodWrongCoordinateType)1881 TEST_F(ValidateImage, SampleDrefImplicitLodWrongCoordinateType) {
1882   const std::string body = R"(
1883 %img = OpLoad %type_image_u32_2d_0001 %uniform_image_u32_2d_0001
1884 %sampler = OpLoad %type_sampler %uniform_sampler
1885 %simg = OpSampledImage %type_sampled_image_u32_2d_0001 %img %sampler
1886 %res1 = OpImageSampleDrefImplicitLod %u32 %simg %img %u32_1
1887 )";
1888 
1889   CompileSuccessfully(GenerateShaderCode(body).c_str());
1890   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1891   EXPECT_THAT(getDiagnosticString(),
1892               HasSubstr("Expected Coordinate to be float scalar or vector"));
1893 }
1894 
TEST_F(ValidateImage,SampleDrefImplicitLodCoordinateSizeTooSmall)1895 TEST_F(ValidateImage, SampleDrefImplicitLodCoordinateSizeTooSmall) {
1896   const std::string body = R"(
1897 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1898 %sampler = OpLoad %type_sampler %uniform_sampler
1899 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1900 %res1 = OpImageSampleDrefImplicitLod %f32 %simg %f32_0_5 %f32_0_5
1901 )";
1902 
1903   CompileSuccessfully(GenerateShaderCode(body).c_str());
1904   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1905   EXPECT_THAT(getDiagnosticString(),
1906               HasSubstr("Expected Coordinate to have at least 2 components, "
1907                         "but given only 1"));
1908 }
1909 
TEST_F(ValidateImage,SampleDrefImplicitLodWrongDrefType)1910 TEST_F(ValidateImage, SampleDrefImplicitLodWrongDrefType) {
1911   const std::string body = R"(
1912 %img = OpLoad %type_image_u32_2d_0001 %uniform_image_u32_2d_0001
1913 %sampler = OpLoad %type_sampler %uniform_sampler
1914 %simg = OpSampledImage %type_sampled_image_u32_2d_0001 %img %sampler
1915 %res1 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec2_00 %f64_1
1916 )";
1917 
1918   CompileSuccessfully(GenerateShaderCode(body).c_str());
1919   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1920   EXPECT_THAT(getDiagnosticString(),
1921               HasSubstr("Expected Dref to be of 32-bit float type"));
1922 }
1923 
TEST_F(ValidateImage,SampleDrefExplicitLodSuccess)1924 TEST_F(ValidateImage, SampleDrefExplicitLodSuccess) {
1925   const std::string body = R"(
1926 %img = OpLoad %type_image_s32_3d_0001 %uniform_image_s32_3d_0001
1927 %sampler = OpLoad %type_sampler %uniform_sampler
1928 %simg = OpSampledImage %type_sampled_image_s32_3d_0001 %img %sampler
1929 %res1 = OpImageSampleDrefExplicitLod %s32 %simg %f32vec4_0000 %f32_1 Lod %f32_1
1930 %res3 = OpImageSampleDrefExplicitLod %s32 %simg %f32vec3_hhh %f32_1 Grad %f32vec3_hhh %f32vec3_hhh
1931 %res4 = OpImageSampleDrefExplicitLod %s32 %simg %f32vec3_hhh %f32_1 ConstOffset %s32vec3_012
1932 %res5 = OpImageSampleDrefExplicitLod %s32 %simg %f32vec4_0000 %f32_1 Offset %s32vec3_012
1933 %res7 = OpImageSampleDrefExplicitLod %s32 %simg %f32vec3_hhh %f32_1 Grad|Offset %f32vec3_hhh %f32vec3_hhh %s32vec3_012
1934 %res8 = OpImageSampleDrefExplicitLod %s32 %simg %f32vec4_0000 %f32_1 Lod|NonPrivateTexelKHR %f32_1
1935 )";
1936 
1937   const std::string extra = R"(
1938 OpCapability VulkanMemoryModelKHR
1939 OpExtension "SPV_KHR_vulkan_memory_model"
1940 )";
1941   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
1942                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
1943                           .c_str());
1944   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1945 }
1946 
TEST_F(ValidateImage,SampleDrefExplicitLodWrongResultType)1947 TEST_F(ValidateImage, SampleDrefExplicitLodWrongResultType) {
1948   const std::string body = R"(
1949 %img = OpLoad %type_image_s32_3d_0001 %uniform_image_s32_3d_0001
1950 %sampler = OpLoad %type_sampler %uniform_sampler
1951 %simg = OpSampledImage %type_sampled_image_s32_3d_0001 %img %sampler
1952 %res1 = OpImageSampleDrefExplicitLod %bool %simg %f32vec3_hhh %s32_1 Lod %f32_1
1953 )";
1954 
1955   CompileSuccessfully(GenerateShaderCode(body).c_str());
1956   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1957   EXPECT_THAT(getDiagnosticString(),
1958               HasSubstr("Expected Result Type to be int or float scalar type"));
1959 }
1960 
TEST_F(ValidateImage,SampleDrefExplicitLodNotSampledImage)1961 TEST_F(ValidateImage, SampleDrefExplicitLodNotSampledImage) {
1962   const std::string body = R"(
1963 %img = OpLoad %type_image_s32_3d_0001 %uniform_image_s32_3d_0001
1964 %res1 = OpImageSampleDrefExplicitLod %s32 %img %f32vec3_hhh %s32_1 Lod %f32_1
1965 )";
1966 
1967   CompileSuccessfully(GenerateShaderCode(body).c_str());
1968   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1969   EXPECT_THAT(
1970       getDiagnosticString(),
1971       HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage"));
1972 }
1973 
TEST_F(ValidateImage,SampleDrefExplicitLodWrongSampledType)1974 TEST_F(ValidateImage, SampleDrefExplicitLodWrongSampledType) {
1975   const std::string body = R"(
1976 %img = OpLoad %type_image_s32_3d_0001 %uniform_image_s32_3d_0001
1977 %sampler = OpLoad %type_sampler %uniform_sampler
1978 %simg = OpSampledImage %type_sampled_image_s32_3d_0001 %img %sampler
1979 %res1 = OpImageSampleDrefExplicitLod %f32 %simg %f32vec3_hhh %s32_1 Lod %f32_1
1980 )";
1981 
1982   CompileSuccessfully(GenerateShaderCode(body).c_str());
1983   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1984   EXPECT_THAT(
1985       getDiagnosticString(),
1986       HasSubstr("Expected Image 'Sampled Type' to be the same as Result Type"));
1987 }
1988 
TEST_F(ValidateImage,SampleDrefExplicitLodVoidSampledType)1989 TEST_F(ValidateImage, SampleDrefExplicitLodVoidSampledType) {
1990   const std::string body = R"(
1991 %img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001
1992 %sampler = OpLoad %type_sampler %uniform_sampler
1993 %simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler
1994 %res1 = OpImageSampleDrefExplicitLod %u32 %simg %f32vec2_00 %s32_1 Lod %f32_1
1995 )";
1996 
1997   CompileSuccessfully(GenerateShaderCode(body).c_str());
1998   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1999   EXPECT_THAT(
2000       getDiagnosticString(),
2001       HasSubstr("Expected Image 'Sampled Type' to be the same as Result Type"));
2002 }
2003 
TEST_F(ValidateImage,SampleDrefExplicitLodWrongCoordinateType)2004 TEST_F(ValidateImage, SampleDrefExplicitLodWrongCoordinateType) {
2005   const std::string body = R"(
2006 %img = OpLoad %type_image_s32_3d_0001 %uniform_image_s32_3d_0001
2007 %sampler = OpLoad %type_sampler %uniform_sampler
2008 %simg = OpSampledImage %type_sampled_image_s32_3d_0001 %img %sampler
2009 %res1 = OpImageSampleDrefExplicitLod %s32 %simg %img %s32_1 Lod %f32_1
2010 )";
2011 
2012   CompileSuccessfully(GenerateShaderCode(body).c_str());
2013   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2014   EXPECT_THAT(getDiagnosticString(),
2015               HasSubstr("Expected Coordinate to be float scalar or vector"));
2016 }
2017 
TEST_F(ValidateImage,SampleDrefExplicitLodCoordinateSizeTooSmall)2018 TEST_F(ValidateImage, SampleDrefExplicitLodCoordinateSizeTooSmall) {
2019   const std::string body = R"(
2020 %img = OpLoad %type_image_s32_3d_0001 %uniform_image_s32_3d_0001
2021 %sampler = OpLoad %type_sampler %uniform_sampler
2022 %simg = OpSampledImage %type_sampled_image_s32_3d_0001 %img %sampler
2023 %res1 = OpImageSampleDrefExplicitLod %s32 %simg %f32vec2_hh %s32_1 Lod %f32_1
2024 )";
2025 
2026   CompileSuccessfully(GenerateShaderCode(body).c_str());
2027   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2028   EXPECT_THAT(getDiagnosticString(),
2029               HasSubstr("Expected Coordinate to have at least 3 components, "
2030                         "but given only 2"));
2031 }
2032 
TEST_F(ValidateImage,SampleDrefExplicitLodWrongDrefType)2033 TEST_F(ValidateImage, SampleDrefExplicitLodWrongDrefType) {
2034   const std::string body = R"(
2035 %img = OpLoad %type_image_s32_3d_0001 %uniform_image_s32_3d_0001
2036 %sampler = OpLoad %type_sampler %uniform_sampler
2037 %simg = OpSampledImage %type_sampled_image_s32_3d_0001 %img %sampler
2038 %res1 = OpImageSampleDrefExplicitLod %s32 %simg %f32vec3_hhh %u32_1 Lod %f32_1
2039 )";
2040 
2041   CompileSuccessfully(GenerateShaderCode(body).c_str());
2042   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2043   EXPECT_THAT(getDiagnosticString(),
2044               HasSubstr("Expected Dref to be of 32-bit float type"));
2045 }
2046 
TEST_F(ValidateImage,SampleProjDrefImplicitLodSuccess)2047 TEST_F(ValidateImage, SampleProjDrefImplicitLodSuccess) {
2048   const std::string body = R"(
2049 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2050 %sampler = OpLoad %type_sampler %uniform_sampler
2051 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2052 %res1 = OpImageSampleProjDrefImplicitLod %f32 %simg %f32vec3_hhh %f32_0_5
2053 %res2 = OpImageSampleProjDrefImplicitLod %f32 %simg %f32vec3_hhh %f32_0_5 Bias %f32_0_25
2054 %res4 = OpImageSampleProjDrefImplicitLod %f32 %simg %f32vec3_hhh %f32_0_5 ConstOffset %s32vec2_01
2055 %res5 = OpImageSampleProjDrefImplicitLod %f32 %simg %f32vec3_hhh %f32_0_5 Offset %s32vec2_01
2056 %res6 = OpImageSampleProjDrefImplicitLod %f32 %simg %f32vec3_hhh %f32_0_5 MinLod %f32_0_5
2057 %res7 = OpImageSampleProjDrefImplicitLod %f32 %simg %f32vec3_hhh %f32_0_5 Bias|Offset|MinLod %f32_0_25 %s32vec2_01 %f32_0_5
2058 %res8 = OpImageSampleProjDrefImplicitLod %f32 %simg %f32vec3_hhh %f32_0_5 NonPrivateTexelKHR
2059 )";
2060 
2061   const std::string extra = R"(
2062 OpCapability VulkanMemoryModelKHR
2063 OpExtension "SPV_KHR_vulkan_memory_model"
2064 )";
2065   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
2066                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
2067                           .c_str());
2068   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2069 }
2070 
TEST_F(ValidateImage,SampleProjDrefImplicitLodWrongResultType)2071 TEST_F(ValidateImage, SampleProjDrefImplicitLodWrongResultType) {
2072   const std::string body = R"(
2073 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2074 %sampler = OpLoad %type_sampler %uniform_sampler
2075 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2076 %res1 = OpImageSampleProjDrefImplicitLod %void %simg %f32vec3_hhh %f32_0_5
2077 )";
2078 
2079   CompileSuccessfully(GenerateShaderCode(body).c_str());
2080   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2081   EXPECT_THAT(getDiagnosticString(),
2082               HasSubstr("Expected Result Type to be int or float scalar type"));
2083 }
2084 
TEST_F(ValidateImage,SampleProjDrefImplicitLodNotSampledImage)2085 TEST_F(ValidateImage, SampleProjDrefImplicitLodNotSampledImage) {
2086   const std::string body = R"(
2087 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2088 %res1 = OpImageSampleProjDrefImplicitLod %f32 %img %f32vec3_hhh %f32_0_5
2089 )";
2090 
2091   CompileSuccessfully(GenerateShaderCode(body).c_str());
2092   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2093   EXPECT_THAT(
2094       getDiagnosticString(),
2095       HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage"));
2096 }
2097 
TEST_F(ValidateImage,SampleProjDrefImplicitLodWrongSampledType)2098 TEST_F(ValidateImage, SampleProjDrefImplicitLodWrongSampledType) {
2099   const std::string body = R"(
2100 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2101 %sampler = OpLoad %type_sampler %uniform_sampler
2102 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2103 %res1 = OpImageSampleProjDrefImplicitLod %u32 %simg %f32vec3_hhh %f32_0_5
2104 )";
2105 
2106   CompileSuccessfully(GenerateShaderCode(body).c_str());
2107   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2108   EXPECT_THAT(
2109       getDiagnosticString(),
2110       HasSubstr("Expected Image 'Sampled Type' to be the same as Result Type"));
2111 }
2112 
TEST_F(ValidateImage,SampleProjDrefImplicitLodVoidSampledType)2113 TEST_F(ValidateImage, SampleProjDrefImplicitLodVoidSampledType) {
2114   const std::string body = R"(
2115 %img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001
2116 %sampler = OpLoad %type_sampler %uniform_sampler
2117 %simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler
2118 %res1 = OpImageSampleProjDrefImplicitLod %u32 %simg %f32vec3_hhh %f32_0_5
2119 )";
2120 
2121   CompileSuccessfully(GenerateShaderCode(body).c_str());
2122   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2123   EXPECT_THAT(
2124       getDiagnosticString(),
2125       HasSubstr("Expected Image 'Sampled Type' to be the same as Result Type"));
2126 }
2127 
TEST_F(ValidateImage,SampleProjDrefImplicitLodWrongCoordinateType)2128 TEST_F(ValidateImage, SampleProjDrefImplicitLodWrongCoordinateType) {
2129   const std::string body = R"(
2130 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2131 %sampler = OpLoad %type_sampler %uniform_sampler
2132 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2133 %res1 = OpImageSampleProjDrefImplicitLod %f32 %simg %img %f32_0_5
2134 )";
2135 
2136   CompileSuccessfully(GenerateShaderCode(body).c_str());
2137   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2138   EXPECT_THAT(getDiagnosticString(),
2139               HasSubstr("Expected Coordinate to be float scalar or vector"));
2140 }
2141 
TEST_F(ValidateImage,SampleProjDrefImplicitLodCoordinateSizeTooSmall)2142 TEST_F(ValidateImage, SampleProjDrefImplicitLodCoordinateSizeTooSmall) {
2143   const std::string body = R"(
2144 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2145 %sampler = OpLoad %type_sampler %uniform_sampler
2146 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2147 %res1 = OpImageSampleProjDrefImplicitLod %f32 %simg %f32vec2_hh %f32_0_5
2148 )";
2149 
2150   CompileSuccessfully(GenerateShaderCode(body).c_str());
2151   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2152   EXPECT_THAT(getDiagnosticString(),
2153               HasSubstr("Expected Coordinate to have at least 3 components, "
2154                         "but given only 2"));
2155 }
2156 
TEST_F(ValidateImage,SampleProjDrefImplicitLodWrongDrefType)2157 TEST_F(ValidateImage, SampleProjDrefImplicitLodWrongDrefType) {
2158   const std::string body = R"(
2159 %img = OpLoad %type_image_u32_2d_0001 %uniform_image_u32_2d_0001
2160 %sampler = OpLoad %type_sampler %uniform_sampler
2161 %simg = OpSampledImage %type_sampled_image_u32_2d_0001 %img %sampler
2162 %res1 = OpImageSampleProjDrefImplicitLod %u32 %simg %f32vec3_hhh %f32vec4_0000
2163 )";
2164 
2165   CompileSuccessfully(GenerateShaderCode(body).c_str());
2166   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2167   EXPECT_THAT(getDiagnosticString(),
2168               HasSubstr("Expected Dref to be of 32-bit float type"));
2169 }
2170 
TEST_F(ValidateImage,SampleProjDrefExplicitLodSuccess)2171 TEST_F(ValidateImage, SampleProjDrefExplicitLodSuccess) {
2172   const std::string body = R"(
2173 %img = OpLoad %type_image_f32_1d_0001 %uniform_image_f32_1d_0001
2174 %sampler = OpLoad %type_sampler %uniform_sampler
2175 %simg = OpSampledImage %type_sampled_image_f32_1d_0001 %img %sampler
2176 %res1 = OpImageSampleProjDrefExplicitLod %f32 %simg %f32vec2_hh %f32_0_5 Lod %f32_1
2177 %res2 = OpImageSampleProjDrefExplicitLod %f32 %simg %f32vec3_hhh %f32_0_5 Grad %f32_0_5 %f32_0_5
2178 %res3 = OpImageSampleProjDrefExplicitLod %f32 %simg %f32vec2_hh %f32_0_5 ConstOffset %s32_1
2179 %res4 = OpImageSampleProjDrefExplicitLod %f32 %simg %f32vec2_hh %f32_0_5 Offset %s32_1
2180 %res5 = OpImageSampleProjDrefExplicitLod %f32 %simg %f32vec2_hh %f32_0_5 Grad|Offset %f32_0_5 %f32_0_5 %s32_1
2181 %res6 = OpImageSampleProjDrefExplicitLod %f32 %simg %f32vec2_hh %f32_0_5 Lod|NonPrivateTexelKHR %f32_1
2182 )";
2183 
2184   const std::string extra = R"(
2185 OpCapability VulkanMemoryModelKHR
2186 OpExtension "SPV_KHR_vulkan_memory_model"
2187 )";
2188   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
2189                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
2190                           .c_str());
2191   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2192 }
2193 
TEST_F(ValidateImage,SampleProjDrefExplicitLodWrongResultType)2194 TEST_F(ValidateImage, SampleProjDrefExplicitLodWrongResultType) {
2195   const std::string body = R"(
2196 %img = OpLoad %type_image_f32_1d_0001 %uniform_image_f32_1d_0001
2197 %sampler = OpLoad %type_sampler %uniform_sampler
2198 %simg = OpSampledImage %type_sampled_image_f32_1d_0001 %img %sampler
2199 %res1 = OpImageSampleProjDrefExplicitLod %bool %simg %f32vec2_hh %f32_0_5 Lod %f32_1
2200 )";
2201 
2202   CompileSuccessfully(GenerateShaderCode(body).c_str());
2203   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2204   EXPECT_THAT(getDiagnosticString(),
2205               HasSubstr("Expected Result Type to be int or float scalar type"));
2206 }
2207 
TEST_F(ValidateImage,SampleProjDrefExplicitLodNotSampledImage)2208 TEST_F(ValidateImage, SampleProjDrefExplicitLodNotSampledImage) {
2209   const std::string body = R"(
2210 %img = OpLoad %type_image_f32_1d_0001 %uniform_image_f32_1d_0001
2211 %res1 = OpImageSampleProjDrefExplicitLod %f32 %img %f32vec2_hh %f32_0_5 Lod %f32_1
2212 )";
2213 
2214   CompileSuccessfully(GenerateShaderCode(body).c_str());
2215   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2216   EXPECT_THAT(
2217       getDiagnosticString(),
2218       HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage"));
2219 }
2220 
TEST_F(ValidateImage,SampleProjDrefExplicitLodWrongSampledType)2221 TEST_F(ValidateImage, SampleProjDrefExplicitLodWrongSampledType) {
2222   const std::string body = R"(
2223 %img = OpLoad %type_image_f32_1d_0001 %uniform_image_f32_1d_0001
2224 %sampler = OpLoad %type_sampler %uniform_sampler
2225 %simg = OpSampledImage %type_sampled_image_f32_1d_0001 %img %sampler
2226 %res1 = OpImageSampleProjDrefExplicitLod %u32 %simg %f32vec2_hh %f32_0_5 Lod %f32_1
2227 )";
2228 
2229   CompileSuccessfully(GenerateShaderCode(body).c_str());
2230   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2231   EXPECT_THAT(
2232       getDiagnosticString(),
2233       HasSubstr("Expected Image 'Sampled Type' to be the same as Result Type"));
2234 }
2235 
TEST_F(ValidateImage,SampleProjDrefExplicitLodVoidSampledType)2236 TEST_F(ValidateImage, SampleProjDrefExplicitLodVoidSampledType) {
2237   const std::string body = R"(
2238 %img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001
2239 %sampler = OpLoad %type_sampler %uniform_sampler
2240 %simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler
2241 %res1 = OpImageSampleProjDrefExplicitLod %u32 %simg %f32vec3_hhh %f32_0_5 Lod %f32_1
2242 )";
2243 
2244   CompileSuccessfully(GenerateShaderCode(body).c_str());
2245   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2246   EXPECT_THAT(
2247       getDiagnosticString(),
2248       HasSubstr("Expected Image 'Sampled Type' to be the same as Result Type"));
2249 }
2250 
TEST_F(ValidateImage,SampleProjDrefExplicitLodWrongCoordinateType)2251 TEST_F(ValidateImage, SampleProjDrefExplicitLodWrongCoordinateType) {
2252   const std::string body = R"(
2253 %img = OpLoad %type_image_f32_1d_0001 %uniform_image_f32_1d_0001
2254 %sampler = OpLoad %type_sampler %uniform_sampler
2255 %simg = OpSampledImage %type_sampled_image_f32_1d_0001 %img %sampler
2256 %res1 = OpImageSampleProjDrefExplicitLod %f32 %simg %img %f32_0_5 Lod %f32_1
2257 )";
2258 
2259   CompileSuccessfully(GenerateShaderCode(body).c_str());
2260   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2261   EXPECT_THAT(getDiagnosticString(),
2262               HasSubstr("Expected Coordinate to be float scalar or vector"));
2263 }
2264 
TEST_F(ValidateImage,SampleProjDrefExplicitLodCoordinateSizeTooSmall)2265 TEST_F(ValidateImage, SampleProjDrefExplicitLodCoordinateSizeTooSmall) {
2266   const std::string body = R"(
2267 %img = OpLoad %type_image_f32_1d_0001 %uniform_image_f32_1d_0001
2268 %sampler = OpLoad %type_sampler %uniform_sampler
2269 %simg = OpSampledImage %type_sampled_image_f32_1d_0001 %img %sampler
2270 %res1 = OpImageSampleProjDrefExplicitLod %f32 %simg %f32_0_5 %f32_0_5 Lod %f32_1
2271 )";
2272 
2273   CompileSuccessfully(GenerateShaderCode(body).c_str());
2274   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2275   EXPECT_THAT(getDiagnosticString(),
2276               HasSubstr("Expected Coordinate to have at least 2 components, "
2277                         "but given only 1"));
2278 }
2279 
TEST_F(ValidateImage,FetchSuccess)2280 TEST_F(ValidateImage, FetchSuccess) {
2281   const std::string body = R"(
2282 %img = OpLoad %type_image_f32_1d_0001 %uniform_image_f32_1d_0001
2283 %res1 = OpImageFetch %f32vec4 %img %u32vec2_01
2284 %res2 = OpImageFetch %f32vec4 %img %u32vec2_01 NonPrivateTexelKHR
2285 )";
2286 
2287   const std::string extra = R"(
2288 OpCapability VulkanMemoryModelKHR
2289 OpExtension "SPV_KHR_vulkan_memory_model"
2290 )";
2291   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
2292                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
2293                           .c_str());
2294   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2295 }
2296 
TEST_F(ValidateImage,FetchWrongResultType)2297 TEST_F(ValidateImage, FetchWrongResultType) {
2298   const std::string body = R"(
2299 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
2300 %res1 = OpImageFetch %f32 %img %u32vec2_01
2301 )";
2302 
2303   CompileSuccessfully(GenerateShaderCode(body).c_str());
2304   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2305   EXPECT_THAT(getDiagnosticString(),
2306               HasSubstr("Expected Result Type to be int or float vector type"));
2307 }
2308 
TEST_F(ValidateImage,FetchWrongNumComponentsResultType)2309 TEST_F(ValidateImage, FetchWrongNumComponentsResultType) {
2310   const std::string body = R"(
2311 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
2312 %res1 = OpImageFetch %f32vec3 %img %u32vec2_01
2313 )";
2314 
2315   CompileSuccessfully(GenerateShaderCode(body).c_str());
2316   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2317   EXPECT_THAT(getDiagnosticString(),
2318               HasSubstr("Expected Result Type to have 4 components"));
2319 }
2320 
TEST_F(ValidateImage,FetchNotImage)2321 TEST_F(ValidateImage, FetchNotImage) {
2322   const std::string body = R"(
2323 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2324 %sampler = OpLoad %type_sampler %uniform_sampler
2325 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2326 %res1 = OpImageFetch %f32vec4 %sampler %u32vec2_01
2327 )";
2328 
2329   CompileSuccessfully(GenerateShaderCode(body).c_str());
2330   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2331   EXPECT_THAT(getDiagnosticString(),
2332               HasSubstr("Expected Image to be of type OpTypeImage"));
2333 }
2334 
TEST_F(ValidateImage,FetchSampledImageDirectly)2335 TEST_F(ValidateImage, FetchSampledImageDirectly) {
2336   const std::string body = R"(
2337 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2338 %sampler = OpLoad %type_sampler %uniform_sampler
2339 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2340 %res1 = OpImageFetch %f32vec4 %simg %u32vec2_01
2341 )";
2342 
2343   CompileSuccessfully(GenerateShaderCode(body).c_str());
2344   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2345   EXPECT_THAT(getDiagnosticString(),
2346               HasSubstr("OpSampledImage instruction must not appear as operand "
2347                         "for OpImageFetch"));
2348 }
2349 
TEST_F(ValidateImage,FetchNotSampled)2350 TEST_F(ValidateImage, FetchNotSampled) {
2351   const std::string body = R"(
2352 %img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
2353 %res1 = OpImageFetch %u32vec4 %img %u32vec2_01
2354 )";
2355 
2356   CompileSuccessfully(GenerateShaderCode(body).c_str());
2357   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2358   EXPECT_THAT(getDiagnosticString(),
2359               HasSubstr("Expected Image 'Sampled' parameter to be 1"));
2360 }
2361 
TEST_F(ValidateImage,FetchCube)2362 TEST_F(ValidateImage, FetchCube) {
2363   const std::string body = R"(
2364 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
2365 %res1 = OpImageFetch %f32vec4 %img %u32vec3_012
2366 )";
2367 
2368   CompileSuccessfully(GenerateShaderCode(body).c_str());
2369   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2370   EXPECT_THAT(getDiagnosticString(), HasSubstr("Image 'Dim' cannot be Cube"));
2371 }
2372 
TEST_F(ValidateImage,FetchWrongSampledType)2373 TEST_F(ValidateImage, FetchWrongSampledType) {
2374   const std::string body = R"(
2375 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
2376 %res1 = OpImageFetch %u32vec4 %img %u32vec2_01
2377 )";
2378 
2379   CompileSuccessfully(GenerateShaderCode(body).c_str());
2380   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2381   EXPECT_THAT(getDiagnosticString(),
2382               HasSubstr("Expected Image 'Sampled Type' to be the same as "
2383                         "Result Type components"));
2384 }
2385 
TEST_F(ValidateImage,FetchVoidSampledType)2386 TEST_F(ValidateImage, FetchVoidSampledType) {
2387   const std::string body = R"(
2388 %img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001
2389 %res1 = OpImageFetch %f32vec4 %img %u32vec2_01
2390 %res2 = OpImageFetch %u32vec4 %img %u32vec2_01
2391 %res3 = OpImageFetch %s32vec4 %img %u32vec2_01
2392 )";
2393 
2394   CompileSuccessfully(GenerateShaderCode(body).c_str());
2395   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
2396 }
2397 
TEST_F(ValidateImage,FetchWrongCoordinateType)2398 TEST_F(ValidateImage, FetchWrongCoordinateType) {
2399   const std::string body = R"(
2400 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
2401 %res1 = OpImageFetch %f32vec4 %img %f32vec2_00
2402 )";
2403 
2404   CompileSuccessfully(GenerateShaderCode(body).c_str());
2405   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2406   EXPECT_THAT(getDiagnosticString(),
2407               HasSubstr("Expected Coordinate to be int scalar or vector"));
2408 }
2409 
TEST_F(ValidateImage,FetchCoordinateSizeTooSmall)2410 TEST_F(ValidateImage, FetchCoordinateSizeTooSmall) {
2411   const std::string body = R"(
2412 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
2413 %res1 = OpImageFetch %f32vec4 %img %u32_1
2414 )";
2415 
2416   CompileSuccessfully(GenerateShaderCode(body).c_str());
2417   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2418   EXPECT_THAT(getDiagnosticString(),
2419               HasSubstr("Expected Coordinate to have at least 2 components, "
2420                         "but given only 1"));
2421 }
2422 
TEST_F(ValidateImage,FetchLodNotInt)2423 TEST_F(ValidateImage, FetchLodNotInt) {
2424   const std::string body = R"(
2425 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2426 %res1 = OpImageFetch %f32vec4 %img %u32vec2_01 Lod %f32_1
2427 )";
2428 
2429   CompileSuccessfully(GenerateShaderCode(body).c_str());
2430   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2431   EXPECT_THAT(getDiagnosticString(),
2432               HasSubstr("Expected Image Operand Lod to be int scalar when used "
2433                         "with OpImageFetch"));
2434 }
2435 
TEST_F(ValidateImage,GatherSuccess)2436 TEST_F(ValidateImage, GatherSuccess) {
2437   const std::string body = R"(
2438 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2439 %sampler = OpLoad %type_sampler %uniform_sampler
2440 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2441 %res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1
2442 %res2 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 ConstOffsets %const_offsets
2443 %res3 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 NonPrivateTexelKHR
2444 )";
2445 
2446   const std::string extra = R"(
2447 OpCapability VulkanMemoryModelKHR
2448 OpExtension "SPV_KHR_vulkan_memory_model"
2449 )";
2450   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
2451                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
2452                           .c_str());
2453   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2454 }
2455 
TEST_F(ValidateImage,GatherWrongResultType)2456 TEST_F(ValidateImage, GatherWrongResultType) {
2457   const std::string body = R"(
2458 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
2459 %sampler = OpLoad %type_sampler %uniform_sampler
2460 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
2461 %res1 = OpImageGather %f32 %simg %f32vec4_0000 %u32_1
2462 )";
2463 
2464   CompileSuccessfully(GenerateShaderCode(body).c_str());
2465   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2466   EXPECT_THAT(getDiagnosticString(),
2467               HasSubstr("Expected Result Type to be int or float vector type"));
2468 }
2469 
TEST_F(ValidateImage,GatherWrongNumComponentsResultType)2470 TEST_F(ValidateImage, GatherWrongNumComponentsResultType) {
2471   const std::string body = R"(
2472 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
2473 %sampler = OpLoad %type_sampler %uniform_sampler
2474 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
2475 %res1 = OpImageGather %f32vec3 %simg %f32vec4_0000 %u32_1
2476 )";
2477 
2478   CompileSuccessfully(GenerateShaderCode(body).c_str());
2479   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2480   EXPECT_THAT(getDiagnosticString(),
2481               HasSubstr("Expected Result Type to have 4 components"));
2482 }
2483 
TEST_F(ValidateImage,GatherNotSampledImage)2484 TEST_F(ValidateImage, GatherNotSampledImage) {
2485   const std::string body = R"(
2486 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
2487 %res1 = OpImageGather %f32vec4 %img %f32vec4_0000 %u32_1
2488 )";
2489 
2490   CompileSuccessfully(GenerateShaderCode(body).c_str());
2491   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2492   EXPECT_THAT(
2493       getDiagnosticString(),
2494       HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage"));
2495 }
2496 
TEST_F(ValidateImage,GatherWrongSampledType)2497 TEST_F(ValidateImage, GatherWrongSampledType) {
2498   const std::string body = R"(
2499 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
2500 %sampler = OpLoad %type_sampler %uniform_sampler
2501 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
2502 %res1 = OpImageGather %u32vec4 %simg %f32vec4_0000 %u32_1
2503 )";
2504 
2505   CompileSuccessfully(GenerateShaderCode(body).c_str());
2506   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2507   EXPECT_THAT(getDiagnosticString(),
2508               HasSubstr("Expected Image 'Sampled Type' to be the same as "
2509                         "Result Type components"));
2510 }
2511 
TEST_F(ValidateImage,GatherVoidSampledType)2512 TEST_F(ValidateImage, GatherVoidSampledType) {
2513   const std::string body = R"(
2514 %img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001
2515 %sampler = OpLoad %type_sampler %uniform_sampler
2516 %simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler
2517 %res1 = OpImageGather %u32vec4 %simg %f32vec2_00 %u32_1
2518 )";
2519 
2520   CompileSuccessfully(GenerateShaderCode(body).c_str());
2521   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
2522 }
2523 
TEST_F(ValidateImage,GatherWrongCoordinateType)2524 TEST_F(ValidateImage, GatherWrongCoordinateType) {
2525   const std::string body = R"(
2526 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
2527 %sampler = OpLoad %type_sampler %uniform_sampler
2528 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
2529 %res1 = OpImageGather %f32vec4 %simg %u32vec4_0123 %u32_1
2530 )";
2531 
2532   CompileSuccessfully(GenerateShaderCode(body).c_str());
2533   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2534   EXPECT_THAT(getDiagnosticString(),
2535               HasSubstr("Expected Coordinate to be float scalar or vector"));
2536 }
2537 
TEST_F(ValidateImage,GatherCoordinateSizeTooSmall)2538 TEST_F(ValidateImage, GatherCoordinateSizeTooSmall) {
2539   const std::string body = R"(
2540 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
2541 %sampler = OpLoad %type_sampler %uniform_sampler
2542 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
2543 %res1 = OpImageGather %f32vec4 %simg %f32_0_5 %u32_1
2544 )";
2545 
2546   CompileSuccessfully(GenerateShaderCode(body).c_str());
2547   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2548   EXPECT_THAT(getDiagnosticString(),
2549               HasSubstr("Expected Coordinate to have at least 4 components, "
2550                         "but given only 1"));
2551 }
2552 
TEST_F(ValidateImage,GatherWrongComponentType)2553 TEST_F(ValidateImage, GatherWrongComponentType) {
2554   const std::string body = R"(
2555 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
2556 %sampler = OpLoad %type_sampler %uniform_sampler
2557 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
2558 %res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %f32_1
2559 )";
2560 
2561   CompileSuccessfully(GenerateShaderCode(body).c_str());
2562   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2563   EXPECT_THAT(getDiagnosticString(),
2564               HasSubstr("Expected Component to be 32-bit int scalar"));
2565 }
2566 
TEST_F(ValidateImage,GatherComponentNot32Bit)2567 TEST_F(ValidateImage, GatherComponentNot32Bit) {
2568   const std::string body = R"(
2569 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
2570 %sampler = OpLoad %type_sampler %uniform_sampler
2571 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
2572 %res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u64_0
2573 )";
2574 
2575   CompileSuccessfully(GenerateShaderCode(body).c_str());
2576   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2577   EXPECT_THAT(getDiagnosticString(),
2578               HasSubstr("Expected Component to be 32-bit int scalar"));
2579 }
2580 
TEST_F(ValidateImage,GatherDimCube)2581 TEST_F(ValidateImage, GatherDimCube) {
2582   const std::string body = R"(
2583 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
2584 %sampler = OpLoad %type_sampler %uniform_sampler
2585 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
2586 %res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 ConstOffsets %const_offsets
2587 )";
2588 
2589   CompileSuccessfully(GenerateShaderCode(body).c_str());
2590   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2591   EXPECT_THAT(
2592       getDiagnosticString(),
2593       HasSubstr(
2594           "Image Operand ConstOffsets cannot be used with Cube Image 'Dim'"));
2595 }
2596 
TEST_F(ValidateImage,GatherConstOffsetsNotArray)2597 TEST_F(ValidateImage, GatherConstOffsetsNotArray) {
2598   const std::string body = R"(
2599 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2600 %sampler = OpLoad %type_sampler %uniform_sampler
2601 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2602 %res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 ConstOffsets %u32vec4_0123
2603 )";
2604 
2605   CompileSuccessfully(GenerateShaderCode(body).c_str());
2606   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2607   EXPECT_THAT(
2608       getDiagnosticString(),
2609       HasSubstr(
2610           "Expected Image Operand ConstOffsets to be an array of size 4"));
2611 }
2612 
TEST_F(ValidateImage,GatherConstOffsetsArrayWrongSize)2613 TEST_F(ValidateImage, GatherConstOffsetsArrayWrongSize) {
2614   const std::string body = R"(
2615 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2616 %sampler = OpLoad %type_sampler %uniform_sampler
2617 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2618 %res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 ConstOffsets %const_offsets3x2
2619 )";
2620 
2621   CompileSuccessfully(GenerateShaderCode(body).c_str());
2622   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2623   EXPECT_THAT(
2624       getDiagnosticString(),
2625       HasSubstr(
2626           "Expected Image Operand ConstOffsets to be an array of size 4"));
2627 }
2628 
TEST_F(ValidateImage,GatherConstOffsetsArrayNotVector)2629 TEST_F(ValidateImage, GatherConstOffsetsArrayNotVector) {
2630   const std::string body = R"(
2631 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2632 %sampler = OpLoad %type_sampler %uniform_sampler
2633 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2634 %res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 ConstOffsets %const_offsets4xu
2635 )";
2636 
2637   CompileSuccessfully(GenerateShaderCode(body).c_str());
2638   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2639   EXPECT_THAT(getDiagnosticString(),
2640               HasSubstr("Expected Image Operand ConstOffsets array componenets "
2641                         "to be int vectors of size 2"));
2642 }
2643 
TEST_F(ValidateImage,GatherConstOffsetsArrayVectorWrongSize)2644 TEST_F(ValidateImage, GatherConstOffsetsArrayVectorWrongSize) {
2645   const std::string body = R"(
2646 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2647 %sampler = OpLoad %type_sampler %uniform_sampler
2648 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2649 %res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 ConstOffsets %const_offsets4x3
2650 )";
2651 
2652   CompileSuccessfully(GenerateShaderCode(body).c_str());
2653   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2654   EXPECT_THAT(getDiagnosticString(),
2655               HasSubstr("Expected Image Operand ConstOffsets array componenets "
2656                         "to be int vectors of size 2"));
2657 }
2658 
TEST_F(ValidateImage,GatherConstOffsetsArrayNotConst)2659 TEST_F(ValidateImage, GatherConstOffsetsArrayNotConst) {
2660   const std::string body = R"(
2661 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2662 %sampler = OpLoad %type_sampler %uniform_sampler
2663 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2664 %offsets = OpUndef %u32vec2arr4
2665 %res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 ConstOffsets %offsets
2666 )";
2667 
2668   CompileSuccessfully(GenerateShaderCode(body).c_str());
2669   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2670   EXPECT_THAT(
2671       getDiagnosticString(),
2672       HasSubstr("Expected Image Operand ConstOffsets to be a const object"));
2673 }
2674 
TEST_F(ValidateImage,NotGatherWithConstOffsets)2675 TEST_F(ValidateImage, NotGatherWithConstOffsets) {
2676   const std::string body = R"(
2677 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2678 %sampler = OpLoad %type_sampler %uniform_sampler
2679 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2680 %res2 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh ConstOffsets %const_offsets
2681 )";
2682 
2683   CompileSuccessfully(GenerateShaderCode(body).c_str());
2684   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2685   EXPECT_THAT(
2686       getDiagnosticString(),
2687       HasSubstr(
2688           "Image Operand ConstOffsets can only be used with OpImageGather "
2689           "and OpImageDrefGather"));
2690 }
2691 
TEST_F(ValidateImage,DrefGatherSuccess)2692 TEST_F(ValidateImage, DrefGatherSuccess) {
2693   const std::string body = R"(
2694 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2695 %sampler = OpLoad %type_sampler %uniform_sampler
2696 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2697 %res1 = OpImageDrefGather %f32vec4 %simg %f32vec4_0000 %f32_0_5
2698 %res2 = OpImageDrefGather %f32vec4 %simg %f32vec4_0000 %f32_0_5 ConstOffsets %const_offsets
2699 %res3 = OpImageDrefGather %f32vec4 %simg %f32vec4_0000 %f32_0_5 NonPrivateTexelKHR
2700 )";
2701 
2702   const std::string extra = R"(
2703 OpCapability VulkanMemoryModelKHR
2704 OpExtension "SPV_KHR_vulkan_memory_model"
2705 )";
2706   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
2707                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
2708                           .c_str());
2709   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2710 }
2711 
TEST_F(ValidateImage,DrefGatherVoidSampledType)2712 TEST_F(ValidateImage, DrefGatherVoidSampledType) {
2713   const std::string body = R"(
2714 %img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001
2715 %sampler = OpLoad %type_sampler %uniform_sampler
2716 %simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler
2717 %res1 = OpImageDrefGather %u32vec4 %simg %f32vec2_00 %f32_0_5
2718 )";
2719 
2720   CompileSuccessfully(GenerateShaderCode(body).c_str());
2721   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2722   EXPECT_THAT(getDiagnosticString(),
2723               HasSubstr("Expected Image 'Sampled Type' to be the same as "
2724                         "Result Type components"));
2725 }
2726 
TEST_F(ValidateImage,DrefGatherWrongDrefType)2727 TEST_F(ValidateImage, DrefGatherWrongDrefType) {
2728   const std::string body = R"(
2729 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
2730 %sampler = OpLoad %type_sampler %uniform_sampler
2731 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
2732 %res1 = OpImageDrefGather %f32vec4 %simg %f32vec4_0000 %u32_1
2733 )";
2734 
2735   CompileSuccessfully(GenerateShaderCode(body).c_str());
2736   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2737   EXPECT_THAT(getDiagnosticString(),
2738               HasSubstr("Expected Dref to be of 32-bit float type"));
2739 }
2740 
TEST_F(ValidateImage,ReadSuccess1)2741 TEST_F(ValidateImage, ReadSuccess1) {
2742   const std::string body = R"(
2743 %img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
2744 %res1 = OpImageRead %u32vec4 %img %u32vec2_01
2745 )";
2746 
2747   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
2748   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
2749   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
2750 }
2751 
TEST_F(ValidateImage,ReadSuccess2)2752 TEST_F(ValidateImage, ReadSuccess2) {
2753   const std::string body = R"(
2754 %img = OpLoad %type_image_f32_1d_0002_rgba32f %uniform_image_f32_1d_0002_rgba32f
2755 %res1 = OpImageRead %f32vec4 %img %u32vec2_01
2756 )";
2757 
2758   const std::string extra = "\nOpCapability Image1D\n";
2759   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
2760   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
2761 }
2762 
TEST_F(ValidateImage,ReadSuccess3)2763 TEST_F(ValidateImage, ReadSuccess3) {
2764   const std::string body = R"(
2765 %img = OpLoad %type_image_f32_cube_0102_rgba32f %uniform_image_f32_cube_0102_rgba32f
2766 %res1 = OpImageRead %f32vec4 %img %u32vec3_012
2767 )";
2768 
2769   const std::string extra = "\nOpCapability ImageCubeArray\n";
2770   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
2771   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
2772 }
2773 
TEST_F(ValidateImage,ReadSuccess4)2774 TEST_F(ValidateImage, ReadSuccess4) {
2775   const std::string body = R"(
2776 %img = OpLoad %type_image_f32_spd_0002 %uniform_image_f32_spd_0002
2777 %res1 = OpImageRead %f32vec4 %img %u32vec2_01
2778 )";
2779 
2780   CompileSuccessfully(GenerateShaderCode(body).c_str());
2781   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
2782 }
2783 
TEST_F(ValidateImage,ReadNeedCapabilityStorageImageReadWithoutFormat)2784 TEST_F(ValidateImage, ReadNeedCapabilityStorageImageReadWithoutFormat) {
2785   const std::string body = R"(
2786 %img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
2787 %res1 = OpImageRead %u32vec4 %img %u32vec2_01
2788 )";
2789 
2790   CompileSuccessfully(GenerateShaderCode(body).c_str());
2791   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
2792 }
2793 
TEST_F(ValidateImage,ReadNeedCapabilityStorageImageReadWithoutFormatVulkan)2794 TEST_F(ValidateImage, ReadNeedCapabilityStorageImageReadWithoutFormatVulkan) {
2795   const std::string body = R"(
2796 %img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
2797 %res1 = OpImageRead %u32vec4 %img %u32vec2_01
2798 )";
2799 
2800   spv_target_env env = SPV_ENV_VULKAN_1_0;
2801   CompileSuccessfully(GenerateShaderCode(body, "", "Fragment", "", env).c_str(),
2802                       env);
2803   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
2804   EXPECT_THAT(getDiagnosticString(),
2805               HasSubstr("Capability StorageImageReadWithoutFormat is required "
2806                         "to read storage image"));
2807 }
2808 
TEST_F(ValidateImage,ReadNeedCapabilityImage1D)2809 TEST_F(ValidateImage, ReadNeedCapabilityImage1D) {
2810   const std::string body = R"(
2811 %img = OpLoad %type_image_f32_1d_0002_rgba32f %uniform_image_f32_1d_0002_rgba32f
2812 %res1 = OpImageRead %f32vec4 %img %u32vec2_01
2813 )";
2814 
2815   CompileSuccessfully(GenerateShaderCode(body).c_str());
2816   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2817   EXPECT_THAT(
2818       getDiagnosticString(),
2819       HasSubstr("Capability Image1D is required to access storage image"));
2820 }
2821 
TEST_F(ValidateImage,ReadNeedCapabilityImageCubeArray)2822 TEST_F(ValidateImage, ReadNeedCapabilityImageCubeArray) {
2823   const std::string body = R"(
2824 %img = OpLoad %type_image_f32_cube_0102_rgba32f %uniform_image_f32_cube_0102_rgba32f
2825 %res1 = OpImageRead %f32vec4 %img %u32vec3_012
2826 )";
2827 
2828   CompileSuccessfully(GenerateShaderCode(body).c_str());
2829   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2830   EXPECT_THAT(
2831       getDiagnosticString(),
2832       HasSubstr(
2833           "Capability ImageCubeArray is required to access storage image"));
2834 }
2835 
2836 // TODO(atgoo@github.com) Disabled until the spec is clarified.
TEST_F(ValidateImage,DISABLED_ReadWrongResultType)2837 TEST_F(ValidateImage, DISABLED_ReadWrongResultType) {
2838   const std::string body = R"(
2839 %img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
2840 %res1 = OpImageRead %f32 %img %u32vec2_01
2841 )";
2842 
2843   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
2844   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
2845   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2846   EXPECT_THAT(getDiagnosticString(),
2847               HasSubstr("Expected Result Type to be int or float vector type"));
2848 }
2849 
2850 // TODO(atgoo@github.com) Disabled until the spec is clarified.
TEST_F(ValidateImage,DISABLED_ReadWrongNumComponentsResultType)2851 TEST_F(ValidateImage, DISABLED_ReadWrongNumComponentsResultType) {
2852   const std::string body = R"(
2853 %img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
2854 %res1 = OpImageRead %f32vec3 %img %u32vec2_01
2855 )";
2856 
2857   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
2858   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
2859   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2860   EXPECT_THAT(getDiagnosticString(),
2861               HasSubstr("Expected Result Type to have 4 components"));
2862 }
2863 
TEST_F(ValidateImage,ReadNotImage)2864 TEST_F(ValidateImage, ReadNotImage) {
2865   const std::string body = R"(
2866 %sampler = OpLoad %type_sampler %uniform_sampler
2867 %res1 = OpImageRead %f32vec4 %sampler %u32vec2_01
2868 )";
2869 
2870   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
2871   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
2872   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2873   EXPECT_THAT(getDiagnosticString(),
2874               HasSubstr("Expected Image to be of type OpTypeImage"));
2875 }
2876 
TEST_F(ValidateImage,ReadImageSampled)2877 TEST_F(ValidateImage, ReadImageSampled) {
2878   const std::string body = R"(
2879 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2880 %res1 = OpImageRead %f32vec4 %img %u32vec2_01
2881 )";
2882 
2883   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
2884   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
2885   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2886   EXPECT_THAT(getDiagnosticString(),
2887               HasSubstr("Expected Image 'Sampled' parameter to be 0 or 2"));
2888 }
2889 
TEST_F(ValidateImage,ReadWrongSampledType)2890 TEST_F(ValidateImage, ReadWrongSampledType) {
2891   const std::string body = R"(
2892 %img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
2893 %res1 = OpImageRead %f32vec4 %img %u32vec2_01
2894 )";
2895 
2896   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
2897   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
2898   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2899   EXPECT_THAT(getDiagnosticString(),
2900               HasSubstr("Expected Image 'Sampled Type' to be the same as "
2901                         "Result Type components"));
2902 }
2903 
TEST_F(ValidateImage,ReadVoidSampledType)2904 TEST_F(ValidateImage, ReadVoidSampledType) {
2905   const std::string body = R"(
2906 %img = OpLoad %type_image_void_2d_0002 %uniform_image_void_2d_0002
2907 %res1 = OpImageRead %f32vec4 %img %u32vec2_01
2908 %res2 = OpImageRead %u32vec4 %img %u32vec2_01
2909 %res3 = OpImageRead %s32vec4 %img %u32vec2_01
2910 )";
2911 
2912   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
2913   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
2914   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
2915 }
2916 
TEST_F(ValidateImage,ReadWrongCoordinateType)2917 TEST_F(ValidateImage, ReadWrongCoordinateType) {
2918   const std::string body = R"(
2919 %img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
2920 %res1 = OpImageRead %u32vec4 %img %f32vec2_00
2921 )";
2922 
2923   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
2924   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
2925   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2926   EXPECT_THAT(getDiagnosticString(),
2927               HasSubstr("Expected Coordinate to be int scalar or vector"));
2928 }
2929 
TEST_F(ValidateImage,ReadCoordinateSizeTooSmall)2930 TEST_F(ValidateImage, ReadCoordinateSizeTooSmall) {
2931   const std::string body = R"(
2932 %img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
2933 %res1 = OpImageRead %u32vec4 %img %u32_1
2934 )";
2935 
2936   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
2937   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
2938   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2939   EXPECT_THAT(getDiagnosticString(),
2940               HasSubstr("Expected Coordinate to have at least 2 components, "
2941                         "but given only 1"));
2942 }
2943 
TEST_F(ValidateImage,WriteSuccess1)2944 TEST_F(ValidateImage, WriteSuccess1) {
2945   const std::string body = R"(
2946 %img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
2947 OpImageWrite %img %u32vec2_01 %u32vec4_0123
2948 )";
2949 
2950   const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n";
2951   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
2952   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
2953 }
2954 
TEST_F(ValidateImage,WriteSuccess2)2955 TEST_F(ValidateImage, WriteSuccess2) {
2956   const std::string body = R"(
2957 %img = OpLoad %type_image_f32_1d_0002_rgba32f %uniform_image_f32_1d_0002_rgba32f
2958 OpImageWrite %img %u32_1 %f32vec4_0000
2959 )";
2960 
2961   const std::string extra = "\nOpCapability Image1D\n";
2962   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
2963   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
2964 }
2965 
TEST_F(ValidateImage,WriteSuccess3)2966 TEST_F(ValidateImage, WriteSuccess3) {
2967   const std::string body = R"(
2968 %img = OpLoad %type_image_f32_cube_0102_rgba32f %uniform_image_f32_cube_0102_rgba32f
2969 OpImageWrite %img %u32vec3_012 %f32vec4_0000
2970 )";
2971 
2972   const std::string extra = "\nOpCapability ImageCubeArray\n";
2973   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
2974   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
2975 }
2976 
TEST_F(ValidateImage,WriteSuccess4)2977 TEST_F(ValidateImage, WriteSuccess4) {
2978   const std::string body = R"(
2979 %img = OpLoad %type_image_f32_2d_0010 %uniform_image_f32_2d_0010
2980 ;TODO(atgoo@github.com) Is it legal to write to MS image without sample index?
2981 OpImageWrite %img %u32vec2_01 %f32vec4_0000
2982 OpImageWrite %img %u32vec2_01 %f32vec4_0000 Sample %u32_1
2983 )";
2984 
2985   const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n";
2986   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
2987   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
2988 }
2989 
TEST_F(ValidateImage,WriteSubpassData)2990 TEST_F(ValidateImage, WriteSubpassData) {
2991   const std::string body = R"(
2992 %img = OpLoad %type_image_f32_spd_0002 %uniform_image_f32_spd_0002
2993 OpImageWrite %img %u32vec2_01 %f32vec4_0000
2994 )";
2995 
2996   CompileSuccessfully(GenerateShaderCode(body).c_str());
2997   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2998   EXPECT_THAT(getDiagnosticString(),
2999               HasSubstr("Image 'Dim' cannot be SubpassData"));
3000 }
3001 
TEST_F(ValidateImage,WriteNeedCapabilityStorageImageWriteWithoutFormat)3002 TEST_F(ValidateImage, WriteNeedCapabilityStorageImageWriteWithoutFormat) {
3003   const std::string body = R"(
3004 %img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
3005 OpImageWrite %img %u32vec2_01 %u32vec4_0123
3006 )";
3007 
3008   CompileSuccessfully(GenerateShaderCode(body).c_str());
3009   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3010 }
3011 
TEST_F(ValidateImage,WriteNeedCapabilityStorageImageWriteWithoutFormatVulkan)3012 TEST_F(ValidateImage, WriteNeedCapabilityStorageImageWriteWithoutFormatVulkan) {
3013   const std::string body = R"(
3014 %img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
3015 OpImageWrite %img %u32vec2_01 %u32vec4_0123
3016 )";
3017 
3018   spv_target_env env = SPV_ENV_VULKAN_1_0;
3019   CompileSuccessfully(GenerateShaderCode(body, "", "Fragment", "", env).c_str(),
3020                       env);
3021   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
3022   EXPECT_THAT(
3023       getDiagnosticString(),
3024       HasSubstr(
3025           "Capability StorageImageWriteWithoutFormat is required to write to "
3026           "storage image"));
3027 }
3028 
TEST_F(ValidateImage,WriteNeedCapabilityImage1D)3029 TEST_F(ValidateImage, WriteNeedCapabilityImage1D) {
3030   const std::string body = R"(
3031 %img = OpLoad %type_image_f32_1d_0002_rgba32f %uniform_image_f32_1d_0002_rgba32f
3032 OpImageWrite %img %u32vec2_01 %f32vec4_0000
3033 )";
3034 
3035   CompileSuccessfully(GenerateShaderCode(body).c_str());
3036   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3037   EXPECT_THAT(getDiagnosticString(),
3038               HasSubstr("Capability Image1D is required to access storage "
3039                         "image"));
3040 }
3041 
TEST_F(ValidateImage,WriteNeedCapabilityImageCubeArray)3042 TEST_F(ValidateImage, WriteNeedCapabilityImageCubeArray) {
3043   const std::string body = R"(
3044 %img = OpLoad %type_image_f32_cube_0102_rgba32f %uniform_image_f32_cube_0102_rgba32f
3045 OpImageWrite %img %u32vec3_012 %f32vec4_0000
3046 )";
3047 
3048   CompileSuccessfully(GenerateShaderCode(body).c_str());
3049   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3050   EXPECT_THAT(
3051       getDiagnosticString(),
3052       HasSubstr(
3053           "Capability ImageCubeArray is required to access storage image"));
3054 }
3055 
TEST_F(ValidateImage,WriteNotImage)3056 TEST_F(ValidateImage, WriteNotImage) {
3057   const std::string body = R"(
3058 %sampler = OpLoad %type_sampler %uniform_sampler
3059 OpImageWrite %sampler %u32vec2_01 %f32vec4_0000
3060 )";
3061 
3062   CompileSuccessfully(GenerateShaderCode(body).c_str());
3063   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3064   EXPECT_THAT(getDiagnosticString(),
3065               HasSubstr("Expected Image to be of type OpTypeImage"));
3066 }
3067 
TEST_F(ValidateImage,WriteImageSampled)3068 TEST_F(ValidateImage, WriteImageSampled) {
3069   const std::string body = R"(
3070 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3071 OpImageWrite %img %u32vec2_01 %f32vec4_0000
3072 )";
3073 
3074   const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n";
3075   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3076   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3077   EXPECT_THAT(getDiagnosticString(),
3078               HasSubstr("Expected Image 'Sampled' parameter to be 0 or 2"));
3079 }
3080 
TEST_F(ValidateImage,WriteWrongCoordinateType)3081 TEST_F(ValidateImage, WriteWrongCoordinateType) {
3082   const std::string body = R"(
3083 %img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
3084 OpImageWrite %img %f32vec2_00 %u32vec4_0123
3085 )";
3086 
3087   const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n";
3088   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3089   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3090   EXPECT_THAT(getDiagnosticString(),
3091               HasSubstr("Expected Coordinate to be int scalar or vector"));
3092 }
3093 
TEST_F(ValidateImage,WriteCoordinateSizeTooSmall)3094 TEST_F(ValidateImage, WriteCoordinateSizeTooSmall) {
3095   const std::string body = R"(
3096 %img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
3097 OpImageWrite %img %u32_1 %u32vec4_0123
3098 )";
3099 
3100   const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n";
3101   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3102   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3103   EXPECT_THAT(getDiagnosticString(),
3104               HasSubstr("Expected Coordinate to have at least 2 components, "
3105                         "but given only 1"));
3106 }
3107 
TEST_F(ValidateImage,WriteTexelWrongType)3108 TEST_F(ValidateImage, WriteTexelWrongType) {
3109   const std::string body = R"(
3110 %img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
3111 OpImageWrite %img %u32vec2_01 %img
3112 )";
3113 
3114   const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n";
3115   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3116   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3117   EXPECT_THAT(getDiagnosticString(),
3118               HasSubstr("Expected Texel to be int or float vector or scalar"));
3119 }
3120 
TEST_F(ValidateImage,DISABLED_WriteTexelNotVector4)3121 TEST_F(ValidateImage, DISABLED_WriteTexelNotVector4) {
3122   const std::string body = R"(
3123 %img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
3124 OpImageWrite %img %u32vec2_01 %u32vec3_012
3125 )";
3126 
3127   const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n";
3128   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3129   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3130   EXPECT_THAT(getDiagnosticString(),
3131               HasSubstr("Expected Texel to have 4 components"));
3132 }
3133 
TEST_F(ValidateImage,WriteTexelWrongComponentType)3134 TEST_F(ValidateImage, WriteTexelWrongComponentType) {
3135   const std::string body = R"(
3136 %img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
3137 OpImageWrite %img %u32vec2_01 %f32vec4_0000
3138 )";
3139 
3140   const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n";
3141   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3142   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3143   EXPECT_THAT(
3144       getDiagnosticString(),
3145       HasSubstr(
3146           "Expected Image 'Sampled Type' to be the same as Texel components"));
3147 }
3148 
TEST_F(ValidateImage,WriteSampleNotInteger)3149 TEST_F(ValidateImage, WriteSampleNotInteger) {
3150   const std::string body = R"(
3151 %img = OpLoad %type_image_f32_2d_0010 %uniform_image_f32_2d_0010
3152 OpImageWrite %img %u32vec2_01 %f32vec4_0000 Sample %f32_1
3153 )";
3154 
3155   const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n";
3156   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3157   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3158   EXPECT_THAT(getDiagnosticString(),
3159               HasSubstr("Expected Image Operand Sample to be int scalar"));
3160 }
3161 
TEST_F(ValidateImage,SampleNotMultisampled)3162 TEST_F(ValidateImage, SampleNotMultisampled) {
3163   const std::string body = R"(
3164 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
3165 OpImageWrite %img %u32vec2_01 %f32vec4_0000 Sample %u32_1
3166 )";
3167 
3168   const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n";
3169   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3170   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3171   EXPECT_THAT(
3172       getDiagnosticString(),
3173       HasSubstr("Image Operand Sample requires non-zero 'MS' parameter"));
3174 }
3175 
TEST_F(ValidateImage,SampleWrongOpcode)3176 TEST_F(ValidateImage, SampleWrongOpcode) {
3177   const std::string body = R"(
3178 %img = OpLoad %type_image_f32_2d_0010 %uniform_image_f32_2d_0010
3179 %sampler = OpLoad %type_sampler %uniform_sampler
3180 %simg = OpSampledImage %type_sampled_image_f32_2d_0010 %img %sampler
3181 %res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_00 Sample %u32_1
3182 )";
3183 
3184   CompileSuccessfully(GenerateShaderCode(body).c_str());
3185   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3186   EXPECT_THAT(getDiagnosticString(),
3187               HasSubstr("Image Operand Sample can only be used with "
3188                         "OpImageFetch, OpImageRead, OpImageWrite, "
3189                         "OpImageSparseFetch and OpImageSparseRead"));
3190 }
3191 
TEST_F(ValidateImage,SampleImageToImageSuccess)3192 TEST_F(ValidateImage, SampleImageToImageSuccess) {
3193   const std::string body = R"(
3194 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3195 %sampler = OpLoad %type_sampler %uniform_sampler
3196 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3197 %img2 = OpImage %type_image_f32_2d_0001 %simg
3198 )";
3199 
3200   CompileSuccessfully(GenerateShaderCode(body).c_str());
3201   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3202 }
3203 
TEST_F(ValidateImage,SampleImageToImageWrongResultType)3204 TEST_F(ValidateImage, SampleImageToImageWrongResultType) {
3205   const std::string body = R"(
3206 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3207 %sampler = OpLoad %type_sampler %uniform_sampler
3208 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3209 %img2 = OpImage %type_sampled_image_f32_2d_0001 %simg
3210 )";
3211 
3212   CompileSuccessfully(GenerateShaderCode(body).c_str());
3213   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3214   EXPECT_THAT(getDiagnosticString(),
3215               HasSubstr("Expected Result Type to be OpTypeImage"));
3216 }
3217 
TEST_F(ValidateImage,SampleImageToImageNotSampledImage)3218 TEST_F(ValidateImage, SampleImageToImageNotSampledImage) {
3219   const std::string body = R"(
3220 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3221 %img2 = OpImage %type_image_f32_2d_0001 %img
3222 )";
3223 
3224   CompileSuccessfully(GenerateShaderCode(body).c_str());
3225   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3226   EXPECT_THAT(
3227       getDiagnosticString(),
3228       HasSubstr("Expected Sample Image to be of type OpTypeSampleImage"));
3229 }
3230 
TEST_F(ValidateImage,SampleImageToImageNotTheSameImageType)3231 TEST_F(ValidateImage, SampleImageToImageNotTheSameImageType) {
3232   const std::string body = R"(
3233 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3234 %sampler = OpLoad %type_sampler %uniform_sampler
3235 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3236 %img2 = OpImage %type_image_f32_2d_0002 %simg
3237 )";
3238 
3239   CompileSuccessfully(GenerateShaderCode(body).c_str());
3240   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3241   EXPECT_THAT(getDiagnosticString(),
3242               HasSubstr("Expected Sample Image image type to be equal to "
3243                         "Result Type"));
3244 }
3245 
TEST_F(ValidateImage,QueryFormatSuccess)3246 TEST_F(ValidateImage, QueryFormatSuccess) {
3247   const std::string body = R"(
3248 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3249 %res1 = OpImageQueryFormat %u32 %img
3250 )";
3251 
3252   CompileSuccessfully(GenerateKernelCode(body).c_str());
3253   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3254 }
3255 
TEST_F(ValidateImage,QueryFormatWrongResultType)3256 TEST_F(ValidateImage, QueryFormatWrongResultType) {
3257   const std::string body = R"(
3258 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3259 %res1 = OpImageQueryFormat %bool %img
3260 )";
3261 
3262   CompileSuccessfully(GenerateKernelCode(body).c_str());
3263   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3264   EXPECT_THAT(getDiagnosticString(),
3265               HasSubstr("Expected Result Type to be int scalar type"));
3266 }
3267 
TEST_F(ValidateImage,QueryFormatNotImage)3268 TEST_F(ValidateImage, QueryFormatNotImage) {
3269   const std::string body = R"(
3270 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3271 %sampler = OpLoad %type_sampler %uniform_sampler
3272 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3273 %res1 = OpImageQueryFormat %u32 %sampler
3274 )";
3275 
3276   CompileSuccessfully(GenerateKernelCode(body).c_str());
3277   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3278   EXPECT_THAT(getDiagnosticString(),
3279               HasSubstr("Expected operand to be of type OpTypeImage"));
3280 }
3281 
TEST_F(ValidateImage,QueryOrderSuccess)3282 TEST_F(ValidateImage, QueryOrderSuccess) {
3283   const std::string body = R"(
3284 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3285 %res1 = OpImageQueryOrder %u32 %img
3286 )";
3287 
3288   CompileSuccessfully(GenerateKernelCode(body).c_str());
3289   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3290 }
3291 
TEST_F(ValidateImage,QueryOrderWrongResultType)3292 TEST_F(ValidateImage, QueryOrderWrongResultType) {
3293   const std::string body = R"(
3294 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3295 %res1 = OpImageQueryOrder %bool %img
3296 )";
3297 
3298   CompileSuccessfully(GenerateKernelCode(body).c_str());
3299   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3300   EXPECT_THAT(getDiagnosticString(),
3301               HasSubstr("Expected Result Type to be int scalar type"));
3302 }
3303 
TEST_F(ValidateImage,QueryOrderNotImage)3304 TEST_F(ValidateImage, QueryOrderNotImage) {
3305   const std::string body = R"(
3306 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3307 %sampler = OpLoad %type_sampler %uniform_sampler
3308 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3309 %res1 = OpImageQueryOrder %u32 %sampler
3310 )";
3311 
3312   CompileSuccessfully(GenerateKernelCode(body).c_str());
3313   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3314   EXPECT_THAT(getDiagnosticString(),
3315               HasSubstr("Expected operand to be of type OpTypeImage"));
3316 }
3317 
TEST_F(ValidateImage,QuerySizeLodSuccess)3318 TEST_F(ValidateImage, QuerySizeLodSuccess) {
3319   const std::string body = R"(
3320 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3321 %res1 = OpImageQuerySizeLod %u32vec2 %img %u32_1
3322 )";
3323 
3324   CompileSuccessfully(GenerateKernelCode(body).c_str());
3325   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3326 }
3327 
TEST_F(ValidateImage,QuerySizeLodWrongResultType)3328 TEST_F(ValidateImage, QuerySizeLodWrongResultType) {
3329   const std::string body = R"(
3330 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3331 %res1 = OpImageQuerySizeLod %f32vec2 %img %u32_1
3332 )";
3333 
3334   CompileSuccessfully(GenerateKernelCode(body).c_str());
3335   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3336   EXPECT_THAT(
3337       getDiagnosticString(),
3338       HasSubstr("Expected Result Type to be int scalar or vector type"));
3339 }
3340 
TEST_F(ValidateImage,QuerySizeLodResultTypeWrongSize)3341 TEST_F(ValidateImage, QuerySizeLodResultTypeWrongSize) {
3342   const std::string body = R"(
3343 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3344 %res1 = OpImageQuerySizeLod %u32 %img %u32_1
3345 )";
3346 
3347   CompileSuccessfully(GenerateKernelCode(body).c_str());
3348   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3349   EXPECT_THAT(getDiagnosticString(),
3350               HasSubstr("Result Type has 1 components, but 2 expected"));
3351 }
3352 
TEST_F(ValidateImage,QuerySizeLodNotImage)3353 TEST_F(ValidateImage, QuerySizeLodNotImage) {
3354   const std::string body = R"(
3355 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3356 %sampler = OpLoad %type_sampler %uniform_sampler
3357 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3358 %res1 = OpImageQuerySizeLod %u32vec2 %sampler %u32_1
3359 )";
3360 
3361   CompileSuccessfully(GenerateKernelCode(body).c_str());
3362   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3363   EXPECT_THAT(getDiagnosticString(),
3364               HasSubstr("Expected Image to be of type OpTypeImage"));
3365 }
3366 
TEST_F(ValidateImage,QuerySizeLodSampledImageDirectly)3367 TEST_F(ValidateImage, QuerySizeLodSampledImageDirectly) {
3368   const std::string body = R"(
3369 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3370 %sampler = OpLoad %type_sampler %uniform_sampler
3371 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3372 %res1 = OpImageQuerySizeLod %u32vec2 %simg %u32_1
3373 )";
3374 
3375   CompileSuccessfully(GenerateShaderCode(body).c_str());
3376   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3377   EXPECT_THAT(getDiagnosticString(),
3378               HasSubstr("OpSampledImage instruction must not appear as operand "
3379                         "for OpImageQuerySizeLod"));
3380 }
3381 
TEST_F(ValidateImage,QuerySizeLodWrongImageDim)3382 TEST_F(ValidateImage, QuerySizeLodWrongImageDim) {
3383   const std::string body = R"(
3384 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
3385 %res1 = OpImageQuerySizeLod %u32vec2 %img %u32_1
3386 )";
3387 
3388   CompileSuccessfully(GenerateKernelCode(body).c_str());
3389   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3390   EXPECT_THAT(getDiagnosticString(),
3391               HasSubstr("Image 'Dim' must be 1D, 2D, 3D or Cube"));
3392 }
3393 
TEST_F(ValidateImage,QuerySizeLodMultisampled)3394 TEST_F(ValidateImage, QuerySizeLodMultisampled) {
3395   const std::string body = R"(
3396 %img = OpLoad %type_image_f32_2d_0010 %uniform_image_f32_2d_0010
3397 %res1 = OpImageQuerySizeLod %u32vec2 %img %u32_1
3398 )";
3399 
3400   CompileSuccessfully(GenerateKernelCode(body).c_str());
3401   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3402   EXPECT_THAT(getDiagnosticString(), HasSubstr("Image 'MS' must be 0"));
3403 }
3404 
TEST_F(ValidateImage,QuerySizeLodWrongLodType)3405 TEST_F(ValidateImage, QuerySizeLodWrongLodType) {
3406   const std::string body = R"(
3407 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3408 %res1 = OpImageQuerySizeLod %u32vec2 %img %f32_0
3409 )";
3410 
3411   CompileSuccessfully(GenerateKernelCode(body).c_str());
3412   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3413   EXPECT_THAT(getDiagnosticString(),
3414               HasSubstr("Expected Level of Detail to be int scalar"));
3415 }
3416 
TEST_F(ValidateImage,QuerySizeSuccess)3417 TEST_F(ValidateImage, QuerySizeSuccess) {
3418   const std::string body = R"(
3419 %img = OpLoad %type_image_f32_2d_0010 %uniform_image_f32_2d_0010
3420 %res1 = OpImageQuerySize %u32vec2 %img
3421 )";
3422 
3423   CompileSuccessfully(GenerateKernelCode(body).c_str());
3424   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3425 }
3426 
TEST_F(ValidateImage,QuerySizeWrongResultType)3427 TEST_F(ValidateImage, QuerySizeWrongResultType) {
3428   const std::string body = R"(
3429 %img = OpLoad %type_image_f32_2d_0010 %uniform_image_f32_2d_0010
3430 %res1 = OpImageQuerySize %f32vec2 %img
3431 )";
3432 
3433   CompileSuccessfully(GenerateKernelCode(body).c_str());
3434   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3435   EXPECT_THAT(
3436       getDiagnosticString(),
3437       HasSubstr("Expected Result Type to be int scalar or vector type"));
3438 }
3439 
TEST_F(ValidateImage,QuerySizeNotImage)3440 TEST_F(ValidateImage, QuerySizeNotImage) {
3441   const std::string body = R"(
3442 %img = OpLoad %type_image_f32_2d_0010 %uniform_image_f32_2d_0010
3443 %sampler = OpLoad %type_sampler %uniform_sampler
3444 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3445 %res1 = OpImageQuerySize %u32vec2 %sampler
3446 )";
3447 
3448   CompileSuccessfully(GenerateKernelCode(body).c_str());
3449   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3450   EXPECT_THAT(getDiagnosticString(),
3451               HasSubstr("Expected Image to be of type OpTypeImage"));
3452 }
3453 
TEST_F(ValidateImage,QuerySizeSampledImageDirectly)3454 TEST_F(ValidateImage, QuerySizeSampledImageDirectly) {
3455   const std::string body = R"(
3456 %img = OpLoad %type_image_f32_2d_0010 %uniform_image_f32_2d_0010
3457 %sampler = OpLoad %type_sampler %uniform_sampler
3458 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3459 %res1 = OpImageQuerySize %u32vec2 %simg
3460 )";
3461 
3462   CompileSuccessfully(GenerateShaderCode(body).c_str());
3463   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3464   EXPECT_THAT(getDiagnosticString(),
3465               HasSubstr("OpSampledImage instruction must not appear as operand "
3466                         "for OpImageQuerySize"));
3467 }
3468 
TEST_F(ValidateImage,QuerySizeDimSubpassDataBad)3469 TEST_F(ValidateImage, QuerySizeDimSubpassDataBad) {
3470   const std::string body = R"(
3471 %img = OpLoad %type_image_f32_spd_0002 %uniform_image_f32_spd_0002
3472 %res1 = OpImageQuerySize %u32vec2 %img
3473 )";
3474 
3475   CompileSuccessfully(GenerateShaderCode(body).c_str());
3476   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3477   EXPECT_THAT(
3478       getDiagnosticString(),
3479       HasSubstr("Image 'Dim' must be 1D, Buffer, 2D, Cube, 3D or Rect"));
3480 }
3481 
TEST_F(ValidateImage,QuerySizeWrongSampling)3482 TEST_F(ValidateImage, QuerySizeWrongSampling) {
3483   const std::string body = R"(
3484 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3485 %res1 = OpImageQuerySize %u32vec2 %img
3486 )";
3487 
3488   CompileSuccessfully(GenerateKernelCode(body).c_str());
3489   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3490   EXPECT_THAT(
3491       getDiagnosticString(),
3492       HasSubstr("Image must have either 'MS'=1 or 'Sampled'=0 or 'Sampled'=2"));
3493 }
3494 
TEST_F(ValidateImage,QuerySizeWrongNumberOfComponents)3495 TEST_F(ValidateImage, QuerySizeWrongNumberOfComponents) {
3496   const std::string body = R"(
3497 %img = OpLoad %type_image_f32_3d_0111 %uniform_image_f32_3d_0111
3498 %res1 = OpImageQuerySize %u32vec2 %img
3499 )";
3500 
3501   CompileSuccessfully(GenerateShaderCode(body).c_str());
3502   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3503   EXPECT_THAT(getDiagnosticString(),
3504               HasSubstr("Result Type has 2 components, but 4 expected"));
3505 }
3506 
TEST_F(ValidateImage,QueryLodSuccessKernel)3507 TEST_F(ValidateImage, QueryLodSuccessKernel) {
3508   const std::string body = R"(
3509 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3510 %sampler = OpLoad %type_sampler %uniform_sampler
3511 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3512 %res1 = OpImageQueryLod %f32vec2 %simg %f32vec2_hh
3513 %res2 = OpImageQueryLod %f32vec2 %simg %u32vec2_01
3514 )";
3515 
3516   CompileSuccessfully(GenerateKernelCode(body).c_str());
3517   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3518 }
3519 
TEST_F(ValidateImage,QueryLodSuccessShader)3520 TEST_F(ValidateImage, QueryLodSuccessShader) {
3521   const std::string body = R"(
3522 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3523 %sampler = OpLoad %type_sampler %uniform_sampler
3524 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3525 %res1 = OpImageQueryLod %f32vec2 %simg %f32vec2_hh
3526 )";
3527 
3528   CompileSuccessfully(GenerateShaderCode(body).c_str());
3529   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3530 }
3531 
TEST_F(ValidateImage,QueryLodWrongResultType)3532 TEST_F(ValidateImage, QueryLodWrongResultType) {
3533   const std::string body = R"(
3534 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3535 %sampler = OpLoad %type_sampler %uniform_sampler
3536 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3537 %res1 = OpImageQueryLod %u32vec2 %simg %f32vec2_hh
3538 )";
3539 
3540   CompileSuccessfully(GenerateKernelCode(body).c_str());
3541   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3542   EXPECT_THAT(getDiagnosticString(),
3543               HasSubstr("Expected Result Type to be float vector type"));
3544 }
3545 
TEST_F(ValidateImage,QueryLodResultTypeWrongSize)3546 TEST_F(ValidateImage, QueryLodResultTypeWrongSize) {
3547   const std::string body = R"(
3548 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3549 %sampler = OpLoad %type_sampler %uniform_sampler
3550 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3551 %res1 = OpImageQueryLod %f32vec3 %simg %f32vec2_hh
3552 )";
3553 
3554   CompileSuccessfully(GenerateKernelCode(body).c_str());
3555   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3556   EXPECT_THAT(getDiagnosticString(),
3557               HasSubstr("Expected Result Type to have 2 components"));
3558 }
3559 
TEST_F(ValidateImage,QueryLodNotSampledImage)3560 TEST_F(ValidateImage, QueryLodNotSampledImage) {
3561   const std::string body = R"(
3562 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3563 %res1 = OpImageQueryLod %f32vec2 %img %f32vec2_hh
3564 )";
3565 
3566   CompileSuccessfully(GenerateKernelCode(body).c_str());
3567   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3568   EXPECT_THAT(
3569       getDiagnosticString(),
3570       HasSubstr("Expected Image operand to be of type OpTypeSampledImage"));
3571 }
3572 
TEST_F(ValidateImage,QueryLodWrongDim)3573 TEST_F(ValidateImage, QueryLodWrongDim) {
3574   const std::string body = R"(
3575 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
3576 %sampler = OpLoad %type_sampler %uniform_sampler
3577 %simg = OpSampledImage %type_sampled_image_f32_rect_0001 %img %sampler
3578 %res1 = OpImageQueryLod %f32vec2 %simg %f32vec2_hh
3579 )";
3580 
3581   CompileSuccessfully(GenerateKernelCode(body).c_str());
3582   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3583   EXPECT_THAT(getDiagnosticString(),
3584               HasSubstr("Image 'Dim' must be 1D, 2D, 3D or Cube"));
3585 }
3586 
TEST_F(ValidateImage,QueryLodWrongCoordinateType)3587 TEST_F(ValidateImage, QueryLodWrongCoordinateType) {
3588   const std::string body = R"(
3589 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3590 %sampler = OpLoad %type_sampler %uniform_sampler
3591 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3592 %res1 = OpImageQueryLod %f32vec2 %simg %u32vec2_01
3593 )";
3594 
3595   CompileSuccessfully(GenerateShaderCode(body).c_str());
3596   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3597   EXPECT_THAT(getDiagnosticString(),
3598               HasSubstr("Expected Coordinate to be float scalar or vector"));
3599 }
3600 
TEST_F(ValidateImage,QueryLodCoordinateSizeTooSmall)3601 TEST_F(ValidateImage, QueryLodCoordinateSizeTooSmall) {
3602   const std::string body = R"(
3603 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3604 %sampler = OpLoad %type_sampler %uniform_sampler
3605 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3606 %res1 = OpImageQueryLod %f32vec2 %simg %f32_0
3607 )";
3608 
3609   CompileSuccessfully(GenerateShaderCode(body).c_str());
3610   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3611   EXPECT_THAT(getDiagnosticString(),
3612               HasSubstr("Expected Coordinate to have at least 2 components, "
3613                         "but given only 1"));
3614 }
3615 
TEST_F(ValidateImage,QueryLevelsSuccess)3616 TEST_F(ValidateImage, QueryLevelsSuccess) {
3617   const std::string body = R"(
3618 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3619 %res1 = OpImageQueryLevels %u32 %img
3620 )";
3621 
3622   CompileSuccessfully(GenerateKernelCode(body).c_str());
3623   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3624 }
3625 
TEST_F(ValidateImage,QueryLevelsWrongResultType)3626 TEST_F(ValidateImage, QueryLevelsWrongResultType) {
3627   const std::string body = R"(
3628 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3629 %res1 = OpImageQueryLevels %f32 %img
3630 )";
3631 
3632   CompileSuccessfully(GenerateKernelCode(body).c_str());
3633   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3634   EXPECT_THAT(getDiagnosticString(),
3635               HasSubstr("Expected Result Type to be int scalar type"));
3636 }
3637 
TEST_F(ValidateImage,QueryLevelsNotImage)3638 TEST_F(ValidateImage, QueryLevelsNotImage) {
3639   const std::string body = R"(
3640 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3641 %sampler = OpLoad %type_sampler %uniform_sampler
3642 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3643 %res1 = OpImageQueryLevels %u32 %sampler
3644 )";
3645 
3646   CompileSuccessfully(GenerateKernelCode(body).c_str());
3647   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3648   EXPECT_THAT(getDiagnosticString(),
3649               HasSubstr("Expected Image to be of type OpTypeImage"));
3650 }
3651 
TEST_F(ValidateImage,QueryLevelsSampledImageDirectly)3652 TEST_F(ValidateImage, QueryLevelsSampledImageDirectly) {
3653   const std::string body = R"(
3654 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3655 %sampler = OpLoad %type_sampler %uniform_sampler
3656 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3657 %res1 = OpImageQueryLevels %u32 %simg
3658 )";
3659 
3660   CompileSuccessfully(GenerateShaderCode(body).c_str());
3661   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3662   EXPECT_THAT(getDiagnosticString(),
3663               HasSubstr("OpSampledImage instruction must not appear as operand "
3664                         "for OpImageQueryLevels"));
3665 }
3666 
TEST_F(ValidateImage,QueryLevelsWrongDim)3667 TEST_F(ValidateImage, QueryLevelsWrongDim) {
3668   const std::string body = R"(
3669 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
3670 %res1 = OpImageQueryLevels %u32 %img
3671 )";
3672 
3673   CompileSuccessfully(GenerateKernelCode(body).c_str());
3674   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3675   EXPECT_THAT(getDiagnosticString(),
3676               HasSubstr("Image 'Dim' must be 1D, 2D, 3D or Cube"));
3677 }
3678 
TEST_F(ValidateImage,QuerySamplesSuccess)3679 TEST_F(ValidateImage, QuerySamplesSuccess) {
3680   const std::string body = R"(
3681 %img = OpLoad %type_image_f32_2d_0010 %uniform_image_f32_2d_0010
3682 %res1 = OpImageQuerySamples %u32 %img
3683 )";
3684 
3685   CompileSuccessfully(GenerateKernelCode(body).c_str());
3686   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3687 }
3688 
TEST_F(ValidateImage,QuerySamplesNot2D)3689 TEST_F(ValidateImage, QuerySamplesNot2D) {
3690   const std::string body = R"(
3691 %img = OpLoad %type_image_f32_3d_0010 %uniform_image_f32_3d_0010
3692 %res1 = OpImageQuerySamples %u32 %img
3693 )";
3694 
3695   CompileSuccessfully(GenerateKernelCode(body).c_str());
3696   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3697   EXPECT_THAT(getDiagnosticString(), HasSubstr("Image 'Dim' must be 2D"));
3698 }
3699 
TEST_F(ValidateImage,QuerySamplesNotMultisampled)3700 TEST_F(ValidateImage, QuerySamplesNotMultisampled) {
3701   const std::string body = R"(
3702 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3703 %res1 = OpImageQuerySamples %u32 %img
3704 )";
3705 
3706   CompileSuccessfully(GenerateKernelCode(body).c_str());
3707   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3708   EXPECT_THAT(getDiagnosticString(), HasSubstr("Image 'MS' must be 1"));
3709 }
3710 
TEST_F(ValidateImage,QueryLodWrongExecutionModel)3711 TEST_F(ValidateImage, QueryLodWrongExecutionModel) {
3712   const std::string body = R"(
3713 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3714 %sampler = OpLoad %type_sampler %uniform_sampler
3715 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3716 %res1 = OpImageQueryLod %f32vec2 %simg %f32vec2_hh
3717 )";
3718 
3719   CompileSuccessfully(GenerateShaderCode(body, "", "Vertex").c_str());
3720   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3721   EXPECT_THAT(
3722       getDiagnosticString(),
3723       HasSubstr(
3724           "OpImageQueryLod requires Fragment or GLCompute execution model"));
3725 }
3726 
TEST_F(ValidateImage,QueryLodWrongExecutionModelWithFunc)3727 TEST_F(ValidateImage, QueryLodWrongExecutionModelWithFunc) {
3728   const std::string body = R"(
3729 %call_ret = OpFunctionCall %void %my_func
3730 OpReturn
3731 OpFunctionEnd
3732 %my_func = OpFunction %void None %func
3733 %my_func_entry = OpLabel
3734 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3735 %sampler = OpLoad %type_sampler %uniform_sampler
3736 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3737 %res1 = OpImageQueryLod %f32vec2 %simg %f32vec2_hh
3738 )";
3739 
3740   CompileSuccessfully(GenerateShaderCode(body, "", "Vertex").c_str());
3741   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3742   EXPECT_THAT(
3743       getDiagnosticString(),
3744       HasSubstr(
3745           "OpImageQueryLod requires Fragment or GLCompute execution model"));
3746 }
3747 
TEST_F(ValidateImage,QueryLodComputeShaderDerivatives)3748 TEST_F(ValidateImage, QueryLodComputeShaderDerivatives) {
3749   const std::string body = R"(
3750 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3751 %sampler = OpLoad %type_sampler %uniform_sampler
3752 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3753 %res1 = OpImageQueryLod %f32vec2 %simg %f32vec2_hh
3754 )";
3755 
3756   const std::string extra = R"(
3757 OpCapability ComputeDerivativeGroupLinearNV
3758 OpExtension "SPV_NV_compute_shader_derivatives"
3759 )";
3760   const std::string mode = R"(
3761 OpExecutionMode %main LocalSize 8 8 1
3762 OpExecutionMode %main DerivativeGroupLinearNV
3763 )";
3764   CompileSuccessfully(
3765       GenerateShaderCode(body, extra, "GLCompute", mode).c_str());
3766   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3767 }
3768 
TEST_F(ValidateImage,QueryLodComputeShaderDerivativesMissingMode)3769 TEST_F(ValidateImage, QueryLodComputeShaderDerivativesMissingMode) {
3770   const std::string body = R"(
3771 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3772 %sampler = OpLoad %type_sampler %uniform_sampler
3773 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3774 %res1 = OpImageQueryLod %f32vec2 %simg %f32vec2_hh
3775 )";
3776 
3777   const std::string extra = R"(
3778 OpCapability ComputeDerivativeGroupLinearNV
3779 OpExtension "SPV_NV_compute_shader_derivatives"
3780 )";
3781   const std::string mode = R"(
3782 OpExecutionMode %main LocalSize 8 8 1
3783 )";
3784   CompileSuccessfully(
3785       GenerateShaderCode(body, extra, "GLCompute", mode).c_str());
3786   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3787   EXPECT_THAT(getDiagnosticString(),
3788               HasSubstr("OpImageQueryLod requires DerivativeGroupQuadsNV or "
3789                         "DerivativeGroupLinearNV execution mode for GLCompute "
3790                         "execution model"));
3791 }
3792 
TEST_F(ValidateImage,ImplicitLodWrongExecutionModel)3793 TEST_F(ValidateImage, ImplicitLodWrongExecutionModel) {
3794   const std::string body = R"(
3795 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3796 %sampler = OpLoad %type_sampler %uniform_sampler
3797 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3798 %res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh
3799 )";
3800 
3801   CompileSuccessfully(GenerateShaderCode(body, "", "Vertex").c_str());
3802   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3803   EXPECT_THAT(getDiagnosticString(),
3804               HasSubstr("ImplicitLod instructions require Fragment or "
3805                         "GLCompute execution model"));
3806 }
3807 
TEST_F(ValidateImage,ImplicitLodComputeShaderDerivatives)3808 TEST_F(ValidateImage, ImplicitLodComputeShaderDerivatives) {
3809   const std::string body = R"(
3810 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3811 %sampler = OpLoad %type_sampler %uniform_sampler
3812 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3813 %res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh
3814 )";
3815 
3816   const std::string extra = R"(
3817 OpCapability ComputeDerivativeGroupLinearNV
3818 OpExtension "SPV_NV_compute_shader_derivatives"
3819 )";
3820   const std::string mode = R"(
3821 OpExecutionMode %main LocalSize 8 8 1
3822 OpExecutionMode %main DerivativeGroupLinearNV
3823 )";
3824   CompileSuccessfully(
3825       GenerateShaderCode(body, extra, "GLCompute", mode).c_str());
3826   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3827 }
3828 
TEST_F(ValidateImage,ImplicitLodComputeShaderDerivativesMissingMode)3829 TEST_F(ValidateImage, ImplicitLodComputeShaderDerivativesMissingMode) {
3830   const std::string body = R"(
3831 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3832 %sampler = OpLoad %type_sampler %uniform_sampler
3833 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3834 %res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh
3835 )";
3836 
3837   const std::string extra = R"(
3838 OpCapability ComputeDerivativeGroupLinearNV
3839 OpExtension "SPV_NV_compute_shader_derivatives"
3840 )";
3841   const std::string mode = R"(
3842 OpExecutionMode %main LocalSize 8 8 1
3843 )";
3844   CompileSuccessfully(
3845       GenerateShaderCode(body, extra, "GLCompute", mode).c_str());
3846   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3847   EXPECT_THAT(
3848       getDiagnosticString(),
3849       HasSubstr("ImplicitLod instructions require DerivativeGroupQuadsNV or "
3850                 "DerivativeGroupLinearNV execution mode for GLCompute "
3851                 "execution model"));
3852 }
3853 
TEST_F(ValidateImage,ReadSubpassDataWrongExecutionModel)3854 TEST_F(ValidateImage, ReadSubpassDataWrongExecutionModel) {
3855   const std::string body = R"(
3856 %img = OpLoad %type_image_f32_spd_0002 %uniform_image_f32_spd_0002
3857 %res1 = OpImageRead %f32vec4 %img %u32vec2_01
3858 )";
3859 
3860   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
3861   CompileSuccessfully(GenerateShaderCode(body, extra, "Vertex").c_str());
3862   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3863   EXPECT_THAT(getDiagnosticString(),
3864               HasSubstr("Dim SubpassData requires Fragment execution model"));
3865 }
3866 
TEST_F(ValidateImage,SparseSampleImplicitLodSuccess)3867 TEST_F(ValidateImage, SparseSampleImplicitLodSuccess) {
3868   const std::string body = R"(
3869 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3870 %sampler = OpLoad %type_sampler %uniform_sampler
3871 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3872 %res1 = OpImageSparseSampleImplicitLod %struct_u32_f32vec4 %simg %f32vec2_hh
3873 %res2 = OpImageSparseSampleImplicitLod %struct_u32_f32vec4 %simg %f32vec2_hh Bias %f32_0_25
3874 %res4 = OpImageSparseSampleImplicitLod %struct_u32_f32vec4 %simg %f32vec2_hh ConstOffset %s32vec2_01
3875 %res5 = OpImageSparseSampleImplicitLod %struct_u32_f32vec4 %simg %f32vec2_hh Offset %s32vec2_01
3876 %res6 = OpImageSparseSampleImplicitLod %struct_u32_f32vec4 %simg %f32vec2_hh MinLod %f32_0_5
3877 %res7 = OpImageSparseSampleImplicitLod %struct_u64_f32vec4 %simg %f32vec2_hh Bias|Offset|MinLod %f32_0_25 %s32vec2_01 %f32_0_5
3878 %res8 = OpImageSparseSampleImplicitLod %struct_u32_f32vec4 %simg %f32vec2_hh NonPrivateTexelKHR
3879 )";
3880 
3881   const std::string extra = R"(
3882 OpCapability VulkanMemoryModelKHR
3883 OpExtension "SPV_KHR_vulkan_memory_model"
3884 )";
3885   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
3886                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
3887                           .c_str());
3888   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
3889 }
3890 
TEST_F(ValidateImage,SparseSampleImplicitLodResultTypeNotStruct)3891 TEST_F(ValidateImage, SparseSampleImplicitLodResultTypeNotStruct) {
3892   const std::string body = R"(
3893 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3894 %sampler = OpLoad %type_sampler %uniform_sampler
3895 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3896 %res1 = OpImageSparseSampleImplicitLod %f32 %simg %f32vec2_hh
3897 )";
3898 
3899   CompileSuccessfully(GenerateShaderCode(body).c_str());
3900   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3901   EXPECT_THAT(getDiagnosticString(),
3902               HasSubstr("Expected Result Type to be OpTypeStruct"));
3903 }
3904 
TEST_F(ValidateImage,SparseSampleImplicitLodResultTypeNotTwoMembers1)3905 TEST_F(ValidateImage, SparseSampleImplicitLodResultTypeNotTwoMembers1) {
3906   const std::string body = R"(
3907 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3908 %sampler = OpLoad %type_sampler %uniform_sampler
3909 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3910 %res1 = OpImageSparseSampleImplicitLod %struct_u32 %simg %f32vec2_hh
3911 )";
3912 
3913   CompileSuccessfully(GenerateShaderCode(body).c_str());
3914   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3915   EXPECT_THAT(getDiagnosticString(),
3916               HasSubstr("Expected Result Type to be a struct containing an int "
3917                         "scalar and a texel"));
3918 }
3919 
TEST_F(ValidateImage,SparseSampleImplicitLodResultTypeNotTwoMembers2)3920 TEST_F(ValidateImage, SparseSampleImplicitLodResultTypeNotTwoMembers2) {
3921   const std::string body = R"(
3922 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3923 %sampler = OpLoad %type_sampler %uniform_sampler
3924 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3925 %res1 = OpImageSparseSampleImplicitLod %struct_u32_f32vec4_u32 %simg %f32vec2_hh
3926 )";
3927 
3928   CompileSuccessfully(GenerateShaderCode(body).c_str());
3929   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3930   EXPECT_THAT(getDiagnosticString(),
3931               HasSubstr("Expected Result Type to be a struct containing an "
3932                         "int scalar and a texel"));
3933 }
3934 
TEST_F(ValidateImage,SparseSampleImplicitLodResultTypeFirstMemberNotInt)3935 TEST_F(ValidateImage, SparseSampleImplicitLodResultTypeFirstMemberNotInt) {
3936   const std::string body = R"(
3937 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3938 %sampler = OpLoad %type_sampler %uniform_sampler
3939 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3940 %res1 = OpImageSparseSampleImplicitLod %struct_f32_f32vec4 %simg %f32vec2_hh
3941 )";
3942 
3943   CompileSuccessfully(GenerateShaderCode(body).c_str());
3944   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3945   EXPECT_THAT(getDiagnosticString(),
3946               HasSubstr("Expected Result Type to be a struct containing an "
3947                         "int scalar and a texel"));
3948 }
3949 
TEST_F(ValidateImage,SparseSampleImplicitLodResultTypeTexelNotVector)3950 TEST_F(ValidateImage, SparseSampleImplicitLodResultTypeTexelNotVector) {
3951   const std::string body = R"(
3952 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3953 %sampler = OpLoad %type_sampler %uniform_sampler
3954 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3955 %res1 = OpImageSparseSampleImplicitLod %struct_u32_u32 %simg %f32vec2_hh
3956 )";
3957 
3958   CompileSuccessfully(GenerateShaderCode(body).c_str());
3959   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3960   EXPECT_THAT(getDiagnosticString(),
3961               HasSubstr("Expected Result Type's second member to be int or "
3962                         "float vector type"));
3963 }
3964 
TEST_F(ValidateImage,SparseSampleImplicitLodWrongNumComponentsTexel)3965 TEST_F(ValidateImage, SparseSampleImplicitLodWrongNumComponentsTexel) {
3966   const std::string body = R"(
3967 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3968 %sampler = OpLoad %type_sampler %uniform_sampler
3969 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3970 %res1 = OpImageSparseSampleImplicitLod %struct_u32_f32vec3 %simg %f32vec2_hh
3971 )";
3972 
3973   CompileSuccessfully(GenerateShaderCode(body).c_str());
3974   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3975   EXPECT_THAT(getDiagnosticString(),
3976               HasSubstr("Expected Result Type's second member to have 4 "
3977                         "components"));
3978 }
3979 
TEST_F(ValidateImage,SparseSampleImplicitLodWrongComponentTypeTexel)3980 TEST_F(ValidateImage, SparseSampleImplicitLodWrongComponentTypeTexel) {
3981   const std::string body = R"(
3982 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3983 %sampler = OpLoad %type_sampler %uniform_sampler
3984 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3985 %res1 = OpImageSparseSampleImplicitLod %struct_u32_u32vec4 %simg %f32vec2_hh
3986 )";
3987 
3988   CompileSuccessfully(GenerateShaderCode(body).c_str());
3989   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3990   EXPECT_THAT(getDiagnosticString(),
3991               HasSubstr("Expected Image 'Sampled Type' to be the same as "
3992                         "Result Type's second member components"));
3993 }
3994 
TEST_F(ValidateImage,SparseSampleDrefImplicitLodSuccess)3995 TEST_F(ValidateImage, SparseSampleDrefImplicitLodSuccess) {
3996   const std::string body = R"(
3997 %img = OpLoad %type_image_u32_2d_0001 %uniform_image_u32_2d_0001
3998 %sampler = OpLoad %type_sampler %uniform_sampler
3999 %simg = OpSampledImage %type_sampled_image_u32_2d_0001 %img %sampler
4000 %res1 = OpImageSparseSampleDrefImplicitLod %struct_u32_u32 %simg %f32vec2_hh %f32_1
4001 %res2 = OpImageSparseSampleDrefImplicitLod %struct_u32_u32 %simg %f32vec2_hh %f32_1 Bias %f32_0_25
4002 %res4 = OpImageSparseSampleDrefImplicitLod %struct_u32_u32 %simg %f32vec2_hh %f32_1 ConstOffset %s32vec2_01
4003 %res5 = OpImageSparseSampleDrefImplicitLod %struct_u32_u32 %simg %f32vec2_hh %f32_1 Offset %s32vec2_01
4004 %res6 = OpImageSparseSampleDrefImplicitLod %struct_u32_u32 %simg %f32vec2_hh %f32_1 MinLod %f32_0_5
4005 %res7 = OpImageSparseSampleDrefImplicitLod %struct_u32_u32 %simg %f32vec2_hh %f32_1 Bias|Offset|MinLod %f32_0_25 %s32vec2_01 %f32_0_5
4006 %res8 = OpImageSparseSampleDrefImplicitLod %struct_u32_u32 %simg %f32vec2_hh %f32_1 NonPrivateTexelKHR
4007 )";
4008 
4009   const std::string extra = R"(
4010 OpCapability VulkanMemoryModelKHR
4011 OpExtension "SPV_KHR_vulkan_memory_model"
4012 )";
4013   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
4014                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
4015                           .c_str());
4016   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4017 }
4018 
TEST_F(ValidateImage,SparseSampleDrefImplicitLodResultTypeNotStruct)4019 TEST_F(ValidateImage, SparseSampleDrefImplicitLodResultTypeNotStruct) {
4020   const std::string body = R"(
4021 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4022 %sampler = OpLoad %type_sampler %uniform_sampler
4023 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4024 %res1 = OpImageSparseSampleDrefImplicitLod %f32 %simg %f32vec2_hh %f32_1
4025 )";
4026 
4027   CompileSuccessfully(GenerateShaderCode(body).c_str());
4028   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4029   EXPECT_THAT(getDiagnosticString(),
4030               HasSubstr("Expected Result Type to be OpTypeStruct"));
4031 }
4032 
TEST_F(ValidateImage,SparseSampleDrefImplicitLodResultTypeNotTwoMembers1)4033 TEST_F(ValidateImage, SparseSampleDrefImplicitLodResultTypeNotTwoMembers1) {
4034   const std::string body = R"(
4035 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4036 %sampler = OpLoad %type_sampler %uniform_sampler
4037 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4038 %res1 = OpImageSparseSampleDrefImplicitLod %struct_u32 %simg %f32vec2_hh %f32_1
4039 )";
4040 
4041   CompileSuccessfully(GenerateShaderCode(body).c_str());
4042   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4043   EXPECT_THAT(
4044       getDiagnosticString(),
4045       HasSubstr("Expected Result Type to be a struct containing an int scalar "
4046                 "and a texel"));
4047 }
4048 
TEST_F(ValidateImage,SparseSampleDrefImplicitLodResultTypeNotTwoMembers2)4049 TEST_F(ValidateImage, SparseSampleDrefImplicitLodResultTypeNotTwoMembers2) {
4050   const std::string body = R"(
4051 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4052 %sampler = OpLoad %type_sampler %uniform_sampler
4053 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4054 %res1 = OpImageSparseSampleDrefImplicitLod %struct_u32_f32_u32 %simg %f32vec2_hh %f32_1
4055 )";
4056 
4057   CompileSuccessfully(GenerateShaderCode(body).c_str());
4058   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4059   EXPECT_THAT(
4060       getDiagnosticString(),
4061       HasSubstr("Expected Result Type to be a struct containing an int scalar "
4062                 "and a texel"));
4063 }
4064 
TEST_F(ValidateImage,SparseSampleDrefImplicitLodResultTypeFirstMemberNotInt)4065 TEST_F(ValidateImage, SparseSampleDrefImplicitLodResultTypeFirstMemberNotInt) {
4066   const std::string body = R"(
4067 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4068 %sampler = OpLoad %type_sampler %uniform_sampler
4069 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4070 %res1 = OpImageSparseSampleDrefImplicitLod %struct_f32_f32 %simg %f32vec2_hh %f32_1
4071 )";
4072 
4073   CompileSuccessfully(GenerateShaderCode(body).c_str());
4074   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4075   EXPECT_THAT(
4076       getDiagnosticString(),
4077       HasSubstr("Expected Result Type to be a struct containing an int scalar "
4078                 "and a texel"));
4079 }
4080 
TEST_F(ValidateImage,SparseSampleDrefImplicitLodDifferentSampledType)4081 TEST_F(ValidateImage, SparseSampleDrefImplicitLodDifferentSampledType) {
4082   const std::string body = R"(
4083 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4084 %sampler = OpLoad %type_sampler %uniform_sampler
4085 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4086 %res1 = OpImageSparseSampleDrefImplicitLod %struct_u32_u32 %simg %f32vec2_hh %f32_1
4087 )";
4088 
4089   CompileSuccessfully(GenerateShaderCode(body).c_str());
4090   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4091   EXPECT_THAT(getDiagnosticString(),
4092               HasSubstr("Expected Image 'Sampled Type' to be the same as "
4093                         "Result Type's second member"));
4094 }
4095 
TEST_F(ValidateImage,SparseFetchSuccess)4096 TEST_F(ValidateImage, SparseFetchSuccess) {
4097   const std::string body = R"(
4098 %img = OpLoad %type_image_f32_1d_0001 %uniform_image_f32_1d_0001
4099 %res1 = OpImageSparseFetch %struct_u32_f32vec4 %img %u32vec2_01
4100 %res2 = OpImageSparseFetch %struct_u32_f32vec4 %img %u32vec2_01 NonPrivateTexelKHR
4101 )";
4102 
4103   const std::string extra = R"(
4104 OpCapability VulkanMemoryModelKHR
4105 OpExtension "SPV_KHR_vulkan_memory_model"
4106 )";
4107   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
4108                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
4109                           .c_str());
4110   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4111 }
4112 
TEST_F(ValidateImage,SparseFetchResultTypeNotStruct)4113 TEST_F(ValidateImage, SparseFetchResultTypeNotStruct) {
4114   const std::string body = R"(
4115 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
4116 %res1 = OpImageSparseFetch %f32 %img %u32vec2_01
4117 )";
4118 
4119   CompileSuccessfully(GenerateShaderCode(body).c_str());
4120   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4121   EXPECT_THAT(getDiagnosticString(),
4122               HasSubstr("Expected Result Type to be OpTypeStruct"));
4123 }
4124 
TEST_F(ValidateImage,SparseFetchResultTypeNotTwoMembers1)4125 TEST_F(ValidateImage, SparseFetchResultTypeNotTwoMembers1) {
4126   const std::string body = R"(
4127 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
4128 %res1 = OpImageSparseFetch %struct_u32 %img %u32vec2_01
4129 )";
4130 
4131   CompileSuccessfully(GenerateShaderCode(body).c_str());
4132   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4133   EXPECT_THAT(getDiagnosticString(),
4134               HasSubstr("Expected Result Type to be a struct containing an "
4135                         "int scalar and a texel"));
4136 }
4137 
TEST_F(ValidateImage,SparseFetchResultTypeNotTwoMembers2)4138 TEST_F(ValidateImage, SparseFetchResultTypeNotTwoMembers2) {
4139   const std::string body = R"(
4140 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
4141 %res1 = OpImageSparseFetch %struct_u32_f32vec4_u32 %img %u32vec2_01
4142 )";
4143 
4144   CompileSuccessfully(GenerateShaderCode(body).c_str());
4145   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4146   EXPECT_THAT(getDiagnosticString(),
4147               HasSubstr("Expected Result Type to be a struct containing an "
4148                         "int scalar and a texel"));
4149 }
4150 
TEST_F(ValidateImage,SparseFetchResultTypeFirstMemberNotInt)4151 TEST_F(ValidateImage, SparseFetchResultTypeFirstMemberNotInt) {
4152   const std::string body = R"(
4153 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
4154 %res1 = OpImageSparseFetch %struct_f32_f32vec4 %img %u32vec2_01
4155 )";
4156 
4157   CompileSuccessfully(GenerateShaderCode(body).c_str());
4158   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4159   EXPECT_THAT(getDiagnosticString(),
4160               HasSubstr("Expected Result Type to be a struct containing an "
4161                         "int scalar and a texel"));
4162 }
4163 
TEST_F(ValidateImage,SparseFetchResultTypeTexelNotVector)4164 TEST_F(ValidateImage, SparseFetchResultTypeTexelNotVector) {
4165   const std::string body = R"(
4166 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
4167 %res1 = OpImageSparseFetch %struct_u32_u32 %img %u32vec2_01
4168 )";
4169 
4170   CompileSuccessfully(GenerateShaderCode(body).c_str());
4171   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4172   EXPECT_THAT(getDiagnosticString(),
4173               HasSubstr("Expected Result Type's second member to be int or "
4174                         "float vector type"));
4175 }
4176 
TEST_F(ValidateImage,SparseFetchWrongNumComponentsTexel)4177 TEST_F(ValidateImage, SparseFetchWrongNumComponentsTexel) {
4178   const std::string body = R"(
4179 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
4180 %res1 = OpImageSparseFetch %struct_u32_f32vec3 %img %u32vec2_01
4181 )";
4182 
4183   CompileSuccessfully(GenerateShaderCode(body).c_str());
4184   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4185   EXPECT_THAT(getDiagnosticString(),
4186               HasSubstr("Expected Result Type's second member to have 4 "
4187                         "components"));
4188 }
4189 
TEST_F(ValidateImage,SparseFetchWrongComponentTypeTexel)4190 TEST_F(ValidateImage, SparseFetchWrongComponentTypeTexel) {
4191   const std::string body = R"(
4192 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
4193 %res1 = OpImageSparseFetch %struct_u32_u32vec4 %img %u32vec2_01
4194 )";
4195 
4196   CompileSuccessfully(GenerateShaderCode(body).c_str());
4197   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4198   EXPECT_THAT(getDiagnosticString(),
4199               HasSubstr("Expected Image 'Sampled Type' to be the same as "
4200                         "Result Type's second member components"));
4201 }
4202 
TEST_F(ValidateImage,SparseReadSuccess)4203 TEST_F(ValidateImage, SparseReadSuccess) {
4204   const std::string body = R"(
4205 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
4206 %res1 = OpImageSparseRead %struct_u32_f32vec4 %img %u32vec2_01
4207 )";
4208 
4209   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
4210   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
4211   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
4212 }
4213 
TEST_F(ValidateImage,SparseReadResultTypeNotStruct)4214 TEST_F(ValidateImage, SparseReadResultTypeNotStruct) {
4215   const std::string body = R"(
4216 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
4217 %res1 = OpImageSparseRead %f32 %img %u32vec2_01
4218 )";
4219 
4220   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
4221   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
4222   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4223   EXPECT_THAT(getDiagnosticString(),
4224               HasSubstr("Expected Result Type to be OpTypeStruct"));
4225 }
4226 
TEST_F(ValidateImage,SparseReadResultTypeNotTwoMembers1)4227 TEST_F(ValidateImage, SparseReadResultTypeNotTwoMembers1) {
4228   const std::string body = R"(
4229 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
4230 %res1 = OpImageSparseRead %struct_u32 %img %u32vec2_01
4231 )";
4232 
4233   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
4234   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
4235   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4236   EXPECT_THAT(getDiagnosticString(),
4237               HasSubstr("Expected Result Type to be a struct containing an "
4238                         "int scalar and a texel"));
4239 }
4240 
TEST_F(ValidateImage,SparseReadResultTypeNotTwoMembers2)4241 TEST_F(ValidateImage, SparseReadResultTypeNotTwoMembers2) {
4242   const std::string body = R"(
4243 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
4244 %res1 = OpImageSparseRead %struct_u32_f32vec4_u32 %img %u32vec2_01
4245 )";
4246 
4247   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
4248   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
4249   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4250   EXPECT_THAT(getDiagnosticString(),
4251               HasSubstr("Expected Result Type to be a struct containing an "
4252                         "int scalar and a texel"));
4253 }
4254 
TEST_F(ValidateImage,SparseReadResultTypeFirstMemberNotInt)4255 TEST_F(ValidateImage, SparseReadResultTypeFirstMemberNotInt) {
4256   const std::string body = R"(
4257 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
4258 %res1 = OpImageSparseRead %struct_f32_f32vec4 %img %u32vec2_01
4259 )";
4260 
4261   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
4262   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
4263   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4264   EXPECT_THAT(getDiagnosticString(),
4265               HasSubstr("Expected Result Type to be a struct containing an "
4266                         "int scalar and a texel"));
4267 }
4268 
TEST_F(ValidateImage,SparseReadResultTypeTexelWrongType)4269 TEST_F(ValidateImage, SparseReadResultTypeTexelWrongType) {
4270   const std::string body = R"(
4271 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
4272 %res1 = OpImageSparseRead %struct_u32_u32arr4 %img %u32vec2_01
4273 )";
4274 
4275   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
4276   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
4277   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4278   EXPECT_THAT(getDiagnosticString(),
4279               HasSubstr("Expected Result Type's second member to be int or "
4280                         "float scalar or vector type"));
4281 }
4282 
TEST_F(ValidateImage,SparseReadWrongComponentTypeTexel)4283 TEST_F(ValidateImage, SparseReadWrongComponentTypeTexel) {
4284   const std::string body = R"(
4285 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
4286 %res1 = OpImageSparseRead %struct_u32_u32vec4 %img %u32vec2_01
4287 )";
4288 
4289   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
4290   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
4291   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4292   EXPECT_THAT(getDiagnosticString(),
4293               HasSubstr("Expected Image 'Sampled Type' to be the same as "
4294                         "Result Type's second member components"));
4295 }
4296 
TEST_F(ValidateImage,SparseReadSubpassDataNotAllowed)4297 TEST_F(ValidateImage, SparseReadSubpassDataNotAllowed) {
4298   const std::string body = R"(
4299 %img = OpLoad %type_image_f32_spd_0002 %uniform_image_f32_spd_0002
4300 %res1 = OpImageSparseRead %struct_u32_f32vec4 %img %u32vec2_01
4301 )";
4302 
4303   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
4304   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment").c_str());
4305   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4306   EXPECT_THAT(
4307       getDiagnosticString(),
4308       HasSubstr("Image Dim SubpassData cannot be used with ImageSparseRead"));
4309 }
4310 
TEST_F(ValidateImage,SparseGatherSuccess)4311 TEST_F(ValidateImage, SparseGatherSuccess) {
4312   const std::string body = R"(
4313 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4314 %sampler = OpLoad %type_sampler %uniform_sampler
4315 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4316 %res1 = OpImageSparseGather %struct_u32_f32vec4 %simg %f32vec4_0000 %u32_1
4317 %res2 = OpImageSparseGather %struct_u32_f32vec4 %simg %f32vec4_0000 %u32_1 NonPrivateTexelKHR
4318 )";
4319 
4320   const std::string extra = R"(
4321 OpCapability VulkanMemoryModelKHR
4322 OpExtension "SPV_KHR_vulkan_memory_model"
4323 )";
4324   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
4325                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
4326                           .c_str());
4327   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4328 }
4329 
TEST_F(ValidateImage,SparseGatherResultTypeNotStruct)4330 TEST_F(ValidateImage, SparseGatherResultTypeNotStruct) {
4331   const std::string body = R"(
4332 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4333 %sampler = OpLoad %type_sampler %uniform_sampler
4334 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4335 %res1 = OpImageSparseGather %f32 %simg %f32vec2_hh %u32_1
4336 )";
4337 
4338   CompileSuccessfully(GenerateShaderCode(body).c_str());
4339   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4340   EXPECT_THAT(getDiagnosticString(),
4341               HasSubstr("Expected Result Type to be OpTypeStruct"));
4342 }
4343 
TEST_F(ValidateImage,SparseGatherResultTypeNotTwoMembers1)4344 TEST_F(ValidateImage, SparseGatherResultTypeNotTwoMembers1) {
4345   const std::string body = R"(
4346 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4347 %sampler = OpLoad %type_sampler %uniform_sampler
4348 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4349 %res1 = OpImageSparseGather %struct_u32 %simg %f32vec2_hh %u32_1
4350 )";
4351 
4352   CompileSuccessfully(GenerateShaderCode(body).c_str());
4353   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4354   EXPECT_THAT(getDiagnosticString(),
4355               HasSubstr("Expected Result Type to be a struct containing an int "
4356                         "scalar and a texel"));
4357 }
4358 
TEST_F(ValidateImage,SparseGatherResultTypeNotTwoMembers2)4359 TEST_F(ValidateImage, SparseGatherResultTypeNotTwoMembers2) {
4360   const std::string body = R"(
4361 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4362 %sampler = OpLoad %type_sampler %uniform_sampler
4363 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4364 %res1 = OpImageSparseGather %struct_u32_f32vec4_u32 %simg %f32vec2_hh %u32_1
4365 )";
4366 
4367   CompileSuccessfully(GenerateShaderCode(body).c_str());
4368   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4369   EXPECT_THAT(getDiagnosticString(),
4370               HasSubstr("Expected Result Type to be a struct containing an int "
4371                         "scalar and a texel"));
4372 }
4373 
TEST_F(ValidateImage,SparseGatherResultTypeFirstMemberNotInt)4374 TEST_F(ValidateImage, SparseGatherResultTypeFirstMemberNotInt) {
4375   const std::string body = R"(
4376 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4377 %sampler = OpLoad %type_sampler %uniform_sampler
4378 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4379 %res1 = OpImageSparseGather %struct_f32_f32vec4 %simg %f32vec2_hh %u32_1
4380 )";
4381 
4382   CompileSuccessfully(GenerateShaderCode(body).c_str());
4383   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4384   EXPECT_THAT(getDiagnosticString(),
4385               HasSubstr("Expected Result Type to be a struct containing an "
4386                         "int scalar and a texel"));
4387 }
4388 
TEST_F(ValidateImage,SparseGatherResultTypeTexelNotVector)4389 TEST_F(ValidateImage, SparseGatherResultTypeTexelNotVector) {
4390   const std::string body = R"(
4391 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4392 %sampler = OpLoad %type_sampler %uniform_sampler
4393 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4394 %res1 = OpImageSparseGather %struct_u32_u32 %simg %f32vec2_hh %u32_1
4395 )";
4396 
4397   CompileSuccessfully(GenerateShaderCode(body).c_str());
4398   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4399   EXPECT_THAT(getDiagnosticString(),
4400               HasSubstr("Expected Result Type's second member to be int or "
4401                         "float vector type"));
4402 }
4403 
TEST_F(ValidateImage,SparseGatherWrongNumComponentsTexel)4404 TEST_F(ValidateImage, SparseGatherWrongNumComponentsTexel) {
4405   const std::string body = R"(
4406 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4407 %sampler = OpLoad %type_sampler %uniform_sampler
4408 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4409 %res1 = OpImageSparseGather %struct_u32_f32vec3 %simg %f32vec2_hh %u32_1
4410 )";
4411 
4412   CompileSuccessfully(GenerateShaderCode(body).c_str());
4413   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4414   EXPECT_THAT(getDiagnosticString(),
4415               HasSubstr("Expected Result Type's second member to have 4 "
4416                         "components"));
4417 }
4418 
TEST_F(ValidateImage,SparseGatherWrongComponentTypeTexel)4419 TEST_F(ValidateImage, SparseGatherWrongComponentTypeTexel) {
4420   const std::string body = R"(
4421 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4422 %sampler = OpLoad %type_sampler %uniform_sampler
4423 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4424 %res1 = OpImageSparseGather %struct_u32_u32vec4 %simg %f32vec2_hh %u32_1
4425 )";
4426 
4427   CompileSuccessfully(GenerateShaderCode(body).c_str());
4428   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4429   EXPECT_THAT(getDiagnosticString(),
4430               HasSubstr("Expected Image 'Sampled Type' to be the same as "
4431                         "Result Type's second member components"));
4432 }
4433 
TEST_F(ValidateImage,SparseTexelsResidentSuccess)4434 TEST_F(ValidateImage, SparseTexelsResidentSuccess) {
4435   const std::string body = R"(
4436 %res1 = OpImageSparseTexelsResident %bool %u32_1
4437 )";
4438 
4439   CompileSuccessfully(GenerateShaderCode(body).c_str());
4440   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
4441 }
4442 
TEST_F(ValidateImage,SparseTexelsResidentResultTypeNotBool)4443 TEST_F(ValidateImage, SparseTexelsResidentResultTypeNotBool) {
4444   const std::string body = R"(
4445 %res1 = OpImageSparseTexelsResident %u32 %u32_1
4446 )";
4447 
4448   CompileSuccessfully(GenerateShaderCode(body).c_str());
4449   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4450   EXPECT_THAT(getDiagnosticString(),
4451               HasSubstr("Expected Result Type to be bool scalar type"));
4452 }
4453 
TEST_F(ValidateImage,MakeTexelVisibleKHRSuccessImageRead)4454 TEST_F(ValidateImage, MakeTexelVisibleKHRSuccessImageRead) {
4455   const std::string body = R"(
4456 %img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
4457 %res1 = OpImageRead %u32vec4 %img %u32vec2_01 MakeTexelVisibleKHR|NonPrivateTexelKHR %u32_2
4458 )";
4459 
4460   const std::string extra = R"(
4461 OpCapability StorageImageReadWithoutFormat
4462 OpCapability VulkanMemoryModelKHR
4463 OpExtension "SPV_KHR_vulkan_memory_model"
4464 )";
4465   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
4466                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
4467                           .c_str());
4468   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4469 }
4470 
TEST_F(ValidateImage,MakeTexelVisibleKHRSuccessImageSparseRead)4471 TEST_F(ValidateImage, MakeTexelVisibleKHRSuccessImageSparseRead) {
4472   const std::string body = R"(
4473 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
4474 %res1 = OpImageSparseRead %struct_u32_f32vec4 %img %u32vec2_01 MakeTexelVisibleKHR|NonPrivateTexelKHR %u32_2
4475 )";
4476 
4477   const std::string extra = R"(
4478 OpCapability StorageImageReadWithoutFormat
4479 OpCapability VulkanMemoryModelKHR
4480 OpExtension "SPV_KHR_vulkan_memory_model"
4481 )";
4482   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
4483                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
4484                           .c_str());
4485   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4486 }
4487 
TEST_F(ValidateImage,MakeTexelVisibleKHRFailureOpcode)4488 TEST_F(ValidateImage, MakeTexelVisibleKHRFailureOpcode) {
4489   const std::string body = R"(
4490 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4491 %sampler = OpLoad %type_sampler %uniform_sampler
4492 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4493 %res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh MakeTexelVisibleKHR|NonPrivateTexelKHR %u32_1
4494 )";
4495 
4496   const std::string extra = R"(
4497 OpCapability StorageImageReadWithoutFormat
4498 OpCapability VulkanMemoryModelKHR
4499 OpExtension "SPV_KHR_vulkan_memory_model"
4500 )";
4501   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
4502                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
4503                           .c_str());
4504   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
4505             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4506   EXPECT_THAT(
4507       getDiagnosticString(),
4508       HasSubstr("Image Operand MakeTexelVisibleKHR can only be used with "
4509                 "OpImageRead or OpImageSparseRead: OpImageSampleImplicitLod"));
4510 }
4511 
TEST_F(ValidateImage,MakeTexelVisibleKHRFailureMissingNonPrivate)4512 TEST_F(ValidateImage, MakeTexelVisibleKHRFailureMissingNonPrivate) {
4513   const std::string body = R"(
4514 %img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
4515 %res1 = OpImageRead %u32vec4 %img %u32vec2_01 MakeTexelVisibleKHR %u32_1
4516 )";
4517 
4518   const std::string extra = R"(
4519 OpCapability StorageImageReadWithoutFormat
4520 OpCapability VulkanMemoryModelKHR
4521 OpExtension "SPV_KHR_vulkan_memory_model"
4522 )";
4523   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
4524                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
4525                           .c_str());
4526   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
4527             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4528   EXPECT_THAT(getDiagnosticString(),
4529               HasSubstr("Image Operand MakeTexelVisibleKHR requires "
4530                         "NonPrivateTexelKHR is also specified: OpImageRead"));
4531 }
4532 
TEST_F(ValidateImage,MakeTexelAvailableKHRSuccessImageWrite)4533 TEST_F(ValidateImage, MakeTexelAvailableKHRSuccessImageWrite) {
4534   const std::string body = R"(
4535 %img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
4536 OpImageWrite %img %u32vec2_01 %u32vec4_0123 MakeTexelAvailableKHR|NonPrivateTexelKHR %u32_2
4537 )";
4538 
4539   const std::string extra = R"(
4540 OpCapability StorageImageWriteWithoutFormat
4541 OpCapability VulkanMemoryModelKHR
4542 OpExtension "SPV_KHR_vulkan_memory_model"
4543 )";
4544   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
4545                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
4546                           .c_str());
4547   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4548 }
4549 
TEST_F(ValidateImage,MakeTexelAvailableKHRFailureOpcode)4550 TEST_F(ValidateImage, MakeTexelAvailableKHRFailureOpcode) {
4551   const std::string body = R"(
4552 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4553 %sampler = OpLoad %type_sampler %uniform_sampler
4554 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4555 %res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh MakeTexelAvailableKHR|NonPrivateTexelKHR %u32_1
4556 )";
4557 
4558   const std::string extra = R"(
4559 OpCapability StorageImageReadWithoutFormat
4560 OpCapability VulkanMemoryModelKHR
4561 OpExtension "SPV_KHR_vulkan_memory_model"
4562 )";
4563   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
4564                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
4565                           .c_str());
4566   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
4567             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4568   EXPECT_THAT(getDiagnosticString(),
4569               HasSubstr("Image Operand MakeTexelAvailableKHR can only be used "
4570                         "with OpImageWrite: OpImageSampleImplicitLod"));
4571 }
4572 
TEST_F(ValidateImage,MakeTexelAvailableKHRFailureMissingNonPrivate)4573 TEST_F(ValidateImage, MakeTexelAvailableKHRFailureMissingNonPrivate) {
4574   const std::string body = R"(
4575 %img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
4576 OpImageWrite %img %u32vec2_01 %u32vec4_0123 MakeTexelAvailableKHR %u32_1
4577 )";
4578 
4579   const std::string extra = R"(
4580 OpCapability StorageImageWriteWithoutFormat
4581 OpCapability VulkanMemoryModelKHR
4582 OpExtension "SPV_KHR_vulkan_memory_model"
4583 )";
4584   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
4585                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
4586                           .c_str());
4587   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
4588             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4589   EXPECT_THAT(getDiagnosticString(),
4590               HasSubstr("Image Operand MakeTexelAvailableKHR requires "
4591                         "NonPrivateTexelKHR is also specified: OpImageWrite"));
4592 }
4593 
TEST_F(ValidateImage,VulkanMemoryModelDeviceScopeImageWriteBad)4594 TEST_F(ValidateImage, VulkanMemoryModelDeviceScopeImageWriteBad) {
4595   const std::string body = R"(
4596 %img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
4597 OpImageWrite %img %u32vec2_01 %u32vec4_0123 MakeTexelAvailableKHR|NonPrivateTexelKHR %u32_1
4598 )";
4599 
4600   const std::string extra = R"(
4601 OpCapability StorageImageWriteWithoutFormat
4602 OpCapability VulkanMemoryModelKHR
4603 OpExtension "SPV_KHR_vulkan_memory_model"
4604 )";
4605   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
4606                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
4607                           .c_str());
4608   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
4609             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4610   EXPECT_THAT(
4611       getDiagnosticString(),
4612       HasSubstr("Use of device scope with VulkanKHR memory model requires the "
4613                 "VulkanMemoryModelDeviceScopeKHR capability"));
4614 }
4615 
TEST_F(ValidateImage,VulkanMemoryModelDeviceScopeImageWriteGood)4616 TEST_F(ValidateImage, VulkanMemoryModelDeviceScopeImageWriteGood) {
4617   const std::string body = R"(
4618 %img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
4619 OpImageWrite %img %u32vec2_01 %u32vec4_0123 MakeTexelAvailableKHR|NonPrivateTexelKHR %u32_1
4620 )";
4621 
4622   const std::string extra = R"(
4623 OpCapability StorageImageWriteWithoutFormat
4624 OpCapability VulkanMemoryModelKHR
4625 OpCapability VulkanMemoryModelDeviceScopeKHR
4626 OpExtension "SPV_KHR_vulkan_memory_model"
4627 )";
4628   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
4629                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
4630                           .c_str());
4631   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4632 }
4633 
TEST_F(ValidateImage,VulkanMemoryModelDeviceScopeImageReadBad)4634 TEST_F(ValidateImage, VulkanMemoryModelDeviceScopeImageReadBad) {
4635   const std::string body = R"(
4636 %img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
4637 %res1 = OpImageRead %u32vec4 %img %u32vec2_01 MakeTexelVisibleKHR|NonPrivateTexelKHR %u32_1
4638 )";
4639 
4640   const std::string extra = R"(
4641 OpCapability StorageImageReadWithoutFormat
4642 OpCapability VulkanMemoryModelKHR
4643 OpExtension "SPV_KHR_vulkan_memory_model"
4644 )";
4645   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
4646                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
4647                           .c_str());
4648   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
4649             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4650   EXPECT_THAT(
4651       getDiagnosticString(),
4652       HasSubstr("Use of device scope with VulkanKHR memory model requires the "
4653                 "VulkanMemoryModelDeviceScopeKHR capability"));
4654 }
4655 
TEST_F(ValidateImage,VulkanMemoryModelDeviceScopeImageReadGood)4656 TEST_F(ValidateImage, VulkanMemoryModelDeviceScopeImageReadGood) {
4657   const std::string body = R"(
4658 %img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
4659 %res1 = OpImageRead %u32vec4 %img %u32vec2_01 MakeTexelVisibleKHR|NonPrivateTexelKHR %u32_1
4660 )";
4661 
4662   const std::string extra = R"(
4663 OpCapability StorageImageReadWithoutFormat
4664 OpCapability VulkanMemoryModelKHR
4665 OpCapability VulkanMemoryModelDeviceScopeKHR
4666 OpExtension "SPV_KHR_vulkan_memory_model"
4667 )";
4668   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
4669                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
4670                           .c_str());
4671   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4672 }
4673 
4674 // This example used to cause a seg fault on OpReturnValue, verifying it doesn't
4675 // anymore.
TEST_F(ValidateImage,Issue2463NoSegFault)4676 TEST_F(ValidateImage, Issue2463NoSegFault) {
4677   const std::string spirv = R"(
4678                OpCapability Linkage
4679                OpCapability Shader
4680           %1 = OpExtInstImport "GLSL.std.450"
4681                OpMemoryModel Logical GLSL450
4682        %void = OpTypeVoid
4683           %6 = OpTypeFunction %void
4684       %float = OpTypeFloat 32
4685           %8 = OpTypeImage %float 3D 0 0 0 1 Unknown
4686 %_ptr_UniformConstant_8 = OpTypePointer UniformConstant %8
4687          %10 = OpTypeSampler
4688 %_ptr_UniformConstant_10 = OpTypePointer UniformConstant %10
4689          %12 = OpTypeSampledImage %8
4690          %13 = OpTypeFunction %12 %_ptr_UniformConstant_8 %_ptr_UniformConstant_10
4691          %23 = OpFunction %12 None %13
4692          %24 = OpFunctionParameter %_ptr_UniformConstant_8
4693          %25 = OpFunctionParameter %_ptr_UniformConstant_10
4694          %26 = OpLabel
4695          %27 = OpLoad %8 %24
4696          %28 = OpLoad %10 %25
4697          %29 = OpSampledImage %12 %27 %28
4698                OpReturnValue %29
4699                OpFunctionEnd
4700 )";
4701 
4702   CompileSuccessfully(spirv);
4703   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4704   EXPECT_THAT(getDiagnosticString(),
4705               HasSubstr("OpSampledImage instruction must not appear as operand "
4706                         "for OpReturnValue"));
4707 }
4708 
TEST_F(ValidateImage,SignExtendV13Bad)4709 TEST_F(ValidateImage, SignExtendV13Bad) {
4710   const std::string body = R"(
4711 %img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
4712 %res1 = OpImageRead %u32vec4 %img %u32vec2_01 SignExtend
4713 )";
4714 
4715   EXPECT_THAT(CompileFailure(GenerateShaderCode(body, "", "Fragment", "",
4716                                                 SPV_ENV_UNIVERSAL_1_3)),
4717               HasSubstr("Invalid image operand 'SignExtend'"));
4718 }
4719 
TEST_F(ValidateImage,ZeroExtendV13Bad)4720 TEST_F(ValidateImage, ZeroExtendV13Bad) {
4721   const std::string body = R"(
4722 %img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
4723 %res1 = OpImageRead %u32vec4 %img %u32vec2_01 ZeroExtend
4724 )";
4725 
4726   EXPECT_THAT(CompileFailure(GenerateShaderCode(body, "", "Fragment", "",
4727                                                 SPV_ENV_UNIVERSAL_1_3)),
4728               HasSubstr("Invalid image operand 'ZeroExtend'"));
4729 }
4730 
TEST_F(ValidateImage,SignExtendScalarUIntTexelV14Good)4731 TEST_F(ValidateImage, SignExtendScalarUIntTexelV14Good) {
4732   // Unsigned int sampled type
4733   const std::string body = R"(
4734 %img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
4735 %res1 = OpImageRead %u32 %img %u32vec2_01 SignExtend
4736 )";
4737   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
4738 
4739   CompileSuccessfully(
4740       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4),
4741       SPV_ENV_UNIVERSAL_1_4);
4742   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
4743   EXPECT_THAT(getDiagnosticString(), Eq(""));
4744 }
4745 
TEST_F(ValidateImage,SignExtendScalarSIntTexelV14Good)4746 TEST_F(ValidateImage, SignExtendScalarSIntTexelV14Good) {
4747   // Signed int sampled type
4748   const std::string body = R"(
4749 %img = OpLoad %type_image_s32_2d_0002 %uniform_image_s32_2d_0002
4750 %res1 = OpImageRead %s32 %img %u32vec2_01 SignExtend
4751 )";
4752   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
4753 
4754   CompileSuccessfully(
4755       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4),
4756       SPV_ENV_UNIVERSAL_1_4);
4757   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
4758   EXPECT_THAT(getDiagnosticString(), Eq(""));
4759 }
4760 
TEST_F(ValidateImage,SignExtendScalarVectorUIntTexelV14Good)4761 TEST_F(ValidateImage, SignExtendScalarVectorUIntTexelV14Good) {
4762   const std::string body = R"(
4763 %img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
4764 %res1 = OpImageRead %u32vec4 %img %u32vec2_01 SignExtend
4765 )";
4766   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
4767 
4768   CompileSuccessfully(
4769       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4),
4770       SPV_ENV_UNIVERSAL_1_4);
4771   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
4772   EXPECT_THAT(getDiagnosticString(), Eq(""));
4773 }
4774 
TEST_F(ValidateImage,SignExtendVectorSIntTexelV14Good)4775 TEST_F(ValidateImage, SignExtendVectorSIntTexelV14Good) {
4776   const std::string body = R"(
4777 %img = OpLoad %type_image_s32_2d_0002 %uniform_image_s32_2d_0002
4778 %res1 = OpImageRead %s32vec4 %img %u32vec2_01 SignExtend
4779 )";
4780   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
4781 
4782   CompileSuccessfully(
4783       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4),
4784       SPV_ENV_UNIVERSAL_1_4);
4785   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
4786   EXPECT_THAT(getDiagnosticString(), Eq(""));
4787 }
4788 
4789 // No negative tests for SignExtend since we don't truly know the
4790 // texel format.
4791 
TEST_F(ValidateImage,ZeroExtendScalarUIntTexelV14Good)4792 TEST_F(ValidateImage, ZeroExtendScalarUIntTexelV14Good) {
4793   // Unsigned int sampled type
4794   const std::string body = R"(
4795 %img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
4796 %res1 = OpImageRead %u32 %img %u32vec2_01 ZeroExtend
4797 )";
4798   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
4799 
4800   CompileSuccessfully(
4801       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4),
4802       SPV_ENV_UNIVERSAL_1_4);
4803   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
4804   EXPECT_THAT(getDiagnosticString(), Eq(""));
4805 }
4806 
TEST_F(ValidateImage,ZeroExtendScalarSIntTexelV14Good)4807 TEST_F(ValidateImage, ZeroExtendScalarSIntTexelV14Good) {
4808   // Zeroed int sampled type
4809   const std::string body = R"(
4810 %img = OpLoad %type_image_s32_2d_0002 %uniform_image_s32_2d_0002
4811 %res1 = OpImageRead %s32 %img %u32vec2_01 ZeroExtend
4812 )";
4813   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
4814 
4815   CompileSuccessfully(
4816       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4),
4817       SPV_ENV_UNIVERSAL_1_4);
4818   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
4819   EXPECT_THAT(getDiagnosticString(), Eq(""));
4820 }
4821 
TEST_F(ValidateImage,ZeroExtendScalarVectorUIntTexelV14Good)4822 TEST_F(ValidateImage, ZeroExtendScalarVectorUIntTexelV14Good) {
4823   const std::string body = R"(
4824 %img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
4825 %res1 = OpImageRead %u32vec4 %img %u32vec2_01 ZeroExtend
4826 )";
4827   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
4828 
4829   CompileSuccessfully(
4830       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4),
4831       SPV_ENV_UNIVERSAL_1_4);
4832   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
4833   EXPECT_THAT(getDiagnosticString(), Eq(""));
4834 }
4835 
TEST_F(ValidateImage,ZeroExtendVectorSIntTexelV14Good)4836 TEST_F(ValidateImage, ZeroExtendVectorSIntTexelV14Good) {
4837   const std::string body = R"(
4838 %img = OpLoad %type_image_s32_2d_0002 %uniform_image_s32_2d_0002
4839 %res1 = OpImageRead %s32vec4 %img %u32vec2_01 ZeroExtend
4840 )";
4841   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
4842 
4843   CompileSuccessfully(
4844       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4),
4845       SPV_ENV_UNIVERSAL_1_4);
4846   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
4847   EXPECT_THAT(getDiagnosticString(), Eq(""));
4848 }
4849 
TEST_F(ValidateImage,ReadLodAMDSuccess1)4850 TEST_F(ValidateImage, ReadLodAMDSuccess1) {
4851   const std::string body = R"(
4852 %img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
4853 %res1 = OpImageRead %u32vec4 %img %u32vec2_01 Lod %u32_0
4854 )";
4855 
4856   const std::string extra =
4857       "\nOpCapability StorageImageReadWithoutFormat\n"
4858       "OpCapability ImageReadWriteLodAMD\n"
4859       "OpExtension \"SPV_AMD_shader_image_load_store_lod\"\n";
4860   CompileSuccessfully(
4861       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_1),
4862       SPV_ENV_UNIVERSAL_1_1);
4863   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
4864 }
4865 
TEST_F(ValidateImage,ReadLodAMDSuccess2)4866 TEST_F(ValidateImage, ReadLodAMDSuccess2) {
4867   const std::string body = R"(
4868 %img = OpLoad %type_image_f32_1d_0002_rgba32f %uniform_image_f32_1d_0002_rgba32f
4869 %res1 = OpImageRead %f32vec4 %img %u32vec2_01 Lod %u32_0
4870 )";
4871 
4872   const std::string extra =
4873       "\nOpCapability Image1D\n"
4874       "OpCapability ImageReadWriteLodAMD\n"
4875       "OpExtension \"SPV_AMD_shader_image_load_store_lod\"\n";
4876   CompileSuccessfully(
4877       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_1),
4878       SPV_ENV_UNIVERSAL_1_1);
4879   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
4880 }
4881 
TEST_F(ValidateImage,ReadLodAMDSuccess3)4882 TEST_F(ValidateImage, ReadLodAMDSuccess3) {
4883   const std::string body = R"(
4884 %img = OpLoad %type_image_f32_cube_0102_rgba32f %uniform_image_f32_cube_0102_rgba32f
4885 %res1 = OpImageRead %f32vec4 %img %u32vec3_012 Lod %u32_0
4886 )";
4887 
4888   const std::string extra =
4889       "\nOpCapability ImageCubeArray\n"
4890       "OpCapability ImageReadWriteLodAMD\n"
4891       "OpExtension \"SPV_AMD_shader_image_load_store_lod\"\n";
4892   CompileSuccessfully(
4893       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_1),
4894       SPV_ENV_UNIVERSAL_1_1);
4895   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
4896 }
4897 
TEST_F(ValidateImage,ReadLodAMDNeedCapability)4898 TEST_F(ValidateImage, ReadLodAMDNeedCapability) {
4899   const std::string body = R"(
4900 %img = OpLoad %type_image_f32_cube_0102_rgba32f %uniform_image_f32_cube_0102_rgba32f
4901 %res1 = OpImageRead %f32vec4 %img %u32vec3_012 Lod %u32_0
4902 )";
4903 
4904   const std::string extra = "\nOpCapability ImageCubeArray\n";
4905   CompileSuccessfully(
4906       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_1),
4907       SPV_ENV_UNIVERSAL_1_1);
4908   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
4909             ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
4910   EXPECT_THAT(getDiagnosticString(),
4911               HasSubstr("Image Operand Lod can only be used with ExplicitLod "
4912                         "opcodes and OpImageFetch"));
4913 }
4914 
TEST_F(ValidateImage,WriteLodAMDSuccess1)4915 TEST_F(ValidateImage, WriteLodAMDSuccess1) {
4916   const std::string body = R"(
4917 %img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
4918 OpImageWrite %img %u32vec2_01 %u32vec4_0123 Lod %u32_0
4919 )";
4920 
4921   const std::string extra =
4922       "\nOpCapability StorageImageWriteWithoutFormat\n"
4923       "OpCapability ImageReadWriteLodAMD\n"
4924       "OpExtension \"SPV_AMD_shader_image_load_store_lod\"\n";
4925   CompileSuccessfully(
4926       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_1),
4927       SPV_ENV_UNIVERSAL_1_1);
4928   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
4929 }
4930 
TEST_F(ValidateImage,WriteLodAMDSuccess2)4931 TEST_F(ValidateImage, WriteLodAMDSuccess2) {
4932   const std::string body = R"(
4933 %img = OpLoad %type_image_f32_1d_0002_rgba32f %uniform_image_f32_1d_0002_rgba32f
4934 OpImageWrite %img %u32_1 %f32vec4_0000 Lod %u32_0
4935 )";
4936 
4937   const std::string extra =
4938       "\nOpCapability Image1D\n"
4939       "OpCapability ImageReadWriteLodAMD\n"
4940       "OpExtension \"SPV_AMD_shader_image_load_store_lod\"\n";
4941   CompileSuccessfully(
4942       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_1),
4943       SPV_ENV_UNIVERSAL_1_1);
4944   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
4945 }
4946 
TEST_F(ValidateImage,WriteLodAMDSuccess3)4947 TEST_F(ValidateImage, WriteLodAMDSuccess3) {
4948   const std::string body = R"(
4949 %img = OpLoad %type_image_f32_cube_0102_rgba32f %uniform_image_f32_cube_0102_rgba32f
4950 OpImageWrite %img %u32vec3_012 %f32vec4_0000 Lod %u32_0
4951 )";
4952 
4953   const std::string extra =
4954       "\nOpCapability ImageCubeArray\n"
4955       "OpCapability ImageReadWriteLodAMD\n"
4956       "OpExtension \"SPV_AMD_shader_image_load_store_lod\"\n";
4957   CompileSuccessfully(
4958       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_1),
4959       SPV_ENV_UNIVERSAL_1_1);
4960   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
4961 }
4962 
TEST_F(ValidateImage,WriteLodAMDNeedCapability)4963 TEST_F(ValidateImage, WriteLodAMDNeedCapability) {
4964   const std::string body = R"(
4965 %img = OpLoad %type_image_f32_cube_0102_rgba32f %uniform_image_f32_cube_0102_rgba32f
4966 OpImageWrite %img %u32vec3_012 %f32vec4_0000 Lod %u32_0
4967 )";
4968 
4969   const std::string extra = "\nOpCapability ImageCubeArray\n";
4970   CompileSuccessfully(
4971       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_1),
4972       SPV_ENV_UNIVERSAL_1_1);
4973   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
4974             ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
4975   EXPECT_THAT(getDiagnosticString(),
4976               HasSubstr("Image Operand Lod can only be used with ExplicitLod "
4977                         "opcodes and OpImageFetch"));
4978 }
4979 
TEST_F(ValidateImage,SparseReadLodAMDSuccess)4980 TEST_F(ValidateImage, SparseReadLodAMDSuccess) {
4981   const std::string body = R"(
4982 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
4983 %res1 = OpImageSparseRead %struct_u32_f32vec4 %img %u32vec2_01 Lod %u32_0
4984 )";
4985 
4986   const std::string extra =
4987       "\nOpCapability StorageImageReadWithoutFormat\n"
4988       "OpCapability ImageReadWriteLodAMD\n"
4989       "OpExtension \"SPV_AMD_shader_image_load_store_lod\"\n";
4990   CompileSuccessfully(
4991       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_1),
4992       SPV_ENV_UNIVERSAL_1_1);
4993   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
4994 }
4995 
TEST_F(ValidateImage,SparseReadLodAMDNeedCapability)4996 TEST_F(ValidateImage, SparseReadLodAMDNeedCapability) {
4997   const std::string body = R"(
4998 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
4999 %res1 = OpImageSparseRead %struct_u32_f32vec4 %img %u32vec2_01 Lod %u32_0
5000 )";
5001 
5002   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
5003   CompileSuccessfully(
5004       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_1),
5005       SPV_ENV_UNIVERSAL_1_1);
5006   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
5007             ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
5008   EXPECT_THAT(getDiagnosticString(),
5009               HasSubstr("Image Operand Lod can only be used with ExplicitLod "
5010                         "opcodes and OpImageFetch"));
5011 }
5012 
TEST_F(ValidateImage,GatherBiasAMDSuccess)5013 TEST_F(ValidateImage, GatherBiasAMDSuccess) {
5014   const std::string body = R"(
5015 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5016 %sampler = OpLoad %type_sampler %uniform_sampler
5017 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5018 %res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 Bias %f32_1
5019 )";
5020 
5021   const std::string extra = R"(
5022 OpCapability ImageGatherBiasLodAMD
5023 OpExtension "SPV_AMD_texture_gather_bias_lod"
5024 )";
5025   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
5026   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
5027 }
5028 
TEST_F(ValidateImage,GatherLodAMDSuccess)5029 TEST_F(ValidateImage, GatherLodAMDSuccess) {
5030   const std::string body = R"(
5031 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5032 %sampler = OpLoad %type_sampler %uniform_sampler
5033 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5034 %res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 Lod %f32_1
5035 )";
5036 
5037   const std::string extra = R"(
5038 OpCapability ImageGatherBiasLodAMD
5039 OpExtension "SPV_AMD_texture_gather_bias_lod"
5040 )";
5041   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
5042   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
5043 }
5044 
TEST_F(ValidateImage,SparseGatherBiasAMDSuccess)5045 TEST_F(ValidateImage, SparseGatherBiasAMDSuccess) {
5046   const std::string body = R"(
5047 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5048 %sampler = OpLoad %type_sampler %uniform_sampler
5049 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5050 %res1 = OpImageSparseGather %struct_u32_f32vec4 %simg %f32vec4_0000 %u32_1 Bias %f32_1
5051 )";
5052 
5053   const std::string extra = R"(
5054 OpCapability ImageGatherBiasLodAMD
5055 OpExtension "SPV_AMD_texture_gather_bias_lod"
5056 )";
5057   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
5058   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
5059 }
5060 
TEST_F(ValidateImage,SparseGatherLodAMDSuccess)5061 TEST_F(ValidateImage, SparseGatherLodAMDSuccess) {
5062   const std::string body = R"(
5063 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5064 %sampler = OpLoad %type_sampler %uniform_sampler
5065 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5066 %res1 = OpImageSparseGather %struct_u32_f32vec4 %simg %f32vec4_0000 %u32_1 Lod %f32_1
5067 )";
5068 
5069   const std::string extra = R"(
5070 OpCapability ImageGatherBiasLodAMD
5071 OpExtension "SPV_AMD_texture_gather_bias_lod"
5072 )";
5073   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
5074   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
5075 }
5076 
5077 // No negative tests for ZeroExtend since we don't truly know the
5078 // texel format.
5079 
5080 // Tests for 64-bit images
5081 static const std::string capabilities_and_extensions_image64 = R"(
5082 OpCapability Int64ImageEXT
5083 OpExtension "SPV_EXT_shader_image_int64"
5084 )";
5085 static const std::string declarations_image64 = R"(
5086 %type_image_u64_buffer_0002_r64ui = OpTypeImage %u64 Buffer 0 0 0 2 R64ui
5087 %ptr_Image_u64 = OpTypePointer Image %u64
5088 %ptr_image_u64_buffer_0002_r64ui = OpTypePointer Private %type_image_u64_buffer_0002_r64ui
5089 %private_image_u64_buffer_0002_r64ui = OpVariable %ptr_image_u64_buffer_0002_r64ui Private
5090 )";
5091 
TEST_F(ValidateImage,Image64MissingCapability)5092 TEST_F(ValidateImage, Image64MissingCapability) {
5093   CompileSuccessfully(GenerateShaderCode("", "", "Fragment", "",
5094                                          SPV_ENV_UNIVERSAL_1_3, "GLSL450",
5095                                          declarations_image64)
5096                           .c_str());
5097   ASSERT_EQ(SPV_ERROR_INVALID_CAPABILITY, ValidateInstructions());
5098 }
5099 
TEST_F(ValidateImage,Image64MissingExtension)5100 TEST_F(ValidateImage, Image64MissingExtension) {
5101   const std::string extra = R"(
5102 OpCapability Int64ImageEXT
5103 )";
5104 
5105   CompileSuccessfully(GenerateShaderCode("", extra, "Fragment", "",
5106                                          SPV_ENV_UNIVERSAL_1_3, "GLSL450",
5107                                          declarations_image64)
5108                           .c_str());
5109   ASSERT_EQ(SPV_ERROR_MISSING_EXTENSION, ValidateInstructions());
5110 }
5111 
TEST_F(ValidateImage,ImageTexelPointer64Success)5112 TEST_F(ValidateImage, ImageTexelPointer64Success) {
5113   const std::string body = R"(
5114 %texel_ptr = OpImageTexelPointer %ptr_Image_u64 %private_image_u64_buffer_0002_r64ui %u32_0 %u32_0
5115 %sum = OpAtomicIAdd %u64 %texel_ptr %u32_1 %u32_0 %u64_1
5116 )";
5117 
5118   CompileSuccessfully(GenerateShaderCode(body,
5119                                          capabilities_and_extensions_image64,
5120                                          "Fragment", "", SPV_ENV_UNIVERSAL_1_3,
5121                                          "GLSL450", declarations_image64)
5122                           .c_str());
5123   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
5124 }
5125 
TEST_F(ValidateImage,ImageTexelPointer64ResultTypeNotPointer)5126 TEST_F(ValidateImage, ImageTexelPointer64ResultTypeNotPointer) {
5127   const std::string body = R"(
5128 %texel_ptr = OpImageTexelPointer %type_image_u64_buffer_0002_r64ui %private_image_u64_buffer_0002_r64ui %u32_0 %u32_0
5129 %sum = OpAtomicIAdd %u64 %texel_ptr %u32_1 %u32_0 %u64_1
5130 )";
5131 
5132   CompileSuccessfully(GenerateShaderCode(body,
5133                                          capabilities_and_extensions_image64,
5134                                          "Fragment", "", SPV_ENV_UNIVERSAL_1_3,
5135                                          "GLSL450", declarations_image64)
5136                           .c_str());
5137   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5138   EXPECT_THAT(getDiagnosticString(),
5139               HasSubstr("Expected Result Type to be OpTypePointer"));
5140 }
5141 
TEST_F(ValidateImage,ImageTexelPointer64ResultTypeNotImageClass)5142 TEST_F(ValidateImage, ImageTexelPointer64ResultTypeNotImageClass) {
5143   const std::string body = R"(
5144 %texel_ptr = OpImageTexelPointer %ptr_image_f32_cube_0101 %private_image_u64_buffer_0002_r64ui %u32_0 %u32_0
5145 %sum = OpAtomicIAdd %u64 %texel_ptr %u32_1 %u32_0 %u64_1
5146 )";
5147 
5148   CompileSuccessfully(GenerateShaderCode(body,
5149                                          capabilities_and_extensions_image64,
5150                                          "Fragment", "", SPV_ENV_UNIVERSAL_1_3,
5151                                          "GLSL450", declarations_image64)
5152                           .c_str());
5153   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5154   EXPECT_THAT(getDiagnosticString(),
5155               HasSubstr("Expected Result Type to be OpTypePointer whose "
5156                         "Storage Class operand is Image"));
5157 }
5158 
TEST_F(ValidateImage,ImageTexelPointer64SampleNotZeroForImageWithMSZero)5159 TEST_F(ValidateImage, ImageTexelPointer64SampleNotZeroForImageWithMSZero) {
5160   const std::string body = R"(
5161 %texel_ptr = OpImageTexelPointer %ptr_Image_u64 %private_image_u64_buffer_0002_r64ui %u32_0 %u32_1
5162 %sum = OpAtomicIAdd %u64 %texel_ptr %u32_1 %u32_0 %u64_1
5163 )";
5164 
5165   CompileSuccessfully(GenerateShaderCode(body,
5166                                          capabilities_and_extensions_image64,
5167                                          "Fragment", "", SPV_ENV_UNIVERSAL_1_3,
5168                                          "GLSL450", declarations_image64)
5169                           .c_str());
5170   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5171   EXPECT_THAT(getDiagnosticString(),
5172               HasSubstr("Expected Sample for Image with MS 0 to be a valid "
5173                         "<id> for the value 0"));
5174 }
5175 
5176 }  // namespace
5177 }  // namespace val
5178 }  // namespace spvtools
5179