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