• 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,SampleImplicitLodVulkanOffsetWrongBeforeLegalization)1794 TEST_F(ValidateImage, SampleImplicitLodVulkanOffsetWrongBeforeLegalization) {
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 Offset %s32vec2_01
1800 )";
1801 
1802   CompileSuccessfully(
1803       GenerateShaderCode(body, "", "Fragment", "", SPV_ENV_VULKAN_1_0).c_str());
1804   getValidatorOptions()->before_hlsl_legalization = true;
1805   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1806 }
1807 
TEST_F(ValidateImage,SampleImplicitLodMoreThanOneOffset)1808 TEST_F(ValidateImage, SampleImplicitLodMoreThanOneOffset) {
1809   const std::string body = R"(
1810 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1811 %sampler = OpLoad %type_sampler %uniform_sampler
1812 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1813 %res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 ConstOffset|Offset %s32vec2_01 %s32vec2_01
1814 )";
1815 
1816   CompileSuccessfully(GenerateShaderCode(body).c_str());
1817   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1818   EXPECT_THAT(
1819       getDiagnosticString(),
1820       HasSubstr("Image Operands Offset, ConstOffset, ConstOffsets, Offsets "
1821                 "cannot be used together"));
1822 }
1823 
TEST_F(ValidateImage,SampleImplicitLodVulkanMoreThanOneOffset)1824 TEST_F(ValidateImage, SampleImplicitLodVulkanMoreThanOneOffset) {
1825   const std::string body = R"(
1826 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1827 %sampler = OpLoad %type_sampler %uniform_sampler
1828 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1829 %res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 ConstOffset|Offset %s32vec2_01 %s32vec2_01
1830 )";
1831 
1832   CompileSuccessfully(
1833       GenerateShaderCode(body, "", "Fragment", "", SPV_ENV_VULKAN_1_0).c_str());
1834   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1835   EXPECT_THAT(getDiagnosticString(),
1836               AnyVUID("VUID-StandaloneSpirv-Offset-04662"));
1837   EXPECT_THAT(
1838       getDiagnosticString(),
1839       HasSubstr("Image Operands Offset, ConstOffset, ConstOffsets, Offsets "
1840                 "cannot be used together"));
1841 }
1842 
TEST_F(ValidateImage,SampleImplicitLodMinLodWrongType)1843 TEST_F(ValidateImage, SampleImplicitLodMinLodWrongType) {
1844   const std::string body = R"(
1845 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
1846 %sampler = OpLoad %type_sampler %uniform_sampler
1847 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
1848 %res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 MinLod %s32_0
1849 )";
1850 
1851   CompileSuccessfully(GenerateShaderCode(body).c_str());
1852   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1853   EXPECT_THAT(getDiagnosticString(),
1854               HasSubstr("Expected Image Operand MinLod to be float scalar"));
1855 }
1856 
TEST_F(ValidateImage,SampleImplicitLodMinLodWrongDim)1857 TEST_F(ValidateImage, SampleImplicitLodMinLodWrongDim) {
1858   const std::string body = R"(
1859 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
1860 %sampler = OpLoad %type_sampler %uniform_sampler
1861 %simg = OpSampledImage %type_sampled_image_f32_rect_0001 %img %sampler
1862 %res2 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh MinLod %f32_0_25
1863 )";
1864 
1865   CompileSuccessfully(GenerateShaderCode(body).c_str());
1866   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1867   EXPECT_THAT(getDiagnosticString(),
1868               HasSubstr("Image Operand MinLod requires 'Dim' parameter to be "
1869                         "1D, 2D, 3D or Cube"));
1870 }
1871 
TEST_F(ValidateImage,SampleProjExplicitLodSuccess2D)1872 TEST_F(ValidateImage, SampleProjExplicitLodSuccess2D) {
1873   const std::string body = R"(
1874 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1875 %sampler = OpLoad %type_sampler %uniform_sampler
1876 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1877 %res1 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec3_hhh Lod %f32_1
1878 %res3 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec3_hhh Grad %f32vec2_10 %f32vec2_01
1879 %res4 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec3_hhh ConstOffset %s32vec2_01
1880 %res5 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec3_hhh Offset %s32vec2_01
1881 %res7 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec3_hhh Grad|Offset %f32vec2_10 %f32vec2_01 %s32vec2_01
1882 %res8 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec3_hhh Lod|NonPrivateTexelKHR %f32_1
1883 )";
1884 
1885   const std::string extra = R"(
1886 OpCapability VulkanMemoryModelKHR
1887 OpExtension "SPV_KHR_vulkan_memory_model"
1888 )";
1889   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
1890                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
1891                           .c_str());
1892   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1893 }
1894 
TEST_F(ValidateImage,SampleProjExplicitLodSuccessRect)1895 TEST_F(ValidateImage, SampleProjExplicitLodSuccessRect) {
1896   const std::string body = R"(
1897 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
1898 %sampler = OpLoad %type_sampler %uniform_sampler
1899 %simg = OpSampledImage %type_sampled_image_f32_rect_0001 %img %sampler
1900 %res1 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec3_hhh Grad %f32vec2_10 %f32vec2_01
1901 %res2 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec3_hhh Grad|Offset %f32vec2_10 %f32vec2_01 %s32vec2_01
1902 )";
1903 
1904   CompileSuccessfully(GenerateShaderCode(body).c_str());
1905   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1906 }
1907 
TEST_F(ValidateImage,SampleProjExplicitLodWrongResultType)1908 TEST_F(ValidateImage, SampleProjExplicitLodWrongResultType) {
1909   const std::string body = R"(
1910 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1911 %sampler = OpLoad %type_sampler %uniform_sampler
1912 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1913 %res1 = OpImageSampleProjExplicitLod %f32 %simg %f32vec3_hhh Lod %f32_1
1914 )";
1915 
1916   CompileSuccessfully(GenerateShaderCode(body).c_str());
1917   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1918   EXPECT_THAT(getDiagnosticString(),
1919               HasSubstr("Expected Result Type to be int or float vector type"));
1920 }
1921 
TEST_F(ValidateImage,SampleProjExplicitLodWrongNumComponentsResultType)1922 TEST_F(ValidateImage, SampleProjExplicitLodWrongNumComponentsResultType) {
1923   const std::string body = R"(
1924 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1925 %sampler = OpLoad %type_sampler %uniform_sampler
1926 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1927 %res1 = OpImageSampleProjExplicitLod %f32vec3 %simg %f32vec3_hhh Lod %f32_1
1928 )";
1929 
1930   CompileSuccessfully(GenerateShaderCode(body).c_str());
1931   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1932   EXPECT_THAT(getDiagnosticString(),
1933               HasSubstr("Expected Result Type to have 4 components"));
1934 }
1935 
TEST_F(ValidateImage,SampleProjExplicitLodNotSampledImage)1936 TEST_F(ValidateImage, SampleProjExplicitLodNotSampledImage) {
1937   const std::string body = R"(
1938 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1939 %res1 = OpImageSampleProjExplicitLod %f32vec4 %img %f32vec3_hhh Lod %f32_1
1940 )";
1941 
1942   CompileSuccessfully(GenerateShaderCode(body).c_str());
1943   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1944   EXPECT_THAT(
1945       getDiagnosticString(),
1946       HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage"));
1947 }
1948 
TEST_F(ValidateImage,SampleProjExplicitLodMultisampleError)1949 TEST_F(ValidateImage, SampleProjExplicitLodMultisampleError) {
1950   const std::string body = R"(
1951 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
1952 %sampler = OpLoad %type_sampler %uniform_sampler
1953 %simg = OpSampledImage %type_sampled_image_f32_2d_0011 %img %sampler
1954 %res1 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec2_hh Lod|Sample %f32_1 %u32_1
1955 )";
1956 
1957   CompileSuccessfully(GenerateShaderCode(body).c_str());
1958   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1959   EXPECT_THAT(getDiagnosticString(),
1960               HasSubstr("Expected Image 'MS' parameter to be 0"));
1961 }
1962 
TEST_F(ValidateImage,SampleProjExplicitLodWrongSampledType)1963 TEST_F(ValidateImage, SampleProjExplicitLodWrongSampledType) {
1964   const std::string body = R"(
1965 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1966 %sampler = OpLoad %type_sampler %uniform_sampler
1967 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1968 %res1 = OpImageSampleProjExplicitLod %u32vec4 %simg %f32vec3_hhh Lod %f32_1
1969 )";
1970 
1971   CompileSuccessfully(GenerateShaderCode(body).c_str());
1972   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1973   EXPECT_THAT(getDiagnosticString(),
1974               HasSubstr("Expected Image 'Sampled Type' to be the same as "
1975                         "Result Type components"));
1976 }
1977 
TEST_F(ValidateImage,SampleProjExplicitLodVoidSampledType)1978 TEST_F(ValidateImage, SampleProjExplicitLodVoidSampledType) {
1979   const std::string body = R"(
1980 %img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001
1981 %sampler = OpLoad %type_sampler %uniform_sampler
1982 %simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler
1983 %res1 = OpImageSampleProjExplicitLod %u32vec4 %simg %f32vec3_hhh Lod %f32_1
1984 )";
1985 
1986   CompileSuccessfully(GenerateShaderCode(body).c_str());
1987   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1988 }
1989 
TEST_F(ValidateImage,SampleProjExplicitLodWrongCoordinateType)1990 TEST_F(ValidateImage, SampleProjExplicitLodWrongCoordinateType) {
1991   const std::string body = R"(
1992 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1993 %sampler = OpLoad %type_sampler %uniform_sampler
1994 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1995 %res1 = OpImageSampleProjExplicitLod %f32vec4 %simg %img Lod %f32_1
1996 )";
1997 
1998   CompileSuccessfully(GenerateShaderCode(body).c_str());
1999   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2000   EXPECT_THAT(getDiagnosticString(),
2001               HasSubstr("Expected Coordinate to be float scalar or vector"));
2002 }
2003 
TEST_F(ValidateImage,SampleProjExplicitLodCoordinateSizeTooSmall)2004 TEST_F(ValidateImage, SampleProjExplicitLodCoordinateSizeTooSmall) {
2005   const std::string body = R"(
2006 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2007 %sampler = OpLoad %type_sampler %uniform_sampler
2008 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2009 %res1 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec2_hh Lod %f32_1
2010 )";
2011 
2012   CompileSuccessfully(GenerateShaderCode(body).c_str());
2013   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2014   EXPECT_THAT(getDiagnosticString(),
2015               HasSubstr("Expected Coordinate to have at least 3 components, "
2016                         "but given only 2"));
2017 }
2018 
TEST_F(ValidateImage,SampleProjImplicitLodSuccess)2019 TEST_F(ValidateImage, SampleProjImplicitLodSuccess) {
2020   const std::string body = R"(
2021 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2022 %sampler = OpLoad %type_sampler %uniform_sampler
2023 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2024 %res1 = OpImageSampleProjImplicitLod %f32vec4 %simg %f32vec3_hhh
2025 %res2 = OpImageSampleProjImplicitLod %f32vec4 %simg %f32vec3_hhh Bias %f32_0_25
2026 %res4 = OpImageSampleProjImplicitLod %f32vec4 %simg %f32vec3_hhh ConstOffset %s32vec2_01
2027 %res5 = OpImageSampleProjImplicitLod %f32vec4 %simg %f32vec3_hhh Offset %s32vec2_01
2028 %res6 = OpImageSampleProjImplicitLod %f32vec4 %simg %f32vec3_hhh MinLod %f32_0_5
2029 %res7 = OpImageSampleProjImplicitLod %f32vec4 %simg %f32vec3_hhh Bias|Offset|MinLod %f32_0_25 %s32vec2_01 %f32_0_5
2030 %res8 = OpImageSampleProjImplicitLod %f32vec4 %simg %f32vec3_hhh NonPrivateTexelKHR
2031 )";
2032 
2033   const std::string extra = R"(
2034 OpCapability VulkanMemoryModelKHR
2035 OpExtension "SPV_KHR_vulkan_memory_model"
2036 )";
2037   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
2038                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
2039                           .c_str());
2040   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2041 }
2042 
TEST_F(ValidateImage,SampleProjImplicitLodWrongResultType)2043 TEST_F(ValidateImage, SampleProjImplicitLodWrongResultType) {
2044   const std::string body = R"(
2045 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2046 %sampler = OpLoad %type_sampler %uniform_sampler
2047 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2048 %res1 = OpImageSampleProjImplicitLod %f32 %simg %f32vec3_hhh
2049 )";
2050 
2051   CompileSuccessfully(GenerateShaderCode(body).c_str());
2052   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2053   EXPECT_THAT(getDiagnosticString(),
2054               HasSubstr("Expected Result Type to be int or float vector type"));
2055 }
2056 
TEST_F(ValidateImage,SampleProjImplicitLodWrongNumComponentsResultType)2057 TEST_F(ValidateImage, SampleProjImplicitLodWrongNumComponentsResultType) {
2058   const std::string body = R"(
2059 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2060 %sampler = OpLoad %type_sampler %uniform_sampler
2061 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2062 %res1 = OpImageSampleProjImplicitLod %f32vec3 %simg %f32vec3_hhh
2063 )";
2064 
2065   CompileSuccessfully(GenerateShaderCode(body).c_str());
2066   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2067   EXPECT_THAT(getDiagnosticString(),
2068               HasSubstr("Expected Result Type to have 4 components"));
2069 }
2070 
TEST_F(ValidateImage,SampleProjImplicitLodNotSampledImage)2071 TEST_F(ValidateImage, SampleProjImplicitLodNotSampledImage) {
2072   const std::string body = R"(
2073 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2074 %res1 = OpImageSampleProjImplicitLod %f32vec4 %img %f32vec3_hhh
2075 )";
2076 
2077   CompileSuccessfully(GenerateShaderCode(body).c_str());
2078   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2079   EXPECT_THAT(
2080       getDiagnosticString(),
2081       HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage"));
2082 }
2083 
TEST_F(ValidateImage,SampleProjImplicitLodMultisampleError)2084 TEST_F(ValidateImage, SampleProjImplicitLodMultisampleError) {
2085   const std::string body = R"(
2086 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
2087 %sampler = OpLoad %type_sampler %uniform_sampler
2088 %simg = OpSampledImage %type_sampled_image_f32_2d_0011 %img %sampler
2089 %res1 = OpImageSampleProjImplicitLod %f32vec4 %simg %f32vec2_hh Sample %u32_1
2090 )";
2091 
2092   CompileSuccessfully(GenerateShaderCode(body).c_str());
2093   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2094   EXPECT_THAT(getDiagnosticString(),
2095               HasSubstr("Expected Image 'MS' parameter to be 0"));
2096 }
2097 
TEST_F(ValidateImage,SampleProjImplicitLodWrongSampledType)2098 TEST_F(ValidateImage, SampleProjImplicitLodWrongSampledType) {
2099   const std::string body = R"(
2100 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2101 %sampler = OpLoad %type_sampler %uniform_sampler
2102 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2103 %res1 = OpImageSampleProjImplicitLod %u32vec4 %simg %f32vec3_hhh
2104 )";
2105 
2106   CompileSuccessfully(GenerateShaderCode(body).c_str());
2107   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2108   EXPECT_THAT(getDiagnosticString(),
2109               HasSubstr("Expected Image 'Sampled Type' to be the same as "
2110                         "Result Type components"));
2111 }
2112 
TEST_F(ValidateImage,SampleProjImplicitLodVoidSampledType)2113 TEST_F(ValidateImage, SampleProjImplicitLodVoidSampledType) {
2114   const std::string body = R"(
2115 %img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001
2116 %sampler = OpLoad %type_sampler %uniform_sampler
2117 %simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler
2118 %res1 = OpImageSampleProjImplicitLod %u32vec4 %simg %f32vec3_hhh
2119 )";
2120 
2121   CompileSuccessfully(GenerateShaderCode(body).c_str());
2122   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
2123 }
2124 
TEST_F(ValidateImage,SampleProjImplicitLodWrongCoordinateType)2125 TEST_F(ValidateImage, SampleProjImplicitLodWrongCoordinateType) {
2126   const std::string body = R"(
2127 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2128 %sampler = OpLoad %type_sampler %uniform_sampler
2129 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2130 %res1 = OpImageSampleProjImplicitLod %f32vec4 %simg %img
2131 )";
2132 
2133   CompileSuccessfully(GenerateShaderCode(body).c_str());
2134   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2135   EXPECT_THAT(getDiagnosticString(),
2136               HasSubstr("Expected Coordinate to be float scalar or vector"));
2137 }
2138 
TEST_F(ValidateImage,SampleProjImplicitLodCoordinateSizeTooSmall)2139 TEST_F(ValidateImage, SampleProjImplicitLodCoordinateSizeTooSmall) {
2140   const std::string body = R"(
2141 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2142 %sampler = OpLoad %type_sampler %uniform_sampler
2143 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2144 %res1 = OpImageSampleProjImplicitLod %f32vec4 %simg %f32vec2_hh
2145 )";
2146 
2147   CompileSuccessfully(GenerateShaderCode(body).c_str());
2148   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2149   EXPECT_THAT(getDiagnosticString(),
2150               HasSubstr("Expected Coordinate to have at least 3 components, "
2151                         "but given only 2"));
2152 }
2153 
TEST_F(ValidateImage,SampleDrefImplicitLodSuccess)2154 TEST_F(ValidateImage, SampleDrefImplicitLodSuccess) {
2155   const std::string body = R"(
2156 %img = OpLoad %type_image_u32_2d_0001 %uniform_image_u32_2d_0001
2157 %sampler = OpLoad %type_sampler %uniform_sampler
2158 %simg = OpSampledImage %type_sampled_image_u32_2d_0001 %img %sampler
2159 %res1 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec2_hh %f32_1
2160 %res2 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec2_hh %f32_1 Bias %f32_0_25
2161 %res4 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec2_hh %f32_1 ConstOffset %s32vec2_01
2162 %res5 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec2_hh %f32_1 Offset %s32vec2_01
2163 %res6 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec2_hh %f32_1 MinLod %f32_0_5
2164 %res7 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec2_hh %f32_1 Bias|Offset|MinLod %f32_0_25 %s32vec2_01 %f32_0_5
2165 %res8 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec2_hh %f32_1 NonPrivateTexelKHR
2166 )";
2167 
2168   const std::string extra = R"(
2169 OpCapability VulkanMemoryModelKHR
2170 OpExtension "SPV_KHR_vulkan_memory_model"
2171 )";
2172   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
2173                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
2174                           .c_str());
2175   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2176 }
2177 
TEST_F(ValidateImage,SampleDrefImplicitLodWrongResultType)2178 TEST_F(ValidateImage, SampleDrefImplicitLodWrongResultType) {
2179   const std::string body = R"(
2180 %img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001
2181 %sampler = OpLoad %type_sampler %uniform_sampler
2182 %simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler
2183 %res1 = OpImageSampleDrefImplicitLod %void %simg %f32vec2_hh %u32_1
2184 )";
2185 
2186   CompileSuccessfully(GenerateShaderCode(body).c_str());
2187   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2188   EXPECT_THAT(getDiagnosticString(),
2189               HasSubstr("Expected Result Type to be int or float scalar type"));
2190 }
2191 
TEST_F(ValidateImage,SampleDrefImplicitLodNotSampledImage)2192 TEST_F(ValidateImage, SampleDrefImplicitLodNotSampledImage) {
2193   const std::string body = R"(
2194 %img = OpLoad %type_image_u32_2d_0001 %uniform_image_u32_2d_0001
2195 %res1 = OpImageSampleDrefImplicitLod %u32 %img %f32vec2_hh %u32_1
2196 )";
2197 
2198   CompileSuccessfully(GenerateShaderCode(body).c_str());
2199   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2200   EXPECT_THAT(
2201       getDiagnosticString(),
2202       HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage"));
2203 }
2204 
TEST_F(ValidateImage,SampleDrefImplicitLodMultisampleError)2205 TEST_F(ValidateImage, SampleDrefImplicitLodMultisampleError) {
2206   const std::string body = R"(
2207 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
2208 %sampler = OpLoad %type_sampler %uniform_sampler
2209 %simg = OpSampledImage %type_sampled_image_f32_2d_0011 %img %sampler
2210 %res1 = OpImageSampleDrefImplicitLod %f32 %simg %f32vec2_hh %f32_1 Sample %u32_1
2211 )";
2212 
2213   CompileSuccessfully(GenerateShaderCode(body).c_str());
2214   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2215   EXPECT_THAT(
2216       getDiagnosticString(),
2217       HasSubstr("Dref sampling operation is invalid for multisample image"));
2218 }
2219 
TEST_F(ValidateImage,SampleDrefImplicitLodWrongSampledType)2220 TEST_F(ValidateImage, SampleDrefImplicitLodWrongSampledType) {
2221   const std::string body = R"(
2222 %img = OpLoad %type_image_u32_2d_0001 %uniform_image_u32_2d_0001
2223 %sampler = OpLoad %type_sampler %uniform_sampler
2224 %simg = OpSampledImage %type_sampled_image_u32_2d_0001 %img %sampler
2225 %res1 = OpImageSampleDrefImplicitLod %f32 %simg %f32vec2_00 %u32_1
2226 )";
2227 
2228   CompileSuccessfully(GenerateShaderCode(body).c_str());
2229   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2230   EXPECT_THAT(
2231       getDiagnosticString(),
2232       HasSubstr("Expected Image 'Sampled Type' to be the same as Result Type"));
2233 }
2234 
TEST_F(ValidateImage,SampleDrefImplicitLodVoidSampledType)2235 TEST_F(ValidateImage, SampleDrefImplicitLodVoidSampledType) {
2236   const std::string body = R"(
2237 %img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001
2238 %sampler = OpLoad %type_sampler %uniform_sampler
2239 %simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler
2240 %res1 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec2_00 %u32_1
2241 )";
2242 
2243   CompileSuccessfully(GenerateShaderCode(body).c_str());
2244   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2245   EXPECT_THAT(
2246       getDiagnosticString(),
2247       HasSubstr("Expected Image 'Sampled Type' to be the same as Result Type"));
2248 }
2249 
TEST_F(ValidateImage,SampleDrefImplicitLodWrongCoordinateType)2250 TEST_F(ValidateImage, SampleDrefImplicitLodWrongCoordinateType) {
2251   const std::string body = R"(
2252 %img = OpLoad %type_image_u32_2d_0001 %uniform_image_u32_2d_0001
2253 %sampler = OpLoad %type_sampler %uniform_sampler
2254 %simg = OpSampledImage %type_sampled_image_u32_2d_0001 %img %sampler
2255 %res1 = OpImageSampleDrefImplicitLod %u32 %simg %img %u32_1
2256 )";
2257 
2258   CompileSuccessfully(GenerateShaderCode(body).c_str());
2259   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2260   EXPECT_THAT(getDiagnosticString(),
2261               HasSubstr("Expected Coordinate to be float scalar or vector"));
2262 }
2263 
TEST_F(ValidateImage,SampleDrefImplicitLodCoordinateSizeTooSmall)2264 TEST_F(ValidateImage, SampleDrefImplicitLodCoordinateSizeTooSmall) {
2265   const std::string body = R"(
2266 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2267 %sampler = OpLoad %type_sampler %uniform_sampler
2268 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2269 %res1 = OpImageSampleDrefImplicitLod %f32 %simg %f32_0_5 %f32_0_5
2270 )";
2271 
2272   CompileSuccessfully(GenerateShaderCode(body).c_str());
2273   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2274   EXPECT_THAT(getDiagnosticString(),
2275               HasSubstr("Expected Coordinate to have at least 2 components, "
2276                         "but given only 1"));
2277 }
2278 
TEST_F(ValidateImage,SampleDrefImplicitLodWrongDrefType)2279 TEST_F(ValidateImage, SampleDrefImplicitLodWrongDrefType) {
2280   const std::string body = R"(
2281 %img = OpLoad %type_image_u32_2d_0001 %uniform_image_u32_2d_0001
2282 %sampler = OpLoad %type_sampler %uniform_sampler
2283 %simg = OpSampledImage %type_sampled_image_u32_2d_0001 %img %sampler
2284 %res1 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec2_00 %f64_1
2285 )";
2286 
2287   CompileSuccessfully(GenerateShaderCode(body).c_str());
2288   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2289   EXPECT_THAT(getDiagnosticString(),
2290               HasSubstr("Expected Dref to be of 32-bit float type"));
2291 }
2292 
TEST_F(ValidateImage,SampleDrefExplicitLodSuccess)2293 TEST_F(ValidateImage, SampleDrefExplicitLodSuccess) {
2294   const std::string body = R"(
2295 %img = OpLoad %type_image_s32_3d_0001 %uniform_image_s32_3d_0001
2296 %sampler = OpLoad %type_sampler %uniform_sampler
2297 %simg = OpSampledImage %type_sampled_image_s32_3d_0001 %img %sampler
2298 %res1 = OpImageSampleDrefExplicitLod %s32 %simg %f32vec4_0000 %f32_1 Lod %f32_1
2299 %res3 = OpImageSampleDrefExplicitLod %s32 %simg %f32vec3_hhh %f32_1 Grad %f32vec3_hhh %f32vec3_hhh
2300 %res4 = OpImageSampleDrefExplicitLod %s32 %simg %f32vec3_hhh %f32_1 ConstOffset %s32vec3_012
2301 %res5 = OpImageSampleDrefExplicitLod %s32 %simg %f32vec4_0000 %f32_1 Offset %s32vec3_012
2302 %res7 = OpImageSampleDrefExplicitLod %s32 %simg %f32vec3_hhh %f32_1 Grad|Offset %f32vec3_hhh %f32vec3_hhh %s32vec3_012
2303 %res8 = OpImageSampleDrefExplicitLod %s32 %simg %f32vec4_0000 %f32_1 Lod|NonPrivateTexelKHR %f32_1
2304 )";
2305 
2306   const std::string extra = R"(
2307 OpCapability VulkanMemoryModelKHR
2308 OpExtension "SPV_KHR_vulkan_memory_model"
2309 )";
2310   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
2311                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
2312                           .c_str());
2313   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2314 }
2315 
TEST_F(ValidateImage,SampleDrefExplicitLodWrongResultType)2316 TEST_F(ValidateImage, SampleDrefExplicitLodWrongResultType) {
2317   const std::string body = R"(
2318 %img = OpLoad %type_image_s32_3d_0001 %uniform_image_s32_3d_0001
2319 %sampler = OpLoad %type_sampler %uniform_sampler
2320 %simg = OpSampledImage %type_sampled_image_s32_3d_0001 %img %sampler
2321 %res1 = OpImageSampleDrefExplicitLod %bool %simg %f32vec3_hhh %s32_1 Lod %f32_1
2322 )";
2323 
2324   CompileSuccessfully(GenerateShaderCode(body).c_str());
2325   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2326   EXPECT_THAT(getDiagnosticString(),
2327               HasSubstr("Expected Result Type to be int or float scalar type"));
2328 }
2329 
TEST_F(ValidateImage,SampleDrefExplicitLodNotSampledImage)2330 TEST_F(ValidateImage, SampleDrefExplicitLodNotSampledImage) {
2331   const std::string body = R"(
2332 %img = OpLoad %type_image_s32_3d_0001 %uniform_image_s32_3d_0001
2333 %res1 = OpImageSampleDrefExplicitLod %s32 %img %f32vec3_hhh %s32_1 Lod %f32_1
2334 )";
2335 
2336   CompileSuccessfully(GenerateShaderCode(body).c_str());
2337   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2338   EXPECT_THAT(
2339       getDiagnosticString(),
2340       HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage"));
2341 }
2342 
TEST_F(ValidateImage,SampleDrefExplicitLodMultisampleError)2343 TEST_F(ValidateImage, SampleDrefExplicitLodMultisampleError) {
2344   const std::string body = R"(
2345 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
2346 %sampler = OpLoad %type_sampler %uniform_sampler
2347 %simg = OpSampledImage %type_sampled_image_f32_2d_0011 %img %sampler
2348 %res1 = OpImageSampleDrefExplicitLod %f32 %simg %f32vec2_hh %f32_1 Lod|Sample %f32_1 %u32_1
2349 )";
2350 
2351   CompileSuccessfully(GenerateShaderCode(body).c_str());
2352   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2353   EXPECT_THAT(
2354       getDiagnosticString(),
2355       HasSubstr("Dref sampling operation is invalid for multisample image"));
2356 }
2357 
TEST_F(ValidateImage,SampleDrefExplicitLodWrongSampledType)2358 TEST_F(ValidateImage, SampleDrefExplicitLodWrongSampledType) {
2359   const std::string body = R"(
2360 %img = OpLoad %type_image_s32_3d_0001 %uniform_image_s32_3d_0001
2361 %sampler = OpLoad %type_sampler %uniform_sampler
2362 %simg = OpSampledImage %type_sampled_image_s32_3d_0001 %img %sampler
2363 %res1 = OpImageSampleDrefExplicitLod %f32 %simg %f32vec3_hhh %s32_1 Lod %f32_1
2364 )";
2365 
2366   CompileSuccessfully(GenerateShaderCode(body).c_str());
2367   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2368   EXPECT_THAT(
2369       getDiagnosticString(),
2370       HasSubstr("Expected Image 'Sampled Type' to be the same as Result Type"));
2371 }
2372 
TEST_F(ValidateImage,SampleDrefExplicitLodVoidSampledType)2373 TEST_F(ValidateImage, SampleDrefExplicitLodVoidSampledType) {
2374   const std::string body = R"(
2375 %img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001
2376 %sampler = OpLoad %type_sampler %uniform_sampler
2377 %simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler
2378 %res1 = OpImageSampleDrefExplicitLod %u32 %simg %f32vec2_00 %s32_1 Lod %f32_1
2379 )";
2380 
2381   CompileSuccessfully(GenerateShaderCode(body).c_str());
2382   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2383   EXPECT_THAT(
2384       getDiagnosticString(),
2385       HasSubstr("Expected Image 'Sampled Type' to be the same as Result Type"));
2386 }
2387 
TEST_F(ValidateImage,SampleDrefExplicitLodWrongCoordinateType)2388 TEST_F(ValidateImage, SampleDrefExplicitLodWrongCoordinateType) {
2389   const std::string body = R"(
2390 %img = OpLoad %type_image_s32_3d_0001 %uniform_image_s32_3d_0001
2391 %sampler = OpLoad %type_sampler %uniform_sampler
2392 %simg = OpSampledImage %type_sampled_image_s32_3d_0001 %img %sampler
2393 %res1 = OpImageSampleDrefExplicitLod %s32 %simg %img %s32_1 Lod %f32_1
2394 )";
2395 
2396   CompileSuccessfully(GenerateShaderCode(body).c_str());
2397   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2398   EXPECT_THAT(getDiagnosticString(),
2399               HasSubstr("Expected Coordinate to be float scalar or vector"));
2400 }
2401 
TEST_F(ValidateImage,SampleDrefExplicitLodCoordinateSizeTooSmall)2402 TEST_F(ValidateImage, SampleDrefExplicitLodCoordinateSizeTooSmall) {
2403   const std::string body = R"(
2404 %img = OpLoad %type_image_s32_3d_0001 %uniform_image_s32_3d_0001
2405 %sampler = OpLoad %type_sampler %uniform_sampler
2406 %simg = OpSampledImage %type_sampled_image_s32_3d_0001 %img %sampler
2407 %res1 = OpImageSampleDrefExplicitLod %s32 %simg %f32vec2_hh %s32_1 Lod %f32_1
2408 )";
2409 
2410   CompileSuccessfully(GenerateShaderCode(body).c_str());
2411   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2412   EXPECT_THAT(getDiagnosticString(),
2413               HasSubstr("Expected Coordinate to have at least 3 components, "
2414                         "but given only 2"));
2415 }
2416 
TEST_F(ValidateImage,SampleDrefExplicitLodWrongDrefType)2417 TEST_F(ValidateImage, SampleDrefExplicitLodWrongDrefType) {
2418   const std::string body = R"(
2419 %img = OpLoad %type_image_s32_3d_0001 %uniform_image_s32_3d_0001
2420 %sampler = OpLoad %type_sampler %uniform_sampler
2421 %simg = OpSampledImage %type_sampled_image_s32_3d_0001 %img %sampler
2422 %res1 = OpImageSampleDrefExplicitLod %s32 %simg %f32vec3_hhh %u32_1 Lod %f32_1
2423 )";
2424 
2425   CompileSuccessfully(GenerateShaderCode(body).c_str());
2426   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2427   EXPECT_THAT(getDiagnosticString(),
2428               HasSubstr("Expected Dref to be of 32-bit float type"));
2429 }
2430 
TEST_F(ValidateImage,SampleProjDrefImplicitLodSuccess)2431 TEST_F(ValidateImage, SampleProjDrefImplicitLodSuccess) {
2432   const std::string body = R"(
2433 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2434 %sampler = OpLoad %type_sampler %uniform_sampler
2435 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2436 %res1 = OpImageSampleProjDrefImplicitLod %f32 %simg %f32vec3_hhh %f32_0_5
2437 %res2 = OpImageSampleProjDrefImplicitLod %f32 %simg %f32vec3_hhh %f32_0_5 Bias %f32_0_25
2438 %res4 = OpImageSampleProjDrefImplicitLod %f32 %simg %f32vec3_hhh %f32_0_5 ConstOffset %s32vec2_01
2439 %res5 = OpImageSampleProjDrefImplicitLod %f32 %simg %f32vec3_hhh %f32_0_5 Offset %s32vec2_01
2440 %res6 = OpImageSampleProjDrefImplicitLod %f32 %simg %f32vec3_hhh %f32_0_5 MinLod %f32_0_5
2441 %res7 = OpImageSampleProjDrefImplicitLod %f32 %simg %f32vec3_hhh %f32_0_5 Bias|Offset|MinLod %f32_0_25 %s32vec2_01 %f32_0_5
2442 %res8 = OpImageSampleProjDrefImplicitLod %f32 %simg %f32vec3_hhh %f32_0_5 NonPrivateTexelKHR
2443 )";
2444 
2445   const std::string extra = R"(
2446 OpCapability VulkanMemoryModelKHR
2447 OpExtension "SPV_KHR_vulkan_memory_model"
2448 )";
2449   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
2450                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
2451                           .c_str());
2452   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2453 }
2454 
TEST_F(ValidateImage,SampleProjDrefImplicitLodWrongResultType)2455 TEST_F(ValidateImage, SampleProjDrefImplicitLodWrongResultType) {
2456   const std::string body = R"(
2457 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2458 %sampler = OpLoad %type_sampler %uniform_sampler
2459 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2460 %res1 = OpImageSampleProjDrefImplicitLod %void %simg %f32vec3_hhh %f32_0_5
2461 )";
2462 
2463   CompileSuccessfully(GenerateShaderCode(body).c_str());
2464   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2465   EXPECT_THAT(getDiagnosticString(),
2466               HasSubstr("Expected Result Type to be int or float scalar type"));
2467 }
2468 
TEST_F(ValidateImage,SampleProjDrefImplicitLodNotSampledImage)2469 TEST_F(ValidateImage, SampleProjDrefImplicitLodNotSampledImage) {
2470   const std::string body = R"(
2471 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2472 %res1 = OpImageSampleProjDrefImplicitLod %f32 %img %f32vec3_hhh %f32_0_5
2473 )";
2474 
2475   CompileSuccessfully(GenerateShaderCode(body).c_str());
2476   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2477   EXPECT_THAT(
2478       getDiagnosticString(),
2479       HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage"));
2480 }
2481 
TEST_F(ValidateImage,SampleProjDrefImplicitLodMultisampleError)2482 TEST_F(ValidateImage, SampleProjDrefImplicitLodMultisampleError) {
2483   const std::string body = R"(
2484 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
2485 %sampler = OpLoad %type_sampler %uniform_sampler
2486 %simg = OpSampledImage %type_sampled_image_f32_2d_0011 %img %sampler
2487 %res1 = OpImageSampleDrefExplicitLod %f32 %simg %f32vec2_hh %f32_1 Sample %u32_1
2488 )";
2489 
2490   CompileSuccessfully(GenerateShaderCode(body).c_str());
2491   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2492   EXPECT_THAT(
2493       getDiagnosticString(),
2494       HasSubstr("Dref sampling operation is invalid for multisample image"));
2495 }
2496 
TEST_F(ValidateImage,SampleProjDrefImplicitLodWrongSampledType)2497 TEST_F(ValidateImage, SampleProjDrefImplicitLodWrongSampledType) {
2498   const std::string body = R"(
2499 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2500 %sampler = OpLoad %type_sampler %uniform_sampler
2501 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2502 %res1 = OpImageSampleProjDrefImplicitLod %u32 %simg %f32vec3_hhh %f32_0_5
2503 )";
2504 
2505   CompileSuccessfully(GenerateShaderCode(body).c_str());
2506   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2507   EXPECT_THAT(
2508       getDiagnosticString(),
2509       HasSubstr("Expected Image 'Sampled Type' to be the same as Result Type"));
2510 }
2511 
TEST_F(ValidateImage,SampleProjDrefImplicitLodVoidSampledType)2512 TEST_F(ValidateImage, SampleProjDrefImplicitLodVoidSampledType) {
2513   const std::string body = R"(
2514 %img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001
2515 %sampler = OpLoad %type_sampler %uniform_sampler
2516 %simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler
2517 %res1 = OpImageSampleProjDrefImplicitLod %u32 %simg %f32vec3_hhh %f32_0_5
2518 )";
2519 
2520   CompileSuccessfully(GenerateShaderCode(body).c_str());
2521   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2522   EXPECT_THAT(
2523       getDiagnosticString(),
2524       HasSubstr("Expected Image 'Sampled Type' to be the same as Result Type"));
2525 }
2526 
TEST_F(ValidateImage,SampleProjDrefImplicitLodWrongCoordinateType)2527 TEST_F(ValidateImage, SampleProjDrefImplicitLodWrongCoordinateType) {
2528   const std::string body = R"(
2529 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2530 %sampler = OpLoad %type_sampler %uniform_sampler
2531 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2532 %res1 = OpImageSampleProjDrefImplicitLod %f32 %simg %img %f32_0_5
2533 )";
2534 
2535   CompileSuccessfully(GenerateShaderCode(body).c_str());
2536   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2537   EXPECT_THAT(getDiagnosticString(),
2538               HasSubstr("Expected Coordinate to be float scalar or vector"));
2539 }
2540 
TEST_F(ValidateImage,SampleProjDrefImplicitLodCoordinateSizeTooSmall)2541 TEST_F(ValidateImage, SampleProjDrefImplicitLodCoordinateSizeTooSmall) {
2542   const std::string body = R"(
2543 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2544 %sampler = OpLoad %type_sampler %uniform_sampler
2545 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2546 %res1 = OpImageSampleProjDrefImplicitLod %f32 %simg %f32vec2_hh %f32_0_5
2547 )";
2548 
2549   CompileSuccessfully(GenerateShaderCode(body).c_str());
2550   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2551   EXPECT_THAT(getDiagnosticString(),
2552               HasSubstr("Expected Coordinate to have at least 3 components, "
2553                         "but given only 2"));
2554 }
2555 
TEST_F(ValidateImage,SampleProjDrefImplicitLodWrongDrefType)2556 TEST_F(ValidateImage, SampleProjDrefImplicitLodWrongDrefType) {
2557   const std::string body = R"(
2558 %img = OpLoad %type_image_u32_2d_0001 %uniform_image_u32_2d_0001
2559 %sampler = OpLoad %type_sampler %uniform_sampler
2560 %simg = OpSampledImage %type_sampled_image_u32_2d_0001 %img %sampler
2561 %res1 = OpImageSampleProjDrefImplicitLod %u32 %simg %f32vec3_hhh %f32vec4_0000
2562 )";
2563 
2564   CompileSuccessfully(GenerateShaderCode(body).c_str());
2565   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2566   EXPECT_THAT(getDiagnosticString(),
2567               HasSubstr("Expected Dref to be of 32-bit float type"));
2568 }
2569 
TEST_F(ValidateImage,SampleProjDrefExplicitLodSuccess)2570 TEST_F(ValidateImage, SampleProjDrefExplicitLodSuccess) {
2571   const std::string body = R"(
2572 %img = OpLoad %type_image_f32_1d_0001 %uniform_image_f32_1d_0001
2573 %sampler = OpLoad %type_sampler %uniform_sampler
2574 %simg = OpSampledImage %type_sampled_image_f32_1d_0001 %img %sampler
2575 %res1 = OpImageSampleProjDrefExplicitLod %f32 %simg %f32vec2_hh %f32_0_5 Lod %f32_1
2576 %res2 = OpImageSampleProjDrefExplicitLod %f32 %simg %f32vec3_hhh %f32_0_5 Grad %f32_0_5 %f32_0_5
2577 %res3 = OpImageSampleProjDrefExplicitLod %f32 %simg %f32vec2_hh %f32_0_5 ConstOffset %s32_1
2578 %res4 = OpImageSampleProjDrefExplicitLod %f32 %simg %f32vec2_hh %f32_0_5 Offset %s32_1
2579 %res5 = OpImageSampleProjDrefExplicitLod %f32 %simg %f32vec2_hh %f32_0_5 Grad|Offset %f32_0_5 %f32_0_5 %s32_1
2580 %res6 = OpImageSampleProjDrefExplicitLod %f32 %simg %f32vec2_hh %f32_0_5 Lod|NonPrivateTexelKHR %f32_1
2581 )";
2582 
2583   const std::string extra = R"(
2584 OpCapability VulkanMemoryModelKHR
2585 OpExtension "SPV_KHR_vulkan_memory_model"
2586 )";
2587   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
2588                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
2589                           .c_str());
2590   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2591 }
2592 
TEST_F(ValidateImage,SampleProjDrefExplicitLodWrongResultType)2593 TEST_F(ValidateImage, SampleProjDrefExplicitLodWrongResultType) {
2594   const std::string body = R"(
2595 %img = OpLoad %type_image_f32_1d_0001 %uniform_image_f32_1d_0001
2596 %sampler = OpLoad %type_sampler %uniform_sampler
2597 %simg = OpSampledImage %type_sampled_image_f32_1d_0001 %img %sampler
2598 %res1 = OpImageSampleProjDrefExplicitLod %bool %simg %f32vec2_hh %f32_0_5 Lod %f32_1
2599 )";
2600 
2601   CompileSuccessfully(GenerateShaderCode(body).c_str());
2602   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2603   EXPECT_THAT(getDiagnosticString(),
2604               HasSubstr("Expected Result Type to be int or float scalar type"));
2605 }
2606 
TEST_F(ValidateImage,SampleProjDrefExplicitLodNotSampledImage)2607 TEST_F(ValidateImage, SampleProjDrefExplicitLodNotSampledImage) {
2608   const std::string body = R"(
2609 %img = OpLoad %type_image_f32_1d_0001 %uniform_image_f32_1d_0001
2610 %res1 = OpImageSampleProjDrefExplicitLod %f32 %img %f32vec2_hh %f32_0_5 Lod %f32_1
2611 )";
2612 
2613   CompileSuccessfully(GenerateShaderCode(body).c_str());
2614   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2615   EXPECT_THAT(
2616       getDiagnosticString(),
2617       HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage"));
2618 }
2619 
TEST_F(ValidateImage,SampleProjDrefExplicitLodMultisampleError)2620 TEST_F(ValidateImage, SampleProjDrefExplicitLodMultisampleError) {
2621   const std::string body = R"(
2622 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
2623 %sampler = OpLoad %type_sampler %uniform_sampler
2624 %simg = OpSampledImage %type_sampled_image_f32_2d_0011 %img %sampler
2625 %res1 = OpImageSampleDrefExplicitLod %f32 %simg %f32vec2_hh %f32_1 Lod|Sample %f32_1 %u32_1
2626 )";
2627 
2628   CompileSuccessfully(GenerateShaderCode(body).c_str());
2629   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2630   EXPECT_THAT(
2631       getDiagnosticString(),
2632       HasSubstr("Dref sampling operation is invalid for multisample image"));
2633 }
2634 
TEST_F(ValidateImage,SampleProjDrefExplicitLodWrongSampledType)2635 TEST_F(ValidateImage, SampleProjDrefExplicitLodWrongSampledType) {
2636   const std::string body = R"(
2637 %img = OpLoad %type_image_f32_1d_0001 %uniform_image_f32_1d_0001
2638 %sampler = OpLoad %type_sampler %uniform_sampler
2639 %simg = OpSampledImage %type_sampled_image_f32_1d_0001 %img %sampler
2640 %res1 = OpImageSampleProjDrefExplicitLod %u32 %simg %f32vec2_hh %f32_0_5 Lod %f32_1
2641 )";
2642 
2643   CompileSuccessfully(GenerateShaderCode(body).c_str());
2644   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2645   EXPECT_THAT(
2646       getDiagnosticString(),
2647       HasSubstr("Expected Image 'Sampled Type' to be the same as Result Type"));
2648 }
2649 
TEST_F(ValidateImage,SampleProjDrefExplicitLodVoidSampledType)2650 TEST_F(ValidateImage, SampleProjDrefExplicitLodVoidSampledType) {
2651   const std::string body = R"(
2652 %img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001
2653 %sampler = OpLoad %type_sampler %uniform_sampler
2654 %simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler
2655 %res1 = OpImageSampleProjDrefExplicitLod %u32 %simg %f32vec3_hhh %f32_0_5 Lod %f32_1
2656 )";
2657 
2658   CompileSuccessfully(GenerateShaderCode(body).c_str());
2659   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2660   EXPECT_THAT(
2661       getDiagnosticString(),
2662       HasSubstr("Expected Image 'Sampled Type' to be the same as Result Type"));
2663 }
2664 
TEST_F(ValidateImage,SampleProjDrefExplicitLodWrongCoordinateType)2665 TEST_F(ValidateImage, SampleProjDrefExplicitLodWrongCoordinateType) {
2666   const std::string body = R"(
2667 %img = OpLoad %type_image_f32_1d_0001 %uniform_image_f32_1d_0001
2668 %sampler = OpLoad %type_sampler %uniform_sampler
2669 %simg = OpSampledImage %type_sampled_image_f32_1d_0001 %img %sampler
2670 %res1 = OpImageSampleProjDrefExplicitLod %f32 %simg %img %f32_0_5 Lod %f32_1
2671 )";
2672 
2673   CompileSuccessfully(GenerateShaderCode(body).c_str());
2674   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2675   EXPECT_THAT(getDiagnosticString(),
2676               HasSubstr("Expected Coordinate to be float scalar or vector"));
2677 }
2678 
TEST_F(ValidateImage,SampleProjDrefExplicitLodCoordinateSizeTooSmall)2679 TEST_F(ValidateImage, SampleProjDrefExplicitLodCoordinateSizeTooSmall) {
2680   const std::string body = R"(
2681 %img = OpLoad %type_image_f32_1d_0001 %uniform_image_f32_1d_0001
2682 %sampler = OpLoad %type_sampler %uniform_sampler
2683 %simg = OpSampledImage %type_sampled_image_f32_1d_0001 %img %sampler
2684 %res1 = OpImageSampleProjDrefExplicitLod %f32 %simg %f32_0_5 %f32_0_5 Lod %f32_1
2685 )";
2686 
2687   CompileSuccessfully(GenerateShaderCode(body).c_str());
2688   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2689   EXPECT_THAT(getDiagnosticString(),
2690               HasSubstr("Expected Coordinate to have at least 2 components, "
2691                         "but given only 1"));
2692 }
2693 
TEST_F(ValidateImage,FetchSuccess)2694 TEST_F(ValidateImage, FetchSuccess) {
2695   const std::string body = R"(
2696 %img = OpLoad %type_image_f32_1d_0001 %uniform_image_f32_1d_0001
2697 %res1 = OpImageFetch %f32vec4 %img %u32vec2_01
2698 %res2 = OpImageFetch %f32vec4 %img %u32vec2_01 NonPrivateTexelKHR
2699 )";
2700 
2701   const std::string extra = R"(
2702 OpCapability VulkanMemoryModelKHR
2703 OpExtension "SPV_KHR_vulkan_memory_model"
2704 )";
2705   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
2706                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
2707                           .c_str());
2708   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2709 }
2710 
TEST_F(ValidateImage,FetchMultisampledSuccess)2711 TEST_F(ValidateImage, FetchMultisampledSuccess) {
2712   const std::string body = R"(
2713 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
2714 %res1 = OpImageFetch %f32vec4 %img %u32vec2_01 Sample %u32_1
2715 %res2 = OpImageFetch %f32vec4 %img %u32vec2_01 Sample|NonPrivateTexelKHR %u32_1
2716 )";
2717 
2718   const std::string extra = R"(
2719 OpCapability VulkanMemoryModelKHR
2720 OpExtension "SPV_KHR_vulkan_memory_model"
2721 )";
2722   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
2723                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
2724                           .c_str());
2725   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2726 }
2727 
TEST_F(ValidateImage,FetchWrongResultType)2728 TEST_F(ValidateImage, FetchWrongResultType) {
2729   const std::string body = R"(
2730 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
2731 %res1 = OpImageFetch %f32 %img %u32vec2_01
2732 )";
2733 
2734   CompileSuccessfully(GenerateShaderCode(body).c_str());
2735   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2736   EXPECT_THAT(getDiagnosticString(),
2737               HasSubstr("Expected Result Type to be int or float vector type"));
2738 }
2739 
TEST_F(ValidateImage,FetchWrongNumComponentsResultType)2740 TEST_F(ValidateImage, FetchWrongNumComponentsResultType) {
2741   const std::string body = R"(
2742 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
2743 %res1 = OpImageFetch %f32vec3 %img %u32vec2_01
2744 )";
2745 
2746   CompileSuccessfully(GenerateShaderCode(body).c_str());
2747   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2748   EXPECT_THAT(getDiagnosticString(),
2749               HasSubstr("Expected Result Type to have 4 components"));
2750 }
2751 
TEST_F(ValidateImage,FetchNotImage)2752 TEST_F(ValidateImage, FetchNotImage) {
2753   const std::string body = R"(
2754 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2755 %sampler = OpLoad %type_sampler %uniform_sampler
2756 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2757 %res1 = OpImageFetch %f32vec4 %sampler %u32vec2_01
2758 )";
2759 
2760   CompileSuccessfully(GenerateShaderCode(body).c_str());
2761   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2762   EXPECT_THAT(getDiagnosticString(),
2763               HasSubstr("Expected Image to be of type OpTypeImage"));
2764 }
2765 
TEST_F(ValidateImage,FetchSampledImageDirectly)2766 TEST_F(ValidateImage, FetchSampledImageDirectly) {
2767   const std::string body = R"(
2768 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2769 %sampler = OpLoad %type_sampler %uniform_sampler
2770 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2771 %res1 = OpImageFetch %f32vec4 %simg %u32vec2_01
2772 )";
2773 
2774   CompileSuccessfully(GenerateShaderCode(body).c_str());
2775   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2776   EXPECT_THAT(getDiagnosticString(),
2777               HasSubstr("OpSampledImage instruction must not appear as operand "
2778                         "for OpImageFetch"));
2779 }
2780 
TEST_F(ValidateImage,FetchNotSampled)2781 TEST_F(ValidateImage, FetchNotSampled) {
2782   const std::string body = R"(
2783 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
2784 %res1 = OpImageFetch %u32vec4 %img %u32vec2_01
2785 )";
2786 
2787   CompileSuccessfully(GenerateShaderCode(body).c_str());
2788   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2789   EXPECT_THAT(getDiagnosticString(),
2790               HasSubstr("Expected Image 'Sampled' parameter to be 1"));
2791 }
2792 
TEST_F(ValidateImage,FetchCube)2793 TEST_F(ValidateImage, FetchCube) {
2794   const std::string body = R"(
2795 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
2796 %res1 = OpImageFetch %f32vec4 %img %u32vec3_012
2797 )";
2798 
2799   CompileSuccessfully(GenerateShaderCode(body).c_str());
2800   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2801   EXPECT_THAT(getDiagnosticString(), HasSubstr("Image 'Dim' cannot be Cube"));
2802 }
2803 
TEST_F(ValidateImage,FetchWrongSampledType)2804 TEST_F(ValidateImage, FetchWrongSampledType) {
2805   const std::string body = R"(
2806 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
2807 %res1 = OpImageFetch %u32vec4 %img %u32vec2_01
2808 )";
2809 
2810   CompileSuccessfully(GenerateShaderCode(body).c_str());
2811   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2812   EXPECT_THAT(getDiagnosticString(),
2813               HasSubstr("Expected Image 'Sampled Type' to be the same as "
2814                         "Result Type components"));
2815 }
2816 
TEST_F(ValidateImage,FetchVoidSampledType)2817 TEST_F(ValidateImage, FetchVoidSampledType) {
2818   const std::string body = R"(
2819 %img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001
2820 %res1 = OpImageFetch %f32vec4 %img %u32vec2_01
2821 %res2 = OpImageFetch %u32vec4 %img %u32vec2_01
2822 %res3 = OpImageFetch %s32vec4 %img %u32vec2_01
2823 )";
2824 
2825   CompileSuccessfully(GenerateShaderCode(body).c_str());
2826   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
2827 }
2828 
TEST_F(ValidateImage,FetchWrongCoordinateType)2829 TEST_F(ValidateImage, FetchWrongCoordinateType) {
2830   const std::string body = R"(
2831 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
2832 %res1 = OpImageFetch %f32vec4 %img %f32vec2_00
2833 )";
2834 
2835   CompileSuccessfully(GenerateShaderCode(body).c_str());
2836   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2837   EXPECT_THAT(getDiagnosticString(),
2838               HasSubstr("Expected Coordinate to be int scalar or vector"));
2839 }
2840 
TEST_F(ValidateImage,FetchCoordinateSizeTooSmall)2841 TEST_F(ValidateImage, FetchCoordinateSizeTooSmall) {
2842   const std::string body = R"(
2843 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
2844 %res1 = OpImageFetch %f32vec4 %img %u32_1
2845 )";
2846 
2847   CompileSuccessfully(GenerateShaderCode(body).c_str());
2848   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2849   EXPECT_THAT(getDiagnosticString(),
2850               HasSubstr("Expected Coordinate to have at least 2 components, "
2851                         "but given only 1"));
2852 }
2853 
TEST_F(ValidateImage,FetchLodNotInt)2854 TEST_F(ValidateImage, FetchLodNotInt) {
2855   const std::string body = R"(
2856 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2857 %res1 = OpImageFetch %f32vec4 %img %u32vec2_01 Lod %f32_1
2858 )";
2859 
2860   CompileSuccessfully(GenerateShaderCode(body).c_str());
2861   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2862   EXPECT_THAT(getDiagnosticString(),
2863               HasSubstr("Expected Image Operand Lod to be int scalar when used "
2864                         "with OpImageFetch"));
2865 }
2866 
TEST_F(ValidateImage,FetchMultisampledMissingSample)2867 TEST_F(ValidateImage, FetchMultisampledMissingSample) {
2868   const std::string body = R"(
2869 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
2870 %res1 = OpImageFetch %f32vec4 %img %u32vec2_01
2871 )";
2872 
2873   CompileSuccessfully(GenerateShaderCode(body).c_str());
2874   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions())
2875       << GenerateShaderCode(body);
2876   EXPECT_THAT(getDiagnosticString(),
2877               HasSubstr("Image Operand Sample is required for operation on "
2878                         "multi-sampled image"))
2879       << getDiagnosticString();
2880 }
2881 
TEST_F(ValidateImage,GatherSuccess)2882 TEST_F(ValidateImage, GatherSuccess) {
2883   const std::string body = R"(
2884 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2885 %sampler = OpLoad %type_sampler %uniform_sampler
2886 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2887 %res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1
2888 %res2 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 ConstOffsets %const_offsets
2889 %res3 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 NonPrivateTexelKHR
2890 )";
2891 
2892   const std::string extra = R"(
2893 OpCapability VulkanMemoryModelKHR
2894 OpExtension "SPV_KHR_vulkan_memory_model"
2895 )";
2896   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
2897                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
2898                           .c_str());
2899   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2900 }
2901 
TEST_F(ValidateImage,GatherWrongResultType)2902 TEST_F(ValidateImage, GatherWrongResultType) {
2903   const std::string body = R"(
2904 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
2905 %sampler = OpLoad %type_sampler %uniform_sampler
2906 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
2907 %res1 = OpImageGather %f32 %simg %f32vec4_0000 %u32_1
2908 )";
2909 
2910   CompileSuccessfully(GenerateShaderCode(body).c_str());
2911   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2912   EXPECT_THAT(getDiagnosticString(),
2913               HasSubstr("Expected Result Type to be int or float vector type"));
2914 }
2915 
TEST_F(ValidateImage,GatherWrongNumComponentsResultType)2916 TEST_F(ValidateImage, GatherWrongNumComponentsResultType) {
2917   const std::string body = R"(
2918 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
2919 %sampler = OpLoad %type_sampler %uniform_sampler
2920 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
2921 %res1 = OpImageGather %f32vec3 %simg %f32vec4_0000 %u32_1
2922 )";
2923 
2924   CompileSuccessfully(GenerateShaderCode(body).c_str());
2925   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2926   EXPECT_THAT(getDiagnosticString(),
2927               HasSubstr("Expected Result Type to have 4 components"));
2928 }
2929 
TEST_F(ValidateImage,GatherNotSampledImage)2930 TEST_F(ValidateImage, GatherNotSampledImage) {
2931   const std::string body = R"(
2932 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
2933 %res1 = OpImageGather %f32vec4 %img %f32vec4_0000 %u32_1
2934 )";
2935 
2936   CompileSuccessfully(GenerateShaderCode(body).c_str());
2937   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2938   EXPECT_THAT(
2939       getDiagnosticString(),
2940       HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage"));
2941 }
2942 
TEST_F(ValidateImage,GatherMultisampleError)2943 TEST_F(ValidateImage, GatherMultisampleError) {
2944   const std::string body = R"(
2945 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
2946 %sampler = OpLoad %type_sampler %uniform_sampler
2947 %simg = OpSampledImage %type_sampled_image_f32_2d_0011 %img %sampler
2948 %res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 Sample %u32_1
2949 )";
2950 
2951   CompileSuccessfully(GenerateShaderCode(body).c_str());
2952   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2953   EXPECT_THAT(getDiagnosticString(),
2954               HasSubstr("Gather operation is invalid for multisample image"));
2955 }
2956 
TEST_F(ValidateImage,GatherWrongSampledType)2957 TEST_F(ValidateImage, GatherWrongSampledType) {
2958   const std::string body = R"(
2959 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
2960 %sampler = OpLoad %type_sampler %uniform_sampler
2961 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
2962 %res1 = OpImageGather %u32vec4 %simg %f32vec4_0000 %u32_1
2963 )";
2964 
2965   CompileSuccessfully(GenerateShaderCode(body).c_str());
2966   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2967   EXPECT_THAT(getDiagnosticString(),
2968               HasSubstr("Expected Image 'Sampled Type' to be the same as "
2969                         "Result Type components"));
2970 }
2971 
TEST_F(ValidateImage,GatherVoidSampledType)2972 TEST_F(ValidateImage, GatherVoidSampledType) {
2973   const std::string body = R"(
2974 %img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001
2975 %sampler = OpLoad %type_sampler %uniform_sampler
2976 %simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler
2977 %res1 = OpImageGather %u32vec4 %simg %f32vec2_00 %u32_1
2978 )";
2979 
2980   CompileSuccessfully(GenerateShaderCode(body).c_str());
2981   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
2982 }
2983 
TEST_F(ValidateImage,GatherWrongCoordinateType)2984 TEST_F(ValidateImage, GatherWrongCoordinateType) {
2985   const std::string body = R"(
2986 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
2987 %sampler = OpLoad %type_sampler %uniform_sampler
2988 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
2989 %res1 = OpImageGather %f32vec4 %simg %u32vec4_0123 %u32_1
2990 )";
2991 
2992   CompileSuccessfully(GenerateShaderCode(body).c_str());
2993   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2994   EXPECT_THAT(getDiagnosticString(),
2995               HasSubstr("Expected Coordinate to be float scalar or vector"));
2996 }
2997 
TEST_F(ValidateImage,GatherCoordinateSizeTooSmall)2998 TEST_F(ValidateImage, GatherCoordinateSizeTooSmall) {
2999   const std::string body = R"(
3000 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
3001 %sampler = OpLoad %type_sampler %uniform_sampler
3002 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
3003 %res1 = OpImageGather %f32vec4 %simg %f32_0_5 %u32_1
3004 )";
3005 
3006   CompileSuccessfully(GenerateShaderCode(body).c_str());
3007   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3008   EXPECT_THAT(getDiagnosticString(),
3009               HasSubstr("Expected Coordinate to have at least 4 components, "
3010                         "but given only 1"));
3011 }
3012 
TEST_F(ValidateImage,GatherWrongComponentType)3013 TEST_F(ValidateImage, GatherWrongComponentType) {
3014   const std::string body = R"(
3015 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
3016 %sampler = OpLoad %type_sampler %uniform_sampler
3017 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
3018 %res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %f32_1
3019 )";
3020 
3021   CompileSuccessfully(GenerateShaderCode(body).c_str());
3022   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3023   EXPECT_THAT(getDiagnosticString(),
3024               HasSubstr("Expected Component to be 32-bit int scalar"));
3025 }
3026 
TEST_F(ValidateImage,GatherComponentNot32Bit)3027 TEST_F(ValidateImage, GatherComponentNot32Bit) {
3028   const std::string body = R"(
3029 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
3030 %sampler = OpLoad %type_sampler %uniform_sampler
3031 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
3032 %res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u64_0
3033 )";
3034 
3035   CompileSuccessfully(GenerateShaderCode(body).c_str());
3036   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3037   EXPECT_THAT(getDiagnosticString(),
3038               HasSubstr("Expected Component to be 32-bit int scalar"));
3039 }
3040 
TEST_F(ValidateImage,GatherComponentSuccessVulkan)3041 TEST_F(ValidateImage, GatherComponentSuccessVulkan) {
3042   const std::string body = R"(
3043 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
3044 %sampler = OpLoad %type_sampler %uniform_sampler
3045 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
3046 %res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_0
3047 )";
3048 
3049   spv_target_env env = SPV_ENV_VULKAN_1_0;
3050   CompileSuccessfully(GenerateShaderCode(body, "", "Fragment", "", env).c_str(),
3051                       env);
3052   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(env));
3053 }
3054 
TEST_F(ValidateImage,GatherComponentNotConstantVulkan)3055 TEST_F(ValidateImage, GatherComponentNotConstantVulkan) {
3056   const std::string body = R"(
3057 %input_u32 = OpLoad %u32 %input_flat_u32
3058 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
3059 %sampler = OpLoad %type_sampler %uniform_sampler
3060 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
3061 %res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %input_u32
3062 )";
3063 
3064   spv_target_env env = SPV_ENV_VULKAN_1_0;
3065   CompileSuccessfully(GenerateShaderCode(body, "", "Fragment", "", env).c_str(),
3066                       env);
3067   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
3068   EXPECT_THAT(getDiagnosticString(),
3069               AnyVUID("VUID-StandaloneSpirv-OpImageGather-04664"));
3070   EXPECT_THAT(getDiagnosticString(),
3071               HasSubstr("Expected Component Operand to be a const object for "
3072                         "Vulkan environment"));
3073 }
3074 
TEST_F(ValidateImage,GatherDimCube)3075 TEST_F(ValidateImage, GatherDimCube) {
3076   const std::string body = R"(
3077 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
3078 %sampler = OpLoad %type_sampler %uniform_sampler
3079 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
3080 %res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 ConstOffsets %const_offsets
3081 )";
3082 
3083   CompileSuccessfully(GenerateShaderCode(body).c_str());
3084   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3085   EXPECT_THAT(
3086       getDiagnosticString(),
3087       HasSubstr(
3088           "Image Operand ConstOffsets cannot be used with Cube Image 'Dim'"));
3089 }
3090 
TEST_F(ValidateImage,GatherConstOffsetsNotArray)3091 TEST_F(ValidateImage, GatherConstOffsetsNotArray) {
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 %u32vec4_0123
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,GatherConstOffsetsArrayWrongSize)3107 TEST_F(ValidateImage, GatherConstOffsetsArrayWrongSize) {
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_offsets3x2
3113 )";
3114 
3115   CompileSuccessfully(GenerateShaderCode(body).c_str());
3116   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3117   EXPECT_THAT(
3118       getDiagnosticString(),
3119       HasSubstr(
3120           "Expected Image Operand ConstOffsets to be an array of size 4"));
3121 }
3122 
TEST_F(ValidateImage,GatherConstOffsetsArrayNotVector)3123 TEST_F(ValidateImage, GatherConstOffsetsArrayNotVector) {
3124   const std::string body = R"(
3125 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3126 %sampler = OpLoad %type_sampler %uniform_sampler
3127 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3128 %res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 ConstOffsets %const_offsets4xu
3129 )";
3130 
3131   CompileSuccessfully(GenerateShaderCode(body).c_str());
3132   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3133   EXPECT_THAT(getDiagnosticString(),
3134               HasSubstr("Expected Image Operand ConstOffsets array componenets "
3135                         "to be int vectors of size 2"));
3136 }
3137 
TEST_F(ValidateImage,GatherConstOffsetsArrayVectorWrongSize)3138 TEST_F(ValidateImage, GatherConstOffsetsArrayVectorWrongSize) {
3139   const std::string body = R"(
3140 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3141 %sampler = OpLoad %type_sampler %uniform_sampler
3142 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3143 %res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 ConstOffsets %const_offsets4x3
3144 )";
3145 
3146   CompileSuccessfully(GenerateShaderCode(body).c_str());
3147   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3148   EXPECT_THAT(getDiagnosticString(),
3149               HasSubstr("Expected Image Operand ConstOffsets array componenets "
3150                         "to be int vectors of size 2"));
3151 }
3152 
TEST_F(ValidateImage,GatherConstOffsetsArrayNotConst)3153 TEST_F(ValidateImage, GatherConstOffsetsArrayNotConst) {
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 %offsets = OpUndef %u32vec2arr4
3159 %res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 ConstOffsets %offsets
3160 )";
3161 
3162   CompileSuccessfully(GenerateShaderCode(body).c_str());
3163   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3164   EXPECT_THAT(
3165       getDiagnosticString(),
3166       HasSubstr("Expected Image Operand ConstOffsets to be a const object"));
3167 }
3168 
TEST_F(ValidateImage,NotGatherWithConstOffsets)3169 TEST_F(ValidateImage, NotGatherWithConstOffsets) {
3170   const std::string body = R"(
3171 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3172 %sampler = OpLoad %type_sampler %uniform_sampler
3173 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3174 %res2 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh ConstOffsets %const_offsets
3175 )";
3176 
3177   CompileSuccessfully(GenerateShaderCode(body).c_str());
3178   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3179   EXPECT_THAT(
3180       getDiagnosticString(),
3181       HasSubstr(
3182           "Image Operand ConstOffsets can only be used with OpImageGather "
3183           "and OpImageDrefGather"));
3184 }
3185 
TEST_F(ValidateImage,DrefGatherSuccess)3186 TEST_F(ValidateImage, DrefGatherSuccess) {
3187   const std::string body = R"(
3188 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3189 %sampler = OpLoad %type_sampler %uniform_sampler
3190 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3191 %res1 = OpImageDrefGather %f32vec4 %simg %f32vec4_0000 %f32_0_5
3192 %res2 = OpImageDrefGather %f32vec4 %simg %f32vec4_0000 %f32_0_5 ConstOffsets %const_offsets
3193 %res3 = OpImageDrefGather %f32vec4 %simg %f32vec4_0000 %f32_0_5 NonPrivateTexelKHR
3194 )";
3195 
3196   const std::string extra = R"(
3197 OpCapability VulkanMemoryModelKHR
3198 OpExtension "SPV_KHR_vulkan_memory_model"
3199 )";
3200   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
3201                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
3202                           .c_str());
3203   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
3204 }
3205 
TEST_F(ValidateImage,DrefGatherMultisampleError)3206 TEST_F(ValidateImage, DrefGatherMultisampleError) {
3207   const std::string body = R"(
3208 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
3209 %sampler = OpLoad %type_sampler %uniform_sampler
3210 %simg = OpSampledImage %type_sampled_image_f32_2d_0011 %img %sampler
3211 %res1 = OpImageDrefGather %f32vec4 %simg %f32vec4_0000 %f32_1 Sample %u32_1
3212 )";
3213 
3214   CompileSuccessfully(GenerateShaderCode(body).c_str());
3215   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3216   EXPECT_THAT(getDiagnosticString(),
3217               HasSubstr("Gather operation is invalid for multisample image"));
3218 }
3219 
TEST_F(ValidateImage,DrefGatherVoidSampledType)3220 TEST_F(ValidateImage, DrefGatherVoidSampledType) {
3221   const std::string body = R"(
3222 %img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001
3223 %sampler = OpLoad %type_sampler %uniform_sampler
3224 %simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler
3225 %res1 = OpImageDrefGather %u32vec4 %simg %f32vec2_00 %f32_0_5
3226 )";
3227 
3228   CompileSuccessfully(GenerateShaderCode(body).c_str());
3229   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3230   EXPECT_THAT(getDiagnosticString(),
3231               HasSubstr("Expected Image 'Sampled Type' to be the same as "
3232                         "Result Type components"));
3233 }
3234 
TEST_F(ValidateImage,DrefGatherWrongDrefType)3235 TEST_F(ValidateImage, DrefGatherWrongDrefType) {
3236   const std::string body = R"(
3237 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
3238 %sampler = OpLoad %type_sampler %uniform_sampler
3239 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
3240 %res1 = OpImageDrefGather %f32vec4 %simg %f32vec4_0000 %u32_1
3241 )";
3242 
3243   CompileSuccessfully(GenerateShaderCode(body).c_str());
3244   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3245   EXPECT_THAT(getDiagnosticString(),
3246               HasSubstr("Expected Dref to be of 32-bit float type"));
3247 }
3248 
TEST_F(ValidateImage,ReadSuccess1)3249 TEST_F(ValidateImage, ReadSuccess1) {
3250   const std::string body = R"(
3251 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
3252 %res1 = OpImageRead %u32vec4 %img %u32vec2_01
3253 )";
3254 
3255   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
3256   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3257   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3258 }
3259 
TEST_F(ValidateImage,ReadSuccess2)3260 TEST_F(ValidateImage, ReadSuccess2) {
3261   const std::string body = R"(
3262 %img = OpLoad %type_image_f32_1d_0002_rgba32f %uniform_image_f32_1d_0002_rgba32f
3263 %res1 = OpImageRead %f32vec4 %img %u32vec2_01
3264 )";
3265 
3266   const std::string extra = "\nOpCapability Image1D\n";
3267   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3268   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3269 }
3270 
TEST_F(ValidateImage,ReadSuccess3)3271 TEST_F(ValidateImage, ReadSuccess3) {
3272   const std::string body = R"(
3273 %img = OpLoad %type_image_f32_cube_0102_rgba32f %uniform_image_f32_cube_0102_rgba32f
3274 %res1 = OpImageRead %f32vec4 %img %u32vec3_012
3275 )";
3276 
3277   const std::string extra = "\nOpCapability ImageCubeArray\n";
3278   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3279   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3280 }
3281 
TEST_F(ValidateImage,ReadSuccess4)3282 TEST_F(ValidateImage, ReadSuccess4) {
3283   const std::string body = R"(
3284 %img = OpLoad %type_image_f32_spd_0002 %uniform_image_f32_spd_0002
3285 %res1 = OpImageRead %f32vec4 %img %u32vec2_01
3286 )";
3287 
3288   CompileSuccessfully(GenerateShaderCode(body).c_str());
3289   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3290 }
3291 
TEST_F(ValidateImage,ReadNeedCapabilityStorageImageReadWithoutFormat)3292 TEST_F(ValidateImage, ReadNeedCapabilityStorageImageReadWithoutFormat) {
3293   const std::string body = R"(
3294 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
3295 %res1 = OpImageRead %u32vec4 %img %u32vec2_01
3296 )";
3297 
3298   CompileSuccessfully(GenerateShaderCode(body).c_str());
3299   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3300 }
3301 
TEST_F(ValidateImage,ReadNeedCapabilityStorageImageReadWithoutFormatVulkan)3302 TEST_F(ValidateImage, ReadNeedCapabilityStorageImageReadWithoutFormatVulkan) {
3303   const std::string body = R"(
3304 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
3305 %res1 = OpImageRead %u32vec4 %img %u32vec2_01
3306 )";
3307 
3308   spv_target_env env = SPV_ENV_VULKAN_1_0;
3309   CompileSuccessfully(GenerateShaderCode(body, "", "Fragment", "", env).c_str(),
3310                       env);
3311   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
3312   EXPECT_THAT(getDiagnosticString(),
3313               HasSubstr("Capability StorageImageReadWithoutFormat is required "
3314                         "to read storage image"));
3315 }
3316 
TEST_F(ValidateImage,ReadNeedCapabilityImage1D)3317 TEST_F(ValidateImage, ReadNeedCapabilityImage1D) {
3318   const std::string body = R"(
3319 %img = OpLoad %type_image_f32_1d_0002_rgba32f %uniform_image_f32_1d_0002_rgba32f
3320 %res1 = OpImageRead %f32vec4 %img %u32vec2_01
3321 )";
3322 
3323   CompileSuccessfully(GenerateShaderCode(body).c_str());
3324   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3325   EXPECT_THAT(
3326       getDiagnosticString(),
3327       HasSubstr("Capability Image1D is required to access storage image"));
3328 }
3329 
TEST_F(ValidateImage,ReadNeedCapabilityImageCubeArray)3330 TEST_F(ValidateImage, ReadNeedCapabilityImageCubeArray) {
3331   const std::string body = R"(
3332 %img = OpLoad %type_image_f32_cube_0102_rgba32f %uniform_image_f32_cube_0102_rgba32f
3333 %res1 = OpImageRead %f32vec4 %img %u32vec3_012
3334 )";
3335 
3336   CompileSuccessfully(GenerateShaderCode(body).c_str());
3337   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3338   EXPECT_THAT(
3339       getDiagnosticString(),
3340       HasSubstr(
3341           "Capability ImageCubeArray is required to access storage image"));
3342 }
3343 
3344 // TODO(atgoo@github.com) Disabled until the spec is clarified.
TEST_F(ValidateImage,DISABLED_ReadWrongResultType)3345 TEST_F(ValidateImage, DISABLED_ReadWrongResultType) {
3346   const std::string body = R"(
3347 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
3348 %res1 = OpImageRead %f32 %img %u32vec2_01
3349 )";
3350 
3351   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
3352   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3353   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3354   EXPECT_THAT(getDiagnosticString(),
3355               HasSubstr("Expected Result Type to be int or float vector type"));
3356 }
3357 
TEST_F(ValidateImage,ReadScalarResultType_Universal)3358 TEST_F(ValidateImage, ReadScalarResultType_Universal) {
3359   const std::string body = R"(
3360 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
3361 %res1 = OpImageRead %u32 %img %u32vec2_01
3362 )";
3363 
3364   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
3365   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3366   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_0));
3367   EXPECT_THAT(getDiagnosticString(), Eq(""));
3368 }
3369 
TEST_F(ValidateImage,ReadUnusualNumComponentsResultType_Universal)3370 TEST_F(ValidateImage, ReadUnusualNumComponentsResultType_Universal) {
3371   const std::string body = R"(
3372 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
3373 %res1 = OpImageRead %u32vec3 %img %u32vec2_01
3374 )";
3375 
3376   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
3377   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3378   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_0));
3379   EXPECT_THAT(getDiagnosticString(), Eq(""));
3380 }
3381 
TEST_F(ValidateImage,ReadWrongNumComponentsResultType_Vulkan)3382 TEST_F(ValidateImage, ReadWrongNumComponentsResultType_Vulkan) {
3383   const std::string body = R"(
3384 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
3385 %res1 = OpImageRead %u32vec3 %img %u32vec2_01
3386 )";
3387 
3388   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
3389   CompileSuccessfully(
3390       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_VULKAN_1_0)
3391           .c_str());
3392   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
3393   EXPECT_THAT(getDiagnosticString(),
3394               AnyVUID("VUID-StandaloneSpirv-Result-04780"));
3395   EXPECT_THAT(getDiagnosticString(),
3396               HasSubstr("Expected Result Type to have 4 components"));
3397 }
3398 
TEST_F(ValidateImage,ReadNotImage)3399 TEST_F(ValidateImage, ReadNotImage) {
3400   const std::string body = R"(
3401 %sampler = OpLoad %type_sampler %uniform_sampler
3402 %res1 = OpImageRead %f32vec4 %sampler %u32vec2_01
3403 )";
3404 
3405   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
3406   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3407   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3408   EXPECT_THAT(getDiagnosticString(),
3409               HasSubstr("Expected Image to be of type OpTypeImage"));
3410 }
3411 
TEST_F(ValidateImage,ReadImageSampled)3412 TEST_F(ValidateImage, ReadImageSampled) {
3413   const std::string body = R"(
3414 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3415 %res1 = OpImageRead %f32vec4 %img %u32vec2_01
3416 )";
3417 
3418   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
3419   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3420   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3421   EXPECT_THAT(getDiagnosticString(),
3422               HasSubstr("Expected Image 'Sampled' parameter to be 0 or 2"));
3423 }
3424 
TEST_F(ValidateImage,ReadWrongSampledType)3425 TEST_F(ValidateImage, ReadWrongSampledType) {
3426   const std::string body = R"(
3427 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
3428 %res1 = OpImageRead %f32vec4 %img %u32vec2_01
3429 )";
3430 
3431   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
3432   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3433   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3434   EXPECT_THAT(getDiagnosticString(),
3435               HasSubstr("Expected Image 'Sampled Type' to be the same as "
3436                         "Result Type components"));
3437 }
3438 
TEST_F(ValidateImage,ReadVoidSampledType)3439 TEST_F(ValidateImage, ReadVoidSampledType) {
3440   const std::string body = R"(
3441 %img = OpLoad %type_image_void_2d_0002 %uniform_image_void_2d_0002
3442 %res1 = OpImageRead %f32vec4 %img %u32vec2_01
3443 %res2 = OpImageRead %u32vec4 %img %u32vec2_01
3444 %res3 = OpImageRead %s32vec4 %img %u32vec2_01
3445 )";
3446 
3447   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
3448   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3449   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3450 }
3451 
TEST_F(ValidateImage,ReadWrongCoordinateType)3452 TEST_F(ValidateImage, ReadWrongCoordinateType) {
3453   const std::string body = R"(
3454 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
3455 %res1 = OpImageRead %u32vec4 %img %f32vec2_00
3456 )";
3457 
3458   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
3459   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3460   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3461   EXPECT_THAT(getDiagnosticString(),
3462               HasSubstr("Expected Coordinate to be int scalar or vector"));
3463 }
3464 
TEST_F(ValidateImage,ReadCoordinateSizeTooSmall)3465 TEST_F(ValidateImage, ReadCoordinateSizeTooSmall) {
3466   const std::string body = R"(
3467 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
3468 %res1 = OpImageRead %u32vec4 %img %u32_1
3469 )";
3470 
3471   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
3472   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3473   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3474   EXPECT_THAT(getDiagnosticString(),
3475               HasSubstr("Expected Coordinate to have at least 2 components, "
3476                         "but given only 1"));
3477 }
3478 
TEST_F(ValidateImage,WriteSuccess1)3479 TEST_F(ValidateImage, WriteSuccess1) {
3480   const std::string body = R"(
3481 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
3482 OpImageWrite %img %u32vec2_01 %u32vec4_0123
3483 )";
3484 
3485   const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n";
3486   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3487   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3488 }
3489 
TEST_F(ValidateImage,WriteSuccess2)3490 TEST_F(ValidateImage, WriteSuccess2) {
3491   const std::string body = R"(
3492 %img = OpLoad %type_image_f32_1d_0002_rgba32f %uniform_image_f32_1d_0002_rgba32f
3493 OpImageWrite %img %u32_1 %f32vec4_0000
3494 )";
3495 
3496   const std::string extra = "\nOpCapability Image1D\n";
3497   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3498   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3499 }
3500 
TEST_F(ValidateImage,WriteSuccess3)3501 TEST_F(ValidateImage, WriteSuccess3) {
3502   const std::string body = R"(
3503 %img = OpLoad %type_image_f32_cube_0102_rgba32f %uniform_image_f32_cube_0102_rgba32f
3504 OpImageWrite %img %u32vec3_012 %f32vec4_0000
3505 )";
3506 
3507   const std::string extra = "\nOpCapability ImageCubeArray\n";
3508   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3509   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3510 }
3511 
TEST_F(ValidateImage,WriteSuccess4)3512 TEST_F(ValidateImage, WriteSuccess4) {
3513   const std::string body = R"(
3514 %img = OpLoad %type_image_f32_2d_0012 %uniform_image_f32_2d_0012
3515 OpImageWrite %img %u32vec2_01 %f32vec4_0000 Sample %u32_1
3516 )";
3517 
3518   const std::string extra = R"(
3519     OpCapability StorageImageWriteWithoutFormat
3520     OpCapability StorageImageMultisample
3521     )";
3522 
3523   const std::string declarations = R"(
3524 %type_image_f32_2d_0012 = OpTypeImage %f32 2D 0 0 1 2 Unknown
3525 %ptr_image_f32_2d_0012 = OpTypePointer UniformConstant %type_image_f32_2d_0012
3526 %uniform_image_f32_2d_0012 = OpVariable %ptr_image_f32_2d_0012 UniformConstant
3527     )";
3528   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
3529                                          SPV_ENV_UNIVERSAL_1_0, "GLSL450",
3530                                          declarations)
3531                           .c_str());
3532   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3533 }
3534 
TEST_F(ValidateImage,WriteSubpassData)3535 TEST_F(ValidateImage, WriteSubpassData) {
3536   const std::string body = R"(
3537 %img = OpLoad %type_image_f32_spd_0002 %uniform_image_f32_spd_0002
3538 OpImageWrite %img %u32vec2_01 %f32vec4_0000
3539 )";
3540 
3541   CompileSuccessfully(GenerateShaderCode(body).c_str());
3542   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3543   EXPECT_THAT(getDiagnosticString(),
3544               HasSubstr("Image 'Dim' cannot be SubpassData"));
3545 }
3546 
TEST_F(ValidateImage,WriteNeedCapabilityStorageImageWriteWithoutFormat)3547 TEST_F(ValidateImage, WriteNeedCapabilityStorageImageWriteWithoutFormat) {
3548   const std::string body = R"(
3549 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
3550 OpImageWrite %img %u32vec2_01 %u32vec4_0123
3551 )";
3552 
3553   CompileSuccessfully(GenerateShaderCode(body).c_str());
3554   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3555 }
3556 
TEST_F(ValidateImage,WriteNeedCapabilityStorageImageWriteWithoutFormatVulkan)3557 TEST_F(ValidateImage, WriteNeedCapabilityStorageImageWriteWithoutFormatVulkan) {
3558   const std::string body = R"(
3559 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
3560 OpImageWrite %img %u32vec2_01 %u32vec4_0123
3561 )";
3562 
3563   spv_target_env env = SPV_ENV_VULKAN_1_0;
3564   CompileSuccessfully(GenerateShaderCode(body, "", "Fragment", "", env).c_str(),
3565                       env);
3566   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
3567   EXPECT_THAT(
3568       getDiagnosticString(),
3569       HasSubstr(
3570           "Capability StorageImageWriteWithoutFormat is required to write to "
3571           "storage image"));
3572 }
3573 
TEST_F(ValidateImage,WriteNeedCapabilityImage1D)3574 TEST_F(ValidateImage, WriteNeedCapabilityImage1D) {
3575   const std::string body = R"(
3576 %img = OpLoad %type_image_f32_1d_0002_rgba32f %uniform_image_f32_1d_0002_rgba32f
3577 OpImageWrite %img %u32vec2_01 %f32vec4_0000
3578 )";
3579 
3580   CompileSuccessfully(GenerateShaderCode(body).c_str());
3581   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3582   EXPECT_THAT(getDiagnosticString(),
3583               HasSubstr("Capability Image1D is required to access storage "
3584                         "image"));
3585 }
3586 
TEST_F(ValidateImage,WriteNeedCapabilityImageCubeArray)3587 TEST_F(ValidateImage, WriteNeedCapabilityImageCubeArray) {
3588   const std::string body = R"(
3589 %img = OpLoad %type_image_f32_cube_0102_rgba32f %uniform_image_f32_cube_0102_rgba32f
3590 OpImageWrite %img %u32vec3_012 %f32vec4_0000
3591 )";
3592 
3593   CompileSuccessfully(GenerateShaderCode(body).c_str());
3594   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3595   EXPECT_THAT(
3596       getDiagnosticString(),
3597       HasSubstr(
3598           "Capability ImageCubeArray is required to access storage image"));
3599 }
3600 
TEST_F(ValidateImage,WriteNotImage)3601 TEST_F(ValidateImage, WriteNotImage) {
3602   const std::string body = R"(
3603 %sampler = OpLoad %type_sampler %uniform_sampler
3604 OpImageWrite %sampler %u32vec2_01 %f32vec4_0000
3605 )";
3606 
3607   CompileSuccessfully(GenerateShaderCode(body).c_str());
3608   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3609   EXPECT_THAT(getDiagnosticString(),
3610               HasSubstr("Expected Image to be of type OpTypeImage"));
3611 }
3612 
TEST_F(ValidateImage,WriteImageSampled)3613 TEST_F(ValidateImage, WriteImageSampled) {
3614   const std::string body = R"(
3615 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3616 OpImageWrite %img %u32vec2_01 %f32vec4_0000
3617 )";
3618 
3619   const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n";
3620   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3621   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3622   EXPECT_THAT(getDiagnosticString(),
3623               HasSubstr("Expected Image 'Sampled' parameter to be 0 or 2"));
3624 }
3625 
TEST_F(ValidateImage,WriteWrongCoordinateType)3626 TEST_F(ValidateImage, WriteWrongCoordinateType) {
3627   const std::string body = R"(
3628 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
3629 OpImageWrite %img %f32vec2_00 %u32vec4_0123
3630 )";
3631 
3632   const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n";
3633   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3634   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3635   EXPECT_THAT(getDiagnosticString(),
3636               HasSubstr("Expected Coordinate to be int scalar or vector"));
3637 }
3638 
TEST_F(ValidateImage,WriteCoordinateSizeTooSmall)3639 TEST_F(ValidateImage, WriteCoordinateSizeTooSmall) {
3640   const std::string body = R"(
3641 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
3642 OpImageWrite %img %u32_1 %u32vec4_0123
3643 )";
3644 
3645   const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n";
3646   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3647   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3648   EXPECT_THAT(getDiagnosticString(),
3649               HasSubstr("Expected Coordinate to have at least 2 components, "
3650                         "but given only 1"));
3651 }
3652 
TEST_F(ValidateImage,WriteTexelWrongType)3653 TEST_F(ValidateImage, WriteTexelWrongType) {
3654   const std::string body = R"(
3655 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
3656 OpImageWrite %img %u32vec2_01 %img
3657 )";
3658 
3659   const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n";
3660   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3661   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3662   EXPECT_THAT(getDiagnosticString(),
3663               HasSubstr("Expected Texel to be int or float vector or scalar"));
3664 }
3665 
TEST_F(ValidateImage,DISABLED_WriteTexelNotVector4)3666 TEST_F(ValidateImage, DISABLED_WriteTexelNotVector4) {
3667   const std::string body = R"(
3668 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
3669 OpImageWrite %img %u32vec2_01 %u32vec3_012
3670 )";
3671 
3672   const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n";
3673   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3674   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3675   EXPECT_THAT(getDiagnosticString(),
3676               HasSubstr("Expected Texel to have 4 components"));
3677 }
3678 
TEST_F(ValidateImage,WriteTexelWrongComponentType)3679 TEST_F(ValidateImage, WriteTexelWrongComponentType) {
3680   const std::string body = R"(
3681 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
3682 OpImageWrite %img %u32vec2_01 %f32vec4_0000
3683 )";
3684 
3685   const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n";
3686   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3687   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3688   EXPECT_THAT(
3689       getDiagnosticString(),
3690       HasSubstr(
3691           "Expected Image 'Sampled Type' to be the same as Texel components"));
3692 }
3693 
TEST_F(ValidateImage,WriteSampleNotInteger)3694 TEST_F(ValidateImage, WriteSampleNotInteger) {
3695   const std::string body = R"(
3696 %img = OpLoad %type_image_f32_2d_0012 %uniform_image_f32_2d_0012
3697 OpImageWrite %img %u32vec2_01 %f32vec4_0000 Sample %f32_1
3698 )";
3699 
3700   const std::string extra = R"(
3701     OpCapability StorageImageWriteWithoutFormat
3702     OpCapability StorageImageMultisample
3703     )";
3704   const std::string declarations = R"(
3705 %type_image_f32_2d_0012 = OpTypeImage %f32 2D 0 0 1 2 Unknown
3706 %ptr_image_f32_2d_0012 = OpTypePointer UniformConstant %type_image_f32_2d_0012
3707 %uniform_image_f32_2d_0012 = OpVariable %ptr_image_f32_2d_0012 UniformConstant
3708     )";
3709   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
3710                                          SPV_ENV_UNIVERSAL_1_0, "GLSL450",
3711                                          declarations)
3712                           .c_str());
3713   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3714   EXPECT_THAT(getDiagnosticString(),
3715               HasSubstr("Expected Image Operand Sample to be int scalar"));
3716 }
3717 
TEST_F(ValidateImage,WriteSampleNotMultisampled)3718 TEST_F(ValidateImage, WriteSampleNotMultisampled) {
3719   const std::string body = R"(
3720 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
3721 OpImageWrite %img %u32vec2_01 %f32vec4_0000 Sample %u32_1
3722 )";
3723 
3724   const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n";
3725   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3726   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3727   EXPECT_THAT(
3728       getDiagnosticString(),
3729       HasSubstr("Image Operand Sample requires non-zero 'MS' parameter"));
3730 }
3731 
TEST_F(ValidateImage,SampleWrongOpcode)3732 TEST_F(ValidateImage, SampleWrongOpcode) {
3733   const std::string body = R"(
3734 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
3735 %sampler = OpLoad %type_sampler %uniform_sampler
3736 %simg = OpSampledImage %type_sampled_image_f32_2d_0011 %img %sampler
3737 %res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_00 Sample %u32_1
3738 )";
3739 
3740   CompileSuccessfully(GenerateShaderCode(body).c_str());
3741   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3742   EXPECT_THAT(getDiagnosticString(),
3743               HasSubstr("Sampling operation is invalid for multisample image"));
3744 }
3745 
TEST_F(ValidateImage,SampleImageToImageSuccess)3746 TEST_F(ValidateImage, SampleImageToImageSuccess) {
3747   const std::string body = R"(
3748 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3749 %sampler = OpLoad %type_sampler %uniform_sampler
3750 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3751 %img2 = OpImage %type_image_f32_2d_0001 %simg
3752 )";
3753 
3754   CompileSuccessfully(GenerateShaderCode(body).c_str());
3755   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3756 }
3757 
TEST_F(ValidateImage,SampleImageToImageWrongResultType)3758 TEST_F(ValidateImage, SampleImageToImageWrongResultType) {
3759   const std::string body = R"(
3760 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3761 %sampler = OpLoad %type_sampler %uniform_sampler
3762 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3763 %img2 = OpImage %type_sampled_image_f32_2d_0001 %simg
3764 )";
3765 
3766   CompileSuccessfully(GenerateShaderCode(body).c_str());
3767   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3768   EXPECT_THAT(getDiagnosticString(),
3769               HasSubstr("Expected Result Type to be OpTypeImage"));
3770 }
3771 
TEST_F(ValidateImage,SampleImageToImageNotSampledImage)3772 TEST_F(ValidateImage, SampleImageToImageNotSampledImage) {
3773   const std::string body = R"(
3774 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3775 %img2 = OpImage %type_image_f32_2d_0001 %img
3776 )";
3777 
3778   CompileSuccessfully(GenerateShaderCode(body).c_str());
3779   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3780   EXPECT_THAT(
3781       getDiagnosticString(),
3782       HasSubstr("Expected Sample Image to be of type OpTypeSampleImage"));
3783 }
3784 
TEST_F(ValidateImage,SampleImageToImageNotTheSameImageType)3785 TEST_F(ValidateImage, SampleImageToImageNotTheSameImageType) {
3786   const std::string body = R"(
3787 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3788 %sampler = OpLoad %type_sampler %uniform_sampler
3789 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3790 %img2 = OpImage %type_image_f32_2d_0002 %simg
3791 )";
3792 
3793   CompileSuccessfully(GenerateShaderCode(body).c_str());
3794   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3795   EXPECT_THAT(getDiagnosticString(),
3796               HasSubstr("Expected Sample Image image type to be equal to "
3797                         "Result Type"));
3798 }
3799 
TEST_F(ValidateImage,QueryFormatSuccess)3800 TEST_F(ValidateImage, QueryFormatSuccess) {
3801   const std::string body = R"(
3802 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3803 %res1 = OpImageQueryFormat %u32 %img
3804 )";
3805 
3806   CompileSuccessfully(GenerateKernelCode(body).c_str());
3807   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3808 }
3809 
TEST_F(ValidateImage,QueryFormatWrongResultType)3810 TEST_F(ValidateImage, QueryFormatWrongResultType) {
3811   const std::string body = R"(
3812 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3813 %res1 = OpImageQueryFormat %bool %img
3814 )";
3815 
3816   CompileSuccessfully(GenerateKernelCode(body).c_str());
3817   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3818   EXPECT_THAT(getDiagnosticString(),
3819               HasSubstr("Expected Result Type to be int scalar type"));
3820 }
3821 
TEST_F(ValidateImage,QueryFormatNotImage)3822 TEST_F(ValidateImage, QueryFormatNotImage) {
3823   const std::string body = R"(
3824 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3825 %sampler = OpLoad %type_sampler %uniform_sampler
3826 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3827 %res1 = OpImageQueryFormat %u32 %sampler
3828 )";
3829 
3830   CompileSuccessfully(GenerateKernelCode(body).c_str());
3831   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3832   EXPECT_THAT(getDiagnosticString(),
3833               HasSubstr("Expected operand to be of type OpTypeImage"));
3834 }
3835 
TEST_F(ValidateImage,QueryOrderSuccess)3836 TEST_F(ValidateImage, QueryOrderSuccess) {
3837   const std::string body = R"(
3838 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3839 %res1 = OpImageQueryOrder %u32 %img
3840 )";
3841 
3842   CompileSuccessfully(GenerateKernelCode(body).c_str());
3843   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3844 }
3845 
TEST_F(ValidateImage,QueryOrderWrongResultType)3846 TEST_F(ValidateImage, QueryOrderWrongResultType) {
3847   const std::string body = R"(
3848 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3849 %res1 = OpImageQueryOrder %bool %img
3850 )";
3851 
3852   CompileSuccessfully(GenerateKernelCode(body).c_str());
3853   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3854   EXPECT_THAT(getDiagnosticString(),
3855               HasSubstr("Expected Result Type to be int scalar type"));
3856 }
3857 
TEST_F(ValidateImage,QueryOrderNotImage)3858 TEST_F(ValidateImage, QueryOrderNotImage) {
3859   const std::string body = R"(
3860 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3861 %sampler = OpLoad %type_sampler %uniform_sampler
3862 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3863 %res1 = OpImageQueryOrder %u32 %sampler
3864 )";
3865 
3866   CompileSuccessfully(GenerateKernelCode(body).c_str());
3867   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3868   EXPECT_THAT(getDiagnosticString(),
3869               HasSubstr("Expected operand to be of type OpTypeImage"));
3870 }
3871 
TEST_F(ValidateImage,QuerySizeLodSuccess)3872 TEST_F(ValidateImage, QuerySizeLodSuccess) {
3873   const std::string body = R"(
3874 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3875 %res1 = OpImageQuerySizeLod %u32vec2 %img %u32_1
3876 )";
3877 
3878   CompileSuccessfully(GenerateKernelCode(body).c_str());
3879   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3880 }
3881 
TEST_F(ValidateImage,QuerySizeLodWrongResultType)3882 TEST_F(ValidateImage, QuerySizeLodWrongResultType) {
3883   const std::string body = R"(
3884 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3885 %res1 = OpImageQuerySizeLod %f32vec2 %img %u32_1
3886 )";
3887 
3888   CompileSuccessfully(GenerateKernelCode(body).c_str());
3889   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3890   EXPECT_THAT(
3891       getDiagnosticString(),
3892       HasSubstr("Expected Result Type to be int scalar or vector type"));
3893 }
3894 
TEST_F(ValidateImage,QuerySizeLodResultTypeWrongSize)3895 TEST_F(ValidateImage, QuerySizeLodResultTypeWrongSize) {
3896   const std::string body = R"(
3897 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3898 %res1 = OpImageQuerySizeLod %u32 %img %u32_1
3899 )";
3900 
3901   CompileSuccessfully(GenerateKernelCode(body).c_str());
3902   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3903   EXPECT_THAT(getDiagnosticString(),
3904               HasSubstr("Result Type has 1 components, but 2 expected"));
3905 }
3906 
TEST_F(ValidateImage,QuerySizeLodNotImage)3907 TEST_F(ValidateImage, QuerySizeLodNotImage) {
3908   const std::string body = R"(
3909 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3910 %sampler = OpLoad %type_sampler %uniform_sampler
3911 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3912 %res1 = OpImageQuerySizeLod %u32vec2 %sampler %u32_1
3913 )";
3914 
3915   CompileSuccessfully(GenerateKernelCode(body).c_str());
3916   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3917   EXPECT_THAT(getDiagnosticString(),
3918               HasSubstr("Expected Image to be of type OpTypeImage"));
3919 }
3920 
TEST_F(ValidateImage,QuerySizeLodSampledImageDirectly)3921 TEST_F(ValidateImage, QuerySizeLodSampledImageDirectly) {
3922   const std::string body = R"(
3923 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3924 %sampler = OpLoad %type_sampler %uniform_sampler
3925 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3926 %res1 = OpImageQuerySizeLod %u32vec2 %simg %u32_1
3927 )";
3928 
3929   CompileSuccessfully(GenerateShaderCode(body).c_str());
3930   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3931   EXPECT_THAT(getDiagnosticString(),
3932               HasSubstr("OpSampledImage instruction must not appear as operand "
3933                         "for OpImageQuerySizeLod"));
3934 }
3935 
TEST_F(ValidateImage,QuerySizeLodMultisampledError)3936 TEST_F(ValidateImage, QuerySizeLodMultisampledError) {
3937   const std::string body = R"(
3938 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
3939 %res1 = OpImageQuerySizeLod %u32vec2 %img %u32_1
3940 )";
3941 
3942   CompileSuccessfully(GenerateKernelCode(body).c_str());
3943   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3944   EXPECT_THAT(getDiagnosticString(), HasSubstr("Image 'MS' must be 0"));
3945 }
3946 
TEST_F(ValidateImage,QuerySizeLodNonSampledUniversalSuccess)3947 TEST_F(ValidateImage, QuerySizeLodNonSampledUniversalSuccess) {
3948   const std::string body = R"(
3949 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
3950 %res1 = OpImageQuerySizeLod %u32vec2 %img %u32_1
3951 )";
3952 
3953   CompileSuccessfully(GenerateShaderCode(body).c_str());
3954   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3955   EXPECT_EQ(getDiagnosticString(), "");
3956 }
3957 
TEST_F(ValidateImage,QuerySizeLodVulkanNonSampledError)3958 TEST_F(ValidateImage, QuerySizeLodVulkanNonSampledError) {
3959   // Create a whole shader module.  Avoid Vulkan incompatibility with
3960   // SampledRrect images inserted by helper function GenerateShaderCode.
3961   const std::string body = R"(
3962 OpCapability Shader
3963 OpCapability ImageQuery
3964 OpMemoryModel Logical Simple
3965 OpEntryPoint Fragment %main "main"
3966 OpExecutionMode %main OriginUpperLeft
3967 
3968 %f32 = OpTypeFloat 32
3969 %u32 = OpTypeInt 32 0
3970 %u32_0 = OpConstant %u32 0
3971 %u32vec2 = OpTypeVector %u32 2
3972 %void = OpTypeVoid
3973 %voidfn = OpTypeFunction %void
3974 
3975 ; Test with a storage image.
3976 %type_image_f32_2d_0002 = OpTypeImage %f32 2D 0 0 0 2 Rgba32f
3977 %ptr_image_f32_2d_0002 = OpTypePointer UniformConstant %type_image_f32_2d_0002
3978 %uniform_image_f32_2d_0002 = OpVariable %ptr_image_f32_2d_0002 UniformConstant
3979 
3980 %main = OpFunction %void None %voidfn
3981 %entry = OpLabel
3982 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
3983 %res1 = OpImageQuerySizeLod %u32vec2 %img %u32_0
3984 OpReturn
3985 OpFunctionEnd
3986 )";
3987 
3988   CompileSuccessfully(body.c_str());
3989   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
3990   EXPECT_THAT(getDiagnosticString(),
3991               AnyVUID("VUID-StandaloneSpirv-OpImageQuerySizeLod-04659"));
3992   EXPECT_THAT(
3993       getDiagnosticString(),
3994       HasSubstr(
3995           "OpImageQuerySizeLod must only consume an \"Image\" operand whose "
3996           "type has its \"Sampled\" operand set to 1"));
3997 }
3998 
TEST_F(ValidateImage,QuerySizeLodWrongImageDim)3999 TEST_F(ValidateImage, QuerySizeLodWrongImageDim) {
4000   const std::string body = R"(
4001 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
4002 %res1 = OpImageQuerySizeLod %u32vec2 %img %u32_1
4003 )";
4004 
4005   CompileSuccessfully(GenerateKernelCode(body).c_str());
4006   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4007   EXPECT_THAT(getDiagnosticString(),
4008               HasSubstr("Image 'Dim' must be 1D, 2D, 3D or Cube"));
4009 }
4010 
TEST_F(ValidateImage,QuerySizeLodWrongLodType)4011 TEST_F(ValidateImage, QuerySizeLodWrongLodType) {
4012   const std::string body = R"(
4013 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4014 %res1 = OpImageQuerySizeLod %u32vec2 %img %f32_0
4015 )";
4016 
4017   CompileSuccessfully(GenerateKernelCode(body).c_str());
4018   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4019   EXPECT_THAT(getDiagnosticString(),
4020               HasSubstr("Expected Level of Detail to be int scalar"));
4021 }
4022 
TEST_F(ValidateImage,QuerySizeSuccess)4023 TEST_F(ValidateImage, QuerySizeSuccess) {
4024   const std::string body = R"(
4025 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
4026 %res1 = OpImageQuerySize %u32vec2 %img
4027 )";
4028 
4029   CompileSuccessfully(GenerateKernelCode(body).c_str());
4030   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
4031 }
4032 
TEST_F(ValidateImage,QuerySizeWrongResultType)4033 TEST_F(ValidateImage, QuerySizeWrongResultType) {
4034   const std::string body = R"(
4035 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
4036 %res1 = OpImageQuerySize %f32vec2 %img
4037 )";
4038 
4039   CompileSuccessfully(GenerateKernelCode(body).c_str());
4040   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4041   EXPECT_THAT(
4042       getDiagnosticString(),
4043       HasSubstr("Expected Result Type to be int scalar or vector type"));
4044 }
4045 
TEST_F(ValidateImage,QuerySizeNotImage)4046 TEST_F(ValidateImage, QuerySizeNotImage) {
4047   const std::string body = R"(
4048 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
4049 %sampler = OpLoad %type_sampler %uniform_sampler
4050 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4051 %res1 = OpImageQuerySize %u32vec2 %sampler
4052 )";
4053 
4054   CompileSuccessfully(GenerateKernelCode(body).c_str());
4055   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4056   EXPECT_THAT(getDiagnosticString(),
4057               HasSubstr("Expected Image to be of type OpTypeImage"));
4058 }
4059 
TEST_F(ValidateImage,QuerySizeSampledImageDirectly)4060 TEST_F(ValidateImage, QuerySizeSampledImageDirectly) {
4061   const std::string body = R"(
4062 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
4063 %sampler = OpLoad %type_sampler %uniform_sampler
4064 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4065 %res1 = OpImageQuerySize %u32vec2 %simg
4066 )";
4067 
4068   CompileSuccessfully(GenerateShaderCode(body).c_str());
4069   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4070   EXPECT_THAT(getDiagnosticString(),
4071               HasSubstr("OpSampledImage instruction must not appear as operand "
4072                         "for OpImageQuerySize"));
4073 }
4074 
TEST_F(ValidateImage,QuerySizeDimSubpassDataBad)4075 TEST_F(ValidateImage, QuerySizeDimSubpassDataBad) {
4076   const std::string body = R"(
4077 %img = OpLoad %type_image_f32_spd_0002 %uniform_image_f32_spd_0002
4078 %res1 = OpImageQuerySize %u32vec2 %img
4079 )";
4080 
4081   CompileSuccessfully(GenerateShaderCode(body).c_str());
4082   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4083   EXPECT_THAT(
4084       getDiagnosticString(),
4085       HasSubstr("Image 'Dim' must be 1D, Buffer, 2D, Cube, 3D or Rect"));
4086 }
4087 
TEST_F(ValidateImage,QuerySizeWrongSampling)4088 TEST_F(ValidateImage, QuerySizeWrongSampling) {
4089   const std::string body = R"(
4090 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4091 %res1 = OpImageQuerySize %u32vec2 %img
4092 )";
4093 
4094   CompileSuccessfully(GenerateKernelCode(body).c_str());
4095   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4096   EXPECT_THAT(
4097       getDiagnosticString(),
4098       HasSubstr("Image must have either 'MS'=1 or 'Sampled'=0 or 'Sampled'=2"));
4099 }
4100 
TEST_F(ValidateImage,QuerySizeWrongNumberOfComponents)4101 TEST_F(ValidateImage, QuerySizeWrongNumberOfComponents) {
4102   const std::string body = R"(
4103 %img = OpLoad %type_image_f32_3d_0111 %uniform_image_f32_3d_0111
4104 %res1 = OpImageQuerySize %u32vec2 %img
4105 )";
4106 
4107   CompileSuccessfully(GenerateShaderCode(body).c_str());
4108   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4109   EXPECT_THAT(getDiagnosticString(),
4110               HasSubstr("Result Type has 2 components, but 4 expected"));
4111 }
4112 
TEST_F(ValidateImage,QueryLodSuccessKernel)4113 TEST_F(ValidateImage, QueryLodSuccessKernel) {
4114   const std::string body = R"(
4115 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4116 %sampler = OpLoad %type_sampler %uniform_sampler
4117 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4118 %res1 = OpImageQueryLod %f32vec2 %simg %f32vec2_hh
4119 %res2 = OpImageQueryLod %f32vec2 %simg %u32vec2_01
4120 )";
4121 
4122   CompileSuccessfully(GenerateKernelCode(body).c_str());
4123   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
4124 }
4125 
TEST_F(ValidateImage,QueryLodSuccessShader)4126 TEST_F(ValidateImage, QueryLodSuccessShader) {
4127   const std::string body = R"(
4128 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4129 %sampler = OpLoad %type_sampler %uniform_sampler
4130 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4131 %res1 = OpImageQueryLod %f32vec2 %simg %f32vec2_hh
4132 )";
4133 
4134   CompileSuccessfully(GenerateShaderCode(body).c_str());
4135   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
4136 }
4137 
TEST_F(ValidateImage,QueryLodWrongResultType)4138 TEST_F(ValidateImage, QueryLodWrongResultType) {
4139   const std::string body = R"(
4140 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4141 %sampler = OpLoad %type_sampler %uniform_sampler
4142 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4143 %res1 = OpImageQueryLod %u32vec2 %simg %f32vec2_hh
4144 )";
4145 
4146   CompileSuccessfully(GenerateKernelCode(body).c_str());
4147   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4148   EXPECT_THAT(getDiagnosticString(),
4149               HasSubstr("Expected Result Type to be float vector type"));
4150 }
4151 
TEST_F(ValidateImage,QueryLodResultTypeWrongSize)4152 TEST_F(ValidateImage, QueryLodResultTypeWrongSize) {
4153   const std::string body = R"(
4154 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4155 %sampler = OpLoad %type_sampler %uniform_sampler
4156 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4157 %res1 = OpImageQueryLod %f32vec3 %simg %f32vec2_hh
4158 )";
4159 
4160   CompileSuccessfully(GenerateKernelCode(body).c_str());
4161   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4162   EXPECT_THAT(getDiagnosticString(),
4163               HasSubstr("Expected Result Type to have 2 components"));
4164 }
4165 
TEST_F(ValidateImage,QueryLodNotSampledImage)4166 TEST_F(ValidateImage, QueryLodNotSampledImage) {
4167   const std::string body = R"(
4168 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4169 %res1 = OpImageQueryLod %f32vec2 %img %f32vec2_hh
4170 )";
4171 
4172   CompileSuccessfully(GenerateKernelCode(body).c_str());
4173   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4174   EXPECT_THAT(
4175       getDiagnosticString(),
4176       HasSubstr("Expected Image operand to be of type OpTypeSampledImage"));
4177 }
4178 
TEST_F(ValidateImage,QueryLodWrongDim)4179 TEST_F(ValidateImage, QueryLodWrongDim) {
4180   const std::string body = R"(
4181 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
4182 %sampler = OpLoad %type_sampler %uniform_sampler
4183 %simg = OpSampledImage %type_sampled_image_f32_rect_0001 %img %sampler
4184 %res1 = OpImageQueryLod %f32vec2 %simg %f32vec2_hh
4185 )";
4186 
4187   CompileSuccessfully(GenerateKernelCode(body).c_str());
4188   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4189   EXPECT_THAT(getDiagnosticString(),
4190               HasSubstr("Image 'Dim' must be 1D, 2D, 3D or Cube"));
4191 }
4192 
TEST_F(ValidateImage,QueryLodWrongCoordinateType)4193 TEST_F(ValidateImage, QueryLodWrongCoordinateType) {
4194   const std::string body = R"(
4195 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4196 %sampler = OpLoad %type_sampler %uniform_sampler
4197 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4198 %res1 = OpImageQueryLod %f32vec2 %simg %u32vec2_01
4199 )";
4200 
4201   CompileSuccessfully(GenerateShaderCode(body).c_str());
4202   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4203   EXPECT_THAT(getDiagnosticString(),
4204               HasSubstr("Expected Coordinate to be float scalar or vector"));
4205 }
4206 
TEST_F(ValidateImage,QueryLodCoordinateSizeTooSmall)4207 TEST_F(ValidateImage, QueryLodCoordinateSizeTooSmall) {
4208   const std::string body = R"(
4209 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4210 %sampler = OpLoad %type_sampler %uniform_sampler
4211 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4212 %res1 = OpImageQueryLod %f32vec2 %simg %f32_0
4213 )";
4214 
4215   CompileSuccessfully(GenerateShaderCode(body).c_str());
4216   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4217   EXPECT_THAT(getDiagnosticString(),
4218               HasSubstr("Expected Coordinate to have at least 2 components, "
4219                         "but given only 1"));
4220 }
4221 
TEST_F(ValidateImage,QueryLevelsSuccess)4222 TEST_F(ValidateImage, QueryLevelsSuccess) {
4223   const std::string body = R"(
4224 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4225 %res1 = OpImageQueryLevels %u32 %img
4226 )";
4227 
4228   CompileSuccessfully(GenerateKernelCode(body).c_str());
4229   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
4230 }
4231 
TEST_F(ValidateImage,QueryLevelsWrongResultType)4232 TEST_F(ValidateImage, QueryLevelsWrongResultType) {
4233   const std::string body = R"(
4234 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4235 %res1 = OpImageQueryLevels %f32 %img
4236 )";
4237 
4238   CompileSuccessfully(GenerateKernelCode(body).c_str());
4239   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4240   EXPECT_THAT(getDiagnosticString(),
4241               HasSubstr("Expected Result Type to be int scalar type"));
4242 }
4243 
TEST_F(ValidateImage,QueryLevelsNotImage)4244 TEST_F(ValidateImage, QueryLevelsNotImage) {
4245   const std::string body = R"(
4246 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4247 %sampler = OpLoad %type_sampler %uniform_sampler
4248 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4249 %res1 = OpImageQueryLevels %u32 %sampler
4250 )";
4251 
4252   CompileSuccessfully(GenerateKernelCode(body).c_str());
4253   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4254   EXPECT_THAT(getDiagnosticString(),
4255               HasSubstr("Expected Image to be of type OpTypeImage"));
4256 }
4257 
TEST_F(ValidateImage,QueryLevelsSampledImageDirectly)4258 TEST_F(ValidateImage, QueryLevelsSampledImageDirectly) {
4259   const std::string body = R"(
4260 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4261 %sampler = OpLoad %type_sampler %uniform_sampler
4262 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4263 %res1 = OpImageQueryLevels %u32 %simg
4264 )";
4265 
4266   CompileSuccessfully(GenerateShaderCode(body).c_str());
4267   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4268   EXPECT_THAT(getDiagnosticString(),
4269               HasSubstr("OpSampledImage instruction must not appear as operand "
4270                         "for OpImageQueryLevels"));
4271 }
4272 
TEST_F(ValidateImage,QueryLevelsWrongDim)4273 TEST_F(ValidateImage, QueryLevelsWrongDim) {
4274   const std::string body = R"(
4275 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
4276 %res1 = OpImageQueryLevels %u32 %img
4277 )";
4278 
4279   CompileSuccessfully(GenerateKernelCode(body).c_str());
4280   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4281   EXPECT_THAT(getDiagnosticString(),
4282               HasSubstr("Image 'Dim' must be 1D, 2D, 3D or Cube"));
4283 }
4284 
TEST_F(ValidateImage,QuerySizeLevelsNonSampledUniversalSuccess)4285 TEST_F(ValidateImage, QuerySizeLevelsNonSampledUniversalSuccess) {
4286   const std::string body = R"(
4287 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
4288 %res1 = OpImageQueryLevels %u32 %img
4289 )";
4290 
4291   CompileSuccessfully(GenerateShaderCode(body).c_str());
4292   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
4293   EXPECT_EQ(getDiagnosticString(), "");
4294 }
4295 
TEST_F(ValidateImage,QuerySizeLevelsVulkanNonSampledError)4296 TEST_F(ValidateImage, QuerySizeLevelsVulkanNonSampledError) {
4297   // Create a whole shader module.  Avoid Vulkan incompatibility with
4298   // SampledRrect images inserted by helper function GenerateShaderCode.
4299   const std::string body = R"(
4300 OpCapability Shader
4301 OpCapability ImageQuery
4302 OpMemoryModel Logical Simple
4303 OpEntryPoint Fragment %main "main"
4304 OpExecutionMode %main OriginUpperLeft
4305 
4306 %f32 = OpTypeFloat 32
4307 %u32 = OpTypeInt 32 0
4308 %void = OpTypeVoid
4309 %voidfn = OpTypeFunction %void
4310 
4311 ; Test with a storage image.
4312 %type_image_f32_2d_0002 = OpTypeImage %f32 2D 0 0 0 2 Rgba32f
4313 %ptr_image_f32_2d_0002 = OpTypePointer UniformConstant %type_image_f32_2d_0002
4314 %uniform_image_f32_2d_0002 = OpVariable %ptr_image_f32_2d_0002 UniformConstant
4315 
4316 %main = OpFunction %void None %voidfn
4317 %entry = OpLabel
4318 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
4319 %res1 = OpImageQueryLevels %u32 %img
4320 OpReturn
4321 OpFunctionEnd
4322 )";
4323 
4324   CompileSuccessfully(body.c_str());
4325   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
4326   EXPECT_THAT(getDiagnosticString(),
4327               AnyVUID("VUID-StandaloneSpirv-OpImageQuerySizeLod-04659"));
4328   EXPECT_THAT(
4329       getDiagnosticString(),
4330       HasSubstr("OpImageQueryLevels must only consume an \"Image\" operand "
4331                 "whose type has its \"Sampled\" operand set to 1"));
4332 }
4333 
TEST_F(ValidateImage,QuerySamplesSuccess)4334 TEST_F(ValidateImage, QuerySamplesSuccess) {
4335   const std::string body = R"(
4336 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
4337 %res1 = OpImageQuerySamples %u32 %img
4338 )";
4339 
4340   CompileSuccessfully(GenerateKernelCode(body).c_str());
4341   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
4342 }
4343 
TEST_F(ValidateImage,QuerySamplesNot2D)4344 TEST_F(ValidateImage, QuerySamplesNot2D) {
4345   const std::string body = R"(
4346 %img = OpLoad %type_image_f32_3d_0011 %uniform_image_f32_3d_0011
4347 %res1 = OpImageQuerySamples %u32 %img
4348 )";
4349 
4350   CompileSuccessfully(GenerateKernelCode(body).c_str());
4351   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4352   EXPECT_THAT(getDiagnosticString(), HasSubstr("Image 'Dim' must be 2D"));
4353 }
4354 
TEST_F(ValidateImage,QuerySamplesNotMultisampled)4355 TEST_F(ValidateImage, QuerySamplesNotMultisampled) {
4356   const std::string body = R"(
4357 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4358 %res1 = OpImageQuerySamples %u32 %img
4359 )";
4360 
4361   CompileSuccessfully(GenerateKernelCode(body).c_str());
4362   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4363   EXPECT_THAT(getDiagnosticString(), HasSubstr("Image 'MS' must be 1"));
4364 }
4365 
TEST_F(ValidateImage,QueryLodWrongExecutionModel)4366 TEST_F(ValidateImage, QueryLodWrongExecutionModel) {
4367   const std::string body = R"(
4368 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4369 %sampler = OpLoad %type_sampler %uniform_sampler
4370 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4371 %res1 = OpImageQueryLod %f32vec2 %simg %f32vec2_hh
4372 )";
4373 
4374   CompileSuccessfully(GenerateShaderCode(body, "", "Vertex").c_str());
4375   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4376   EXPECT_THAT(
4377       getDiagnosticString(),
4378       HasSubstr(
4379           "OpImageQueryLod requires Fragment or GLCompute execution model"));
4380 }
4381 
TEST_F(ValidateImage,QueryLodWrongExecutionModelWithFunc)4382 TEST_F(ValidateImage, QueryLodWrongExecutionModelWithFunc) {
4383   const std::string body = R"(
4384 %call_ret = OpFunctionCall %void %my_func
4385 OpReturn
4386 OpFunctionEnd
4387 %my_func = OpFunction %void None %func
4388 %my_func_entry = OpLabel
4389 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4390 %sampler = OpLoad %type_sampler %uniform_sampler
4391 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4392 %res1 = OpImageQueryLod %f32vec2 %simg %f32vec2_hh
4393 )";
4394 
4395   CompileSuccessfully(GenerateShaderCode(body, "", "Vertex").c_str());
4396   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4397   EXPECT_THAT(
4398       getDiagnosticString(),
4399       HasSubstr(
4400           "OpImageQueryLod requires Fragment or GLCompute execution model"));
4401 }
4402 
TEST_F(ValidateImage,QueryLodComputeShaderDerivatives)4403 TEST_F(ValidateImage, QueryLodComputeShaderDerivatives) {
4404   const std::string body = R"(
4405 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4406 %sampler = OpLoad %type_sampler %uniform_sampler
4407 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4408 %res1 = OpImageQueryLod %f32vec2 %simg %f32vec2_hh
4409 )";
4410 
4411   const std::string extra = R"(
4412 OpCapability ComputeDerivativeGroupLinearNV
4413 OpExtension "SPV_NV_compute_shader_derivatives"
4414 )";
4415   const std::string mode = R"(
4416 OpExecutionMode %main LocalSize 8 8 1
4417 OpExecutionMode %main DerivativeGroupLinearNV
4418 )";
4419   CompileSuccessfully(
4420       GenerateShaderCode(body, extra, "GLCompute", mode).c_str());
4421   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
4422 }
4423 
TEST_F(ValidateImage,QueryLodUniversalSuccess)4424 TEST_F(ValidateImage, QueryLodUniversalSuccess) {
4425   // Create a whole shader module.  Avoid Vulkan incompatibility with
4426   // SampledRrect images inserted by helper function GenerateShaderCode.
4427   const std::string body = R"(
4428 OpCapability Shader
4429 OpCapability ImageQuery
4430 OpMemoryModel Logical Simple
4431 OpEntryPoint Fragment %main "main"
4432 OpExecutionMode %main OriginUpperLeft
4433 
4434 OpDecorate %uniform_image_f32_2d_0000 DescriptorSet 0
4435 OpDecorate %uniform_image_f32_2d_0000 Binding 0
4436 OpDecorate %sampler DescriptorSet 0
4437 OpDecorate %sampler Binding 1
4438 
4439 %f32 = OpTypeFloat 32
4440 %f32vec2 = OpTypeVector %f32 2
4441 %f32vec2_null = OpConstantNull %f32vec2
4442 %u32 = OpTypeInt 32 0
4443 %u32vec2 = OpTypeVector %u32 2
4444 %void = OpTypeVoid
4445 %voidfn = OpTypeFunction %void
4446 
4447 ; Test with an image with sampled = 0
4448 %type_image_f32_2d_0000 = OpTypeImage %f32 2D 0 0 0 0 Rgba32f
4449 %ptr_image_f32_2d_0000 = OpTypePointer UniformConstant %type_image_f32_2d_0000
4450 %uniform_image_f32_2d_0000 = OpVariable %ptr_image_f32_2d_0000 UniformConstant
4451 %sampled_image_ty = OpTypeSampledImage %type_image_f32_2d_0000
4452 
4453 %sampler_ty = OpTypeSampler
4454 %ptr_sampler_ty = OpTypePointer UniformConstant %sampler_ty
4455 %sampler = OpVariable %ptr_sampler_ty UniformConstant
4456 
4457 
4458 %main = OpFunction %void None %voidfn
4459 %entry = OpLabel
4460 %img = OpLoad %type_image_f32_2d_0000 %uniform_image_f32_2d_0000
4461 %s = OpLoad %sampler_ty %sampler
4462 %simg = OpSampledImage %sampled_image_ty %img %s
4463 %res1 = OpImageQueryLod %f32vec2 %simg %f32vec2_null
4464 OpReturn
4465 OpFunctionEnd
4466 )";
4467 
4468   CompileSuccessfully(body.c_str());
4469   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
4470 }
4471 
TEST_F(ValidateImage,QueryLodVulkanNonSampledError)4472 TEST_F(ValidateImage, QueryLodVulkanNonSampledError) {
4473   // Create a whole shader module.  Avoid Vulkan incompatibility with
4474   // SampledRrect images inserted by helper function GenerateShaderCode.
4475   const std::string body = R"(
4476 OpCapability Shader
4477 OpCapability ImageQuery
4478 OpMemoryModel Logical Simple
4479 OpEntryPoint Fragment %main "main"
4480 OpExecutionMode %main OriginUpperLeft
4481 
4482 OpDecorate %sampled_image DescriptorSet 0
4483 OpDecorate %sampled_image Binding 0
4484 
4485 %f32 = OpTypeFloat 32
4486 %f32vec2 = OpTypeVector %f32 2
4487 %f32vec2_null = OpConstantNull %f32vec2
4488 %u32 = OpTypeInt 32 0
4489 %u32vec2 = OpTypeVector %u32 2
4490 %void = OpTypeVoid
4491 %voidfn = OpTypeFunction %void
4492 
4493 ; Test with an image with Sampled = 2
4494 ; In Vulkan it Sampled must be 1 or 2, checked in another part of the
4495 ; validation flow.
4496 %type_image_f32_2d_0002 = OpTypeImage %f32 2D 0 0 0 2 Rgba32f
4497 
4498 ; Expect to fail here.
4499 %sampled_image_ty = OpTypeSampledImage %type_image_f32_2d_0002
4500 %ptr_sampled_image_ty = OpTypePointer UniformConstant %sampled_image_ty
4501 %sampled_image = OpVariable %ptr_sampled_image_ty UniformConstant
4502 
4503 %main = OpFunction %void None %voidfn
4504 %entry = OpLabel
4505 %simg = OpLoad %sampled_image_ty %sampled_image
4506 %res1 = OpImageQueryLod %f32vec2 %simg %f32vec2_null
4507 OpReturn
4508 OpFunctionEnd
4509 )";
4510 
4511   CompileSuccessfully(body.c_str());
4512   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
4513   EXPECT_THAT(getDiagnosticString(),
4514               AnyVUID("VUID-StandaloneSpirv-OpTypeImage-04657"));
4515   EXPECT_THAT(getDiagnosticString(),
4516               HasSubstr("Sampled image type requires an image type with "
4517                         "\"Sampled\" operand set to 0 or 1"));
4518 }
4519 
TEST_F(ValidateImage,QueryLodComputeShaderDerivativesMissingMode)4520 TEST_F(ValidateImage, QueryLodComputeShaderDerivativesMissingMode) {
4521   const std::string body = R"(
4522 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4523 %sampler = OpLoad %type_sampler %uniform_sampler
4524 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4525 %res1 = OpImageQueryLod %f32vec2 %simg %f32vec2_hh
4526 )";
4527 
4528   const std::string extra = R"(
4529 OpCapability ComputeDerivativeGroupLinearNV
4530 OpExtension "SPV_NV_compute_shader_derivatives"
4531 )";
4532   const std::string mode = R"(
4533 OpExecutionMode %main LocalSize 8 8 1
4534 )";
4535   CompileSuccessfully(
4536       GenerateShaderCode(body, extra, "GLCompute", mode).c_str());
4537   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4538   EXPECT_THAT(getDiagnosticString(),
4539               HasSubstr("OpImageQueryLod requires DerivativeGroupQuadsNV or "
4540                         "DerivativeGroupLinearNV execution mode for GLCompute "
4541                         "execution model"));
4542 }
4543 
TEST_F(ValidateImage,ImplicitLodWrongExecutionModel)4544 TEST_F(ValidateImage, ImplicitLodWrongExecutionModel) {
4545   const std::string body = R"(
4546 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4547 %sampler = OpLoad %type_sampler %uniform_sampler
4548 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4549 %res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh
4550 )";
4551 
4552   CompileSuccessfully(GenerateShaderCode(body, "", "Vertex").c_str());
4553   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4554   EXPECT_THAT(getDiagnosticString(),
4555               HasSubstr("ImplicitLod instructions require Fragment or "
4556                         "GLCompute execution model"));
4557 }
4558 
TEST_F(ValidateImage,ImplicitLodComputeShaderDerivatives)4559 TEST_F(ValidateImage, ImplicitLodComputeShaderDerivatives) {
4560   const std::string body = R"(
4561 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4562 %sampler = OpLoad %type_sampler %uniform_sampler
4563 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4564 %res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh
4565 )";
4566 
4567   const std::string extra = R"(
4568 OpCapability ComputeDerivativeGroupLinearNV
4569 OpExtension "SPV_NV_compute_shader_derivatives"
4570 )";
4571   const std::string mode = R"(
4572 OpExecutionMode %main LocalSize 8 8 1
4573 OpExecutionMode %main DerivativeGroupLinearNV
4574 )";
4575   CompileSuccessfully(
4576       GenerateShaderCode(body, extra, "GLCompute", mode).c_str());
4577   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
4578 }
4579 
TEST_F(ValidateImage,ImplicitLodComputeShaderDerivativesMissingMode)4580 TEST_F(ValidateImage, ImplicitLodComputeShaderDerivativesMissingMode) {
4581   const std::string body = R"(
4582 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4583 %sampler = OpLoad %type_sampler %uniform_sampler
4584 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4585 %res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh
4586 )";
4587 
4588   const std::string extra = R"(
4589 OpCapability ComputeDerivativeGroupLinearNV
4590 OpExtension "SPV_NV_compute_shader_derivatives"
4591 )";
4592   const std::string mode = R"(
4593 OpExecutionMode %main LocalSize 8 8 1
4594 )";
4595   CompileSuccessfully(
4596       GenerateShaderCode(body, extra, "GLCompute", mode).c_str());
4597   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4598   EXPECT_THAT(
4599       getDiagnosticString(),
4600       HasSubstr("ImplicitLod instructions require DerivativeGroupQuadsNV or "
4601                 "DerivativeGroupLinearNV execution mode for GLCompute "
4602                 "execution model"));
4603 }
4604 
TEST_F(ValidateImage,ReadSubpassDataWrongExecutionModel)4605 TEST_F(ValidateImage, ReadSubpassDataWrongExecutionModel) {
4606   const std::string body = R"(
4607 %img = OpLoad %type_image_f32_spd_0002 %uniform_image_f32_spd_0002
4608 %res1 = OpImageRead %f32vec4 %img %u32vec2_01
4609 )";
4610 
4611   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
4612   CompileSuccessfully(GenerateShaderCode(body, extra, "Vertex").c_str());
4613   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4614   EXPECT_THAT(getDiagnosticString(),
4615               HasSubstr("Dim SubpassData requires Fragment execution model"));
4616 }
4617 
TEST_F(ValidateImage,SparseSampleImplicitLodSuccess)4618 TEST_F(ValidateImage, SparseSampleImplicitLodSuccess) {
4619   const std::string body = R"(
4620 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4621 %sampler = OpLoad %type_sampler %uniform_sampler
4622 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4623 %res1 = OpImageSparseSampleImplicitLod %struct_u32_f32vec4 %simg %f32vec2_hh
4624 %res2 = OpImageSparseSampleImplicitLod %struct_u32_f32vec4 %simg %f32vec2_hh Bias %f32_0_25
4625 %res4 = OpImageSparseSampleImplicitLod %struct_u32_f32vec4 %simg %f32vec2_hh ConstOffset %s32vec2_01
4626 %res5 = OpImageSparseSampleImplicitLod %struct_u32_f32vec4 %simg %f32vec2_hh Offset %s32vec2_01
4627 %res6 = OpImageSparseSampleImplicitLod %struct_u32_f32vec4 %simg %f32vec2_hh MinLod %f32_0_5
4628 %res7 = OpImageSparseSampleImplicitLod %struct_u64_f32vec4 %simg %f32vec2_hh Bias|Offset|MinLod %f32_0_25 %s32vec2_01 %f32_0_5
4629 %res8 = OpImageSparseSampleImplicitLod %struct_u32_f32vec4 %simg %f32vec2_hh NonPrivateTexelKHR
4630 )";
4631 
4632   const std::string extra = R"(
4633 OpCapability VulkanMemoryModelKHR
4634 OpExtension "SPV_KHR_vulkan_memory_model"
4635 )";
4636   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
4637                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
4638                           .c_str());
4639   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4640 }
4641 
TEST_F(ValidateImage,SparseSampleImplicitLodResultTypeNotStruct)4642 TEST_F(ValidateImage, SparseSampleImplicitLodResultTypeNotStruct) {
4643   const std::string body = R"(
4644 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4645 %sampler = OpLoad %type_sampler %uniform_sampler
4646 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4647 %res1 = OpImageSparseSampleImplicitLod %f32 %simg %f32vec2_hh
4648 )";
4649 
4650   CompileSuccessfully(GenerateShaderCode(body).c_str());
4651   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4652   EXPECT_THAT(getDiagnosticString(),
4653               HasSubstr("Expected Result Type to be OpTypeStruct"));
4654 }
4655 
TEST_F(ValidateImage,SparseSampleImplicitLodResultTypeNotTwoMembers1)4656 TEST_F(ValidateImage, SparseSampleImplicitLodResultTypeNotTwoMembers1) {
4657   const std::string body = R"(
4658 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4659 %sampler = OpLoad %type_sampler %uniform_sampler
4660 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4661 %res1 = OpImageSparseSampleImplicitLod %struct_u32 %simg %f32vec2_hh
4662 )";
4663 
4664   CompileSuccessfully(GenerateShaderCode(body).c_str());
4665   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4666   EXPECT_THAT(getDiagnosticString(),
4667               HasSubstr("Expected Result Type to be a struct containing an int "
4668                         "scalar and a texel"));
4669 }
4670 
TEST_F(ValidateImage,SparseSampleImplicitLodResultTypeNotTwoMembers2)4671 TEST_F(ValidateImage, SparseSampleImplicitLodResultTypeNotTwoMembers2) {
4672   const std::string body = R"(
4673 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4674 %sampler = OpLoad %type_sampler %uniform_sampler
4675 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4676 %res1 = OpImageSparseSampleImplicitLod %struct_u32_f32vec4_u32 %simg %f32vec2_hh
4677 )";
4678 
4679   CompileSuccessfully(GenerateShaderCode(body).c_str());
4680   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4681   EXPECT_THAT(getDiagnosticString(),
4682               HasSubstr("Expected Result Type to be a struct containing an "
4683                         "int scalar and a texel"));
4684 }
4685 
TEST_F(ValidateImage,SparseSampleImplicitLodResultTypeFirstMemberNotInt)4686 TEST_F(ValidateImage, SparseSampleImplicitLodResultTypeFirstMemberNotInt) {
4687   const std::string body = R"(
4688 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4689 %sampler = OpLoad %type_sampler %uniform_sampler
4690 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4691 %res1 = OpImageSparseSampleImplicitLod %struct_f32_f32vec4 %simg %f32vec2_hh
4692 )";
4693 
4694   CompileSuccessfully(GenerateShaderCode(body).c_str());
4695   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4696   EXPECT_THAT(getDiagnosticString(),
4697               HasSubstr("Expected Result Type to be a struct containing an "
4698                         "int scalar and a texel"));
4699 }
4700 
TEST_F(ValidateImage,SparseSampleImplicitLodResultTypeTexelNotVector)4701 TEST_F(ValidateImage, SparseSampleImplicitLodResultTypeTexelNotVector) {
4702   const std::string body = R"(
4703 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4704 %sampler = OpLoad %type_sampler %uniform_sampler
4705 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4706 %res1 = OpImageSparseSampleImplicitLod %struct_u32_u32 %simg %f32vec2_hh
4707 )";
4708 
4709   CompileSuccessfully(GenerateShaderCode(body).c_str());
4710   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4711   EXPECT_THAT(getDiagnosticString(),
4712               HasSubstr("Expected Result Type's second member to be int or "
4713                         "float vector type"));
4714 }
4715 
TEST_F(ValidateImage,SparseSampleImplicitLodWrongNumComponentsTexel)4716 TEST_F(ValidateImage, SparseSampleImplicitLodWrongNumComponentsTexel) {
4717   const std::string body = R"(
4718 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4719 %sampler = OpLoad %type_sampler %uniform_sampler
4720 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4721 %res1 = OpImageSparseSampleImplicitLod %struct_u32_f32vec3 %simg %f32vec2_hh
4722 )";
4723 
4724   CompileSuccessfully(GenerateShaderCode(body).c_str());
4725   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4726   EXPECT_THAT(getDiagnosticString(),
4727               HasSubstr("Expected Result Type's second member to have 4 "
4728                         "components"));
4729 }
4730 
TEST_F(ValidateImage,SparseSampleImplicitLodWrongComponentTypeTexel)4731 TEST_F(ValidateImage, SparseSampleImplicitLodWrongComponentTypeTexel) {
4732   const std::string body = R"(
4733 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4734 %sampler = OpLoad %type_sampler %uniform_sampler
4735 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4736 %res1 = OpImageSparseSampleImplicitLod %struct_u32_u32vec4 %simg %f32vec2_hh
4737 )";
4738 
4739   CompileSuccessfully(GenerateShaderCode(body).c_str());
4740   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4741   EXPECT_THAT(getDiagnosticString(),
4742               HasSubstr("Expected Image 'Sampled Type' to be the same as "
4743                         "Result Type's second member components"));
4744 }
4745 
TEST_F(ValidateImage,SparseSampleDrefImplicitLodSuccess)4746 TEST_F(ValidateImage, SparseSampleDrefImplicitLodSuccess) {
4747   const std::string body = R"(
4748 %img = OpLoad %type_image_u32_2d_0001 %uniform_image_u32_2d_0001
4749 %sampler = OpLoad %type_sampler %uniform_sampler
4750 %simg = OpSampledImage %type_sampled_image_u32_2d_0001 %img %sampler
4751 %res1 = OpImageSparseSampleDrefImplicitLod %struct_u32_u32 %simg %f32vec2_hh %f32_1
4752 %res2 = OpImageSparseSampleDrefImplicitLod %struct_u32_u32 %simg %f32vec2_hh %f32_1 Bias %f32_0_25
4753 %res4 = OpImageSparseSampleDrefImplicitLod %struct_u32_u32 %simg %f32vec2_hh %f32_1 ConstOffset %s32vec2_01
4754 %res5 = OpImageSparseSampleDrefImplicitLod %struct_u32_u32 %simg %f32vec2_hh %f32_1 Offset %s32vec2_01
4755 %res6 = OpImageSparseSampleDrefImplicitLod %struct_u32_u32 %simg %f32vec2_hh %f32_1 MinLod %f32_0_5
4756 %res7 = OpImageSparseSampleDrefImplicitLod %struct_u32_u32 %simg %f32vec2_hh %f32_1 Bias|Offset|MinLod %f32_0_25 %s32vec2_01 %f32_0_5
4757 %res8 = OpImageSparseSampleDrefImplicitLod %struct_u32_u32 %simg %f32vec2_hh %f32_1 NonPrivateTexelKHR
4758 )";
4759 
4760   const std::string extra = R"(
4761 OpCapability VulkanMemoryModelKHR
4762 OpExtension "SPV_KHR_vulkan_memory_model"
4763 )";
4764   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
4765                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
4766                           .c_str());
4767   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4768 }
4769 
TEST_F(ValidateImage,SparseSampleDrefImplicitLodResultTypeNotStruct)4770 TEST_F(ValidateImage, SparseSampleDrefImplicitLodResultTypeNotStruct) {
4771   const std::string body = R"(
4772 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4773 %sampler = OpLoad %type_sampler %uniform_sampler
4774 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4775 %res1 = OpImageSparseSampleDrefImplicitLod %f32 %simg %f32vec2_hh %f32_1
4776 )";
4777 
4778   CompileSuccessfully(GenerateShaderCode(body).c_str());
4779   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4780   EXPECT_THAT(getDiagnosticString(),
4781               HasSubstr("Expected Result Type to be OpTypeStruct"));
4782 }
4783 
TEST_F(ValidateImage,SparseSampleDrefImplicitLodResultTypeNotTwoMembers1)4784 TEST_F(ValidateImage, SparseSampleDrefImplicitLodResultTypeNotTwoMembers1) {
4785   const std::string body = R"(
4786 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4787 %sampler = OpLoad %type_sampler %uniform_sampler
4788 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4789 %res1 = OpImageSparseSampleDrefImplicitLod %struct_u32 %simg %f32vec2_hh %f32_1
4790 )";
4791 
4792   CompileSuccessfully(GenerateShaderCode(body).c_str());
4793   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4794   EXPECT_THAT(
4795       getDiagnosticString(),
4796       HasSubstr("Expected Result Type to be a struct containing an int scalar "
4797                 "and a texel"));
4798 }
4799 
TEST_F(ValidateImage,SparseSampleDrefImplicitLodResultTypeNotTwoMembers2)4800 TEST_F(ValidateImage, SparseSampleDrefImplicitLodResultTypeNotTwoMembers2) {
4801   const std::string body = R"(
4802 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4803 %sampler = OpLoad %type_sampler %uniform_sampler
4804 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4805 %res1 = OpImageSparseSampleDrefImplicitLod %struct_u32_f32_u32 %simg %f32vec2_hh %f32_1
4806 )";
4807 
4808   CompileSuccessfully(GenerateShaderCode(body).c_str());
4809   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4810   EXPECT_THAT(
4811       getDiagnosticString(),
4812       HasSubstr("Expected Result Type to be a struct containing an int scalar "
4813                 "and a texel"));
4814 }
4815 
TEST_F(ValidateImage,SparseSampleDrefImplicitLodResultTypeFirstMemberNotInt)4816 TEST_F(ValidateImage, SparseSampleDrefImplicitLodResultTypeFirstMemberNotInt) {
4817   const std::string body = R"(
4818 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4819 %sampler = OpLoad %type_sampler %uniform_sampler
4820 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4821 %res1 = OpImageSparseSampleDrefImplicitLod %struct_f32_f32 %simg %f32vec2_hh %f32_1
4822 )";
4823 
4824   CompileSuccessfully(GenerateShaderCode(body).c_str());
4825   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4826   EXPECT_THAT(
4827       getDiagnosticString(),
4828       HasSubstr("Expected Result Type to be a struct containing an int scalar "
4829                 "and a texel"));
4830 }
4831 
TEST_F(ValidateImage,SparseSampleDrefImplicitLodDifferentSampledType)4832 TEST_F(ValidateImage, SparseSampleDrefImplicitLodDifferentSampledType) {
4833   const std::string body = R"(
4834 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4835 %sampler = OpLoad %type_sampler %uniform_sampler
4836 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4837 %res1 = OpImageSparseSampleDrefImplicitLod %struct_u32_u32 %simg %f32vec2_hh %f32_1
4838 )";
4839 
4840   CompileSuccessfully(GenerateShaderCode(body).c_str());
4841   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4842   EXPECT_THAT(getDiagnosticString(),
4843               HasSubstr("Expected Image 'Sampled Type' to be the same as "
4844                         "Result Type's second member"));
4845 }
4846 
TEST_F(ValidateImage,SparseFetchSuccess)4847 TEST_F(ValidateImage, SparseFetchSuccess) {
4848   const std::string body = R"(
4849 %img = OpLoad %type_image_f32_1d_0001 %uniform_image_f32_1d_0001
4850 %res1 = OpImageSparseFetch %struct_u32_f32vec4 %img %u32vec2_01
4851 %res2 = OpImageSparseFetch %struct_u32_f32vec4 %img %u32vec2_01 NonPrivateTexelKHR
4852 )";
4853 
4854   const std::string extra = R"(
4855 OpCapability VulkanMemoryModelKHR
4856 OpExtension "SPV_KHR_vulkan_memory_model"
4857 )";
4858   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
4859                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
4860                           .c_str());
4861   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4862 }
4863 
TEST_F(ValidateImage,SparseFetchResultTypeNotStruct)4864 TEST_F(ValidateImage, SparseFetchResultTypeNotStruct) {
4865   const std::string body = R"(
4866 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
4867 %res1 = OpImageSparseFetch %f32 %img %u32vec2_01
4868 )";
4869 
4870   CompileSuccessfully(GenerateShaderCode(body).c_str());
4871   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4872   EXPECT_THAT(getDiagnosticString(),
4873               HasSubstr("Expected Result Type to be OpTypeStruct"));
4874 }
4875 
TEST_F(ValidateImage,SparseFetchResultTypeNotTwoMembers1)4876 TEST_F(ValidateImage, SparseFetchResultTypeNotTwoMembers1) {
4877   const std::string body = R"(
4878 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
4879 %res1 = OpImageSparseFetch %struct_u32 %img %u32vec2_01
4880 )";
4881 
4882   CompileSuccessfully(GenerateShaderCode(body).c_str());
4883   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4884   EXPECT_THAT(getDiagnosticString(),
4885               HasSubstr("Expected Result Type to be a struct containing an "
4886                         "int scalar and a texel"));
4887 }
4888 
TEST_F(ValidateImage,SparseFetchResultTypeNotTwoMembers2)4889 TEST_F(ValidateImage, SparseFetchResultTypeNotTwoMembers2) {
4890   const std::string body = R"(
4891 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
4892 %res1 = OpImageSparseFetch %struct_u32_f32vec4_u32 %img %u32vec2_01
4893 )";
4894 
4895   CompileSuccessfully(GenerateShaderCode(body).c_str());
4896   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4897   EXPECT_THAT(getDiagnosticString(),
4898               HasSubstr("Expected Result Type to be a struct containing an "
4899                         "int scalar and a texel"));
4900 }
4901 
TEST_F(ValidateImage,SparseFetchResultTypeFirstMemberNotInt)4902 TEST_F(ValidateImage, SparseFetchResultTypeFirstMemberNotInt) {
4903   const std::string body = R"(
4904 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
4905 %res1 = OpImageSparseFetch %struct_f32_f32vec4 %img %u32vec2_01
4906 )";
4907 
4908   CompileSuccessfully(GenerateShaderCode(body).c_str());
4909   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4910   EXPECT_THAT(getDiagnosticString(),
4911               HasSubstr("Expected Result Type to be a struct containing an "
4912                         "int scalar and a texel"));
4913 }
4914 
TEST_F(ValidateImage,SparseFetchResultTypeTexelNotVector)4915 TEST_F(ValidateImage, SparseFetchResultTypeTexelNotVector) {
4916   const std::string body = R"(
4917 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
4918 %res1 = OpImageSparseFetch %struct_u32_u32 %img %u32vec2_01
4919 )";
4920 
4921   CompileSuccessfully(GenerateShaderCode(body).c_str());
4922   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4923   EXPECT_THAT(getDiagnosticString(),
4924               HasSubstr("Expected Result Type's second member to be int or "
4925                         "float vector type"));
4926 }
4927 
TEST_F(ValidateImage,SparseFetchWrongNumComponentsTexel)4928 TEST_F(ValidateImage, SparseFetchWrongNumComponentsTexel) {
4929   const std::string body = R"(
4930 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
4931 %res1 = OpImageSparseFetch %struct_u32_f32vec3 %img %u32vec2_01
4932 )";
4933 
4934   CompileSuccessfully(GenerateShaderCode(body).c_str());
4935   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4936   EXPECT_THAT(getDiagnosticString(),
4937               HasSubstr("Expected Result Type's second member to have 4 "
4938                         "components"));
4939 }
4940 
TEST_F(ValidateImage,SparseFetchWrongComponentTypeTexel)4941 TEST_F(ValidateImage, SparseFetchWrongComponentTypeTexel) {
4942   const std::string body = R"(
4943 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
4944 %res1 = OpImageSparseFetch %struct_u32_u32vec4 %img %u32vec2_01
4945 )";
4946 
4947   CompileSuccessfully(GenerateShaderCode(body).c_str());
4948   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4949   EXPECT_THAT(getDiagnosticString(),
4950               HasSubstr("Expected Image 'Sampled Type' to be the same as "
4951                         "Result Type's second member components"));
4952 }
4953 
TEST_F(ValidateImage,SparseReadSuccess)4954 TEST_F(ValidateImage, SparseReadSuccess) {
4955   const std::string body = R"(
4956 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
4957 %res1 = OpImageSparseRead %struct_u32_f32vec4 %img %u32vec2_01
4958 )";
4959 
4960   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
4961   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
4962   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
4963 }
4964 
TEST_F(ValidateImage,SparseReadResultTypeNotStruct)4965 TEST_F(ValidateImage, SparseReadResultTypeNotStruct) {
4966   const std::string body = R"(
4967 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
4968 %res1 = OpImageSparseRead %f32 %img %u32vec2_01
4969 )";
4970 
4971   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
4972   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
4973   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4974   EXPECT_THAT(getDiagnosticString(),
4975               HasSubstr("Expected Result Type to be OpTypeStruct"));
4976 }
4977 
TEST_F(ValidateImage,SparseReadResultTypeNotTwoMembers1)4978 TEST_F(ValidateImage, SparseReadResultTypeNotTwoMembers1) {
4979   const std::string body = R"(
4980 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
4981 %res1 = OpImageSparseRead %struct_u32 %img %u32vec2_01
4982 )";
4983 
4984   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
4985   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
4986   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4987   EXPECT_THAT(getDiagnosticString(),
4988               HasSubstr("Expected Result Type to be a struct containing an "
4989                         "int scalar and a texel"));
4990 }
4991 
TEST_F(ValidateImage,SparseReadResultTypeNotTwoMembers2)4992 TEST_F(ValidateImage, SparseReadResultTypeNotTwoMembers2) {
4993   const std::string body = R"(
4994 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
4995 %res1 = OpImageSparseRead %struct_u32_f32vec4_u32 %img %u32vec2_01
4996 )";
4997 
4998   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
4999   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
5000   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5001   EXPECT_THAT(getDiagnosticString(),
5002               HasSubstr("Expected Result Type to be a struct containing an "
5003                         "int scalar and a texel"));
5004 }
5005 
TEST_F(ValidateImage,SparseReadResultTypeFirstMemberNotInt)5006 TEST_F(ValidateImage, SparseReadResultTypeFirstMemberNotInt) {
5007   const std::string body = R"(
5008 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
5009 %res1 = OpImageSparseRead %struct_f32_f32vec4 %img %u32vec2_01
5010 )";
5011 
5012   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
5013   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
5014   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5015   EXPECT_THAT(getDiagnosticString(),
5016               HasSubstr("Expected Result Type to be a struct containing an "
5017                         "int scalar and a texel"));
5018 }
5019 
TEST_F(ValidateImage,SparseReadResultTypeTexelWrongType)5020 TEST_F(ValidateImage, SparseReadResultTypeTexelWrongType) {
5021   const std::string body = R"(
5022 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
5023 %res1 = OpImageSparseRead %struct_u32_u32arr4 %img %u32vec2_01
5024 )";
5025 
5026   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
5027   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
5028   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5029   EXPECT_THAT(getDiagnosticString(),
5030               HasSubstr("Expected Result Type's second member to be int or "
5031                         "float scalar or vector type"));
5032 }
5033 
TEST_F(ValidateImage,SparseReadWrongComponentTypeTexel)5034 TEST_F(ValidateImage, SparseReadWrongComponentTypeTexel) {
5035   const std::string body = R"(
5036 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
5037 %res1 = OpImageSparseRead %struct_u32_u32vec4 %img %u32vec2_01
5038 )";
5039 
5040   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
5041   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
5042   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5043   EXPECT_THAT(getDiagnosticString(),
5044               HasSubstr("Expected Image 'Sampled Type' to be the same as "
5045                         "Result Type's second member components"));
5046 }
5047 
TEST_F(ValidateImage,SparseReadSubpassDataNotAllowed)5048 TEST_F(ValidateImage, SparseReadSubpassDataNotAllowed) {
5049   const std::string body = R"(
5050 %img = OpLoad %type_image_f32_spd_0002 %uniform_image_f32_spd_0002
5051 %res1 = OpImageSparseRead %struct_u32_f32vec4 %img %u32vec2_01
5052 )";
5053 
5054   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
5055   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment").c_str());
5056   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5057   EXPECT_THAT(
5058       getDiagnosticString(),
5059       HasSubstr("Image Dim SubpassData cannot be used with ImageSparseRead"));
5060 }
5061 
TEST_F(ValidateImage,SparseGatherSuccess)5062 TEST_F(ValidateImage, SparseGatherSuccess) {
5063   const std::string body = R"(
5064 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5065 %sampler = OpLoad %type_sampler %uniform_sampler
5066 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5067 %res1 = OpImageSparseGather %struct_u32_f32vec4 %simg %f32vec4_0000 %u32_1
5068 %res2 = OpImageSparseGather %struct_u32_f32vec4 %simg %f32vec4_0000 %u32_1 NonPrivateTexelKHR
5069 )";
5070 
5071   const std::string extra = R"(
5072 OpCapability VulkanMemoryModelKHR
5073 OpExtension "SPV_KHR_vulkan_memory_model"
5074 )";
5075   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
5076                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
5077                           .c_str());
5078   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5079 }
5080 
TEST_F(ValidateImage,SparseGatherResultTypeNotStruct)5081 TEST_F(ValidateImage, SparseGatherResultTypeNotStruct) {
5082   const std::string body = R"(
5083 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5084 %sampler = OpLoad %type_sampler %uniform_sampler
5085 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5086 %res1 = OpImageSparseGather %f32 %simg %f32vec2_hh %u32_1
5087 )";
5088 
5089   CompileSuccessfully(GenerateShaderCode(body).c_str());
5090   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5091   EXPECT_THAT(getDiagnosticString(),
5092               HasSubstr("Expected Result Type to be OpTypeStruct"));
5093 }
5094 
TEST_F(ValidateImage,SparseGatherResultTypeNotTwoMembers1)5095 TEST_F(ValidateImage, SparseGatherResultTypeNotTwoMembers1) {
5096   const std::string body = R"(
5097 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5098 %sampler = OpLoad %type_sampler %uniform_sampler
5099 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5100 %res1 = OpImageSparseGather %struct_u32 %simg %f32vec2_hh %u32_1
5101 )";
5102 
5103   CompileSuccessfully(GenerateShaderCode(body).c_str());
5104   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5105   EXPECT_THAT(getDiagnosticString(),
5106               HasSubstr("Expected Result Type to be a struct containing an int "
5107                         "scalar and a texel"));
5108 }
5109 
TEST_F(ValidateImage,SparseGatherResultTypeNotTwoMembers2)5110 TEST_F(ValidateImage, SparseGatherResultTypeNotTwoMembers2) {
5111   const std::string body = R"(
5112 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5113 %sampler = OpLoad %type_sampler %uniform_sampler
5114 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5115 %res1 = OpImageSparseGather %struct_u32_f32vec4_u32 %simg %f32vec2_hh %u32_1
5116 )";
5117 
5118   CompileSuccessfully(GenerateShaderCode(body).c_str());
5119   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5120   EXPECT_THAT(getDiagnosticString(),
5121               HasSubstr("Expected Result Type to be a struct containing an int "
5122                         "scalar and a texel"));
5123 }
5124 
TEST_F(ValidateImage,SparseGatherResultTypeFirstMemberNotInt)5125 TEST_F(ValidateImage, SparseGatherResultTypeFirstMemberNotInt) {
5126   const std::string body = R"(
5127 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5128 %sampler = OpLoad %type_sampler %uniform_sampler
5129 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5130 %res1 = OpImageSparseGather %struct_f32_f32vec4 %simg %f32vec2_hh %u32_1
5131 )";
5132 
5133   CompileSuccessfully(GenerateShaderCode(body).c_str());
5134   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5135   EXPECT_THAT(getDiagnosticString(),
5136               HasSubstr("Expected Result Type to be a struct containing an "
5137                         "int scalar and a texel"));
5138 }
5139 
TEST_F(ValidateImage,SparseGatherResultTypeTexelNotVector)5140 TEST_F(ValidateImage, SparseGatherResultTypeTexelNotVector) {
5141   const std::string body = R"(
5142 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5143 %sampler = OpLoad %type_sampler %uniform_sampler
5144 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5145 %res1 = OpImageSparseGather %struct_u32_u32 %simg %f32vec2_hh %u32_1
5146 )";
5147 
5148   CompileSuccessfully(GenerateShaderCode(body).c_str());
5149   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5150   EXPECT_THAT(getDiagnosticString(),
5151               HasSubstr("Expected Result Type's second member to be int or "
5152                         "float vector type"));
5153 }
5154 
TEST_F(ValidateImage,SparseGatherWrongNumComponentsTexel)5155 TEST_F(ValidateImage, SparseGatherWrongNumComponentsTexel) {
5156   const std::string body = R"(
5157 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5158 %sampler = OpLoad %type_sampler %uniform_sampler
5159 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5160 %res1 = OpImageSparseGather %struct_u32_f32vec3 %simg %f32vec2_hh %u32_1
5161 )";
5162 
5163   CompileSuccessfully(GenerateShaderCode(body).c_str());
5164   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5165   EXPECT_THAT(getDiagnosticString(),
5166               HasSubstr("Expected Result Type's second member to have 4 "
5167                         "components"));
5168 }
5169 
TEST_F(ValidateImage,SparseGatherWrongComponentTypeTexel)5170 TEST_F(ValidateImage, SparseGatherWrongComponentTypeTexel) {
5171   const std::string body = R"(
5172 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5173 %sampler = OpLoad %type_sampler %uniform_sampler
5174 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5175 %res1 = OpImageSparseGather %struct_u32_u32vec4 %simg %f32vec2_hh %u32_1
5176 )";
5177 
5178   CompileSuccessfully(GenerateShaderCode(body).c_str());
5179   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5180   EXPECT_THAT(getDiagnosticString(),
5181               HasSubstr("Expected Image 'Sampled Type' to be the same as "
5182                         "Result Type's second member components"));
5183 }
5184 
TEST_F(ValidateImage,SparseTexelsResidentSuccess)5185 TEST_F(ValidateImage, SparseTexelsResidentSuccess) {
5186   const std::string body = R"(
5187 %res1 = OpImageSparseTexelsResident %bool %u32_1
5188 )";
5189 
5190   CompileSuccessfully(GenerateShaderCode(body).c_str());
5191   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
5192 }
5193 
TEST_F(ValidateImage,SparseTexelsResidentResultTypeNotBool)5194 TEST_F(ValidateImage, SparseTexelsResidentResultTypeNotBool) {
5195   const std::string body = R"(
5196 %res1 = OpImageSparseTexelsResident %u32 %u32_1
5197 )";
5198 
5199   CompileSuccessfully(GenerateShaderCode(body).c_str());
5200   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5201   EXPECT_THAT(getDiagnosticString(),
5202               HasSubstr("Expected Result Type to be bool scalar type"));
5203 }
5204 
TEST_F(ValidateImage,MakeTexelVisibleKHRSuccessImageRead)5205 TEST_F(ValidateImage, MakeTexelVisibleKHRSuccessImageRead) {
5206   const std::string body = R"(
5207 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
5208 %res1 = OpImageRead %u32vec4 %img %u32vec2_01 MakeTexelVisibleKHR|NonPrivateTexelKHR %u32_2
5209 )";
5210 
5211   const std::string extra = R"(
5212 OpCapability StorageImageReadWithoutFormat
5213 OpCapability VulkanMemoryModelKHR
5214 OpExtension "SPV_KHR_vulkan_memory_model"
5215 )";
5216   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
5217                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
5218                           .c_str());
5219   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5220 }
5221 
TEST_F(ValidateImage,MakeTexelVisibleKHRSuccessImageSparseRead)5222 TEST_F(ValidateImage, MakeTexelVisibleKHRSuccessImageSparseRead) {
5223   const std::string body = R"(
5224 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
5225 %res1 = OpImageSparseRead %struct_u32_f32vec4 %img %u32vec2_01 MakeTexelVisibleKHR|NonPrivateTexelKHR %u32_2
5226 )";
5227 
5228   const std::string extra = R"(
5229 OpCapability StorageImageReadWithoutFormat
5230 OpCapability VulkanMemoryModelKHR
5231 OpExtension "SPV_KHR_vulkan_memory_model"
5232 )";
5233   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
5234                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
5235                           .c_str());
5236   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5237 }
5238 
TEST_F(ValidateImage,MakeTexelVisibleKHRFailureOpcode)5239 TEST_F(ValidateImage, MakeTexelVisibleKHRFailureOpcode) {
5240   const std::string body = R"(
5241 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5242 %sampler = OpLoad %type_sampler %uniform_sampler
5243 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5244 %res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh MakeTexelVisibleKHR|NonPrivateTexelKHR %u32_1
5245 )";
5246 
5247   const std::string extra = R"(
5248 OpCapability StorageImageReadWithoutFormat
5249 OpCapability VulkanMemoryModelKHR
5250 OpExtension "SPV_KHR_vulkan_memory_model"
5251 )";
5252   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
5253                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
5254                           .c_str());
5255   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
5256             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5257   EXPECT_THAT(
5258       getDiagnosticString(),
5259       HasSubstr("Image Operand MakeTexelVisibleKHR can only be used with "
5260                 "OpImageRead or OpImageSparseRead: OpImageSampleImplicitLod"));
5261 }
5262 
TEST_F(ValidateImage,MakeTexelVisibleKHRFailureMissingNonPrivate)5263 TEST_F(ValidateImage, MakeTexelVisibleKHRFailureMissingNonPrivate) {
5264   const std::string body = R"(
5265 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
5266 %res1 = OpImageRead %u32vec4 %img %u32vec2_01 MakeTexelVisibleKHR %u32_1
5267 )";
5268 
5269   const std::string extra = R"(
5270 OpCapability StorageImageReadWithoutFormat
5271 OpCapability VulkanMemoryModelKHR
5272 OpExtension "SPV_KHR_vulkan_memory_model"
5273 )";
5274   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
5275                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
5276                           .c_str());
5277   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
5278             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5279   EXPECT_THAT(getDiagnosticString(),
5280               HasSubstr("Image Operand MakeTexelVisibleKHR requires "
5281                         "NonPrivateTexelKHR is also specified: OpImageRead"));
5282 }
5283 
TEST_F(ValidateImage,MakeTexelAvailableKHRSuccessImageWrite)5284 TEST_F(ValidateImage, MakeTexelAvailableKHRSuccessImageWrite) {
5285   const std::string body = R"(
5286 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
5287 OpImageWrite %img %u32vec2_01 %u32vec4_0123 MakeTexelAvailableKHR|NonPrivateTexelKHR %u32_2
5288 )";
5289 
5290   const std::string extra = R"(
5291 OpCapability StorageImageWriteWithoutFormat
5292 OpCapability VulkanMemoryModelKHR
5293 OpExtension "SPV_KHR_vulkan_memory_model"
5294 )";
5295   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
5296                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
5297                           .c_str());
5298   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5299 }
5300 
TEST_F(ValidateImage,MakeTexelAvailableKHRFailureOpcode)5301 TEST_F(ValidateImage, MakeTexelAvailableKHRFailureOpcode) {
5302   const std::string body = R"(
5303 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5304 %sampler = OpLoad %type_sampler %uniform_sampler
5305 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5306 %res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh MakeTexelAvailableKHR|NonPrivateTexelKHR %u32_1
5307 )";
5308 
5309   const std::string extra = R"(
5310 OpCapability StorageImageReadWithoutFormat
5311 OpCapability VulkanMemoryModelKHR
5312 OpExtension "SPV_KHR_vulkan_memory_model"
5313 )";
5314   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
5315                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
5316                           .c_str());
5317   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
5318             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5319   EXPECT_THAT(getDiagnosticString(),
5320               HasSubstr("Image Operand MakeTexelAvailableKHR can only be used "
5321                         "with OpImageWrite: OpImageSampleImplicitLod"));
5322 }
5323 
TEST_F(ValidateImage,MakeTexelAvailableKHRFailureMissingNonPrivate)5324 TEST_F(ValidateImage, MakeTexelAvailableKHRFailureMissingNonPrivate) {
5325   const std::string body = R"(
5326 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
5327 OpImageWrite %img %u32vec2_01 %u32vec4_0123 MakeTexelAvailableKHR %u32_1
5328 )";
5329 
5330   const std::string extra = R"(
5331 OpCapability StorageImageWriteWithoutFormat
5332 OpCapability VulkanMemoryModelKHR
5333 OpExtension "SPV_KHR_vulkan_memory_model"
5334 )";
5335   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
5336                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
5337                           .c_str());
5338   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
5339             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5340   EXPECT_THAT(getDiagnosticString(),
5341               HasSubstr("Image Operand MakeTexelAvailableKHR requires "
5342                         "NonPrivateTexelKHR is also specified: OpImageWrite"));
5343 }
5344 
TEST_F(ValidateImage,VulkanMemoryModelDeviceScopeImageWriteBad)5345 TEST_F(ValidateImage, VulkanMemoryModelDeviceScopeImageWriteBad) {
5346   const std::string body = R"(
5347 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
5348 OpImageWrite %img %u32vec2_01 %u32vec4_0123 MakeTexelAvailableKHR|NonPrivateTexelKHR %u32_1
5349 )";
5350 
5351   const std::string extra = R"(
5352 OpCapability StorageImageWriteWithoutFormat
5353 OpCapability VulkanMemoryModelKHR
5354 OpExtension "SPV_KHR_vulkan_memory_model"
5355 )";
5356   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
5357                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
5358                           .c_str());
5359   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
5360             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5361   EXPECT_THAT(
5362       getDiagnosticString(),
5363       HasSubstr("Use of device scope with VulkanKHR memory model requires the "
5364                 "VulkanMemoryModelDeviceScopeKHR capability"));
5365 }
5366 
TEST_F(ValidateImage,VulkanMemoryModelDeviceScopeImageWriteGood)5367 TEST_F(ValidateImage, VulkanMemoryModelDeviceScopeImageWriteGood) {
5368   const std::string body = R"(
5369 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
5370 OpImageWrite %img %u32vec2_01 %u32vec4_0123 MakeTexelAvailableKHR|NonPrivateTexelKHR %u32_1
5371 )";
5372 
5373   const std::string extra = R"(
5374 OpCapability StorageImageWriteWithoutFormat
5375 OpCapability VulkanMemoryModelKHR
5376 OpCapability VulkanMemoryModelDeviceScopeKHR
5377 OpExtension "SPV_KHR_vulkan_memory_model"
5378 )";
5379   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
5380                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
5381                           .c_str());
5382   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5383 }
5384 
TEST_F(ValidateImage,VulkanMemoryModelDeviceScopeImageReadBad)5385 TEST_F(ValidateImage, VulkanMemoryModelDeviceScopeImageReadBad) {
5386   const std::string body = R"(
5387 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
5388 %res1 = OpImageRead %u32vec4 %img %u32vec2_01 MakeTexelVisibleKHR|NonPrivateTexelKHR %u32_1
5389 )";
5390 
5391   const std::string extra = R"(
5392 OpCapability StorageImageReadWithoutFormat
5393 OpCapability VulkanMemoryModelKHR
5394 OpExtension "SPV_KHR_vulkan_memory_model"
5395 )";
5396   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
5397                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
5398                           .c_str());
5399   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
5400             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5401   EXPECT_THAT(
5402       getDiagnosticString(),
5403       HasSubstr("Use of device scope with VulkanKHR memory model requires the "
5404                 "VulkanMemoryModelDeviceScopeKHR capability"));
5405 }
5406 
TEST_F(ValidateImage,VulkanMemoryModelDeviceScopeImageReadGood)5407 TEST_F(ValidateImage, VulkanMemoryModelDeviceScopeImageReadGood) {
5408   const std::string body = R"(
5409 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
5410 %res1 = OpImageRead %u32vec4 %img %u32vec2_01 MakeTexelVisibleKHR|NonPrivateTexelKHR %u32_1
5411 )";
5412 
5413   const std::string extra = R"(
5414 OpCapability StorageImageReadWithoutFormat
5415 OpCapability VulkanMemoryModelKHR
5416 OpCapability VulkanMemoryModelDeviceScopeKHR
5417 OpExtension "SPV_KHR_vulkan_memory_model"
5418 )";
5419   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
5420                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
5421                           .c_str());
5422   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5423 }
5424 
5425 // This example used to cause a seg fault on OpReturnValue, verifying it doesn't
5426 // anymore.
TEST_F(ValidateImage,Issue2463NoSegFault)5427 TEST_F(ValidateImage, Issue2463NoSegFault) {
5428   const std::string spirv = R"(
5429                OpCapability Linkage
5430                OpCapability Shader
5431           %1 = OpExtInstImport "GLSL.std.450"
5432                OpMemoryModel Logical GLSL450
5433        %void = OpTypeVoid
5434           %6 = OpTypeFunction %void
5435       %float = OpTypeFloat 32
5436           %8 = OpTypeImage %float 3D 0 0 0 1 Unknown
5437 %_ptr_UniformConstant_8 = OpTypePointer UniformConstant %8
5438          %10 = OpTypeSampler
5439 %_ptr_UniformConstant_10 = OpTypePointer UniformConstant %10
5440          %12 = OpTypeSampledImage %8
5441          %13 = OpTypeFunction %12 %_ptr_UniformConstant_8 %_ptr_UniformConstant_10
5442          %23 = OpFunction %12 None %13
5443          %24 = OpFunctionParameter %_ptr_UniformConstant_8
5444          %25 = OpFunctionParameter %_ptr_UniformConstant_10
5445          %26 = OpLabel
5446          %27 = OpLoad %8 %24
5447          %28 = OpLoad %10 %25
5448          %29 = OpSampledImage %12 %27 %28
5449                OpReturnValue %29
5450                OpFunctionEnd
5451 )";
5452 
5453   CompileSuccessfully(spirv);
5454   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5455   EXPECT_THAT(getDiagnosticString(),
5456               HasSubstr("OpSampledImage instruction must not appear as operand "
5457                         "for OpReturnValue"));
5458 }
5459 
TEST_F(ValidateImage,SignExtendV13Bad)5460 TEST_F(ValidateImage, SignExtendV13Bad) {
5461   const std::string body = R"(
5462 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
5463 %res1 = OpImageRead %u32vec4 %img %u32vec2_01 SignExtend
5464 )";
5465 
5466   EXPECT_THAT(CompileFailure(GenerateShaderCode(body, "", "Fragment", "",
5467                                                 SPV_ENV_UNIVERSAL_1_3)),
5468               HasSubstr("Invalid image operand 'SignExtend'"));
5469 }
5470 
TEST_F(ValidateImage,ZeroExtendV13Bad)5471 TEST_F(ValidateImage, ZeroExtendV13Bad) {
5472   const std::string body = R"(
5473 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
5474 %res1 = OpImageRead %u32vec4 %img %u32vec2_01 ZeroExtend
5475 )";
5476 
5477   EXPECT_THAT(CompileFailure(GenerateShaderCode(body, "", "Fragment", "",
5478                                                 SPV_ENV_UNIVERSAL_1_3)),
5479               HasSubstr("Invalid image operand 'ZeroExtend'"));
5480 }
5481 
TEST_F(ValidateImage,SignExtendScalarUIntTexelV14Good)5482 TEST_F(ValidateImage, SignExtendScalarUIntTexelV14Good) {
5483   // Unsigned int sampled type
5484   const std::string body = R"(
5485 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
5486 %res1 = OpImageRead %u32 %img %u32vec2_01 SignExtend
5487 )";
5488   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
5489 
5490   CompileSuccessfully(
5491       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4),
5492       SPV_ENV_UNIVERSAL_1_4);
5493   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
5494   EXPECT_THAT(getDiagnosticString(), Eq(""));
5495 }
5496 
TEST_F(ValidateImage,SignExtendScalarSIntTexelV14Good)5497 TEST_F(ValidateImage, SignExtendScalarSIntTexelV14Good) {
5498   // Signed int sampled type
5499   const std::string body = R"(
5500 %img = OpLoad %type_image_s32_2d_0002 %uniform_image_s32_2d_0002
5501 %res1 = OpImageRead %s32 %img %u32vec2_01 SignExtend
5502 )";
5503   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
5504 
5505   CompileSuccessfully(
5506       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4),
5507       SPV_ENV_UNIVERSAL_1_4);
5508   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
5509   EXPECT_THAT(getDiagnosticString(), Eq(""));
5510 }
5511 
TEST_F(ValidateImage,SignExtendScalarVectorUIntTexelV14Good)5512 TEST_F(ValidateImage, SignExtendScalarVectorUIntTexelV14Good) {
5513   const std::string body = R"(
5514 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
5515 %res1 = OpImageRead %u32vec4 %img %u32vec2_01 SignExtend
5516 )";
5517   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
5518 
5519   CompileSuccessfully(
5520       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4),
5521       SPV_ENV_UNIVERSAL_1_4);
5522   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
5523   EXPECT_THAT(getDiagnosticString(), Eq(""));
5524 }
5525 
TEST_F(ValidateImage,SignExtendVectorSIntTexelV14Good)5526 TEST_F(ValidateImage, SignExtendVectorSIntTexelV14Good) {
5527   const std::string body = R"(
5528 %img = OpLoad %type_image_s32_2d_0002 %uniform_image_s32_2d_0002
5529 %res1 = OpImageRead %s32vec4 %img %u32vec2_01 SignExtend
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 
5540 // No negative tests for SignExtend since we don't truly know the
5541 // texel format.
5542 
TEST_F(ValidateImage,ZeroExtendScalarUIntTexelV14Good)5543 TEST_F(ValidateImage, ZeroExtendScalarUIntTexelV14Good) {
5544   // Unsigned int sampled type
5545   const std::string body = R"(
5546 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
5547 %res1 = OpImageRead %u32 %img %u32vec2_01 ZeroExtend
5548 )";
5549   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
5550 
5551   CompileSuccessfully(
5552       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4),
5553       SPV_ENV_UNIVERSAL_1_4);
5554   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
5555   EXPECT_THAT(getDiagnosticString(), Eq(""));
5556 }
5557 
TEST_F(ValidateImage,ZeroExtendScalarSIntTexelV14Good)5558 TEST_F(ValidateImage, ZeroExtendScalarSIntTexelV14Good) {
5559   // Zeroed int sampled type
5560   const std::string body = R"(
5561 %img = OpLoad %type_image_s32_2d_0002 %uniform_image_s32_2d_0002
5562 %res1 = OpImageRead %s32 %img %u32vec2_01 ZeroExtend
5563 )";
5564   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
5565 
5566   CompileSuccessfully(
5567       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4),
5568       SPV_ENV_UNIVERSAL_1_4);
5569   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
5570   EXPECT_THAT(getDiagnosticString(), Eq(""));
5571 }
5572 
TEST_F(ValidateImage,ZeroExtendScalarVectorUIntTexelV14Good)5573 TEST_F(ValidateImage, ZeroExtendScalarVectorUIntTexelV14Good) {
5574   const std::string body = R"(
5575 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
5576 %res1 = OpImageRead %u32vec4 %img %u32vec2_01 ZeroExtend
5577 )";
5578   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
5579 
5580   CompileSuccessfully(
5581       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4),
5582       SPV_ENV_UNIVERSAL_1_4);
5583   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
5584   EXPECT_THAT(getDiagnosticString(), Eq(""));
5585 }
5586 
TEST_F(ValidateImage,ZeroExtendVectorSIntTexelV14Good)5587 TEST_F(ValidateImage, ZeroExtendVectorSIntTexelV14Good) {
5588   const std::string body = R"(
5589 %img = OpLoad %type_image_s32_2d_0002 %uniform_image_s32_2d_0002
5590 %res1 = OpImageRead %s32vec4 %img %u32vec2_01 ZeroExtend
5591 )";
5592   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
5593 
5594   CompileSuccessfully(
5595       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4),
5596       SPV_ENV_UNIVERSAL_1_4);
5597   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
5598   EXPECT_THAT(getDiagnosticString(), Eq(""));
5599 }
5600 
TEST_F(ValidateImage,ReadLodAMDSuccess1)5601 TEST_F(ValidateImage, ReadLodAMDSuccess1) {
5602   const std::string body = R"(
5603 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
5604 %res1 = OpImageRead %u32vec4 %img %u32vec2_01 Lod %u32_0
5605 )";
5606 
5607   const std::string extra =
5608       "\nOpCapability StorageImageReadWithoutFormat\n"
5609       "OpCapability ImageReadWriteLodAMD\n"
5610       "OpExtension \"SPV_AMD_shader_image_load_store_lod\"\n";
5611   CompileSuccessfully(
5612       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_1),
5613       SPV_ENV_UNIVERSAL_1_1);
5614   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
5615 }
5616 
TEST_F(ValidateImage,ReadLodAMDSuccess2)5617 TEST_F(ValidateImage, ReadLodAMDSuccess2) {
5618   const std::string body = R"(
5619 %img = OpLoad %type_image_f32_1d_0002_rgba32f %uniform_image_f32_1d_0002_rgba32f
5620 %res1 = OpImageRead %f32vec4 %img %u32vec2_01 Lod %u32_0
5621 )";
5622 
5623   const std::string extra =
5624       "\nOpCapability Image1D\n"
5625       "OpCapability ImageReadWriteLodAMD\n"
5626       "OpExtension \"SPV_AMD_shader_image_load_store_lod\"\n";
5627   CompileSuccessfully(
5628       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_1),
5629       SPV_ENV_UNIVERSAL_1_1);
5630   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
5631 }
5632 
TEST_F(ValidateImage,ReadLodAMDSuccess3)5633 TEST_F(ValidateImage, ReadLodAMDSuccess3) {
5634   const std::string body = R"(
5635 %img = OpLoad %type_image_f32_cube_0102_rgba32f %uniform_image_f32_cube_0102_rgba32f
5636 %res1 = OpImageRead %f32vec4 %img %u32vec3_012 Lod %u32_0
5637 )";
5638 
5639   const std::string extra =
5640       "\nOpCapability ImageCubeArray\n"
5641       "OpCapability ImageReadWriteLodAMD\n"
5642       "OpExtension \"SPV_AMD_shader_image_load_store_lod\"\n";
5643   CompileSuccessfully(
5644       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_1),
5645       SPV_ENV_UNIVERSAL_1_1);
5646   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
5647 }
5648 
TEST_F(ValidateImage,ReadLodAMDNeedCapability)5649 TEST_F(ValidateImage, ReadLodAMDNeedCapability) {
5650   const std::string body = R"(
5651 %img = OpLoad %type_image_f32_cube_0102_rgba32f %uniform_image_f32_cube_0102_rgba32f
5652 %res1 = OpImageRead %f32vec4 %img %u32vec3_012 Lod %u32_0
5653 )";
5654 
5655   const std::string extra = "\nOpCapability ImageCubeArray\n";
5656   CompileSuccessfully(
5657       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_1),
5658       SPV_ENV_UNIVERSAL_1_1);
5659   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
5660             ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
5661   EXPECT_THAT(getDiagnosticString(),
5662               HasSubstr("Image Operand Lod can only be used with ExplicitLod "
5663                         "opcodes and OpImageFetch"));
5664 }
5665 
TEST_F(ValidateImage,WriteLodAMDSuccess1)5666 TEST_F(ValidateImage, WriteLodAMDSuccess1) {
5667   const std::string body = R"(
5668 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
5669 OpImageWrite %img %u32vec2_01 %u32vec4_0123 Lod %u32_0
5670 )";
5671 
5672   const std::string extra =
5673       "\nOpCapability StorageImageWriteWithoutFormat\n"
5674       "OpCapability ImageReadWriteLodAMD\n"
5675       "OpExtension \"SPV_AMD_shader_image_load_store_lod\"\n";
5676   CompileSuccessfully(
5677       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_1),
5678       SPV_ENV_UNIVERSAL_1_1);
5679   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
5680 }
5681 
TEST_F(ValidateImage,WriteLodAMDSuccess2)5682 TEST_F(ValidateImage, WriteLodAMDSuccess2) {
5683   const std::string body = R"(
5684 %img = OpLoad %type_image_f32_1d_0002_rgba32f %uniform_image_f32_1d_0002_rgba32f
5685 OpImageWrite %img %u32_1 %f32vec4_0000 Lod %u32_0
5686 )";
5687 
5688   const std::string extra =
5689       "\nOpCapability Image1D\n"
5690       "OpCapability ImageReadWriteLodAMD\n"
5691       "OpExtension \"SPV_AMD_shader_image_load_store_lod\"\n";
5692   CompileSuccessfully(
5693       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_1),
5694       SPV_ENV_UNIVERSAL_1_1);
5695   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
5696 }
5697 
TEST_F(ValidateImage,WriteLodAMDSuccess3)5698 TEST_F(ValidateImage, WriteLodAMDSuccess3) {
5699   const std::string body = R"(
5700 %img = OpLoad %type_image_f32_cube_0102_rgba32f %uniform_image_f32_cube_0102_rgba32f
5701 OpImageWrite %img %u32vec3_012 %f32vec4_0000 Lod %u32_0
5702 )";
5703 
5704   const std::string extra =
5705       "\nOpCapability ImageCubeArray\n"
5706       "OpCapability ImageReadWriteLodAMD\n"
5707       "OpExtension \"SPV_AMD_shader_image_load_store_lod\"\n";
5708   CompileSuccessfully(
5709       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_1),
5710       SPV_ENV_UNIVERSAL_1_1);
5711   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
5712 }
5713 
TEST_F(ValidateImage,WriteLodAMDNeedCapability)5714 TEST_F(ValidateImage, WriteLodAMDNeedCapability) {
5715   const std::string body = R"(
5716 %img = OpLoad %type_image_f32_cube_0102_rgba32f %uniform_image_f32_cube_0102_rgba32f
5717 OpImageWrite %img %u32vec3_012 %f32vec4_0000 Lod %u32_0
5718 )";
5719 
5720   const std::string extra = "\nOpCapability ImageCubeArray\n";
5721   CompileSuccessfully(
5722       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_1),
5723       SPV_ENV_UNIVERSAL_1_1);
5724   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
5725             ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
5726   EXPECT_THAT(getDiagnosticString(),
5727               HasSubstr("Image Operand Lod can only be used with ExplicitLod "
5728                         "opcodes and OpImageFetch"));
5729 }
5730 
TEST_F(ValidateImage,SparseReadLodAMDSuccess)5731 TEST_F(ValidateImage, SparseReadLodAMDSuccess) {
5732   const std::string body = R"(
5733 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
5734 %res1 = OpImageSparseRead %struct_u32_f32vec4 %img %u32vec2_01 Lod %u32_0
5735 )";
5736 
5737   const std::string extra =
5738       "\nOpCapability StorageImageReadWithoutFormat\n"
5739       "OpCapability ImageReadWriteLodAMD\n"
5740       "OpExtension \"SPV_AMD_shader_image_load_store_lod\"\n";
5741   CompileSuccessfully(
5742       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_1),
5743       SPV_ENV_UNIVERSAL_1_1);
5744   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
5745 }
5746 
TEST_F(ValidateImage,SparseReadLodAMDNeedCapability)5747 TEST_F(ValidateImage, SparseReadLodAMDNeedCapability) {
5748   const std::string body = R"(
5749 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
5750 %res1 = OpImageSparseRead %struct_u32_f32vec4 %img %u32vec2_01 Lod %u32_0
5751 )";
5752 
5753   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
5754   CompileSuccessfully(
5755       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_1),
5756       SPV_ENV_UNIVERSAL_1_1);
5757   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
5758             ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
5759   EXPECT_THAT(getDiagnosticString(),
5760               HasSubstr("Image Operand Lod can only be used with ExplicitLod "
5761                         "opcodes and OpImageFetch"));
5762 }
5763 
TEST_F(ValidateImage,GatherBiasAMDSuccess)5764 TEST_F(ValidateImage, GatherBiasAMDSuccess) {
5765   const std::string body = R"(
5766 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5767 %sampler = OpLoad %type_sampler %uniform_sampler
5768 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5769 %res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 Bias %f32_1
5770 )";
5771 
5772   const std::string extra = R"(
5773 OpCapability ImageGatherBiasLodAMD
5774 OpExtension "SPV_AMD_texture_gather_bias_lod"
5775 )";
5776   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
5777   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
5778 }
5779 
TEST_F(ValidateImage,GatherLodAMDSuccess)5780 TEST_F(ValidateImage, GatherLodAMDSuccess) {
5781   const std::string body = R"(
5782 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5783 %sampler = OpLoad %type_sampler %uniform_sampler
5784 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5785 %res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 Lod %f32_1
5786 )";
5787 
5788   const std::string extra = R"(
5789 OpCapability ImageGatherBiasLodAMD
5790 OpExtension "SPV_AMD_texture_gather_bias_lod"
5791 )";
5792   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
5793   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
5794 }
5795 
TEST_F(ValidateImage,SparseGatherBiasAMDSuccess)5796 TEST_F(ValidateImage, SparseGatherBiasAMDSuccess) {
5797   const std::string body = R"(
5798 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5799 %sampler = OpLoad %type_sampler %uniform_sampler
5800 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5801 %res1 = OpImageSparseGather %struct_u32_f32vec4 %simg %f32vec4_0000 %u32_1 Bias %f32_1
5802 )";
5803 
5804   const std::string extra = R"(
5805 OpCapability ImageGatherBiasLodAMD
5806 OpExtension "SPV_AMD_texture_gather_bias_lod"
5807 )";
5808   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
5809   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
5810 }
5811 
TEST_F(ValidateImage,SparseGatherLodAMDSuccess)5812 TEST_F(ValidateImage, SparseGatherLodAMDSuccess) {
5813   const std::string body = R"(
5814 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5815 %sampler = OpLoad %type_sampler %uniform_sampler
5816 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5817 %res1 = OpImageSparseGather %struct_u32_f32vec4 %simg %f32vec4_0000 %u32_1 Lod %f32_1
5818 )";
5819 
5820   const std::string extra = R"(
5821 OpCapability ImageGatherBiasLodAMD
5822 OpExtension "SPV_AMD_texture_gather_bias_lod"
5823 )";
5824   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
5825   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
5826 }
5827 
5828 // No negative tests for ZeroExtend since we don't truly know the
5829 // texel format.
5830 
5831 // Tests for 64-bit images
5832 static const std::string capabilities_and_extensions_image64 = R"(
5833 OpCapability Int64ImageEXT
5834 OpExtension "SPV_EXT_shader_image_int64"
5835 )";
5836 static const std::string capabilities_and_extensions_image64_atomic = R"(
5837 OpCapability Int64Atomics
5838 OpCapability Int64ImageEXT
5839 OpExtension "SPV_EXT_shader_image_int64"
5840 )";
5841 static const std::string declarations_image64 = R"(
5842 %type_image_u64_buffer_0002_r64ui = OpTypeImage %u64 Buffer 0 0 0 2 R64ui
5843 %ptr_Image_u64 = OpTypePointer Image %u64
5844 %ptr_image_u64_buffer_0002_r64ui = OpTypePointer Private %type_image_u64_buffer_0002_r64ui
5845 %private_image_u64_buffer_0002_r64ui = OpVariable %ptr_image_u64_buffer_0002_r64ui Private
5846 )";
5847 static const std::string declarations_image64i = R"(
5848 %type_image_s64_buffer_0002_r64i = OpTypeImage %s64 Buffer 0 0 0 2 R64i
5849 %ptr_Image_s64 = OpTypePointer Image %s64
5850 %ptr_image_s64_buffer_0002_r64i = OpTypePointer Private %type_image_s64_buffer_0002_r64i
5851 %private_image_s64_buffer_0002_r64i = OpVariable %ptr_image_s64_buffer_0002_r64i Private
5852 )";
5853 
TEST_F(ValidateImage,Image64MissingCapability)5854 TEST_F(ValidateImage, Image64MissingCapability) {
5855   CompileSuccessfully(GenerateShaderCode("", "", "Fragment", "",
5856                                          SPV_ENV_UNIVERSAL_1_3, "GLSL450",
5857                                          declarations_image64)
5858                           .c_str());
5859   ASSERT_EQ(SPV_ERROR_INVALID_CAPABILITY, ValidateInstructions());
5860 }
5861 
TEST_F(ValidateImage,Image64MissingExtension)5862 TEST_F(ValidateImage, Image64MissingExtension) {
5863   const std::string extra = R"(
5864 OpCapability Int64ImageEXT
5865 )";
5866 
5867   CompileSuccessfully(GenerateShaderCode("", extra, "Fragment", "",
5868                                          SPV_ENV_UNIVERSAL_1_3, "GLSL450",
5869                                          declarations_image64)
5870                           .c_str());
5871   ASSERT_EQ(SPV_ERROR_MISSING_EXTENSION, ValidateInstructions());
5872 }
5873 
TEST_F(ValidateImage,ImageTexelPointer64Success)5874 TEST_F(ValidateImage, ImageTexelPointer64Success) {
5875   const std::string body = R"(
5876 %texel_ptr = OpImageTexelPointer %ptr_Image_u64 %private_image_u64_buffer_0002_r64ui %u32_0 %u32_0
5877 %sum = OpAtomicIAdd %u64 %texel_ptr %u32_1 %u32_0 %u64_1
5878 )";
5879 
5880   CompileSuccessfully(
5881       GenerateShaderCode(body, capabilities_and_extensions_image64_atomic,
5882                          "Fragment", "", SPV_ENV_UNIVERSAL_1_3, "GLSL450",
5883                          declarations_image64)
5884           .c_str());
5885   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
5886 }
5887 
TEST_F(ValidateImage,ImageTexelPointer64ResultTypeNotPointer)5888 TEST_F(ValidateImage, ImageTexelPointer64ResultTypeNotPointer) {
5889   const std::string body = R"(
5890 %texel_ptr = OpImageTexelPointer %type_image_u64_buffer_0002_r64ui %private_image_u64_buffer_0002_r64ui %u32_0 %u32_0
5891 %sum = OpAtomicIAdd %u64 %texel_ptr %u32_1 %u32_0 %u64_1
5892 )";
5893 
5894   CompileSuccessfully(
5895       GenerateShaderCode(body, capabilities_and_extensions_image64_atomic,
5896                          "Fragment", "", SPV_ENV_UNIVERSAL_1_3, "GLSL450",
5897                          declarations_image64)
5898           .c_str());
5899   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5900   EXPECT_THAT(getDiagnosticString(),
5901               HasSubstr("Expected Result Type to be OpTypePointer"));
5902 }
5903 
TEST_F(ValidateImage,ImageTexelPointer64ResultTypeNotImageClass)5904 TEST_F(ValidateImage, ImageTexelPointer64ResultTypeNotImageClass) {
5905   const std::string body = R"(
5906 %texel_ptr = OpImageTexelPointer %ptr_image_f32_cube_0101 %private_image_u64_buffer_0002_r64ui %u32_0 %u32_0
5907 %sum = OpAtomicIAdd %u64 %texel_ptr %u32_1 %u32_0 %u64_1
5908 )";
5909 
5910   CompileSuccessfully(
5911       GenerateShaderCode(body, capabilities_and_extensions_image64_atomic,
5912                          "Fragment", "", SPV_ENV_UNIVERSAL_1_3, "GLSL450",
5913                          declarations_image64)
5914           .c_str());
5915   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5916   EXPECT_THAT(getDiagnosticString(),
5917               HasSubstr("Expected Result Type to be OpTypePointer whose "
5918                         "Storage Class operand is Image"));
5919 }
5920 
TEST_F(ValidateImage,ImageTexelPointer64SampleNotZeroForImageWithMSZero)5921 TEST_F(ValidateImage, ImageTexelPointer64SampleNotZeroForImageWithMSZero) {
5922   const std::string body = R"(
5923 %texel_ptr = OpImageTexelPointer %ptr_Image_u64 %private_image_u64_buffer_0002_r64ui %u32_0 %u32_1
5924 %sum = OpAtomicIAdd %u64 %texel_ptr %u32_1 %u32_0 %u64_1
5925 )";
5926 
5927   CompileSuccessfully(
5928       GenerateShaderCode(body, capabilities_and_extensions_image64_atomic,
5929                          "Fragment", "", SPV_ENV_UNIVERSAL_1_3, "GLSL450",
5930                          declarations_image64)
5931           .c_str());
5932   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5933   EXPECT_THAT(getDiagnosticString(),
5934               HasSubstr("Expected Sample for Image with MS 0 to be a valid "
5935                         "<id> for the value 0"));
5936 }
5937 
TEST_F(ValidateImage,ImageTexelPointerR32uiSuccessVulkan)5938 TEST_F(ValidateImage, ImageTexelPointerR32uiSuccessVulkan) {
5939   const std::string body = R"(
5940 %texel_ptr = OpImageTexelPointer %ptr_Image_u32 %private_image_u32_buffer_0002_r32ui %u32_0 %u32_0
5941 )";
5942 
5943   spv_target_env env = SPV_ENV_VULKAN_1_0;
5944   CompileSuccessfully(GenerateShaderCode(body, "", "Fragment", "", env).c_str(),
5945                       env);
5946   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(env));
5947 }
5948 
TEST_F(ValidateImage,ImageTexelPointerR32iSuccessVulkan)5949 TEST_F(ValidateImage, ImageTexelPointerR32iSuccessVulkan) {
5950   const std::string& declarations = R"(
5951 %type_image_s32_buffer_0002_r32i = OpTypeImage %s32 Buffer 0 0 0 2 R32i
5952 %ptr_Image_s32 = OpTypePointer Image %s32
5953 %ptr_image_s32_buffer_0002_r32i = OpTypePointer Private %type_image_s32_buffer_0002_r32i
5954 %private_image_s32_buffer_0002_r32i = OpVariable %ptr_image_s32_buffer_0002_r32i Private
5955 )";
5956 
5957   const std::string body = R"(
5958 %texel_ptr = OpImageTexelPointer %ptr_Image_s32 %private_image_s32_buffer_0002_r32i %u32_0 %u32_0
5959 )";
5960 
5961   spv_target_env env = SPV_ENV_VULKAN_1_0;
5962   CompileSuccessfully(
5963       GenerateShaderCode(body, "", "Fragment", "", env, "GLSL450", declarations)
5964           .c_str(),
5965       env);
5966   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(env));
5967 }
5968 
TEST_F(ValidateImage,ImageTexelPointerR64uiSuccessVulkan)5969 TEST_F(ValidateImage, ImageTexelPointerR64uiSuccessVulkan) {
5970   const std::string body = R"(
5971 %texel_ptr = OpImageTexelPointer %ptr_Image_u64 %private_image_u64_buffer_0002_r64ui %u32_0 %u32_0
5972 )";
5973 
5974   spv_target_env env = SPV_ENV_VULKAN_1_0;
5975   CompileSuccessfully(
5976       GenerateShaderCode(body, capabilities_and_extensions_image64, "Fragment",
5977                          "", env, "GLSL450", declarations_image64)
5978           .c_str(),
5979       env);
5980   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(env));
5981 }
5982 
TEST_F(ValidateImage,ImageTexelPointerR64iSuccessVulkan)5983 TEST_F(ValidateImage, ImageTexelPointerR64iSuccessVulkan) {
5984   const std::string body = R"(
5985 %texel_ptr = OpImageTexelPointer %ptr_Image_s64 %private_image_s64_buffer_0002_r64i %u32_0 %u32_0
5986 )";
5987 
5988   spv_target_env env = SPV_ENV_VULKAN_1_0;
5989   CompileSuccessfully(
5990       GenerateShaderCode(body, capabilities_and_extensions_image64, "Fragment",
5991                          "", env, "GLSL450", declarations_image64i)
5992           .c_str(),
5993       env);
5994   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(env));
5995 }
5996 
TEST_F(ValidateImage,ImageTexelPointerR32fSuccessVulkan)5997 TEST_F(ValidateImage, ImageTexelPointerR32fSuccessVulkan) {
5998   const std::string& declarations = R"(
5999 %type_image_f32_buffer_0002_r32f = OpTypeImage %f32 Buffer 0 0 0 2 R32f
6000 %ptr_image_f32_buffer_0002_r32f = OpTypePointer Private %type_image_f32_buffer_0002_r32f
6001 %private_image_f32_buffer_0002_r32f = OpVariable %ptr_image_f32_buffer_0002_r32f Private
6002 )";
6003 
6004   const std::string body = R"(
6005 %texel_ptr = OpImageTexelPointer %ptr_Image_f32 %private_image_f32_buffer_0002_r32f %u32_0 %u32_0
6006 )";
6007 
6008   spv_target_env env = SPV_ENV_VULKAN_1_0;
6009   CompileSuccessfully(
6010       GenerateShaderCode(body, "", "Fragment", "", env, "GLSL450", declarations)
6011           .c_str(),
6012       env);
6013   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(env));
6014 }
6015 
TEST_F(ValidateImage,ImageTexelPointerRgba32iVulkan)6016 TEST_F(ValidateImage, ImageTexelPointerRgba32iVulkan) {
6017   const std::string& declarations = R"(
6018 %type_image_s32_buffer_0002_rgba32i = OpTypeImage %s32 Buffer 0 0 0 2 Rgba32i
6019 %ptr_Image_s32 = OpTypePointer Image %s32
6020 %ptr_image_s32_buffer_0002_rgba32i = OpTypePointer Private %type_image_s32_buffer_0002_rgba32i
6021 %private_image_s32_buffer_0002_rgba32i = OpVariable %ptr_image_s32_buffer_0002_rgba32i Private
6022 )";
6023 
6024   const std::string body = R"(
6025 %texel_ptr = OpImageTexelPointer %ptr_Image_s32 %private_image_s32_buffer_0002_rgba32i %u32_0 %u32_0
6026 )";
6027 
6028   spv_target_env env = SPV_ENV_VULKAN_1_0;
6029   CompileSuccessfully(
6030       GenerateShaderCode(body, "", "Fragment", "", env, "GLSL450", declarations)
6031           .c_str(),
6032       env);
6033   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
6034   EXPECT_THAT(getDiagnosticString(),
6035               AnyVUID("VUID-StandaloneSpirv-OpImageTexelPointer-04658"));
6036   EXPECT_THAT(getDiagnosticString(),
6037               HasSubstr("Expected the Image Format in Image to be R64i, R64ui, "
6038                         "R32f, R32i, or R32ui for Vulkan environment"));
6039 }
6040 
TEST_F(ValidateImage,ImageTexelPointerRgba16fVulkan)6041 TEST_F(ValidateImage, ImageTexelPointerRgba16fVulkan) {
6042   const std::string& declarations = R"(
6043 %type_image_s32_buffer_0002_rgba16f = OpTypeImage %s32 Buffer 0 0 0 2 Rgba16f
6044 %ptr_Image_s32 = OpTypePointer Image %s32
6045 %ptr_image_s32_buffer_0002_rgba16f = OpTypePointer Private %type_image_s32_buffer_0002_rgba16f
6046 %private_image_s32_buffer_0002_rgba16f = OpVariable %ptr_image_s32_buffer_0002_rgba16f Private
6047 )";
6048 
6049   const std::string body = R"(
6050 %texel_ptr = OpImageTexelPointer %ptr_Image_s32 %private_image_s32_buffer_0002_rgba16f %u32_0 %u32_0
6051 )";
6052 
6053   spv_target_env env = SPV_ENV_VULKAN_1_0;
6054   CompileSuccessfully(
6055       GenerateShaderCode(body, "", "Fragment", "", env, "GLSL450", declarations)
6056           .c_str(),
6057       env);
6058   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
6059   EXPECT_THAT(getDiagnosticString(),
6060               AnyVUID("VUID-StandaloneSpirv-OpImageTexelPointer-04658"));
6061   EXPECT_THAT(getDiagnosticString(),
6062               HasSubstr("Expected the Image Format in Image to be R64i, R64ui, "
6063                         "R32f, R32i, or R32ui for Vulkan environment"));
6064 }
6065 
TEST_F(ValidateImage,ImageExecutionModeLimitationNoMode)6066 TEST_F(ValidateImage, ImageExecutionModeLimitationNoMode) {
6067   const std::string text = R"(
6068 OpCapability Shader
6069 OpMemoryModel Logical GLSL450
6070 OpEntryPoint GLCompute %2 " " %4
6071 %void = OpTypeVoid
6072 %8 = OpTypeFunction %void
6073 %float = OpTypeFloat 32
6074 %v4float = OpTypeVector %float 4
6075 %12 = OpTypeImage %float 2D 0 0 0 1 Rgba8ui
6076 %13 = OpTypeSampledImage %12
6077 %_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
6078 %5 = OpVariable %_ptr_UniformConstant_13 UniformConstant
6079 %_ptr_Input_v4float = OpTypePointer Input %v4float
6080 %4 = OpVariable %_ptr_Input_v4float Input
6081 %v2float = OpTypeVector %float 2
6082 %float_1_35631564en19 = OpConstant %float 1.35631564e-19
6083 %2 = OpFunction %void None %8
6084 %8224 = OpLabel
6085 %6 = OpLoad %13 %5
6086 %19 = OpLoad %v4float %4
6087 %20 = OpVectorShuffle %v2float %19 %19 0 1
6088 %21 = OpVectorTimesScalar %v2float %20 %float_1_35631564en19
6089 %65312 = OpImageSampleImplicitLod %v4float %6 %21
6090 OpUnreachable
6091 OpFunctionEnd
6092 )";
6093 
6094   CompileSuccessfully(text);
6095   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6096   EXPECT_THAT(getDiagnosticString(),
6097               HasSubstr("ImplicitLod instructions require "
6098                         "DerivativeGroupQuadsNV or DerivativeGroupLinearNV "
6099                         "execution mode for GLCompute execution model"));
6100 }
6101 
6102 }  // namespace
6103 }  // namespace val
6104 }  // namespace spvtools
6105