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