1 // Copyright (c) 2017 Google Inc.
2 // Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights
3 // reserved.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 
17 // Tests for unique type declaration rules validator.
18 
19 #include <sstream>
20 #include <string>
21 
22 #include "gmock/gmock.h"
23 #include "test/unit_spirv.h"
24 #include "test/val/val_fixtures.h"
25 
26 namespace spvtools {
27 namespace val {
28 namespace {
29 
30 using ::testing::Eq;
31 using ::testing::HasSubstr;
32 using ::testing::Not;
33 
34 using ValidateImage = spvtest::ValidateBase<bool>;
35 
GenerateShaderCode(const std::string & body,const std::string & capabilities_and_extensions="",const std::string & execution_model="Fragment",const std::string & execution_mode="",const spv_target_env env=SPV_ENV_UNIVERSAL_1_0,const std::string & memory_model="GLSL450",const std::string & declarations="")36 std::string GenerateShaderCode(
37     const std::string& body,
38     const std::string& capabilities_and_extensions = "",
39     const std::string& execution_model = "Fragment",
40     const std::string& execution_mode = "",
41     const spv_target_env env = SPV_ENV_UNIVERSAL_1_0,
42     const std::string& memory_model = "GLSL450",
43     const std::string& declarations = "") {
44   std::ostringstream ss;
45   ss << R"(
46 OpCapability Shader
47 OpCapability InputAttachment
48 OpCapability ImageGatherExtended
49 OpCapability MinLod
50 OpCapability Sampled1D
51 OpCapability ImageQuery
52 OpCapability Int64
53 OpCapability Float64
54 OpCapability SparseResidency
55 OpCapability ImageBuffer
56 )";
57 
58   if (env == SPV_ENV_UNIVERSAL_1_0) {
59     ss << "OpCapability SampledRect\n";
60   }
61 
62   // In 1.4, the entry point must list all module-scope variables used.  Just
63   // list all of them.
64   //
65   // For Vulkan, anything Location decoration needs to be an interface variable
66   std::string interface_vars =
67       (env != SPV_ENV_UNIVERSAL_1_4) ? "%input_flat_u32" :
68                                      R"(
69 %uniform_image_f32_1d_0001
70 %uniform_image_f32_1d_0002_rgba32f
71 %uniform_image_f32_2d_0001
72 %uniform_image_f32_2d_0011 ; multisampled sampled
73 %uniform_image_u32_2d_0001
74 %uniform_image_u32_2d_0002
75 %uniform_image_s32_3d_0001
76 %uniform_image_f32_2d_0002
77 %uniform_image_s32_2d_0002
78 %uniform_image_f32_spd_0002
79 %uniform_image_f32_3d_0111
80 %uniform_image_f32_cube_0101
81 %uniform_image_f32_cube_0102_rgba32f
82 %uniform_sampler
83 %private_image_u32_buffer_0002_r32ui
84 %private_image_u32_spd_0002
85 %private_image_f32_buffer_0002_r32ui
86 %input_flat_u32
87 )";
88 
89   ss << capabilities_and_extensions;
90   ss << "OpMemoryModel Logical " << memory_model << "\n";
91   ss << "OpEntryPoint " << execution_model
92      << " %main \"main\" " + interface_vars + "\n";
93   if (execution_model == "Fragment") {
94     ss << "OpExecutionMode %main OriginUpperLeft\n";
95   }
96   ss << execution_mode;
97 
98   if (env == SPV_ENV_VULKAN_1_0) {
99     ss << R"(
100 OpDecorate %uniform_image_f32_1d_0001 DescriptorSet 0
101 OpDecorate %uniform_image_f32_1d_0001 Binding 0
102 OpDecorate %uniform_image_f32_1d_0002_rgba32f DescriptorSet 0
103 OpDecorate %uniform_image_f32_1d_0002_rgba32f Binding 1
104 OpDecorate %uniform_image_f32_2d_0001 DescriptorSet 0
105 OpDecorate %uniform_image_f32_2d_0001 Binding 2
106 OpDecorate %uniform_image_f32_2d_0011 DescriptorSet 0
107 OpDecorate %uniform_image_f32_2d_0011 Binding 3
108 OpDecorate %uniform_image_u32_2d_0001 DescriptorSet 1
109 OpDecorate %uniform_image_u32_2d_0001 Binding 0
110 OpDecorate %uniform_image_u32_2d_0002 DescriptorSet 1
111 OpDecorate %uniform_image_u32_2d_0002 Binding 1
112 OpDecorate %uniform_image_s32_3d_0001 DescriptorSet 1
113 OpDecorate %uniform_image_s32_3d_0001 Binding 2
114 OpDecorate %uniform_image_f32_2d_0002 DescriptorSet 1
115 OpDecorate %uniform_image_f32_2d_0002 Binding 3
116 OpDecorate %uniform_image_s32_2d_0002 DescriptorSet 1
117 OpDecorate %uniform_image_s32_2d_0002 Binding 4
118 OpDecorate %uniform_image_f32_spd_0002 DescriptorSet 2
119 OpDecorate %uniform_image_f32_spd_0002 Binding 0
120 OpDecorate %uniform_image_f32_3d_0111 DescriptorSet 2
121 OpDecorate %uniform_image_f32_3d_0111 Binding 1
122 OpDecorate %uniform_image_f32_cube_0101 DescriptorSet 2
123 OpDecorate %uniform_image_f32_cube_0101 Binding 2
124 OpDecorate %uniform_image_f32_cube_0102_rgba32f DescriptorSet 2
125 OpDecorate %uniform_image_f32_cube_0102_rgba32f Binding 3
126 OpDecorate %uniform_sampler DescriptorSet 3
127 OpDecorate %uniform_sampler Binding 0
128 OpDecorate %input_flat_u32 Flat
129 OpDecorate %input_flat_u32 Location 0
130 )";
131   }
132 
133   ss << R"(
134 %void = OpTypeVoid
135 %func = OpTypeFunction %void
136 %bool = OpTypeBool
137 %f32 = OpTypeFloat 32
138 %f64 = OpTypeFloat 64
139 %u32 = OpTypeInt 32 0
140 %s32 = OpTypeInt 32 1
141 %u64 = OpTypeInt 64 0
142 %s64 = OpTypeInt 64 1
143 %s32vec2 = OpTypeVector %s32 2
144 %u32vec2 = OpTypeVector %u32 2
145 %f32vec2 = OpTypeVector %f32 2
146 %u32vec3 = OpTypeVector %u32 3
147 %s32vec3 = OpTypeVector %s32 3
148 %f32vec3 = OpTypeVector %f32 3
149 %u32vec4 = OpTypeVector %u32 4
150 %s32vec4 = OpTypeVector %s32 4
151 %f32vec4 = OpTypeVector %f32 4
152 %boolvec4 = OpTypeVector %bool 4
153 
154 %f32_0 = OpConstant %f32 0
155 %f32_1 = OpConstant %f32 1
156 %f32_0_5 = OpConstant %f32 0.5
157 %f32_0_25 = OpConstant %f32 0.25
158 %f32_0_75 = OpConstant %f32 0.75
159 
160 %f64_0 = OpConstant %f64 0
161 %f64_1 = OpConstant %f64 1
162 
163 %s32_0 = OpConstant %s32 0
164 %s32_1 = OpConstant %s32 1
165 %s32_2 = OpConstant %s32 2
166 %s32_3 = OpConstant %s32 3
167 %s32_4 = OpConstant %s32 4
168 %s32_m1 = OpConstant %s32 -1
169 
170 %u32_0 = OpConstant %u32 0
171 %u32_1 = OpConstant %u32 1
172 %u32_2 = OpConstant %u32 2
173 %u32_3 = OpConstant %u32 3
174 %u32_4 = OpConstant %u32 4
175 
176 %u64_0 = OpConstant %u64 0
177 %u64_1 = OpConstant %u64 1
178 
179 %bool_t = OpConstantTrue %bool
180 
181 %u32vec2arr4 = OpTypeArray %u32vec2 %u32_4
182 %u32vec2arr3 = OpTypeArray %u32vec2 %u32_3
183 %u32arr4 = OpTypeArray %u32 %u32_4
184 %u32vec3arr4 = OpTypeArray %u32vec3 %u32_4
185 
186 %struct_u32_f32vec4 = OpTypeStruct %u32 %f32vec4
187 %struct_u64_f32vec4 = OpTypeStruct %u64 %f32vec4
188 %struct_u32_u32vec4 = OpTypeStruct %u32 %u32vec4
189 %struct_u32_f32vec3 = OpTypeStruct %u32 %f32vec3
190 %struct_f32_f32vec4 = OpTypeStruct %f32 %f32vec4
191 %struct_u32_u32 = OpTypeStruct %u32 %u32
192 %struct_f32_f32 = OpTypeStruct %f32 %f32
193 %struct_u32 = OpTypeStruct %u32
194 %struct_u32_f32_u32 = OpTypeStruct %u32 %f32 %u32
195 %struct_u32_f32vec4_u32 = OpTypeStruct %u32 %f32vec4 %u32
196 %struct_u32_u32arr4 = OpTypeStruct %u32 %u32arr4
197 
198 %u32vec2_01 = OpConstantComposite %u32vec2 %u32_0 %u32_1
199 %u32vec2_12 = OpConstantComposite %u32vec2 %u32_1 %u32_2
200 %u32vec3_012 = OpConstantComposite %u32vec3 %u32_0 %u32_1 %u32_2
201 %u32vec3_123 = OpConstantComposite %u32vec3 %u32_1 %u32_2 %u32_3
202 %u32vec4_0123 = OpConstantComposite %u32vec4 %u32_0 %u32_1 %u32_2 %u32_3
203 %u32vec4_1234 = OpConstantComposite %u32vec4 %u32_1 %u32_2 %u32_3 %u32_4
204 
205 %s32vec2_01 = OpConstantComposite %s32vec2 %s32_0 %s32_1
206 %s32vec2_12 = OpConstantComposite %s32vec2 %s32_1 %s32_2
207 %s32vec3_012 = OpConstantComposite %s32vec3 %s32_0 %s32_1 %s32_2
208 %s32vec3_123 = OpConstantComposite %s32vec3 %s32_1 %s32_2 %s32_3
209 %s32vec4_0123 = OpConstantComposite %s32vec4 %s32_0 %s32_1 %s32_2 %s32_3
210 %s32vec4_1234 = OpConstantComposite %s32vec4 %s32_1 %s32_2 %s32_3 %s32_4
211 
212 %f32vec2_00 = OpConstantComposite %f32vec2 %f32_0 %f32_0
213 %f32vec2_01 = OpConstantComposite %f32vec2 %f32_0 %f32_1
214 %f32vec2_10 = OpConstantComposite %f32vec2 %f32_1 %f32_0
215 %f32vec2_11 = OpConstantComposite %f32vec2 %f32_1 %f32_1
216 %f32vec2_hh = OpConstantComposite %f32vec2 %f32_0_5 %f32_0_5
217 
218 %f32vec3_000 = OpConstantComposite %f32vec3 %f32_0 %f32_0 %f32_0
219 %f32vec3_hhh = OpConstantComposite %f32vec3 %f32_0_5 %f32_0_5 %f32_0_5
220 
221 %f32vec4_0000 = OpConstantComposite %f32vec4 %f32_0 %f32_0 %f32_0 %f32_0
222 
223 %boolvec4_tttt = OpConstantComposite %boolvec4 %bool_t %bool_t %bool_t %bool_t
224 
225 %const_offsets = OpConstantComposite %u32vec2arr4 %u32vec2_01 %u32vec2_12 %u32vec2_01 %u32vec2_12
226 %const_offsets3x2 = OpConstantComposite %u32vec2arr3 %u32vec2_01 %u32vec2_12 %u32vec2_01
227 %const_offsets4xu = OpConstantComposite %u32arr4 %u32_0 %u32_0 %u32_0 %u32_0
228 %const_offsets4x3 = OpConstantComposite %u32vec3arr4 %u32vec3_012 %u32vec3_012 %u32vec3_012 %u32vec3_012
229 
230 %type_image_f32_1d_0001 = OpTypeImage %f32 1D 0 0 0 1 Unknown
231 %ptr_image_f32_1d_0001 = OpTypePointer UniformConstant %type_image_f32_1d_0001
232 %uniform_image_f32_1d_0001 = OpVariable %ptr_image_f32_1d_0001 UniformConstant
233 %type_sampled_image_f32_1d_0001 = OpTypeSampledImage %type_image_f32_1d_0001
234 
235 %type_image_f32_1d_0002_rgba32f = OpTypeImage %f32 1D 0 0 0 2 Rgba32f
236 %ptr_image_f32_1d_0002_rgba32f = OpTypePointer UniformConstant %type_image_f32_1d_0002_rgba32f
237 %uniform_image_f32_1d_0002_rgba32f = OpVariable %ptr_image_f32_1d_0002_rgba32f UniformConstant
238 
239 %type_image_f32_2d_0001 = OpTypeImage %f32 2D 0 0 0 1 Unknown
240 %ptr_image_f32_2d_0001 = OpTypePointer UniformConstant %type_image_f32_2d_0001
241 %uniform_image_f32_2d_0001 = OpVariable %ptr_image_f32_2d_0001 UniformConstant
242 %type_sampled_image_f32_2d_0001 = OpTypeSampledImage %type_image_f32_2d_0001
243 
244 %type_image_f32_2d_0011 = OpTypeImage %f32 2D 0 0 1 1 Unknown
245 %ptr_image_f32_2d_0011 = OpTypePointer UniformConstant %type_image_f32_2d_0011
246 %uniform_image_f32_2d_0011 = OpVariable %ptr_image_f32_2d_0011 UniformConstant
247 %type_sampled_image_f32_2d_0011 = OpTypeSampledImage %type_image_f32_2d_0011
248 
249 %type_image_u32_2d_0001 = OpTypeImage %u32 2D 0 0 0 1 Unknown
250 %ptr_image_u32_2d_0001 = OpTypePointer UniformConstant %type_image_u32_2d_0001
251 %uniform_image_u32_2d_0001 = OpVariable %ptr_image_u32_2d_0001 UniformConstant
252 %type_sampled_image_u32_2d_0001 = OpTypeSampledImage %type_image_u32_2d_0001
253 
254 %type_image_u32_3d_0001 = OpTypeImage %u32 3D 0 0 0 1 Unknown
255 %ptr_image_u32_3d_0001 = OpTypePointer UniformConstant %type_image_u32_3d_0001
256 %uniform_image_u32_3d_0001 = OpVariable %ptr_image_u32_3d_0001 UniformConstant
257 %type_sampled_image_u32_3d_0001 = OpTypeSampledImage %type_image_u32_3d_0001
258 
259 %type_image_u32_2d_0002 = OpTypeImage %u32 2D 0 0 0 2 Unknown
260 %ptr_image_u32_2d_0002 = OpTypePointer UniformConstant %type_image_u32_2d_0002
261 %uniform_image_u32_2d_0002 = OpVariable %ptr_image_u32_2d_0002 UniformConstant
262 
263 %type_image_s32_3d_0001 = OpTypeImage %s32 3D 0 0 0 1 Unknown
264 %ptr_image_s32_3d_0001 = OpTypePointer UniformConstant %type_image_s32_3d_0001
265 %uniform_image_s32_3d_0001 = OpVariable %ptr_image_s32_3d_0001 UniformConstant
266 %type_sampled_image_s32_3d_0001 = OpTypeSampledImage %type_image_s32_3d_0001
267 
268 %type_image_f32_2d_0002 = OpTypeImage %f32 2D 0 0 0 2 Unknown
269 %ptr_image_f32_2d_0002 = OpTypePointer UniformConstant %type_image_f32_2d_0002
270 %uniform_image_f32_2d_0002 = OpVariable %ptr_image_f32_2d_0002 UniformConstant
271 
272 %type_image_s32_2d_0002 = OpTypeImage %s32 2D 0 0 0 2 Unknown
273 %ptr_image_s32_2d_0002 = OpTypePointer UniformConstant %type_image_s32_2d_0002
274 %uniform_image_s32_2d_0002 = OpVariable %ptr_image_s32_2d_0002 UniformConstant
275 
276 %type_image_f32_spd_0002 = OpTypeImage %f32 SubpassData 0 0 0 2 Unknown
277 %ptr_image_f32_spd_0002 = OpTypePointer UniformConstant %type_image_f32_spd_0002
278 %uniform_image_f32_spd_0002 = OpVariable %ptr_image_f32_spd_0002 UniformConstant
279 
280 %type_image_f32_3d_0111 = OpTypeImage %f32 3D 0 1 1 1 Unknown
281 %ptr_image_f32_3d_0111 = OpTypePointer UniformConstant %type_image_f32_3d_0111
282 %uniform_image_f32_3d_0111 = OpVariable %ptr_image_f32_3d_0111 UniformConstant
283 %type_sampled_image_f32_3d_0111 = OpTypeSampledImage %type_image_f32_3d_0111
284 
285 %type_image_f32_3d_0001 = OpTypeImage %f32 3D 0 0 0 1 Unknown
286 %ptr_image_f32_3d_0001 = OpTypePointer UniformConstant %type_image_f32_3d_0001
287 %uniform_image_f32_3d_0001 = OpVariable %ptr_image_f32_3d_0001 UniformConstant
288 %type_sampled_image_f32_3d_0001 = OpTypeSampledImage %type_image_f32_3d_0001
289 
290 %type_image_f32_cube_0101 = OpTypeImage %f32 Cube 0 1 0 1 Unknown
291 %ptr_image_f32_cube_0101 = OpTypePointer UniformConstant %type_image_f32_cube_0101
292 %uniform_image_f32_cube_0101 = OpVariable %ptr_image_f32_cube_0101 UniformConstant
293 %type_sampled_image_f32_cube_0101 = OpTypeSampledImage %type_image_f32_cube_0101
294 
295 %type_image_f32_cube_0102_rgba32f = OpTypeImage %f32 Cube 0 1 0 2 Rgba32f
296 %ptr_image_f32_cube_0102_rgba32f = OpTypePointer UniformConstant %type_image_f32_cube_0102_rgba32f
297 %uniform_image_f32_cube_0102_rgba32f = OpVariable %ptr_image_f32_cube_0102_rgba32f UniformConstant
298 
299 %type_sampler = OpTypeSampler
300 %ptr_sampler = OpTypePointer UniformConstant %type_sampler
301 %uniform_sampler = OpVariable %ptr_sampler UniformConstant
302 
303 %type_image_u32_buffer_0002_r32ui = OpTypeImage %u32 Buffer 0 0 0 2 R32ui
304 %ptr_Image_u32 = OpTypePointer Image %u32
305 %ptr_image_u32_buffer_0002_r32ui = OpTypePointer Private %type_image_u32_buffer_0002_r32ui
306 %private_image_u32_buffer_0002_r32ui = OpVariable %ptr_image_u32_buffer_0002_r32ui Private
307 
308 %ptr_Image_u32arr4 = OpTypePointer Image %u32arr4
309 
310 %type_image_u32_spd_0002 = OpTypeImage %u32 SubpassData 0 0 0 2 Unknown
311 %ptr_image_u32_spd_0002 = OpTypePointer Private %type_image_u32_spd_0002
312 %private_image_u32_spd_0002 = OpVariable %ptr_image_u32_spd_0002 Private
313 
314 %type_image_f32_buffer_0002_r32ui = OpTypeImage %f32 Buffer 0 0 0 2 R32ui
315 %ptr_Image_f32 = OpTypePointer Image %f32
316 %ptr_image_f32_buffer_0002_r32ui = OpTypePointer Private %type_image_f32_buffer_0002_r32ui
317 %private_image_f32_buffer_0002_r32ui = OpVariable %ptr_image_f32_buffer_0002_r32ui Private
318 
319 %ptr_input_flat_u32 = OpTypePointer Input %u32
320 %input_flat_u32 = OpVariable %ptr_input_flat_u32 Input
321 )";
322 
323   if (env == SPV_ENV_UNIVERSAL_1_0) {
324     ss << R"(
325 %type_image_void_2d_0001 = OpTypeImage %void 2D 0 0 0 1 Unknown
326 %ptr_image_void_2d_0001 = OpTypePointer UniformConstant %type_image_void_2d_0001
327 %uniform_image_void_2d_0001 = OpVariable %ptr_image_void_2d_0001 UniformConstant
328 %type_sampled_image_void_2d_0001 = OpTypeSampledImage %type_image_void_2d_0001
329 
330 %type_image_void_2d_0002 = OpTypeImage %void 2D 0 0 0 2 Unknown
331 %ptr_image_void_2d_0002 = OpTypePointer UniformConstant %type_image_void_2d_0002
332 %uniform_image_void_2d_0002 = OpVariable %ptr_image_void_2d_0002 UniformConstant
333 
334 %type_image_f32_rect_0001 = OpTypeImage %f32 Rect 0 0 0 1 Unknown
335 %ptr_image_f32_rect_0001 = OpTypePointer UniformConstant %type_image_f32_rect_0001
336 %uniform_image_f32_rect_0001 = OpVariable %ptr_image_f32_rect_0001 UniformConstant
337 %type_sampled_image_f32_rect_0001 = OpTypeSampledImage %type_image_f32_rect_0001
338 )";
339   }
340 
341   ss << declarations;
342 
343   ss << R"(
344 %main = OpFunction %void None %func
345 %main_entry = OpLabel
346 )";
347 
348   ss << body;
349 
350   ss << R"(
351 OpReturn
352 OpFunctionEnd)";
353 
354   return ss.str();
355 }
356 
GenerateKernelCode(const std::string & body,const std::string & capabilities_and_extensions="",const std::string & declarations="")357 std::string GenerateKernelCode(
358     const std::string& body,
359     const std::string& capabilities_and_extensions = "",
360     const std::string& declarations = "") {
361   std::ostringstream ss;
362   ss << R"(
363 OpCapability Addresses
364 OpCapability Kernel
365 OpCapability Linkage
366 OpCapability ImageQuery
367 OpCapability ImageGatherExtended
368 OpCapability InputAttachment
369 OpCapability SampledRect
370 )";
371 
372   ss << capabilities_and_extensions;
373   ss << R"(
374 OpMemoryModel Physical32 OpenCL
375 %void = OpTypeVoid
376 %func = OpTypeFunction %void
377 %bool = OpTypeBool
378 %f32 = OpTypeFloat 32
379 %u32 = OpTypeInt 32 0
380 %u32vec2 = OpTypeVector %u32 2
381 %f32vec2 = OpTypeVector %f32 2
382 %u32vec3 = OpTypeVector %u32 3
383 %f32vec3 = OpTypeVector %f32 3
384 %u32vec4 = OpTypeVector %u32 4
385 %f32vec4 = OpTypeVector %f32 4
386 
387 %f32_0 = OpConstant %f32 0
388 %f32_1 = OpConstant %f32 1
389 %f32_0_5 = OpConstant %f32 0.5
390 %f32_0_25 = OpConstant %f32 0.25
391 %f32_0_75 = OpConstant %f32 0.75
392 
393 %u32_0 = OpConstant %u32 0
394 %u32_1 = OpConstant %u32 1
395 %u32_2 = OpConstant %u32 2
396 %u32_3 = OpConstant %u32 3
397 %u32_4 = OpConstant %u32 4
398 
399 %u32vec2_01 = OpConstantComposite %u32vec2 %u32_0 %u32_1
400 %u32vec2_12 = OpConstantComposite %u32vec2 %u32_1 %u32_2
401 %u32vec3_012 = OpConstantComposite %u32vec3 %u32_0 %u32_1 %u32_2
402 %u32vec3_123 = OpConstantComposite %u32vec3 %u32_1 %u32_2 %u32_3
403 %u32vec4_0123 = OpConstantComposite %u32vec4 %u32_0 %u32_1 %u32_2 %u32_3
404 %u32vec4_1234 = OpConstantComposite %u32vec4 %u32_1 %u32_2 %u32_3 %u32_4
405 
406 %f32vec2_00 = OpConstantComposite %f32vec2 %f32_0 %f32_0
407 %f32vec2_01 = OpConstantComposite %f32vec2 %f32_0 %f32_1
408 %f32vec2_10 = OpConstantComposite %f32vec2 %f32_1 %f32_0
409 %f32vec2_11 = OpConstantComposite %f32vec2 %f32_1 %f32_1
410 %f32vec2_hh = OpConstantComposite %f32vec2 %f32_0_5 %f32_0_5
411 
412 %f32vec3_000 = OpConstantComposite %f32vec3 %f32_0 %f32_0 %f32_0
413 %f32vec3_hhh = OpConstantComposite %f32vec3 %f32_0_5 %f32_0_5 %f32_0_5
414 
415 %f32vec4_0000 = OpConstantComposite %f32vec4 %f32_0 %f32_0 %f32_0 %f32_0
416 
417 %type_image_f32_2d_0001 = OpTypeImage %f32 2D 0 0 0 1 Unknown
418 %ptr_image_f32_2d_0001 = OpTypePointer UniformConstant %type_image_f32_2d_0001
419 %uniform_image_f32_2d_0001 = OpVariable %ptr_image_f32_2d_0001 UniformConstant
420 %type_sampled_image_f32_2d_0001 = OpTypeSampledImage %type_image_f32_2d_0001
421 
422 %type_image_f32_2d_0011 = OpTypeImage %f32 2D 0 0 1 1 Unknown
423 %ptr_image_f32_2d_0011 = OpTypePointer UniformConstant %type_image_f32_2d_0011
424 %uniform_image_f32_2d_0011 = OpVariable %ptr_image_f32_2d_0011 UniformConstant
425 %type_sampled_image_f32_2d_0011 = OpTypeSampledImage %type_image_f32_2d_0011
426 
427 %type_image_f32_3d_0011 = OpTypeImage %f32 3D 0 0 1 1 Unknown
428 %ptr_image_f32_3d_0011 = OpTypePointer UniformConstant %type_image_f32_3d_0011
429 %uniform_image_f32_3d_0011 = OpVariable %ptr_image_f32_3d_0011 UniformConstant
430 %type_sampled_image_f32_3d_0011 = OpTypeSampledImage %type_image_f32_3d_0011
431 
432 %type_image_f32_rect_0001 = OpTypeImage %f32 Rect 0 0 0 1 Unknown
433 %ptr_image_f32_rect_0001 = OpTypePointer UniformConstant %type_image_f32_rect_0001
434 %uniform_image_f32_rect_0001 = OpVariable %ptr_image_f32_rect_0001 UniformConstant
435 %type_sampled_image_f32_rect_0001 = OpTypeSampledImage %type_image_f32_rect_0001
436 
437 %type_sampler = OpTypeSampler
438 %ptr_sampler = OpTypePointer UniformConstant %type_sampler
439 %uniform_sampler = OpVariable %ptr_sampler UniformConstant
440 )";
441 
442   ss << declarations;
443 
444   ss << R"(
445 %main = OpFunction %void None %func
446 %main_entry = OpLabel
447 )";
448 
449   ss << body;
450   ss << R"(
451 OpReturn
452 OpFunctionEnd)";
453 
454   return ss.str();
455 }
456 
GetKernelHeader()457 std::string GetKernelHeader() {
458   return R"(
459   OpCapability Kernel
460   OpCapability Addresses
461   OpCapability Linkage
462   OpMemoryModel Physical32 OpenCL
463   %void = OpTypeVoid
464   %func = OpTypeFunction %void
465   %f32 = OpTypeFloat 32
466   %u32 = OpTypeInt 32 0
467   )";
468 }
469 
TrivialMain()470 std::string TrivialMain() {
471   return R"(
472   %main = OpFunction %void None %func
473   %entry = OpLabel
474   OpReturn
475   OpFunctionEnd
476   )";
477 }
478 
GetShaderHeader(const std::string & capabilities_and_extensions="",bool include_entry_point=true)479 std::string GetShaderHeader(const std::string& capabilities_and_extensions = "",
480                             bool include_entry_point = true) {
481   std::ostringstream ss;
482   ss << R"(
483 OpCapability Shader
484 OpCapability Int64
485 OpCapability Float64
486 )";
487 
488   if (!include_entry_point) {
489     ss << "OpCapability Linkage\n";
490   }
491   ss << capabilities_and_extensions;
492 
493   ss << R"(
494 OpMemoryModel Logical GLSL450
495 )";
496 
497   if (include_entry_point) {
498     ss << "OpEntryPoint Fragment %main \"main\"\n";
499     ss << "OpExecutionMode %main OriginUpperLeft";
500   }
501   ss << R"(
502 %void = OpTypeVoid
503 %func = OpTypeFunction %void
504 %bool = OpTypeBool
505 %f32 = OpTypeFloat 32
506 %f64 = OpTypeFloat 64
507 %u32 = OpTypeInt 32 0
508 %u64 = OpTypeInt 64 0
509 %s32 = OpTypeInt 32 1
510 %s64 = OpTypeInt 64 1
511 )";
512 
513   return ss.str();
514 }
515 
TEST_F(ValidateImage,TypeImageWrongSampledType)516 TEST_F(ValidateImage, TypeImageWrongSampledType) {
517   const std::string code = GetShaderHeader("", false) + R"(
518 %img_type = OpTypeImage %bool 2D 0 0 0 1 Unknown
519 )";
520 
521   CompileSuccessfully(code.c_str());
522   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
523   EXPECT_THAT(getDiagnosticString(),
524               HasSubstr("Expected Sampled Type to be either void or "
525                         "numerical scalar "
526                         "type"));
527 }
528 
TEST_F(ValidateImage,TypeImageVoidSampledTypeVulkan)529 TEST_F(ValidateImage, TypeImageVoidSampledTypeVulkan) {
530   const std::string code = GetShaderHeader() + R"(
531 %img_type = OpTypeImage %void 2D 0 0 0 1 Unknown
532 %main = OpFunction %void None %func
533 %main_lab = OpLabel
534 OpReturn
535 OpFunctionEnd
536 )";
537 
538   const spv_target_env env = SPV_ENV_VULKAN_1_0;
539   CompileSuccessfully(code, env);
540   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
541   EXPECT_THAT(getDiagnosticString(),
542               AnyVUID("VUID-StandaloneSpirv-OpTypeImage-04656"));
543   EXPECT_THAT(getDiagnosticString(),
544               HasSubstr("Expected Sampled Type to be a 32-bit int, 64-bit int "
545                         "or 32-bit float scalar type for Vulkan environment"));
546 }
547 
TEST_F(ValidateImage,TypeImageU32SampledTypeVulkan)548 TEST_F(ValidateImage, TypeImageU32SampledTypeVulkan) {
549   const std::string code = GetShaderHeader() + R"(
550 %img_type = OpTypeImage %u32 2D 0 0 0 1 Unknown
551 %main = OpFunction %void None %func
552 %main_lab = OpLabel
553 OpReturn
554 OpFunctionEnd
555 )";
556 
557   const spv_target_env env = SPV_ENV_VULKAN_1_0;
558   CompileSuccessfully(code, env);
559   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(env));
560   EXPECT_THAT(getDiagnosticString(), Eq(""));
561 }
562 
TEST_F(ValidateImage,TypeImageI32SampledTypeVulkan)563 TEST_F(ValidateImage, TypeImageI32SampledTypeVulkan) {
564   const std::string code = GetShaderHeader() + R"(
565 %img_type = OpTypeImage %s32 2D 0 0 0 1 Unknown
566 %main = OpFunction %void None %func
567 %main_lab = OpLabel
568 OpReturn
569 OpFunctionEnd
570 )";
571 
572   const spv_target_env env = SPV_ENV_VULKAN_1_0;
573   CompileSuccessfully(code, env);
574   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(env));
575   EXPECT_THAT(getDiagnosticString(), Eq(""));
576 }
577 
TEST_F(ValidateImage,TypeImageI64SampledTypeNoCapabilityVulkan)578 TEST_F(ValidateImage, TypeImageI64SampledTypeNoCapabilityVulkan) {
579   const std::string code = GetShaderHeader() + R"(
580 %img_type = OpTypeImage %s64 2D 0 0 0 1 Unknown
581 %main = OpFunction %void None %func
582 %main_lab = OpLabel
583 OpReturn
584 OpFunctionEnd
585 )";
586 
587   const spv_target_env env = SPV_ENV_VULKAN_1_0;
588   CompileSuccessfully(code, env);
589   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
590   EXPECT_THAT(getDiagnosticString(),
591               HasSubstr("Capability Int64ImageEXT is required when using "
592                         "Sampled Type of 64-bit int"));
593 }
594 
TEST_F(ValidateImage,TypeImageI64SampledTypeVulkan)595 TEST_F(ValidateImage, TypeImageI64SampledTypeVulkan) {
596   const std::string code = GetShaderHeader(
597                                "OpCapability Int64ImageEXT\nOpExtension "
598                                "\"SPV_EXT_shader_image_int64\"\n") +
599                            R"(
600 %img_type = OpTypeImage %s64 2D 0 0 0 1 Unknown
601 %main = OpFunction %void None %func
602 %main_lab = OpLabel
603 OpReturn
604 OpFunctionEnd
605 )";
606 
607   const spv_target_env env = SPV_ENV_VULKAN_1_0;
608   CompileSuccessfully(code, env);
609   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(env));
610   EXPECT_THAT(getDiagnosticString(), Eq(""));
611 }
612 
TEST_F(ValidateImage,TypeImageU64SampledTypeNoCapabilityVulkan)613 TEST_F(ValidateImage, TypeImageU64SampledTypeNoCapabilityVulkan) {
614   const std::string code = GetShaderHeader() + R"(
615 %img_type = OpTypeImage %u64 2D 0 0 0 1 Unknown
616 %main = OpFunction %void None %func
617 %main_lab = OpLabel
618 OpReturn
619 OpFunctionEnd
620 )";
621 
622   const spv_target_env env = SPV_ENV_VULKAN_1_0;
623   CompileSuccessfully(code, env);
624   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
625   EXPECT_THAT(getDiagnosticString(),
626               HasSubstr("Capability Int64ImageEXT is required when using "
627                         "Sampled Type of 64-bit int"));
628 }
629 
TEST_F(ValidateImage,TypeImageU64SampledTypeVulkan)630 TEST_F(ValidateImage, TypeImageU64SampledTypeVulkan) {
631   const std::string code = GetShaderHeader(
632                                "OpCapability Int64ImageEXT\nOpExtension "
633                                "\"SPV_EXT_shader_image_int64\"\n") +
634                            R"(
635 %img_type = OpTypeImage %u64 2D 0 0 0 1 Unknown
636 %main = OpFunction %void None %func
637 %main_lab = OpLabel
638 OpReturn
639 OpFunctionEnd
640 )";
641 
642   const spv_target_env env = SPV_ENV_VULKAN_1_0;
643   CompileSuccessfully(code, env);
644   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(env));
645   EXPECT_THAT(getDiagnosticString(), Eq(""));
646 }
647 
TEST_F(ValidateImage,TypeImageF32SampledTypeVulkan)648 TEST_F(ValidateImage, TypeImageF32SampledTypeVulkan) {
649   const std::string code = GetShaderHeader() + R"(
650 %img_type = OpTypeImage %f32 2D 0 0 0 1 Unknown
651 %main = OpFunction %void None %func
652 %main_lab = OpLabel
653 OpReturn
654 OpFunctionEnd
655 )";
656 
657   const spv_target_env env = SPV_ENV_VULKAN_1_0;
658   CompileSuccessfully(code, env);
659   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(env));
660   EXPECT_THAT(getDiagnosticString(), Eq(""));
661 }
662 
TEST_F(ValidateImage,TypeImageF64SampledTypeVulkan)663 TEST_F(ValidateImage, TypeImageF64SampledTypeVulkan) {
664   const std::string code = GetShaderHeader() + R"(
665 %img_type = OpTypeImage %f64 2D 0 0 0 1 Unknown
666 %main = OpFunction %void None %func
667 %main_lab = OpLabel
668 OpReturn
669 OpFunctionEnd
670 )";
671 
672   const spv_target_env env = SPV_ENV_VULKAN_1_0;
673   CompileSuccessfully(code, env);
674   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
675   EXPECT_THAT(getDiagnosticString(),
676               AnyVUID("VUID-StandaloneSpirv-OpTypeImage-04656"));
677   EXPECT_THAT(getDiagnosticString(),
678               HasSubstr("Expected Sampled Type to be a 32-bit int, 64-bit int "
679                         "or 32-bit float scalar type for Vulkan environment"));
680 }
681 
TEST_F(ValidateImage,TypeImageF64SampledTypeWithInt64Vulkan)682 TEST_F(ValidateImage, TypeImageF64SampledTypeWithInt64Vulkan) {
683   const std::string code = GetShaderHeader(
684                                "OpCapability Int64ImageEXT\nOpExtension "
685                                "\"SPV_EXT_shader_image_int64\"\n") +
686                            R"(
687 %img_type = OpTypeImage %f64 2D 0 0 0 1 Unknown
688 %main = OpFunction %void None %func
689 %main_lab = OpLabel
690 OpReturn
691 OpFunctionEnd
692 )";
693 
694   const spv_target_env env = SPV_ENV_VULKAN_1_0;
695   CompileSuccessfully(code, env);
696   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
697   EXPECT_THAT(getDiagnosticString(),
698               AnyVUID("VUID-StandaloneSpirv-OpTypeImage-04656"));
699   EXPECT_THAT(getDiagnosticString(),
700               HasSubstr("Expected Sampled Type to be a 32-bit int, 64-bit int "
701                         "or 32-bit float scalar type for Vulkan environment"));
702 }
703 
TEST_F(ValidateImage,TypeImageWrongDepth)704 TEST_F(ValidateImage, TypeImageWrongDepth) {
705   const std::string code = GetShaderHeader("", false) + R"(
706 %img_type = OpTypeImage %f32 2D 3 0 0 1 Unknown
707 )";
708 
709   CompileSuccessfully(code.c_str());
710   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
711   EXPECT_THAT(getDiagnosticString(),
712               HasSubstr("Invalid Depth 3 (must be 0, 1 or 2)"));
713 }
714 
TEST_F(ValidateImage,TypeImageWrongArrayed)715 TEST_F(ValidateImage, TypeImageWrongArrayed) {
716   const std::string code = GetShaderHeader("", false) + R"(
717 %img_type = OpTypeImage %f32 2D 0 2 0 1 Unknown
718 )";
719 
720   CompileSuccessfully(code.c_str());
721   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
722   EXPECT_THAT(getDiagnosticString(),
723               HasSubstr("Invalid Arrayed 2 (must be 0 or 1)"));
724 }
725 
TEST_F(ValidateImage,TypeImageWrongMS)726 TEST_F(ValidateImage, TypeImageWrongMS) {
727   const std::string code = GetShaderHeader("", false) + R"(
728 %img_type = OpTypeImage %f32 2D 0 0 2 1 Unknown
729 )";
730 
731   CompileSuccessfully(code.c_str());
732   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
733   EXPECT_THAT(getDiagnosticString(),
734               HasSubstr("Invalid MS 2 (must be 0 or 1)"));
735 }
736 
TEST_F(ValidateImage,TypeImageWrongSampled)737 TEST_F(ValidateImage, TypeImageWrongSampled) {
738   const std::string code = GetShaderHeader("", false) + R"(
739 %img_type = OpTypeImage %f32 2D 0 0 0 3 Unknown
740 )";
741 
742   CompileSuccessfully(code.c_str());
743   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
744   EXPECT_THAT(getDiagnosticString(),
745               HasSubstr("Invalid Sampled 3 (must be 0, 1 or 2)"));
746 }
747 
TEST_F(ValidateImage,TypeImageWrongSampledForSubpassData)748 TEST_F(ValidateImage, TypeImageWrongSampledForSubpassData) {
749   const std::string code =
750       GetShaderHeader("OpCapability InputAttachment\n", false) +
751       R"(
752 %img_type = OpTypeImage %f32 SubpassData 0 0 0 1 Unknown
753 )";
754 
755   CompileSuccessfully(code.c_str());
756   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
757   EXPECT_THAT(getDiagnosticString(),
758               HasSubstr("Dim SubpassData requires Sampled to be 2"));
759 }
760 
TEST_F(ValidateImage,TypeImageWrongSampledForSubpassDataVulkan)761 TEST_F(ValidateImage, TypeImageWrongSampledForSubpassDataVulkan) {
762   const std::string code = GetShaderHeader("OpCapability InputAttachment\n") +
763                            R"(
764 %img_type = OpTypeImage %f32 SubpassData 0 0 0 1 Unknown
765 )" + TrivialMain();
766 
767   CompileSuccessfully(code.c_str());
768   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
769   EXPECT_THAT(getDiagnosticString(),
770               AnyVUID("VUID-StandaloneSpirv-OpTypeImage-06214"));
771   EXPECT_THAT(getDiagnosticString(),
772               HasSubstr("Dim SubpassData requires Sampled to be 2"));
773 }
774 
TEST_F(ValidateImage,TypeImageWrongArrayForSubpassDataVulkan)775 TEST_F(ValidateImage, TypeImageWrongArrayForSubpassDataVulkan) {
776   const std::string code = GetShaderHeader("OpCapability InputAttachment\n") +
777                            R"(
778 %img_type = OpTypeImage %f32 SubpassData 0 1 0 2 Unknown
779 )" + TrivialMain();
780 
781   CompileSuccessfully(code.c_str());
782   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
783   EXPECT_THAT(getDiagnosticString(),
784               AnyVUID("VUID-StandaloneSpirv-OpTypeImage-06214"));
785   EXPECT_THAT(getDiagnosticString(),
786               HasSubstr("Dim SubpassData requires Arrayed to be 0"));
787 }
788 
TEST_F(ValidateImage,TypeImageWrongSampledTypeForTileImageDataEXT)789 TEST_F(ValidateImage, TypeImageWrongSampledTypeForTileImageDataEXT) {
790   const std::string code = GetShaderHeader(
791                                "OpCapability TileImageColorReadAccessEXT\n"
792                                "OpExtension \"SPV_EXT_shader_tile_image\"\n",
793                                false) +
794                            R"(
795 %img_type = OpTypeImage %void TileImageDataEXT 0 0 0 2 Unknown
796 )";
797 
798   CompileSuccessfully(code.c_str());
799   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
800   EXPECT_THAT(
801       getDiagnosticString(),
802       HasSubstr(
803           "Dim TileImageDataEXT requires Sampled Type to be not OpTypeVoid"));
804 }
805 
TEST_F(ValidateImage,TypeImageWrongSampledForTileImageDataEXT)806 TEST_F(ValidateImage, TypeImageWrongSampledForTileImageDataEXT) {
807   const std::string code = GetShaderHeader(
808                                "OpCapability TileImageColorReadAccessEXT\n"
809                                "OpExtension \"SPV_EXT_shader_tile_image\"\n",
810                                false) +
811                            R"(
812 %img_type = OpTypeImage %f32 TileImageDataEXT 0 0 0 1 Unknown
813 )";
814 
815   CompileSuccessfully(code.c_str());
816   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
817   EXPECT_THAT(getDiagnosticString(),
818               HasSubstr("Dim TileImageDataEXT requires Sampled to be 2"));
819 }
820 
TEST_F(ValidateImage,TypeImageWrongFormatForTileImageDataEXT)821 TEST_F(ValidateImage, TypeImageWrongFormatForTileImageDataEXT) {
822   const std::string code = GetShaderHeader(
823                                "OpCapability TileImageColorReadAccessEXT\n"
824                                "OpExtension \"SPV_EXT_shader_tile_image\"\n",
825                                false) +
826                            R"(
827 %img_type = OpTypeImage %f32 TileImageDataEXT 0 0 0 2 Rgba32f
828 )";
829 
830   CompileSuccessfully(code.c_str());
831   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
832   EXPECT_THAT(getDiagnosticString(),
833               HasSubstr("Dim TileImageDataEXT requires format Unknown"));
834 }
835 
TEST_F(ValidateImage,TypeImageWrongDepthForTileImageDataEXT)836 TEST_F(ValidateImage, TypeImageWrongDepthForTileImageDataEXT) {
837   const std::string code = GetShaderHeader(
838                                "OpCapability TileImageColorReadAccessEXT\n"
839                                "OpExtension \"SPV_EXT_shader_tile_image\"\n",
840                                false) +
841                            R"(
842 %img_type = OpTypeImage %f32 TileImageDataEXT 1 0 0 2 Unknown
843 )";
844 
845   CompileSuccessfully(code.c_str());
846   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
847   EXPECT_THAT(getDiagnosticString(),
848               HasSubstr("Dim TileImageDataEXT requires Depth to be 0"));
849 }
850 
TEST_F(ValidateImage,TypeImageWrongArrayedForTileImageDataEXT)851 TEST_F(ValidateImage, TypeImageWrongArrayedForTileImageDataEXT) {
852   const std::string code = GetShaderHeader(
853                                "OpCapability TileImageColorReadAccessEXT\n"
854                                "OpExtension \"SPV_EXT_shader_tile_image\"\n",
855                                false) +
856                            R"(
857 %img_type = OpTypeImage %f32 TileImageDataEXT 0 1 0 2 Unknown
858 )";
859 
860   CompileSuccessfully(code.c_str());
861   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
862   EXPECT_THAT(getDiagnosticString(),
863               HasSubstr("Dim TileImageDataEXT requires Arrayed to be 0"));
864 }
865 
TEST_F(ValidateImage,TypeSampledImage_TileImageDataEXT_Error)866 TEST_F(ValidateImage, TypeSampledImage_TileImageDataEXT_Error) {
867   const std::string code = GetShaderHeader(
868                                "OpCapability TileImageColorReadAccessEXT\n"
869                                "OpExtension \"SPV_EXT_shader_tile_image\"\n",
870                                false) +
871                            R"(
872 %img_type = OpTypeImage %f32 TileImageDataEXT 0 0 0 2 Unknown
873 %simg_type = OpTypeSampledImage %img_type
874 )";
875 
876   CompileSuccessfully(code.c_str());
877   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
878   EXPECT_THAT(getDiagnosticString(),
879               HasSubstr("Sampled image type requires an image type with "
880                         "\"Sampled\" operand set to 0 or 1"));
881 }
882 
TEST_F(ValidateImage,ImageTexelPointerImageDimTileImageDataEXTBad)883 TEST_F(ValidateImage, ImageTexelPointerImageDimTileImageDataEXTBad) {
884   const std::string body = R"(
885 %texel_ptr = OpImageTexelPointer %ptr_Image_u32 %tile_image_u32_tid_0002 %u32_0 %u32_0
886 %sum = OpAtomicIAdd %u32 %texel_ptr %u32_1 %u32_0 %u32_1
887 )";
888   const std::string decl = R"(
889 %type_image_u32_tid_0002 = OpTypeImage %u32 TileImageDataEXT 0 0 0 2 Unknown
890 %ptr_image_u32_tid_0002 = OpTypePointer TileImageEXT %type_image_u32_tid_0002
891 %tile_image_u32_tid_0002 = OpVariable %ptr_image_u32_tid_0002 TileImageEXT
892 )";
893 
894   const std::string extra = R"(
895 OpCapability TileImageColorReadAccessEXT
896 OpExtension "SPV_EXT_shader_tile_image"
897 )";
898 
899   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
900                                          SPV_ENV_UNIVERSAL_1_5, "GLSL450", decl)
901                           .c_str());
902   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
903   EXPECT_THAT(getDiagnosticString(),
904               HasSubstr("Image Dim TileImageDataEXT cannot be used with "
905                         "OpImageTexelPointer"));
906 }
907 
TEST_F(ValidateImage,ReadTileImageDataEXT)908 TEST_F(ValidateImage, ReadTileImageDataEXT) {
909   const std::string body = R"(
910 %img = OpLoad %type_image_f32_tid_0002 %uniform_image_f32_tid_0002
911 %res1 = OpImageRead %f32vec4 %img %u32vec2_01
912 )";
913 
914   const std::string decl = R"(
915 %type_image_f32_tid_0002 = OpTypeImage %f32 TileImageDataEXT 0 0 0 2 Unknown
916 %ptr_image_f32_tid_0002 = OpTypePointer UniformConstant %type_image_f32_tid_0002
917 %uniform_image_f32_tid_0002 = OpVariable %ptr_image_f32_tid_0002 UniformConstant
918 )";
919 
920   const std::string extra = R"(
921 OpCapability StorageImageReadWithoutFormat
922 OpCapability TileImageColorReadAccessEXT
923 OpExtension "SPV_EXT_shader_tile_image"
924 )";
925 
926   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
927                                          SPV_ENV_UNIVERSAL_1_5, "GLSL450", decl)
928                           .c_str());
929   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
930   EXPECT_THAT(
931       getDiagnosticString(),
932       HasSubstr("Image Dim TileImageDataEXT cannot be used with ImageRead"));
933 }
934 
TEST_F(ValidateImage,WriteTileImageDataEXT)935 TEST_F(ValidateImage, WriteTileImageDataEXT) {
936   const std::string body = R"(
937 %img = OpLoad %type_image_f32_tid_0002 %uniform_image_f32_tid_0002
938 OpImageWrite %img %u32vec2_01 %f32vec4_0000
939 )";
940 
941   const std::string decl = R"(
942 %type_image_f32_tid_0002 = OpTypeImage %f32 TileImageDataEXT 0 0 0 2 Unknown
943 %ptr_image_f32_tid_0002 = OpTypePointer UniformConstant %type_image_f32_tid_0002
944 %uniform_image_f32_tid_0002 = OpVariable %ptr_image_f32_tid_0002 UniformConstant
945 )";
946 
947   const std::string extra = R"(
948 OpCapability TileImageColorReadAccessEXT
949 OpExtension "SPV_EXT_shader_tile_image"
950 )";
951 
952   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
953                                          SPV_ENV_UNIVERSAL_1_5, "GLSL450", decl)
954                           .c_str());
955   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
956   EXPECT_THAT(getDiagnosticString(),
957               HasSubstr("Image 'Dim' cannot be TileImageDataEXT"));
958 }
959 
TEST_F(ValidateImage,QueryFormatTileImageDataEXT)960 TEST_F(ValidateImage, QueryFormatTileImageDataEXT) {
961   const std::string body = R"(
962 %img = OpLoad %type_image_f32_tid_0002 %uniform_image_f32_tid_0002
963 %res1 = OpImageQueryFormat %u32 %img
964 )";
965 
966   const std::string decl = R"(
967 %type_image_f32_tid_0002 = OpTypeImage %f32 TileImageDataEXT 0 0 0 2 Unknown
968 %ptr_image_f32_tid_0002 = OpTypePointer UniformConstant %type_image_f32_tid_0002
969 %uniform_image_f32_tid_0002 = OpVariable %ptr_image_f32_tid_0002 UniformConstant
970 )";
971 
972   const std::string extra = R"(
973 OpCapability TileImageColorReadAccessEXT
974 OpExtension "SPV_EXT_shader_tile_image"
975 )";
976 
977   CompileSuccessfully(GenerateKernelCode(body, extra, decl).c_str());
978 
979   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
980   EXPECT_THAT(getDiagnosticString(),
981               HasSubstr("Image 'Dim' cannot be TileImageDataEXT"));
982 }
983 
TEST_F(ValidateImage,QueryOrderTileImageDataEXT)984 TEST_F(ValidateImage, QueryOrderTileImageDataEXT) {
985   const std::string body = R"(
986 %img = OpLoad %type_image_f32_tid_0002 %uniform_image_f32_tid_0002
987 %res1 = OpImageQueryOrder %u32 %img
988 )";
989 
990   const std::string decl = R"(
991 %type_image_f32_tid_0002 = OpTypeImage %f32 TileImageDataEXT 0 0 0 2 Unknown
992 %ptr_image_f32_tid_0002 = OpTypePointer UniformConstant %type_image_f32_tid_0002
993 %uniform_image_f32_tid_0002 = OpVariable %ptr_image_f32_tid_0002 UniformConstant
994 )";
995 
996   const std::string extra = R"(
997 OpCapability TileImageColorReadAccessEXT
998 OpExtension "SPV_EXT_shader_tile_image"
999 )";
1000 
1001   CompileSuccessfully(GenerateKernelCode(body, extra, decl).c_str());
1002 
1003   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1004   EXPECT_THAT(getDiagnosticString(),
1005               HasSubstr("Image 'Dim' cannot be TileImageDataEXT"));
1006 }
1007 
TEST_F(ValidateImage,SparseFetchTileImageDataEXT)1008 TEST_F(ValidateImage, SparseFetchTileImageDataEXT) {
1009   const std::string body = R"(
1010 %img = OpLoad %type_image_f32_tid_0002 %uniform_image_f32_tid_0002
1011 %res1 = OpImageSparseFetch %struct_u32_f32vec4 %img %u32vec2_01
1012 )";
1013 
1014   const std::string decl = R"(
1015 %type_image_f32_tid_0002 = OpTypeImage %f32 TileImageDataEXT 0 0 0 2 Unknown
1016 %ptr_image_f32_tid_0002 = OpTypePointer UniformConstant %type_image_f32_tid_0002
1017 %uniform_image_f32_tid_0002 = OpVariable %ptr_image_f32_tid_0002 UniformConstant
1018 )";
1019 
1020   const std::string extra = R"(
1021 OpCapability StorageImageReadWithoutFormat
1022 OpCapability TileImageColorReadAccessEXT
1023 OpExtension "SPV_EXT_shader_tile_image"
1024 )";
1025 
1026   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
1027                                          SPV_ENV_UNIVERSAL_1_5, "GLSL450", decl)
1028                           .c_str());
1029   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1030   EXPECT_THAT(getDiagnosticString(),
1031               HasSubstr("Expected Image 'Sampled' parameter to be 1"));
1032 }
1033 
TEST_F(ValidateImage,SparseReadTileImageDataEXT)1034 TEST_F(ValidateImage, SparseReadTileImageDataEXT) {
1035   const std::string body = R"(
1036 %img = OpLoad %type_image_f32_tid_0002 %uniform_image_f32_tid_0002
1037 %res1 = OpImageSparseRead %struct_u32_f32vec4 %img %u32vec2_01
1038 )";
1039 
1040   const std::string decl = R"(
1041 %type_image_f32_tid_0002 = OpTypeImage %f32 TileImageDataEXT 0 0 0 2 Unknown
1042 %ptr_image_f32_tid_0002 = OpTypePointer UniformConstant %type_image_f32_tid_0002
1043 %uniform_image_f32_tid_0002 = OpVariable %ptr_image_f32_tid_0002 UniformConstant
1044 )";
1045 
1046   const std::string extra = R"(
1047 OpCapability StorageImageReadWithoutFormat
1048 OpCapability TileImageColorReadAccessEXT
1049 OpExtension "SPV_EXT_shader_tile_image"
1050 )";
1051 
1052   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
1053                                          SPV_ENV_UNIVERSAL_1_5, "GLSL450", decl)
1054                           .c_str());
1055   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1056   EXPECT_THAT(
1057       getDiagnosticString(),
1058       HasSubstr(
1059           "Image Dim TileImageDataEXT cannot be used with ImageSparseRead"));
1060 }
1061 
TEST_F(ValidateImage,TypeImage_OpenCL_Sampled0_OK)1062 TEST_F(ValidateImage, TypeImage_OpenCL_Sampled0_OK) {
1063   const std::string code = GetKernelHeader() + R"(
1064 %img_type = OpTypeImage %void 2D 0 0 0 0 Unknown ReadOnly
1065 )";
1066 
1067   CompileSuccessfully(code.c_str());
1068   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_OPENCL_2_1));
1069   EXPECT_THAT(getDiagnosticString(), Eq(""));
1070 }
1071 
TEST_F(ValidateImage,TypeImage_OpenCL_Sampled1_Invalid)1072 TEST_F(ValidateImage, TypeImage_OpenCL_Sampled1_Invalid) {
1073   const std::string code = GetKernelHeader() + R"(
1074 %img_type = OpTypeImage %void 2D 0 0 0 1 Unknown ReadOnly
1075 )";
1076 
1077   CompileSuccessfully(code.c_str());
1078   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_2_1));
1079   EXPECT_THAT(getDiagnosticString(),
1080               HasSubstr("Sampled must be 0 in the OpenCL environment."));
1081 }
1082 
TEST_F(ValidateImage,TypeImage_OpenCL_Sampled2_Invalid)1083 TEST_F(ValidateImage, TypeImage_OpenCL_Sampled2_Invalid) {
1084   const std::string code = GetKernelHeader() + R"(
1085 %img_type = OpTypeImage %void 2D 0 0 0 2 Unknown ReadOnly
1086 )";
1087 
1088   CompileSuccessfully(code.c_str());
1089   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_2_1));
1090   EXPECT_THAT(getDiagnosticString(),
1091               HasSubstr("Sampled must be 0 in the OpenCL environment."));
1092 }
1093 
TEST_F(ValidateImage,TypeImage_OpenCL_AccessQualifierMissing)1094 TEST_F(ValidateImage, TypeImage_OpenCL_AccessQualifierMissing) {
1095   const std::string code = GetKernelHeader() + R"(
1096 %img_type = OpTypeImage %void 2D 0 0 0 0 Unknown
1097 )";
1098 
1099   CompileSuccessfully(code.c_str());
1100   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_2_1));
1101   EXPECT_THAT(getDiagnosticString(),
1102               HasSubstr("In the OpenCL environment, the optional Access "
1103                         "Qualifier must be present"));
1104 }
1105 
TEST_F(ValidateImage,TypeImage_Vulkan_Sampled1_OK)1106 TEST_F(ValidateImage, TypeImage_Vulkan_Sampled1_OK) {
1107   const std::string code = GetShaderHeader() + R"(
1108 %img_type = OpTypeImage %f32 2D 0 0 0 1 Unknown
1109 )" + TrivialMain();
1110 
1111   CompileSuccessfully(code.c_str());
1112   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1113   EXPECT_THAT(getDiagnosticString(), Eq(""));
1114 }
1115 
TEST_F(ValidateImage,TypeImage_Vulkan_Sampled2_OK)1116 TEST_F(ValidateImage, TypeImage_Vulkan_Sampled2_OK) {
1117   const std::string code = GetShaderHeader() + R"(
1118 %img_type = OpTypeImage %f32 2D 0 0 0 2 Rgba32f
1119 )" + TrivialMain();
1120 
1121   CompileSuccessfully(code.c_str());
1122   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1123   EXPECT_THAT(getDiagnosticString(), Eq(""));
1124 }
1125 
TEST_F(ValidateImage,TypeImage_Vulkan_Sampled0_Invalid)1126 TEST_F(ValidateImage, TypeImage_Vulkan_Sampled0_Invalid) {
1127   const std::string code = GetShaderHeader() + R"(
1128 %img_type = OpTypeImage %f32 2D 0 0 0 0 Unknown
1129 )" + TrivialMain();
1130 
1131   CompileSuccessfully(code.c_str());
1132   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1133   EXPECT_THAT(getDiagnosticString(),
1134               AnyVUID("VUID-StandaloneSpirv-OpTypeImage-04657"));
1135   EXPECT_THAT(getDiagnosticString(),
1136               HasSubstr("Sampled must be 1 or 2 in the Vulkan environment."));
1137 }
1138 
TEST_F(ValidateImage,TypeImageWrongFormatForSubpassData)1139 TEST_F(ValidateImage, TypeImageWrongFormatForSubpassData) {
1140   const std::string code =
1141       GetShaderHeader("OpCapability InputAttachment\n", false) +
1142       R"(
1143 %img_type = OpTypeImage %f32 SubpassData 0 0 0 2 Rgba32f
1144 )";
1145 
1146   CompileSuccessfully(code.c_str());
1147   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1148   EXPECT_THAT(getDiagnosticString(),
1149               HasSubstr("Dim SubpassData requires format Unknown"));
1150 }
1151 
TEST_F(ValidateImage,TypeImageMultisampleStorageImage_MissingCapability)1152 TEST_F(ValidateImage, TypeImageMultisampleStorageImage_MissingCapability) {
1153   const std::string code = GetShaderHeader("", false) +
1154                            R"(
1155 %img_type = OpTypeImage %f32 2D 0 0 1 2 Rgba32f
1156 )";
1157 
1158   CompileSuccessfully(code.c_str());
1159   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()) << code;
1160   EXPECT_THAT(getDiagnosticString(),
1161               HasSubstr("Capability StorageImageMultisample is required when "
1162                         "using multisampled storage image"));
1163 }
1164 
TEST_F(ValidateImage,TypeImageMultisampleStorageImage_UsesCapability)1165 TEST_F(ValidateImage, TypeImageMultisampleStorageImage_UsesCapability) {
1166   const std::string code =
1167       GetShaderHeader("OpCapability StorageImageMultisample\n", false) +
1168       R"(
1169 %img_type = OpTypeImage %f32 2D 0 0 1 2 Rgba32f
1170 )";
1171 
1172   CompileSuccessfully(code.c_str());
1173   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()) << code;
1174   EXPECT_THAT(getDiagnosticString(), Eq(""));
1175 }
1176 
TEST_F(ValidateImage,TypeImageMultisampleSubpassData_OK)1177 TEST_F(ValidateImage, TypeImageMultisampleSubpassData_OK) {
1178   const std::string code =
1179       GetShaderHeader("OpCapability InputAttachment\n", false) +
1180       R"(
1181 %img_type = OpTypeImage %f32 SubpassData 0 0 1 2 Unknown
1182 )";
1183 
1184   CompileSuccessfully(code.c_str());
1185   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()) << code;
1186   EXPECT_THAT(getDiagnosticString(), Eq(""));
1187 }
1188 
TEST_F(ValidateImage,TypeSampledImage_NotImage_Error)1189 TEST_F(ValidateImage, TypeSampledImage_NotImage_Error) {
1190   const std::string code = GetShaderHeader("", false) + R"(
1191 %simg_type = OpTypeSampledImage %f32
1192 )";
1193 
1194   CompileSuccessfully(code.c_str());
1195   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1196   EXPECT_THAT(getDiagnosticString(),
1197               HasSubstr("Expected Image to be of type OpTypeImage"));
1198 }
1199 
TEST_F(ValidateImage,TypeSampledImage_Sampled0_Success)1200 TEST_F(ValidateImage, TypeSampledImage_Sampled0_Success) {
1201   // This is ok in the OpenCL and universal environments.
1202   // Vulkan will reject an OpTypeImage with Sampled=0, checked elsewhere.
1203   const std::string code = GetShaderHeader() + R"(
1204 %imty = OpTypeImage %f32 2D 0 0 0 0 Unknown
1205 %simg_type = OpTypeSampledImage %imty
1206 )" + TrivialMain();
1207 
1208   CompileSuccessfully(code.c_str());
1209   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1210   EXPECT_EQ(getDiagnosticString(), "");
1211 }
1212 
TEST_F(ValidateImage,TypeSampledImage_Sampled2_Error)1213 TEST_F(ValidateImage, TypeSampledImage_Sampled2_Error) {
1214   const std::string code = GetShaderHeader() + R"(
1215 %storage_image = OpTypeImage %f32 2D 0 0 0 2 Rgba32f
1216 %simg_type = OpTypeSampledImage %storage_image
1217 )" + TrivialMain();
1218 
1219   CompileSuccessfully(code.c_str());
1220   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1221   EXPECT_THAT(getDiagnosticString(),
1222               HasSubstr("Sampled image type requires an image type with "
1223                         "\"Sampled\" operand set to 0 or 1"));
1224 }
1225 
TEST_F(ValidateImage,TypeSampledImage_Sampled1_Success)1226 TEST_F(ValidateImage, TypeSampledImage_Sampled1_Success) {
1227   const std::string code = GetShaderHeader() + R"(
1228 %im = OpTypeImage %f32 2D 0 0 0 1 Unknown
1229 %simg_type = OpTypeSampledImage %im
1230 )" + TrivialMain();
1231 
1232   CompileSuccessfully(code.c_str());
1233   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1234   EXPECT_EQ(getDiagnosticString(), "");
1235 }
1236 
TEST_F(ValidateImage,SampledImageSuccess)1237 TEST_F(ValidateImage, SampledImageSuccess) {
1238   const std::string body = R"(
1239 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1240 %sampler = OpLoad %type_sampler %uniform_sampler
1241 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1242 )";
1243 
1244   CompileSuccessfully(GenerateShaderCode(body).c_str());
1245   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1246 }
1247 
TEST_F(ValidateImage,SampledImageVulkanSuccess)1248 TEST_F(ValidateImage, SampledImageVulkanSuccess) {
1249   const std::string body = R"(
1250 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1251 %sampler = OpLoad %type_sampler %uniform_sampler
1252 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1253 )";
1254 
1255   const spv_target_env env = SPV_ENV_VULKAN_1_0;
1256   CompileSuccessfully(GenerateShaderCode(body, "", "Fragment", "", env), env);
1257   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(env));
1258 }
1259 
TEST_F(ValidateImage,SampledImageWrongResultType)1260 TEST_F(ValidateImage, SampledImageWrongResultType) {
1261   const std::string body = R"(
1262 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1263 %sampler = OpLoad %type_sampler %uniform_sampler
1264 %simg = OpSampledImage %type_image_f32_2d_0001 %img %sampler
1265 )";
1266 
1267   CompileSuccessfully(GenerateShaderCode(body).c_str());
1268   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1269   EXPECT_THAT(getDiagnosticString(),
1270               HasSubstr("Expected Result Type to be OpTypeSampledImage"));
1271 }
1272 
TEST_F(ValidateImage,SampledImageNotImage)1273 TEST_F(ValidateImage, SampledImageNotImage) {
1274   const std::string body = R"(
1275 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1276 %sampler = OpLoad %type_sampler %uniform_sampler
1277 %simg1 = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1278 %simg2 = OpSampledImage %type_sampled_image_f32_2d_0001 %simg1 %sampler
1279 )";
1280 
1281   CompileSuccessfully(GenerateShaderCode(body).c_str());
1282   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1283   EXPECT_THAT(getDiagnosticString(),
1284               HasSubstr("Expected Image to be of type OpTypeImage"));
1285 }
1286 
TEST_F(ValidateImage,SampledImageImageNotForSampling)1287 TEST_F(ValidateImage, SampledImageImageNotForSampling) {
1288   const std::string code = GetShaderHeader() + R"(
1289 %im_ty = OpTypeImage %f32 2D 0 0 0 2 Unknown
1290 %sampler_ty = OpTypeSampler
1291 %sampled_image_ty = OpTypeSampledImage %im_ty ; will fail here first!
1292 
1293 %ptr_im_ty = OpTypePointer UniformConstant %im_ty
1294 %var_im = OpVariable %ptr_im_ty UniformConstant
1295 
1296 %ptr_sampler_ty = OpTypePointer UniformConstant %sampler_ty
1297 %var_sampler = OpVariable %ptr_sampler_ty UniformConstant
1298 
1299 %main = OpFunction %void None %func
1300 %entry = OpLabel
1301 %im = OpLoad %im_ty %var_im
1302 %sampler = OpLoad %sampler_ty %var_sampler
1303 %sampled_image = OpSampledImage %sampled_image_ty %im %sampler
1304 OpReturn
1305 OpFunctionEnd
1306 )";
1307 
1308   CompileSuccessfully(code.c_str());
1309   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1310   EXPECT_THAT(getDiagnosticString(),
1311               HasSubstr("Sampled image type requires an image type with "
1312                         "\"Sampled\" operand set to 0 or 1"))
1313       << code;
1314 }
1315 
TEST_F(ValidateImage,SampledImageNotSampler)1316 TEST_F(ValidateImage, SampledImageNotSampler) {
1317   const std::string body = R"(
1318 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1319 %sampler = OpLoad %type_sampler %uniform_sampler
1320 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %img
1321 )";
1322 
1323   CompileSuccessfully(GenerateShaderCode(body).c_str());
1324   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1325   EXPECT_THAT(getDiagnosticString(),
1326               HasSubstr("Expected Sampler to be of type OpTypeSampler"));
1327 }
1328 
TEST_F(ValidateImage,SampledImageIsStorage)1329 TEST_F(ValidateImage, SampledImageIsStorage) {
1330   const std::string declarations = R"(
1331 %type_sampled_image_f32_2d_0002 = OpTypeSampledImage %type_image_f32_2d_0002
1332 )";
1333   const std::string body = R"(
1334 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
1335 %sampler = OpLoad %type_sampler %uniform_sampler
1336 %simg = OpSampledImage %type_sampled_image_f32_2d_0002 %img %sampler
1337 )";
1338 
1339   CompileSuccessfully(GenerateShaderCode(body, "", "Fragment", "",
1340                                          SPV_ENV_UNIVERSAL_1_0, "GLSL450",
1341                                          declarations)
1342                           .c_str());
1343   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1344   EXPECT_THAT(getDiagnosticString(),
1345               HasSubstr("Sampled image type requires an image type with "
1346                         "\"Sampled\" operand set to 0 or 1"));
1347 }
1348 
TEST_F(ValidateImage,ImageTexelPointerSuccess)1349 TEST_F(ValidateImage, ImageTexelPointerSuccess) {
1350   const std::string body = R"(
1351 %texel_ptr = OpImageTexelPointer %ptr_Image_u32 %private_image_u32_buffer_0002_r32ui %u32_0 %u32_0
1352 %sum = OpAtomicIAdd %u32 %texel_ptr %u32_1 %u32_0 %u32_1
1353 )";
1354 
1355   CompileSuccessfully(GenerateShaderCode(body).c_str());
1356   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1357 }
1358 
TEST_F(ValidateImage,ImageTexelPointerResultTypeNotPointer)1359 TEST_F(ValidateImage, ImageTexelPointerResultTypeNotPointer) {
1360   const std::string body = R"(
1361 %texel_ptr = OpImageTexelPointer %type_image_u32_buffer_0002_r32ui %private_image_u32_buffer_0002_r32ui %u32_0 %u32_0
1362 %sum = OpAtomicIAdd %u32 %texel_ptr %u32_1 %u32_0 %u32_1
1363 )";
1364 
1365   CompileSuccessfully(GenerateShaderCode(body).c_str());
1366   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1367   EXPECT_THAT(getDiagnosticString(),
1368               HasSubstr("Expected Result Type to be OpTypePointer"));
1369 }
1370 
TEST_F(ValidateImage,ImageTexelPointerResultTypeNotImageClass)1371 TEST_F(ValidateImage, ImageTexelPointerResultTypeNotImageClass) {
1372   const std::string body = R"(
1373 %texel_ptr = OpImageTexelPointer %ptr_image_f32_cube_0101 %private_image_u32_buffer_0002_r32ui %u32_0 %u32_0
1374 %sum = OpAtomicIAdd %u32 %texel_ptr %u32_1 %u32_0 %u32_1
1375 )";
1376 
1377   CompileSuccessfully(GenerateShaderCode(body).c_str());
1378   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1379   EXPECT_THAT(getDiagnosticString(),
1380               HasSubstr("Expected Result Type to be OpTypePointer whose "
1381                         "Storage Class operand is Image"));
1382 }
1383 
TEST_F(ValidateImage,ImageTexelPointerResultTypeNotNumericNorVoid)1384 TEST_F(ValidateImage, ImageTexelPointerResultTypeNotNumericNorVoid) {
1385   const std::string body = R"(
1386 %texel_ptr = OpImageTexelPointer %ptr_Image_u32arr4 %private_image_u32_buffer_0002_r32ui %u32_0 %u32_0
1387 %sum = OpAtomicIAdd %u32 %texel_ptr %u32_1 %u32_0 %u32_1
1388 )";
1389 
1390   CompileSuccessfully(GenerateShaderCode(body).c_str());
1391   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1392   EXPECT_THAT(
1393       getDiagnosticString(),
1394       HasSubstr("Expected Result Type to be OpTypePointer whose Type operand "
1395                 "must be a scalar numerical type or OpTypeVoid"));
1396 }
1397 
TEST_F(ValidateImage,ImageTexelPointerImageNotResultTypePointer)1398 TEST_F(ValidateImage, ImageTexelPointerImageNotResultTypePointer) {
1399   const std::string body = R"(
1400 %texel_ptr = OpImageTexelPointer %ptr_Image_u32 %type_image_f32_buffer_0002_r32ui %u32_0 %u32_0
1401 %sum = OpAtomicIAdd %u32 %texel_ptr %u32_1 %u32_0 %u32_1
1402 )";
1403 
1404   CompileSuccessfully(GenerateShaderCode(body).c_str());
1405   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1406   EXPECT_THAT(getDiagnosticString(),
1407               HasSubstr("Operand '148[%148]' cannot be a "
1408                         "type"));
1409 }
1410 
TEST_F(ValidateImage,ImageTexelPointerImageNotImage)1411 TEST_F(ValidateImage, ImageTexelPointerImageNotImage) {
1412   const std::string body = R"(
1413 %texel_ptr = OpImageTexelPointer %ptr_Image_u32 %uniform_sampler %u32_0 %u32_0
1414 %sum = OpAtomicIAdd %u32 %texel_ptr %u32_1 %u32_0 %u32_1
1415 )";
1416 
1417   CompileSuccessfully(GenerateShaderCode(body).c_str());
1418   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1419   EXPECT_THAT(
1420       getDiagnosticString(),
1421       HasSubstr("Expected Image to be OpTypePointer with Type OpTypeImage"));
1422 }
1423 
TEST_F(ValidateImage,ImageTexelPointerImageSampledNotResultType)1424 TEST_F(ValidateImage, ImageTexelPointerImageSampledNotResultType) {
1425   const std::string body = R"(
1426 %texel_ptr = OpImageTexelPointer %ptr_Image_u32 %uniform_image_f32_cube_0101 %u32_0 %u32_0
1427 %sum = OpAtomicIAdd %u32 %texel_ptr %u32_1 %u32_0 %u32_1
1428 )";
1429 
1430   CompileSuccessfully(GenerateShaderCode(body).c_str());
1431   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1432   EXPECT_THAT(getDiagnosticString(),
1433               HasSubstr("Expected Image 'Sampled Type' to be the same as the "
1434                         "Type pointed to by Result Type"));
1435 }
1436 
TEST_F(ValidateImage,ImageTexelPointerImageDimSubpassDataBad)1437 TEST_F(ValidateImage, ImageTexelPointerImageDimSubpassDataBad) {
1438   const std::string body = R"(
1439 %texel_ptr = OpImageTexelPointer %ptr_Image_u32 %private_image_u32_spd_0002 %u32_0 %u32_0
1440 %sum = OpAtomicIAdd %u32 %texel_ptr %u32_1 %u32_0 %u32_1
1441 )";
1442 
1443   CompileSuccessfully(GenerateShaderCode(body).c_str());
1444   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1445   EXPECT_THAT(
1446       getDiagnosticString(),
1447       HasSubstr(
1448           "Image Dim SubpassData cannot be used with OpImageTexelPointer"));
1449 }
1450 
TEST_F(ValidateImage,ImageTexelPointerImageCoordTypeBad)1451 TEST_F(ValidateImage, ImageTexelPointerImageCoordTypeBad) {
1452   const std::string body = R"(
1453 %texel_ptr = OpImageTexelPointer %ptr_Image_f32 %private_image_f32_buffer_0002_r32ui %f32_0 %f32_0
1454 %sum = OpAtomicIAdd %f32 %texel_ptr %f32_1 %f32_0 %f32_1
1455 )";
1456 
1457   CompileSuccessfully(GenerateShaderCode(body).c_str());
1458   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1459   EXPECT_THAT(getDiagnosticString(),
1460               HasSubstr("Expected Coordinate to be integer scalar or vector"));
1461 }
1462 
TEST_F(ValidateImage,ImageTexelPointerImageCoordSizeBad)1463 TEST_F(ValidateImage, ImageTexelPointerImageCoordSizeBad) {
1464   const std::string body = R"(
1465 %texel_ptr = OpImageTexelPointer %ptr_Image_u32 %uniform_image_u32_2d_0002 %u32vec3_012 %u32_0
1466 %sum = OpAtomicIAdd %u32 %texel_ptr %u32_1 %u32_0 %u32_1
1467 )";
1468 
1469   CompileSuccessfully(GenerateShaderCode(body).c_str());
1470   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1471   EXPECT_THAT(
1472       getDiagnosticString(),
1473       HasSubstr("Expected Coordinate to have 2 components, but given 3"));
1474 }
1475 
TEST_F(ValidateImage,ImageTexelPointerSampleNotIntScalar)1476 TEST_F(ValidateImage, ImageTexelPointerSampleNotIntScalar) {
1477   const std::string body = R"(
1478 %texel_ptr = OpImageTexelPointer %ptr_Image_u32 %private_image_u32_buffer_0002_r32ui %u32_0 %f32_0
1479 %sum = OpAtomicIAdd %u32 %texel_ptr %u32_1 %u32_0 %u32_1
1480 )";
1481 
1482   CompileSuccessfully(GenerateShaderCode(body).c_str());
1483   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1484   EXPECT_THAT(getDiagnosticString(),
1485               HasSubstr("Expected Sample to be integer scalar"));
1486 }
1487 
TEST_F(ValidateImage,ImageTexelPointerSampleNotZeroForImageWithMSZero)1488 TEST_F(ValidateImage, ImageTexelPointerSampleNotZeroForImageWithMSZero) {
1489   const std::string body = R"(
1490 %texel_ptr = OpImageTexelPointer %ptr_Image_u32 %private_image_u32_buffer_0002_r32ui %u32_0 %u32_1
1491 %sum = OpAtomicIAdd %u32 %texel_ptr %u32_1 %u32_0 %u32_1
1492 )";
1493 
1494   CompileSuccessfully(GenerateShaderCode(body).c_str());
1495   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1496   EXPECT_THAT(getDiagnosticString(),
1497               HasSubstr("Expected Sample for Image with MS 0 to be a valid "
1498                         "<id> for the value 0"));
1499 }
1500 
TEST_F(ValidateImage,SampleImplicitLodSuccess)1501 TEST_F(ValidateImage, SampleImplicitLodSuccess) {
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 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh
1507 %res2 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh Bias %f32_0_25
1508 %res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh ConstOffset %s32vec2_01
1509 %res5 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh Offset %s32vec2_01
1510 %res6 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh MinLod %f32_0_5
1511 %res7 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh Bias|Offset|MinLod %f32_0_25 %s32vec2_01 %f32_0_5
1512 %res8 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh NonPrivateTexelKHR
1513 )";
1514 
1515   const std::string extra = R"(
1516 OpCapability VulkanMemoryModelKHR
1517 OpExtension "SPV_KHR_vulkan_memory_model"
1518 )";
1519   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
1520                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
1521                           .c_str());
1522   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1523 }
1524 
TEST_F(ValidateImage,SampleImplicitLodWrongResultType)1525 TEST_F(ValidateImage, SampleImplicitLodWrongResultType) {
1526   const std::string body = R"(
1527 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1528 %sampler = OpLoad %type_sampler %uniform_sampler
1529 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1530 %res1 = OpImageSampleImplicitLod %f32 %simg %f32vec2_hh
1531 )";
1532 
1533   CompileSuccessfully(GenerateShaderCode(body).c_str());
1534   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1535   EXPECT_THAT(getDiagnosticString(),
1536               HasSubstr("Expected Result Type to be int or float vector type"));
1537 }
1538 
TEST_F(ValidateImage,SampleImplicitLodWrongNumComponentsResultType)1539 TEST_F(ValidateImage, SampleImplicitLodWrongNumComponentsResultType) {
1540   const std::string body = R"(
1541 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1542 %sampler = OpLoad %type_sampler %uniform_sampler
1543 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1544 %res1 = OpImageSampleImplicitLod %f32vec3 %simg %f32vec2_hh
1545 )";
1546 
1547   CompileSuccessfully(GenerateShaderCode(body).c_str());
1548   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1549   EXPECT_THAT(getDiagnosticString(),
1550               HasSubstr("Expected Result Type to have 4 components"));
1551 }
1552 
TEST_F(ValidateImage,SampleImplicitLodNotSampledImage)1553 TEST_F(ValidateImage, SampleImplicitLodNotSampledImage) {
1554   const std::string body = R"(
1555 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1556 %res1 = OpImageSampleImplicitLod %f32vec4 %img %f32vec2_hh
1557 )";
1558 
1559   CompileSuccessfully(GenerateShaderCode(body).c_str());
1560   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1561   EXPECT_THAT(
1562       getDiagnosticString(),
1563       HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage"));
1564 }
1565 
TEST_F(ValidateImage,SampleImplicitLodMultisampleError)1566 TEST_F(ValidateImage, SampleImplicitLodMultisampleError) {
1567   const std::string body = R"(
1568 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
1569 %sampler = OpLoad %type_sampler %uniform_sampler
1570 %simg = OpSampledImage %type_sampled_image_f32_2d_0011 %img %sampler
1571 %res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_hh Sample %u32_1
1572 )";
1573 
1574   CompileSuccessfully(GenerateShaderCode(body).c_str());
1575   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1576   EXPECT_THAT(getDiagnosticString(),
1577               HasSubstr("Sampling operation is invalid for multisample image"));
1578 }
1579 
TEST_F(ValidateImage,SampleImplicitLodWrongSampledType)1580 TEST_F(ValidateImage, SampleImplicitLodWrongSampledType) {
1581   const std::string body = R"(
1582 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1583 %sampler = OpLoad %type_sampler %uniform_sampler
1584 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1585 %res1 = OpImageSampleImplicitLod %u32vec4 %simg %f32vec2_00
1586 )";
1587 
1588   CompileSuccessfully(GenerateShaderCode(body).c_str());
1589   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1590   EXPECT_THAT(getDiagnosticString(),
1591               HasSubstr("Expected Image 'Sampled Type' to be the same as "
1592                         "Result Type components"));
1593 }
1594 
TEST_F(ValidateImage,SampleImplicitLodVoidSampledType)1595 TEST_F(ValidateImage, SampleImplicitLodVoidSampledType) {
1596   const std::string body = R"(
1597 %img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001
1598 %sampler = OpLoad %type_sampler %uniform_sampler
1599 %simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler
1600 %res1 = OpImageSampleImplicitLod %u32vec4 %simg %f32vec2_00
1601 )";
1602 
1603   CompileSuccessfully(GenerateShaderCode(body).c_str());
1604   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1605 }
1606 
TEST_F(ValidateImage,SampleImplicitLodWrongCoordinateType)1607 TEST_F(ValidateImage, SampleImplicitLodWrongCoordinateType) {
1608   const std::string body = R"(
1609 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1610 %sampler = OpLoad %type_sampler %uniform_sampler
1611 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1612 %res1 = OpImageSampleImplicitLod %f32vec4 %simg %img
1613 )";
1614 
1615   CompileSuccessfully(GenerateShaderCode(body).c_str());
1616   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1617   EXPECT_THAT(getDiagnosticString(),
1618               HasSubstr("Expected Coordinate to be float scalar or vector"));
1619 }
1620 
TEST_F(ValidateImage,SampleImplicitLodCoordinateSizeTooSmall)1621 TEST_F(ValidateImage, SampleImplicitLodCoordinateSizeTooSmall) {
1622   const std::string body = R"(
1623 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1624 %sampler = OpLoad %type_sampler %uniform_sampler
1625 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1626 %res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32_0_5
1627 )";
1628 
1629   CompileSuccessfully(GenerateShaderCode(body).c_str());
1630   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1631   EXPECT_THAT(getDiagnosticString(),
1632               HasSubstr("Expected Coordinate to have at least 2 components, "
1633                         "but given only 1"));
1634 }
1635 
TEST_F(ValidateImage,SampleExplicitLodSuccessShader)1636 TEST_F(ValidateImage, SampleExplicitLodSuccessShader) {
1637   const std::string body = R"(
1638 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1639 %sampler = OpLoad %type_sampler %uniform_sampler
1640 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1641 %res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec4_0000 Lod %f32_1
1642 %res2 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_hh Grad %f32vec2_10 %f32vec2_01
1643 %res3 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_hh ConstOffset %s32vec2_01
1644 %res4 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec3_hhh Offset %s32vec2_01
1645 %res5 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_hh Grad|Offset|MinLod %f32vec2_10 %f32vec2_01 %s32vec2_01 %f32_0_5
1646 %res6 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec4_0000 Lod|NonPrivateTexelKHR %f32_1
1647 )";
1648 
1649   const std::string extra = R"(
1650 OpCapability VulkanMemoryModelKHR
1651 OpExtension "SPV_KHR_vulkan_memory_model"
1652 )";
1653   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
1654                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
1655                           .c_str());
1656   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1657 }
1658 
TEST_F(ValidateImage,SampleExplicitLodSuccessKernel)1659 TEST_F(ValidateImage, SampleExplicitLodSuccessKernel) {
1660   const std::string body = R"(
1661 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1662 %sampler = OpLoad %type_sampler %uniform_sampler
1663 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1664 %res1 = OpImageSampleExplicitLod %f32vec4 %simg %u32vec4_0123 Lod %f32_1
1665 %res2 = OpImageSampleExplicitLod %f32vec4 %simg %u32vec2_01 Grad %f32vec2_10 %f32vec2_01
1666 %res3 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_hh ConstOffset %u32vec2_01
1667 %res4 = OpImageSampleExplicitLod %f32vec4 %simg %u32vec2_01 Offset %u32vec2_01
1668 %res5 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_hh Grad|Offset %f32vec2_10 %f32vec2_01 %u32vec2_01
1669 )";
1670 
1671   CompileSuccessfully(GenerateKernelCode(body).c_str());
1672   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1673 }
1674 
TEST_F(ValidateImage,SampleExplicitLodSuccessCubeArrayed)1675 TEST_F(ValidateImage, SampleExplicitLodSuccessCubeArrayed) {
1676   const std::string body = R"(
1677 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
1678 %sampler = OpLoad %type_sampler %uniform_sampler
1679 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
1680 %res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec4_0000 Grad %f32vec3_hhh %f32vec3_hhh
1681 )";
1682 
1683   CompileSuccessfully(GenerateShaderCode(body).c_str());
1684   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1685 }
1686 
TEST_F(ValidateImage,SampleExplicitLodWrongResultType)1687 TEST_F(ValidateImage, SampleExplicitLodWrongResultType) {
1688   const std::string body = R"(
1689 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1690 %sampler = OpLoad %type_sampler %uniform_sampler
1691 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1692 %res1 = OpImageSampleExplicitLod %f32 %simg %f32vec2_hh Lod %f32_1
1693 )";
1694 
1695   CompileSuccessfully(GenerateShaderCode(body).c_str());
1696   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1697   EXPECT_THAT(getDiagnosticString(),
1698               HasSubstr("Expected Result Type to be int or float vector type"));
1699 }
1700 
TEST_F(ValidateImage,SampleExplicitLodWrongNumComponentsResultType)1701 TEST_F(ValidateImage, SampleExplicitLodWrongNumComponentsResultType) {
1702   const std::string body = R"(
1703 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1704 %sampler = OpLoad %type_sampler %uniform_sampler
1705 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1706 %res1 = OpImageSampleExplicitLod %f32vec3 %simg %f32vec2_hh Lod %f32_1
1707 )";
1708 
1709   CompileSuccessfully(GenerateShaderCode(body).c_str());
1710   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1711   EXPECT_THAT(getDiagnosticString(),
1712               HasSubstr("Expected Result Type to have 4 components"));
1713 }
1714 
TEST_F(ValidateImage,SampleExplicitLodNotSampledImage)1715 TEST_F(ValidateImage, SampleExplicitLodNotSampledImage) {
1716   const std::string body = R"(
1717 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1718 %res1 = OpImageSampleExplicitLod %f32vec4 %img %f32vec2_hh Lod %f32_1
1719 )";
1720 
1721   CompileSuccessfully(GenerateShaderCode(body).c_str());
1722   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1723   EXPECT_THAT(
1724       getDiagnosticString(),
1725       HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage"));
1726 }
1727 
TEST_F(ValidateImage,SampleExplicitLodMultisampleError)1728 TEST_F(ValidateImage, SampleExplicitLodMultisampleError) {
1729   const std::string body = R"(
1730 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
1731 %sampler = OpLoad %type_sampler %uniform_sampler
1732 %simg = OpSampledImage %type_sampled_image_f32_2d_0011 %img %sampler
1733 %res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh Lod|Sample %f32_0 %u32_1
1734 )";
1735 
1736   CompileSuccessfully(GenerateShaderCode(body).c_str());
1737   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1738   EXPECT_THAT(getDiagnosticString(),
1739               HasSubstr("Sampling operation is invalid for multisample image"));
1740 }
1741 
TEST_F(ValidateImage,SampleExplicitLodWrongSampledType)1742 TEST_F(ValidateImage, SampleExplicitLodWrongSampledType) {
1743   const std::string body = R"(
1744 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1745 %sampler = OpLoad %type_sampler %uniform_sampler
1746 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1747 %res1 = OpImageSampleExplicitLod %u32vec4 %simg %f32vec2_00 Lod %f32_1
1748 )";
1749 
1750   CompileSuccessfully(GenerateShaderCode(body).c_str());
1751   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1752   EXPECT_THAT(getDiagnosticString(),
1753               HasSubstr("Expected Image 'Sampled Type' to be the same as "
1754                         "Result Type components"));
1755 }
1756 
TEST_F(ValidateImage,SampleExplicitLodVoidSampledType)1757 TEST_F(ValidateImage, SampleExplicitLodVoidSampledType) {
1758   const std::string body = R"(
1759 %img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001
1760 %sampler = OpLoad %type_sampler %uniform_sampler
1761 %simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler
1762 %res1 = OpImageSampleExplicitLod %u32vec4 %simg %f32vec2_00 Lod %f32_1
1763 )";
1764 
1765   CompileSuccessfully(GenerateShaderCode(body).c_str());
1766   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1767 }
1768 
TEST_F(ValidateImage,SampleExplicitLodWrongCoordinateType)1769 TEST_F(ValidateImage, SampleExplicitLodWrongCoordinateType) {
1770   const std::string body = R"(
1771 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1772 %sampler = OpLoad %type_sampler %uniform_sampler
1773 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1774 %res1 = OpImageSampleExplicitLod %f32vec4 %simg %img Lod %f32_1
1775 )";
1776 
1777   CompileSuccessfully(GenerateShaderCode(body).c_str());
1778   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1779   EXPECT_THAT(getDiagnosticString(),
1780               HasSubstr("Expected Coordinate to be float scalar or vector"));
1781 }
1782 
TEST_F(ValidateImage,SampleExplicitLodCoordinateSizeTooSmall)1783 TEST_F(ValidateImage, SampleExplicitLodCoordinateSizeTooSmall) {
1784   const std::string body = R"(
1785 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1786 %sampler = OpLoad %type_sampler %uniform_sampler
1787 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1788 %res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32_0_5 Lod %f32_1
1789 )";
1790 
1791   CompileSuccessfully(GenerateShaderCode(body).c_str());
1792   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1793   EXPECT_THAT(getDiagnosticString(),
1794               HasSubstr("Expected Coordinate to have at least 2 components, "
1795                         "but given only 1"));
1796 }
1797 
TEST_F(ValidateImage,SampleExplicitLodBias)1798 TEST_F(ValidateImage, SampleExplicitLodBias) {
1799   const std::string body = R"(
1800 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1801 %sampler = OpLoad %type_sampler %uniform_sampler
1802 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1803 %res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_00 Bias|Lod %f32_1 %f32_1
1804 )";
1805 
1806   CompileSuccessfully(GenerateShaderCode(body).c_str());
1807   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1808   EXPECT_THAT(
1809       getDiagnosticString(),
1810       HasSubstr(
1811           "Image Operand Bias can only be used with ImplicitLod opcodes"));
1812 }
1813 
TEST_F(ValidateImage,LodAndGrad)1814 TEST_F(ValidateImage, LodAndGrad) {
1815   const std::string body = R"(
1816 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1817 %sampler = OpLoad %type_sampler %uniform_sampler
1818 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1819 %res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_00 Lod|Grad %f32_1 %f32vec2_hh %f32vec2_hh
1820 )";
1821 
1822   CompileSuccessfully(GenerateShaderCode(body).c_str());
1823   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1824   EXPECT_THAT(
1825       getDiagnosticString(),
1826       HasSubstr(
1827           "Image Operand bits Lod and Grad cannot be set at the same time"));
1828 }
1829 
TEST_F(ValidateImage,ImplicitLodWithLod)1830 TEST_F(ValidateImage, ImplicitLodWithLod) {
1831   const std::string body = R"(
1832 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1833 %sampler = OpLoad %type_sampler %uniform_sampler
1834 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1835 %res2 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh Lod %f32_0_5
1836 )";
1837 
1838   CompileSuccessfully(GenerateShaderCode(body).c_str());
1839   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1840   EXPECT_THAT(
1841       getDiagnosticString(),
1842       HasSubstr("Image Operand Lod can only be used with ExplicitLod opcodes "
1843                 "and OpImageFetch"));
1844 }
1845 
TEST_F(ValidateImage,LodWrongType)1846 TEST_F(ValidateImage, LodWrongType) {
1847   const std::string body = R"(
1848 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1849 %sampler = OpLoad %type_sampler %uniform_sampler
1850 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1851 %res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_00 Lod %f32vec2_hh)";
1852 
1853   CompileSuccessfully(GenerateShaderCode(body).c_str());
1854   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1855   EXPECT_THAT(getDiagnosticString(),
1856               HasSubstr("Expected Image Operand Lod to be float scalar when "
1857                         "used with ExplicitLod"));
1858 }
1859 
TEST_F(ValidateImage,LodWrongDim)1860 TEST_F(ValidateImage, LodWrongDim) {
1861   const std::string body = R"(
1862 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
1863 %sampler = OpLoad %type_sampler %uniform_sampler
1864 %simg = OpSampledImage %type_sampled_image_f32_rect_0001 %img %sampler
1865 %res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_00 Lod %f32_0)";
1866 
1867   CompileSuccessfully(GenerateShaderCode(body).c_str());
1868   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1869   EXPECT_THAT(getDiagnosticString(),
1870               HasSubstr("Image Operand Lod requires 'Dim' parameter to be 1D, "
1871                         "2D, 3D or Cube"));
1872 }
1873 
TEST_F(ValidateImage,MinLodIncompatible)1874 TEST_F(ValidateImage, MinLodIncompatible) {
1875   const std::string body = R"(
1876 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1877 %sampler = OpLoad %type_sampler %uniform_sampler
1878 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1879 %res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_00 Lod|MinLod %f32_0 %f32_0)";
1880 
1881   CompileSuccessfully(GenerateShaderCode(body).c_str());
1882   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1883   EXPECT_THAT(
1884       getDiagnosticString(),
1885       HasSubstr(
1886           "Image Operand MinLod can only be used with ImplicitLod opcodes or "
1887           "together with Image Operand Grad"));
1888 }
1889 
TEST_F(ValidateImage,ImplicitLodWithGrad)1890 TEST_F(ValidateImage, ImplicitLodWithGrad) {
1891   const std::string body = R"(
1892 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1893 %sampler = OpLoad %type_sampler %uniform_sampler
1894 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1895 %res2 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh Grad %f32vec2_hh %f32vec2_hh
1896 )";
1897 
1898   CompileSuccessfully(GenerateShaderCode(body).c_str());
1899   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1900   EXPECT_THAT(
1901       getDiagnosticString(),
1902       HasSubstr(
1903           "Image Operand Grad can only be used with ExplicitLod opcodes"));
1904 }
1905 
TEST_F(ValidateImage,SampleImplicitLodCubeArrayedSuccess)1906 TEST_F(ValidateImage, SampleImplicitLodCubeArrayedSuccess) {
1907   const std::string body = R"(
1908 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
1909 %sampler = OpLoad %type_sampler %uniform_sampler
1910 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
1911 %res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000
1912 %res2 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 Bias %f32_0_25
1913 %res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 MinLod %f32_0_5
1914 %res5 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 Bias|MinLod %f32_0_25 %f32_0_5
1915 )";
1916 
1917   CompileSuccessfully(GenerateShaderCode(body).c_str());
1918   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1919 }
1920 
TEST_F(ValidateImage,SampleImplicitLodBiasWrongType)1921 TEST_F(ValidateImage, SampleImplicitLodBiasWrongType) {
1922   const std::string body = R"(
1923 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1924 %sampler = OpLoad %type_sampler %uniform_sampler
1925 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1926 %res2 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh Bias %u32_0
1927 )";
1928 
1929   CompileSuccessfully(GenerateShaderCode(body).c_str());
1930   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1931   EXPECT_THAT(getDiagnosticString(),
1932               HasSubstr("Expected Image Operand Bias to be float scalar"));
1933 }
1934 
TEST_F(ValidateImage,SampleImplicitLodBiasWrongDim)1935 TEST_F(ValidateImage, SampleImplicitLodBiasWrongDim) {
1936   const std::string body = R"(
1937 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
1938 %sampler = OpLoad %type_sampler %uniform_sampler
1939 %simg = OpSampledImage %type_sampled_image_f32_rect_0001 %img %sampler
1940 %res2 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh Bias %f32_0
1941 )";
1942 
1943   CompileSuccessfully(GenerateShaderCode(body).c_str());
1944   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1945   EXPECT_THAT(getDiagnosticString(),
1946               HasSubstr("Image Operand Bias requires 'Dim' parameter to be 1D, "
1947                         "2D, 3D or Cube"));
1948 }
1949 
TEST_F(ValidateImage,SampleExplicitLodGradDxWrongType)1950 TEST_F(ValidateImage, SampleExplicitLodGradDxWrongType) {
1951   const std::string body = R"(
1952 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
1953 %sampler = OpLoad %type_sampler %uniform_sampler
1954 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
1955 %res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec4_0000 Grad %s32vec3_012 %f32vec3_hhh
1956 )";
1957 
1958   CompileSuccessfully(GenerateShaderCode(body).c_str());
1959   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1960   EXPECT_THAT(getDiagnosticString(),
1961               HasSubstr("Expected both Image Operand Grad ids to be float "
1962                         "scalars or vectors"));
1963 }
1964 
TEST_F(ValidateImage,SampleExplicitLodGradDyWrongType)1965 TEST_F(ValidateImage, SampleExplicitLodGradDyWrongType) {
1966   const std::string body = R"(
1967 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
1968 %sampler = OpLoad %type_sampler %uniform_sampler
1969 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
1970 %res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec4_0000 Grad  %f32vec3_hhh %s32vec3_012
1971 )";
1972 
1973   CompileSuccessfully(GenerateShaderCode(body).c_str());
1974   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1975   EXPECT_THAT(getDiagnosticString(),
1976               HasSubstr("Expected both Image Operand Grad ids to be float "
1977                         "scalars or vectors"));
1978 }
1979 
TEST_F(ValidateImage,SampleExplicitLodGradDxWrongSize)1980 TEST_F(ValidateImage, SampleExplicitLodGradDxWrongSize) {
1981   const std::string body = R"(
1982 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
1983 %sampler = OpLoad %type_sampler %uniform_sampler
1984 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
1985 %res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec4_0000 Grad %f32vec2_00 %f32vec3_hhh
1986 )";
1987 
1988   CompileSuccessfully(GenerateShaderCode(body).c_str());
1989   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1990   EXPECT_THAT(
1991       getDiagnosticString(),
1992       HasSubstr(
1993           "Expected Image Operand Grad dx to have 3 components, but given 2"));
1994 }
1995 
TEST_F(ValidateImage,SampleExplicitLodGradDyWrongSize)1996 TEST_F(ValidateImage, SampleExplicitLodGradDyWrongSize) {
1997   const std::string body = R"(
1998 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
1999 %sampler = OpLoad %type_sampler %uniform_sampler
2000 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
2001 %res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec4_0000 Grad %f32vec3_hhh %f32vec2_00
2002 )";
2003 
2004   CompileSuccessfully(GenerateShaderCode(body).c_str());
2005   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2006   EXPECT_THAT(
2007       getDiagnosticString(),
2008       HasSubstr(
2009           "Expected Image Operand Grad dy to have 3 components, but given 2"));
2010 }
2011 
TEST_F(ValidateImage,SampleImplicitLodConstOffsetCubeDim)2012 TEST_F(ValidateImage, SampleImplicitLodConstOffsetCubeDim) {
2013   const std::string body = R"(
2014 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
2015 %sampler = OpLoad %type_sampler %uniform_sampler
2016 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
2017 %res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 ConstOffset %s32vec3_012
2018 )";
2019 
2020   CompileSuccessfully(GenerateShaderCode(body).c_str());
2021   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2022   EXPECT_THAT(
2023       getDiagnosticString(),
2024       HasSubstr(
2025           "Image Operand ConstOffset cannot be used with Cube Image 'Dim'"));
2026 }
2027 
TEST_F(ValidateImage,SampleImplicitLodConstOffsetWrongType)2028 TEST_F(ValidateImage, SampleImplicitLodConstOffsetWrongType) {
2029   const std::string body = R"(
2030 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2031 %sampler = OpLoad %type_sampler %uniform_sampler
2032 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2033 %res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_00 ConstOffset %f32vec2_00
2034 )";
2035 
2036   CompileSuccessfully(GenerateShaderCode(body).c_str());
2037   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2038   EXPECT_THAT(
2039       getDiagnosticString(),
2040       HasSubstr(
2041           "Expected Image Operand ConstOffset to be int scalar or vector"));
2042 }
2043 
TEST_F(ValidateImage,SampleImplicitLodConstOffsetWrongSize)2044 TEST_F(ValidateImage, SampleImplicitLodConstOffsetWrongSize) {
2045   const std::string body = R"(
2046 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2047 %sampler = OpLoad %type_sampler %uniform_sampler
2048 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2049 %res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_00 ConstOffset %s32vec3_012
2050 )";
2051 
2052   CompileSuccessfully(GenerateShaderCode(body).c_str());
2053   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2054   EXPECT_THAT(getDiagnosticString(),
2055               HasSubstr("Expected Image Operand ConstOffset to have 2 "
2056                         "components, but given 3"));
2057 }
2058 
TEST_F(ValidateImage,SampleImplicitLodConstOffsetNotConst)2059 TEST_F(ValidateImage, SampleImplicitLodConstOffsetNotConst) {
2060   const std::string body = R"(
2061 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2062 %sampler = OpLoad %type_sampler %uniform_sampler
2063 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2064 %offset = OpSNegate %s32vec3 %s32vec3_012
2065 %res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_00 ConstOffset %offset
2066 )";
2067 
2068   CompileSuccessfully(GenerateShaderCode(body).c_str());
2069   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2070   EXPECT_THAT(
2071       getDiagnosticString(),
2072       HasSubstr("Expected Image Operand ConstOffset to be a const object"));
2073 }
2074 
TEST_F(ValidateImage,SampleImplicitLodOffsetCubeDim)2075 TEST_F(ValidateImage, SampleImplicitLodOffsetCubeDim) {
2076   const std::string body = R"(
2077 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
2078 %sampler = OpLoad %type_sampler %uniform_sampler
2079 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
2080 %res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 Offset %s32vec3_012
2081 )";
2082 
2083   CompileSuccessfully(GenerateShaderCode(body).c_str());
2084   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2085   EXPECT_THAT(
2086       getDiagnosticString(),
2087       HasSubstr("Image Operand Offset cannot be used with Cube Image 'Dim'"));
2088 }
2089 
TEST_F(ValidateImage,SampleImplicitLodOffsetWrongType)2090 TEST_F(ValidateImage, SampleImplicitLodOffsetWrongType) {
2091   const std::string body = R"(
2092 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2093 %sampler = OpLoad %type_sampler %uniform_sampler
2094 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2095 %res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 Offset %f32vec2_00
2096 )";
2097 
2098   CompileSuccessfully(GenerateShaderCode(body).c_str());
2099   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2100   EXPECT_THAT(
2101       getDiagnosticString(),
2102       HasSubstr("Expected Image Operand Offset to be int scalar or vector"));
2103 }
2104 
TEST_F(ValidateImage,SampleImplicitLodOffsetWrongSize)2105 TEST_F(ValidateImage, SampleImplicitLodOffsetWrongSize) {
2106   const std::string body = R"(
2107 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2108 %sampler = OpLoad %type_sampler %uniform_sampler
2109 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2110 %res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 Offset %s32vec3_012
2111 )";
2112 
2113   CompileSuccessfully(GenerateShaderCode(body).c_str());
2114   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2115   EXPECT_THAT(
2116       getDiagnosticString(),
2117       HasSubstr(
2118           "Expected Image Operand Offset to have 2 components, but given 3"));
2119 }
2120 
TEST_F(ValidateImage,SampleImplicitLodVulkanOffsetWrongSize)2121 TEST_F(ValidateImage, SampleImplicitLodVulkanOffsetWrongSize) {
2122   const std::string body = R"(
2123 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2124 %sampler = OpLoad %type_sampler %uniform_sampler
2125 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2126 %res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 Offset %s32vec2_01
2127 )";
2128 
2129   CompileSuccessfully(
2130       GenerateShaderCode(body, "", "Fragment", "", SPV_ENV_VULKAN_1_0).c_str());
2131   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
2132   EXPECT_THAT(getDiagnosticString(),
2133               AnyVUID("VUID-StandaloneSpirv-Offset-04663"));
2134   EXPECT_THAT(getDiagnosticString(),
2135               HasSubstr("Image Operand Offset can only be used with "
2136                         "OpImage*Gather operations"));
2137 }
2138 
TEST_F(ValidateImage,SampleImplicitLodVulkanOffsetWrongBeforeLegalization)2139 TEST_F(ValidateImage, SampleImplicitLodVulkanOffsetWrongBeforeLegalization) {
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 %res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 Offset %s32vec2_01
2145 )";
2146 
2147   CompileSuccessfully(
2148       GenerateShaderCode(body, "", "Fragment", "", SPV_ENV_VULKAN_1_0).c_str());
2149   getValidatorOptions()->before_hlsl_legalization = true;
2150   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
2151 }
2152 
TEST_F(ValidateImage,SampleImplicitLodMoreThanOneOffset)2153 TEST_F(ValidateImage, SampleImplicitLodMoreThanOneOffset) {
2154   const std::string body = R"(
2155 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2156 %sampler = OpLoad %type_sampler %uniform_sampler
2157 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2158 %res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 ConstOffset|Offset %s32vec2_01 %s32vec2_01
2159 )";
2160 
2161   CompileSuccessfully(GenerateShaderCode(body).c_str());
2162   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2163   EXPECT_THAT(
2164       getDiagnosticString(),
2165       HasSubstr("Image Operands Offset, ConstOffset, ConstOffsets, Offsets "
2166                 "cannot be used together"));
2167 }
2168 
TEST_F(ValidateImage,SampleImplicitLodVulkanMoreThanOneOffset)2169 TEST_F(ValidateImage, SampleImplicitLodVulkanMoreThanOneOffset) {
2170   const std::string body = R"(
2171 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2172 %sampler = OpLoad %type_sampler %uniform_sampler
2173 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2174 %res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 ConstOffset|Offset %s32vec2_01 %s32vec2_01
2175 )";
2176 
2177   CompileSuccessfully(
2178       GenerateShaderCode(body, "", "Fragment", "", SPV_ENV_VULKAN_1_0).c_str());
2179   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
2180   EXPECT_THAT(
2181       getDiagnosticString(),
2182       HasSubstr("Image Operands Offset, ConstOffset, ConstOffsets, Offsets "
2183                 "cannot be used together"));
2184 }
2185 
TEST_F(ValidateImage,SampleImplicitLodMinLodWrongType)2186 TEST_F(ValidateImage, SampleImplicitLodMinLodWrongType) {
2187   const std::string body = R"(
2188 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
2189 %sampler = OpLoad %type_sampler %uniform_sampler
2190 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
2191 %res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 MinLod %s32_0
2192 )";
2193 
2194   CompileSuccessfully(GenerateShaderCode(body).c_str());
2195   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2196   EXPECT_THAT(getDiagnosticString(),
2197               HasSubstr("Expected Image Operand MinLod to be float scalar"));
2198 }
2199 
TEST_F(ValidateImage,SampleImplicitLodMinLodWrongDim)2200 TEST_F(ValidateImage, SampleImplicitLodMinLodWrongDim) {
2201   const std::string body = R"(
2202 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
2203 %sampler = OpLoad %type_sampler %uniform_sampler
2204 %simg = OpSampledImage %type_sampled_image_f32_rect_0001 %img %sampler
2205 %res2 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh MinLod %f32_0_25
2206 )";
2207 
2208   CompileSuccessfully(GenerateShaderCode(body).c_str());
2209   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2210   EXPECT_THAT(getDiagnosticString(),
2211               HasSubstr("Image Operand MinLod requires 'Dim' parameter to be "
2212                         "1D, 2D, 3D or Cube"));
2213 }
2214 
TEST_F(ValidateImage,SampleProjExplicitLodSuccess2D)2215 TEST_F(ValidateImage, SampleProjExplicitLodSuccess2D) {
2216   const std::string body = R"(
2217 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2218 %sampler = OpLoad %type_sampler %uniform_sampler
2219 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2220 %res1 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec3_hhh Lod %f32_1
2221 %res3 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec3_hhh Grad %f32vec2_10 %f32vec2_01
2222 %res4 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec3_hhh ConstOffset %s32vec2_01
2223 %res5 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec3_hhh Offset %s32vec2_01
2224 %res7 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec3_hhh Grad|Offset %f32vec2_10 %f32vec2_01 %s32vec2_01
2225 %res8 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec3_hhh Lod|NonPrivateTexelKHR %f32_1
2226 )";
2227 
2228   const std::string extra = R"(
2229 OpCapability VulkanMemoryModelKHR
2230 OpExtension "SPV_KHR_vulkan_memory_model"
2231 )";
2232   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
2233                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
2234                           .c_str());
2235   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2236 }
2237 
TEST_F(ValidateImage,SampleProjExplicitLodSuccessRect)2238 TEST_F(ValidateImage, SampleProjExplicitLodSuccessRect) {
2239   const std::string body = R"(
2240 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
2241 %sampler = OpLoad %type_sampler %uniform_sampler
2242 %simg = OpSampledImage %type_sampled_image_f32_rect_0001 %img %sampler
2243 %res1 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec3_hhh Grad %f32vec2_10 %f32vec2_01
2244 %res2 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec3_hhh Grad|Offset %f32vec2_10 %f32vec2_01 %s32vec2_01
2245 )";
2246 
2247   CompileSuccessfully(GenerateShaderCode(body).c_str());
2248   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
2249 }
2250 
TEST_F(ValidateImage,SampleProjExplicitLodWrongResultType)2251 TEST_F(ValidateImage, SampleProjExplicitLodWrongResultType) {
2252   const std::string body = R"(
2253 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2254 %sampler = OpLoad %type_sampler %uniform_sampler
2255 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2256 %res1 = OpImageSampleProjExplicitLod %f32 %simg %f32vec3_hhh Lod %f32_1
2257 )";
2258 
2259   CompileSuccessfully(GenerateShaderCode(body).c_str());
2260   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2261   EXPECT_THAT(getDiagnosticString(),
2262               HasSubstr("Expected Result Type to be int or float vector type"));
2263 }
2264 
TEST_F(ValidateImage,SampleProjExplicitLodWrongNumComponentsResultType)2265 TEST_F(ValidateImage, SampleProjExplicitLodWrongNumComponentsResultType) {
2266   const std::string body = R"(
2267 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2268 %sampler = OpLoad %type_sampler %uniform_sampler
2269 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2270 %res1 = OpImageSampleProjExplicitLod %f32vec3 %simg %f32vec3_hhh Lod %f32_1
2271 )";
2272 
2273   CompileSuccessfully(GenerateShaderCode(body).c_str());
2274   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2275   EXPECT_THAT(getDiagnosticString(),
2276               HasSubstr("Expected Result Type to have 4 components"));
2277 }
2278 
TEST_F(ValidateImage,SampleProjExplicitLodNotSampledImage)2279 TEST_F(ValidateImage, SampleProjExplicitLodNotSampledImage) {
2280   const std::string body = R"(
2281 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2282 %res1 = OpImageSampleProjExplicitLod %f32vec4 %img %f32vec3_hhh Lod %f32_1
2283 )";
2284 
2285   CompileSuccessfully(GenerateShaderCode(body).c_str());
2286   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2287   EXPECT_THAT(
2288       getDiagnosticString(),
2289       HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage"));
2290 }
2291 
TEST_F(ValidateImage,SampleProjExplicitLodMultisampleError)2292 TEST_F(ValidateImage, SampleProjExplicitLodMultisampleError) {
2293   const std::string body = R"(
2294 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
2295 %sampler = OpLoad %type_sampler %uniform_sampler
2296 %simg = OpSampledImage %type_sampled_image_f32_2d_0011 %img %sampler
2297 %res1 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec2_hh Lod|Sample %f32_1 %u32_1
2298 )";
2299 
2300   CompileSuccessfully(GenerateShaderCode(body).c_str());
2301   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2302   EXPECT_THAT(getDiagnosticString(),
2303               HasSubstr("Expected Image 'MS' parameter to be 0"));
2304 }
2305 
TEST_F(ValidateImage,SampleProjExplicitLodWrongSampledType)2306 TEST_F(ValidateImage, SampleProjExplicitLodWrongSampledType) {
2307   const std::string body = R"(
2308 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2309 %sampler = OpLoad %type_sampler %uniform_sampler
2310 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2311 %res1 = OpImageSampleProjExplicitLod %u32vec4 %simg %f32vec3_hhh Lod %f32_1
2312 )";
2313 
2314   CompileSuccessfully(GenerateShaderCode(body).c_str());
2315   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2316   EXPECT_THAT(getDiagnosticString(),
2317               HasSubstr("Expected Image 'Sampled Type' to be the same as "
2318                         "Result Type components"));
2319 }
2320 
TEST_F(ValidateImage,SampleProjExplicitLodVoidSampledType)2321 TEST_F(ValidateImage, SampleProjExplicitLodVoidSampledType) {
2322   const std::string body = R"(
2323 %img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001
2324 %sampler = OpLoad %type_sampler %uniform_sampler
2325 %simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler
2326 %res1 = OpImageSampleProjExplicitLod %u32vec4 %simg %f32vec3_hhh Lod %f32_1
2327 )";
2328 
2329   CompileSuccessfully(GenerateShaderCode(body).c_str());
2330   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
2331 }
2332 
TEST_F(ValidateImage,SampleProjExplicitLodWrongCoordinateType)2333 TEST_F(ValidateImage, SampleProjExplicitLodWrongCoordinateType) {
2334   const std::string body = R"(
2335 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2336 %sampler = OpLoad %type_sampler %uniform_sampler
2337 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2338 %res1 = OpImageSampleProjExplicitLod %f32vec4 %simg %img Lod %f32_1
2339 )";
2340 
2341   CompileSuccessfully(GenerateShaderCode(body).c_str());
2342   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2343   EXPECT_THAT(getDiagnosticString(),
2344               HasSubstr("Expected Coordinate to be float scalar or vector"));
2345 }
2346 
TEST_F(ValidateImage,SampleProjExplicitLodCoordinateSizeTooSmall)2347 TEST_F(ValidateImage, SampleProjExplicitLodCoordinateSizeTooSmall) {
2348   const std::string body = R"(
2349 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2350 %sampler = OpLoad %type_sampler %uniform_sampler
2351 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2352 %res1 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec2_hh Lod %f32_1
2353 )";
2354 
2355   CompileSuccessfully(GenerateShaderCode(body).c_str());
2356   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2357   EXPECT_THAT(getDiagnosticString(),
2358               HasSubstr("Expected Coordinate to have at least 3 components, "
2359                         "but given only 2"));
2360 }
2361 
TEST_F(ValidateImage,SampleProjImplicitLodSuccess)2362 TEST_F(ValidateImage, SampleProjImplicitLodSuccess) {
2363   const std::string body = R"(
2364 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2365 %sampler = OpLoad %type_sampler %uniform_sampler
2366 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2367 %res1 = OpImageSampleProjImplicitLod %f32vec4 %simg %f32vec3_hhh
2368 %res2 = OpImageSampleProjImplicitLod %f32vec4 %simg %f32vec3_hhh Bias %f32_0_25
2369 %res4 = OpImageSampleProjImplicitLod %f32vec4 %simg %f32vec3_hhh ConstOffset %s32vec2_01
2370 %res5 = OpImageSampleProjImplicitLod %f32vec4 %simg %f32vec3_hhh Offset %s32vec2_01
2371 %res6 = OpImageSampleProjImplicitLod %f32vec4 %simg %f32vec3_hhh MinLod %f32_0_5
2372 %res7 = OpImageSampleProjImplicitLod %f32vec4 %simg %f32vec3_hhh Bias|Offset|MinLod %f32_0_25 %s32vec2_01 %f32_0_5
2373 %res8 = OpImageSampleProjImplicitLod %f32vec4 %simg %f32vec3_hhh NonPrivateTexelKHR
2374 )";
2375 
2376   const std::string extra = R"(
2377 OpCapability VulkanMemoryModelKHR
2378 OpExtension "SPV_KHR_vulkan_memory_model"
2379 )";
2380   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
2381                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
2382                           .c_str());
2383   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2384 }
2385 
TEST_F(ValidateImage,SampleProjImplicitLodWrongResultType)2386 TEST_F(ValidateImage, SampleProjImplicitLodWrongResultType) {
2387   const std::string body = R"(
2388 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2389 %sampler = OpLoad %type_sampler %uniform_sampler
2390 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2391 %res1 = OpImageSampleProjImplicitLod %f32 %simg %f32vec3_hhh
2392 )";
2393 
2394   CompileSuccessfully(GenerateShaderCode(body).c_str());
2395   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2396   EXPECT_THAT(getDiagnosticString(),
2397               HasSubstr("Expected Result Type to be int or float vector type"));
2398 }
2399 
TEST_F(ValidateImage,SampleProjImplicitLodWrongNumComponentsResultType)2400 TEST_F(ValidateImage, SampleProjImplicitLodWrongNumComponentsResultType) {
2401   const std::string body = R"(
2402 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2403 %sampler = OpLoad %type_sampler %uniform_sampler
2404 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2405 %res1 = OpImageSampleProjImplicitLod %f32vec3 %simg %f32vec3_hhh
2406 )";
2407 
2408   CompileSuccessfully(GenerateShaderCode(body).c_str());
2409   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2410   EXPECT_THAT(getDiagnosticString(),
2411               HasSubstr("Expected Result Type to have 4 components"));
2412 }
2413 
TEST_F(ValidateImage,SampleProjImplicitLodNotSampledImage)2414 TEST_F(ValidateImage, SampleProjImplicitLodNotSampledImage) {
2415   const std::string body = R"(
2416 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2417 %res1 = OpImageSampleProjImplicitLod %f32vec4 %img %f32vec3_hhh
2418 )";
2419 
2420   CompileSuccessfully(GenerateShaderCode(body).c_str());
2421   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2422   EXPECT_THAT(
2423       getDiagnosticString(),
2424       HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage"));
2425 }
2426 
TEST_F(ValidateImage,SampleProjImplicitLodMultisampleError)2427 TEST_F(ValidateImage, SampleProjImplicitLodMultisampleError) {
2428   const std::string body = R"(
2429 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
2430 %sampler = OpLoad %type_sampler %uniform_sampler
2431 %simg = OpSampledImage %type_sampled_image_f32_2d_0011 %img %sampler
2432 %res1 = OpImageSampleProjImplicitLod %f32vec4 %simg %f32vec2_hh Sample %u32_1
2433 )";
2434 
2435   CompileSuccessfully(GenerateShaderCode(body).c_str());
2436   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2437   EXPECT_THAT(getDiagnosticString(),
2438               HasSubstr("Expected Image 'MS' parameter to be 0"));
2439 }
2440 
TEST_F(ValidateImage,SampleProjImplicitLodWrongSampledType)2441 TEST_F(ValidateImage, SampleProjImplicitLodWrongSampledType) {
2442   const std::string body = R"(
2443 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2444 %sampler = OpLoad %type_sampler %uniform_sampler
2445 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2446 %res1 = OpImageSampleProjImplicitLod %u32vec4 %simg %f32vec3_hhh
2447 )";
2448 
2449   CompileSuccessfully(GenerateShaderCode(body).c_str());
2450   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2451   EXPECT_THAT(getDiagnosticString(),
2452               HasSubstr("Expected Image 'Sampled Type' to be the same as "
2453                         "Result Type components"));
2454 }
2455 
TEST_F(ValidateImage,SampleProjImplicitLodVoidSampledType)2456 TEST_F(ValidateImage, SampleProjImplicitLodVoidSampledType) {
2457   const std::string body = R"(
2458 %img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001
2459 %sampler = OpLoad %type_sampler %uniform_sampler
2460 %simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler
2461 %res1 = OpImageSampleProjImplicitLod %u32vec4 %simg %f32vec3_hhh
2462 )";
2463 
2464   CompileSuccessfully(GenerateShaderCode(body).c_str());
2465   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
2466 }
2467 
TEST_F(ValidateImage,SampleProjImplicitLodWrongCoordinateType)2468 TEST_F(ValidateImage, SampleProjImplicitLodWrongCoordinateType) {
2469   const std::string body = R"(
2470 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2471 %sampler = OpLoad %type_sampler %uniform_sampler
2472 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2473 %res1 = OpImageSampleProjImplicitLod %f32vec4 %simg %img
2474 )";
2475 
2476   CompileSuccessfully(GenerateShaderCode(body).c_str());
2477   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2478   EXPECT_THAT(getDiagnosticString(),
2479               HasSubstr("Expected Coordinate to be float scalar or vector"));
2480 }
2481 
TEST_F(ValidateImage,SampleProjImplicitLodCoordinateSizeTooSmall)2482 TEST_F(ValidateImage, SampleProjImplicitLodCoordinateSizeTooSmall) {
2483   const std::string body = R"(
2484 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2485 %sampler = OpLoad %type_sampler %uniform_sampler
2486 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2487 %res1 = OpImageSampleProjImplicitLod %f32vec4 %simg %f32vec2_hh
2488 )";
2489 
2490   CompileSuccessfully(GenerateShaderCode(body).c_str());
2491   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2492   EXPECT_THAT(getDiagnosticString(),
2493               HasSubstr("Expected Coordinate to have at least 3 components, "
2494                         "but given only 2"));
2495 }
2496 
TEST_F(ValidateImage,SampleDrefImplicitLodSuccess)2497 TEST_F(ValidateImage, SampleDrefImplicitLodSuccess) {
2498   const std::string body = R"(
2499 %img = OpLoad %type_image_u32_2d_0001 %uniform_image_u32_2d_0001
2500 %sampler = OpLoad %type_sampler %uniform_sampler
2501 %simg = OpSampledImage %type_sampled_image_u32_2d_0001 %img %sampler
2502 %res1 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec2_hh %f32_1
2503 %res2 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec2_hh %f32_1 Bias %f32_0_25
2504 %res4 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec2_hh %f32_1 ConstOffset %s32vec2_01
2505 %res5 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec2_hh %f32_1 Offset %s32vec2_01
2506 %res6 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec2_hh %f32_1 MinLod %f32_0_5
2507 %res7 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec2_hh %f32_1 Bias|Offset|MinLod %f32_0_25 %s32vec2_01 %f32_0_5
2508 %res8 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec2_hh %f32_1 NonPrivateTexelKHR
2509 )";
2510 
2511   const std::string extra = R"(
2512 OpCapability VulkanMemoryModelKHR
2513 OpExtension "SPV_KHR_vulkan_memory_model"
2514 )";
2515   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
2516                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
2517                           .c_str());
2518   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2519 }
2520 
TEST_F(ValidateImage,SampleDrefImplicitLodWrongResultType)2521 TEST_F(ValidateImage, SampleDrefImplicitLodWrongResultType) {
2522   const std::string body = R"(
2523 %img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001
2524 %sampler = OpLoad %type_sampler %uniform_sampler
2525 %simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler
2526 %res1 = OpImageSampleDrefImplicitLod %void %simg %f32vec2_hh %u32_1
2527 )";
2528 
2529   CompileSuccessfully(GenerateShaderCode(body).c_str());
2530   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2531   EXPECT_THAT(getDiagnosticString(),
2532               HasSubstr("Expected Result Type to be int or float scalar type"));
2533 }
2534 
TEST_F(ValidateImage,SampleDrefImplicitLodNotSampledImage)2535 TEST_F(ValidateImage, SampleDrefImplicitLodNotSampledImage) {
2536   const std::string body = R"(
2537 %img = OpLoad %type_image_u32_2d_0001 %uniform_image_u32_2d_0001
2538 %res1 = OpImageSampleDrefImplicitLod %u32 %img %f32vec2_hh %u32_1
2539 )";
2540 
2541   CompileSuccessfully(GenerateShaderCode(body).c_str());
2542   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2543   EXPECT_THAT(
2544       getDiagnosticString(),
2545       HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage"));
2546 }
2547 
TEST_F(ValidateImage,SampleDrefImplicitLodMultisampleError)2548 TEST_F(ValidateImage, SampleDrefImplicitLodMultisampleError) {
2549   const std::string body = R"(
2550 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
2551 %sampler = OpLoad %type_sampler %uniform_sampler
2552 %simg = OpSampledImage %type_sampled_image_f32_2d_0011 %img %sampler
2553 %res1 = OpImageSampleDrefImplicitLod %f32 %simg %f32vec2_hh %f32_1 Sample %u32_1
2554 )";
2555 
2556   CompileSuccessfully(GenerateShaderCode(body).c_str());
2557   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2558   EXPECT_THAT(
2559       getDiagnosticString(),
2560       HasSubstr("Dref sampling operation is invalid for multisample image"));
2561 }
2562 
TEST_F(ValidateImage,SampleDrefImplicitLodWrongSampledType)2563 TEST_F(ValidateImage, SampleDrefImplicitLodWrongSampledType) {
2564   const std::string body = R"(
2565 %img = OpLoad %type_image_u32_2d_0001 %uniform_image_u32_2d_0001
2566 %sampler = OpLoad %type_sampler %uniform_sampler
2567 %simg = OpSampledImage %type_sampled_image_u32_2d_0001 %img %sampler
2568 %res1 = OpImageSampleDrefImplicitLod %f32 %simg %f32vec2_00 %u32_1
2569 )";
2570 
2571   CompileSuccessfully(GenerateShaderCode(body).c_str());
2572   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2573   EXPECT_THAT(
2574       getDiagnosticString(),
2575       HasSubstr("Expected Image 'Sampled Type' to be the same as Result Type"));
2576 }
2577 
TEST_F(ValidateImage,SampleDrefImplicitLodVoidSampledType)2578 TEST_F(ValidateImage, SampleDrefImplicitLodVoidSampledType) {
2579   const std::string body = R"(
2580 %img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001
2581 %sampler = OpLoad %type_sampler %uniform_sampler
2582 %simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler
2583 %res1 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec2_00 %u32_1
2584 )";
2585 
2586   CompileSuccessfully(GenerateShaderCode(body).c_str());
2587   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2588   EXPECT_THAT(
2589       getDiagnosticString(),
2590       HasSubstr("Expected Image 'Sampled Type' to be the same as Result Type"));
2591 }
2592 
TEST_F(ValidateImage,SampleDrefImplicitLodWrongCoordinateType)2593 TEST_F(ValidateImage, SampleDrefImplicitLodWrongCoordinateType) {
2594   const std::string body = R"(
2595 %img = OpLoad %type_image_u32_2d_0001 %uniform_image_u32_2d_0001
2596 %sampler = OpLoad %type_sampler %uniform_sampler
2597 %simg = OpSampledImage %type_sampled_image_u32_2d_0001 %img %sampler
2598 %res1 = OpImageSampleDrefImplicitLod %u32 %simg %img %u32_1
2599 )";
2600 
2601   CompileSuccessfully(GenerateShaderCode(body).c_str());
2602   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2603   EXPECT_THAT(getDiagnosticString(),
2604               HasSubstr("Expected Coordinate to be float scalar or vector"));
2605 }
2606 
TEST_F(ValidateImage,SampleDrefImplicitLodCoordinateSizeTooSmall)2607 TEST_F(ValidateImage, SampleDrefImplicitLodCoordinateSizeTooSmall) {
2608   const std::string body = R"(
2609 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2610 %sampler = OpLoad %type_sampler %uniform_sampler
2611 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2612 %res1 = OpImageSampleDrefImplicitLod %f32 %simg %f32_0_5 %f32_0_5
2613 )";
2614 
2615   CompileSuccessfully(GenerateShaderCode(body).c_str());
2616   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2617   EXPECT_THAT(getDiagnosticString(),
2618               HasSubstr("Expected Coordinate to have at least 2 components, "
2619                         "but given only 1"));
2620 }
2621 
TEST_F(ValidateImage,SampleDrefImplicitLodWrongDrefType)2622 TEST_F(ValidateImage, SampleDrefImplicitLodWrongDrefType) {
2623   const std::string body = R"(
2624 %img = OpLoad %type_image_u32_2d_0001 %uniform_image_u32_2d_0001
2625 %sampler = OpLoad %type_sampler %uniform_sampler
2626 %simg = OpSampledImage %type_sampled_image_u32_2d_0001 %img %sampler
2627 %res1 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec2_00 %f64_1
2628 )";
2629 
2630   CompileSuccessfully(GenerateShaderCode(body).c_str());
2631   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2632   EXPECT_THAT(getDiagnosticString(),
2633               HasSubstr("Expected Dref to be of 32-bit float type"));
2634 }
2635 
TEST_F(ValidateImage,SampleDrefImplicitLodWrongDimVulkan)2636 TEST_F(ValidateImage, SampleDrefImplicitLodWrongDimVulkan) {
2637   const std::string body = R"(
2638 %img = OpLoad %type_image_u32_3d_0001 %uniform_image_u32_3d_0001
2639 %sampler = OpLoad %type_sampler %uniform_sampler
2640 %simg = OpSampledImage %type_sampled_image_u32_3d_0001 %img %sampler
2641 %res1 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec3_hhh %f32_1
2642 )";
2643 
2644   CompileSuccessfully(
2645       GenerateShaderCode(body, "", "Fragment", "", SPV_ENV_VULKAN_1_0).c_str());
2646   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
2647   EXPECT_THAT(getDiagnosticString(),
2648               AnyVUID("VUID-StandaloneSpirv-OpImage-04777"));
2649   EXPECT_THAT(getDiagnosticString(),
2650               HasSubstr("In Vulkan, OpImage*Dref* instructions must not use "
2651                         "images with a 3D Dim"));
2652 }
2653 
TEST_F(ValidateImage,SampleDrefExplicitLodSuccess)2654 TEST_F(ValidateImage, SampleDrefExplicitLodSuccess) {
2655   const std::string body = R"(
2656 %img = OpLoad %type_image_s32_3d_0001 %uniform_image_s32_3d_0001
2657 %sampler = OpLoad %type_sampler %uniform_sampler
2658 %simg = OpSampledImage %type_sampled_image_s32_3d_0001 %img %sampler
2659 %res1 = OpImageSampleDrefExplicitLod %s32 %simg %f32vec4_0000 %f32_1 Lod %f32_1
2660 %res3 = OpImageSampleDrefExplicitLod %s32 %simg %f32vec3_hhh %f32_1 Grad %f32vec3_hhh %f32vec3_hhh
2661 %res4 = OpImageSampleDrefExplicitLod %s32 %simg %f32vec3_hhh %f32_1 ConstOffset %s32vec3_012
2662 %res5 = OpImageSampleDrefExplicitLod %s32 %simg %f32vec4_0000 %f32_1 Offset %s32vec3_012
2663 %res7 = OpImageSampleDrefExplicitLod %s32 %simg %f32vec3_hhh %f32_1 Grad|Offset %f32vec3_hhh %f32vec3_hhh %s32vec3_012
2664 %res8 = OpImageSampleDrefExplicitLod %s32 %simg %f32vec4_0000 %f32_1 Lod|NonPrivateTexelKHR %f32_1
2665 )";
2666 
2667   const std::string extra = R"(
2668 OpCapability VulkanMemoryModelKHR
2669 OpExtension "SPV_KHR_vulkan_memory_model"
2670 )";
2671   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
2672                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
2673                           .c_str());
2674   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2675 }
2676 
TEST_F(ValidateImage,SampleDrefExplicitLodWrongResultType)2677 TEST_F(ValidateImage, SampleDrefExplicitLodWrongResultType) {
2678   const std::string body = R"(
2679 %img = OpLoad %type_image_s32_3d_0001 %uniform_image_s32_3d_0001
2680 %sampler = OpLoad %type_sampler %uniform_sampler
2681 %simg = OpSampledImage %type_sampled_image_s32_3d_0001 %img %sampler
2682 %res1 = OpImageSampleDrefExplicitLod %bool %simg %f32vec3_hhh %s32_1 Lod %f32_1
2683 )";
2684 
2685   CompileSuccessfully(GenerateShaderCode(body).c_str());
2686   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2687   EXPECT_THAT(getDiagnosticString(),
2688               HasSubstr("Expected Result Type to be int or float scalar type"));
2689 }
2690 
TEST_F(ValidateImage,SampleDrefExplicitLodNotSampledImage)2691 TEST_F(ValidateImage, SampleDrefExplicitLodNotSampledImage) {
2692   const std::string body = R"(
2693 %img = OpLoad %type_image_s32_3d_0001 %uniform_image_s32_3d_0001
2694 %res1 = OpImageSampleDrefExplicitLod %s32 %img %f32vec3_hhh %s32_1 Lod %f32_1
2695 )";
2696 
2697   CompileSuccessfully(GenerateShaderCode(body).c_str());
2698   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2699   EXPECT_THAT(
2700       getDiagnosticString(),
2701       HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage"));
2702 }
2703 
TEST_F(ValidateImage,SampleDrefExplicitLodMultisampleError)2704 TEST_F(ValidateImage, SampleDrefExplicitLodMultisampleError) {
2705   const std::string body = R"(
2706 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
2707 %sampler = OpLoad %type_sampler %uniform_sampler
2708 %simg = OpSampledImage %type_sampled_image_f32_2d_0011 %img %sampler
2709 %res1 = OpImageSampleDrefExplicitLod %f32 %simg %f32vec2_hh %f32_1 Lod|Sample %f32_1 %u32_1
2710 )";
2711 
2712   CompileSuccessfully(GenerateShaderCode(body).c_str());
2713   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2714   EXPECT_THAT(
2715       getDiagnosticString(),
2716       HasSubstr("Dref sampling operation is invalid for multisample image"));
2717 }
2718 
TEST_F(ValidateImage,SampleDrefExplicitLodWrongSampledType)2719 TEST_F(ValidateImage, SampleDrefExplicitLodWrongSampledType) {
2720   const std::string body = R"(
2721 %img = OpLoad %type_image_s32_3d_0001 %uniform_image_s32_3d_0001
2722 %sampler = OpLoad %type_sampler %uniform_sampler
2723 %simg = OpSampledImage %type_sampled_image_s32_3d_0001 %img %sampler
2724 %res1 = OpImageSampleDrefExplicitLod %f32 %simg %f32vec3_hhh %s32_1 Lod %f32_1
2725 )";
2726 
2727   CompileSuccessfully(GenerateShaderCode(body).c_str());
2728   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2729   EXPECT_THAT(
2730       getDiagnosticString(),
2731       HasSubstr("Expected Image 'Sampled Type' to be the same as Result Type"));
2732 }
2733 
TEST_F(ValidateImage,SampleDrefExplicitLodVoidSampledType)2734 TEST_F(ValidateImage, SampleDrefExplicitLodVoidSampledType) {
2735   const std::string body = R"(
2736 %img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001
2737 %sampler = OpLoad %type_sampler %uniform_sampler
2738 %simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler
2739 %res1 = OpImageSampleDrefExplicitLod %u32 %simg %f32vec2_00 %s32_1 Lod %f32_1
2740 )";
2741 
2742   CompileSuccessfully(GenerateShaderCode(body).c_str());
2743   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2744   EXPECT_THAT(
2745       getDiagnosticString(),
2746       HasSubstr("Expected Image 'Sampled Type' to be the same as Result Type"));
2747 }
2748 
TEST_F(ValidateImage,SampleDrefExplicitLodWrongCoordinateType)2749 TEST_F(ValidateImage, SampleDrefExplicitLodWrongCoordinateType) {
2750   const std::string body = R"(
2751 %img = OpLoad %type_image_s32_3d_0001 %uniform_image_s32_3d_0001
2752 %sampler = OpLoad %type_sampler %uniform_sampler
2753 %simg = OpSampledImage %type_sampled_image_s32_3d_0001 %img %sampler
2754 %res1 = OpImageSampleDrefExplicitLod %s32 %simg %img %s32_1 Lod %f32_1
2755 )";
2756 
2757   CompileSuccessfully(GenerateShaderCode(body).c_str());
2758   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2759   EXPECT_THAT(getDiagnosticString(),
2760               HasSubstr("Expected Coordinate to be float scalar or vector"));
2761 }
2762 
TEST_F(ValidateImage,SampleDrefExplicitLodCoordinateSizeTooSmall)2763 TEST_F(ValidateImage, SampleDrefExplicitLodCoordinateSizeTooSmall) {
2764   const std::string body = R"(
2765 %img = OpLoad %type_image_s32_3d_0001 %uniform_image_s32_3d_0001
2766 %sampler = OpLoad %type_sampler %uniform_sampler
2767 %simg = OpSampledImage %type_sampled_image_s32_3d_0001 %img %sampler
2768 %res1 = OpImageSampleDrefExplicitLod %s32 %simg %f32vec2_hh %s32_1 Lod %f32_1
2769 )";
2770 
2771   CompileSuccessfully(GenerateShaderCode(body).c_str());
2772   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2773   EXPECT_THAT(getDiagnosticString(),
2774               HasSubstr("Expected Coordinate to have at least 3 components, "
2775                         "but given only 2"));
2776 }
2777 
TEST_F(ValidateImage,SampleDrefExplicitLodWrongDrefType)2778 TEST_F(ValidateImage, SampleDrefExplicitLodWrongDrefType) {
2779   const std::string body = R"(
2780 %img = OpLoad %type_image_s32_3d_0001 %uniform_image_s32_3d_0001
2781 %sampler = OpLoad %type_sampler %uniform_sampler
2782 %simg = OpSampledImage %type_sampled_image_s32_3d_0001 %img %sampler
2783 %res1 = OpImageSampleDrefExplicitLod %s32 %simg %f32vec3_hhh %u32_1 Lod %f32_1
2784 )";
2785 
2786   CompileSuccessfully(GenerateShaderCode(body).c_str());
2787   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2788   EXPECT_THAT(getDiagnosticString(),
2789               HasSubstr("Expected Dref to be of 32-bit float type"));
2790 }
2791 
TEST_F(ValidateImage,SampleProjDrefImplicitLodSuccess)2792 TEST_F(ValidateImage, SampleProjDrefImplicitLodSuccess) {
2793   const std::string body = R"(
2794 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2795 %sampler = OpLoad %type_sampler %uniform_sampler
2796 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2797 %res1 = OpImageSampleProjDrefImplicitLod %f32 %simg %f32vec3_hhh %f32_0_5
2798 %res2 = OpImageSampleProjDrefImplicitLod %f32 %simg %f32vec3_hhh %f32_0_5 Bias %f32_0_25
2799 %res4 = OpImageSampleProjDrefImplicitLod %f32 %simg %f32vec3_hhh %f32_0_5 ConstOffset %s32vec2_01
2800 %res5 = OpImageSampleProjDrefImplicitLod %f32 %simg %f32vec3_hhh %f32_0_5 Offset %s32vec2_01
2801 %res6 = OpImageSampleProjDrefImplicitLod %f32 %simg %f32vec3_hhh %f32_0_5 MinLod %f32_0_5
2802 %res7 = OpImageSampleProjDrefImplicitLod %f32 %simg %f32vec3_hhh %f32_0_5 Bias|Offset|MinLod %f32_0_25 %s32vec2_01 %f32_0_5
2803 %res8 = OpImageSampleProjDrefImplicitLod %f32 %simg %f32vec3_hhh %f32_0_5 NonPrivateTexelKHR
2804 )";
2805 
2806   const std::string extra = R"(
2807 OpCapability VulkanMemoryModelKHR
2808 OpExtension "SPV_KHR_vulkan_memory_model"
2809 )";
2810   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
2811                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
2812                           .c_str());
2813   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2814 }
2815 
TEST_F(ValidateImage,SampleProjDrefImplicitLodWrongResultType)2816 TEST_F(ValidateImage, SampleProjDrefImplicitLodWrongResultType) {
2817   const std::string body = R"(
2818 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2819 %sampler = OpLoad %type_sampler %uniform_sampler
2820 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2821 %res1 = OpImageSampleProjDrefImplicitLod %void %simg %f32vec3_hhh %f32_0_5
2822 )";
2823 
2824   CompileSuccessfully(GenerateShaderCode(body).c_str());
2825   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2826   EXPECT_THAT(getDiagnosticString(),
2827               HasSubstr("Expected Result Type to be int or float scalar type"));
2828 }
2829 
TEST_F(ValidateImage,SampleProjDrefImplicitLodNotSampledImage)2830 TEST_F(ValidateImage, SampleProjDrefImplicitLodNotSampledImage) {
2831   const std::string body = R"(
2832 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2833 %res1 = OpImageSampleProjDrefImplicitLod %f32 %img %f32vec3_hhh %f32_0_5
2834 )";
2835 
2836   CompileSuccessfully(GenerateShaderCode(body).c_str());
2837   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2838   EXPECT_THAT(
2839       getDiagnosticString(),
2840       HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage"));
2841 }
2842 
TEST_F(ValidateImage,SampleProjDrefImplicitLodMultisampleError)2843 TEST_F(ValidateImage, SampleProjDrefImplicitLodMultisampleError) {
2844   const std::string body = R"(
2845 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
2846 %sampler = OpLoad %type_sampler %uniform_sampler
2847 %simg = OpSampledImage %type_sampled_image_f32_2d_0011 %img %sampler
2848 %res1 = OpImageSampleDrefExplicitLod %f32 %simg %f32vec2_hh %f32_1 Sample %u32_1
2849 )";
2850 
2851   CompileSuccessfully(GenerateShaderCode(body).c_str());
2852   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2853   EXPECT_THAT(
2854       getDiagnosticString(),
2855       HasSubstr("Dref sampling operation is invalid for multisample image"));
2856 }
2857 
TEST_F(ValidateImage,SampleProjDrefImplicitLodWrongSampledType)2858 TEST_F(ValidateImage, SampleProjDrefImplicitLodWrongSampledType) {
2859   const std::string body = R"(
2860 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2861 %sampler = OpLoad %type_sampler %uniform_sampler
2862 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2863 %res1 = OpImageSampleProjDrefImplicitLod %u32 %simg %f32vec3_hhh %f32_0_5
2864 )";
2865 
2866   CompileSuccessfully(GenerateShaderCode(body).c_str());
2867   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2868   EXPECT_THAT(
2869       getDiagnosticString(),
2870       HasSubstr("Expected Image 'Sampled Type' to be the same as Result Type"));
2871 }
2872 
TEST_F(ValidateImage,SampleProjDrefImplicitLodVoidSampledType)2873 TEST_F(ValidateImage, SampleProjDrefImplicitLodVoidSampledType) {
2874   const std::string body = R"(
2875 %img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001
2876 %sampler = OpLoad %type_sampler %uniform_sampler
2877 %simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler
2878 %res1 = OpImageSampleProjDrefImplicitLod %u32 %simg %f32vec3_hhh %f32_0_5
2879 )";
2880 
2881   CompileSuccessfully(GenerateShaderCode(body).c_str());
2882   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2883   EXPECT_THAT(
2884       getDiagnosticString(),
2885       HasSubstr("Expected Image 'Sampled Type' to be the same as Result Type"));
2886 }
2887 
TEST_F(ValidateImage,SampleProjDrefImplicitLodWrongCoordinateType)2888 TEST_F(ValidateImage, SampleProjDrefImplicitLodWrongCoordinateType) {
2889   const std::string body = R"(
2890 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2891 %sampler = OpLoad %type_sampler %uniform_sampler
2892 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2893 %res1 = OpImageSampleProjDrefImplicitLod %f32 %simg %img %f32_0_5
2894 )";
2895 
2896   CompileSuccessfully(GenerateShaderCode(body).c_str());
2897   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2898   EXPECT_THAT(getDiagnosticString(),
2899               HasSubstr("Expected Coordinate to be float scalar or vector"));
2900 }
2901 
TEST_F(ValidateImage,SampleProjDrefImplicitLodCoordinateSizeTooSmall)2902 TEST_F(ValidateImage, SampleProjDrefImplicitLodCoordinateSizeTooSmall) {
2903   const std::string body = R"(
2904 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2905 %sampler = OpLoad %type_sampler %uniform_sampler
2906 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2907 %res1 = OpImageSampleProjDrefImplicitLod %f32 %simg %f32vec2_hh %f32_0_5
2908 )";
2909 
2910   CompileSuccessfully(GenerateShaderCode(body).c_str());
2911   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2912   EXPECT_THAT(getDiagnosticString(),
2913               HasSubstr("Expected Coordinate to have at least 3 components, "
2914                         "but given only 2"));
2915 }
2916 
TEST_F(ValidateImage,SampleProjDrefImplicitLodWrongDrefType)2917 TEST_F(ValidateImage, SampleProjDrefImplicitLodWrongDrefType) {
2918   const std::string body = R"(
2919 %img = OpLoad %type_image_u32_2d_0001 %uniform_image_u32_2d_0001
2920 %sampler = OpLoad %type_sampler %uniform_sampler
2921 %simg = OpSampledImage %type_sampled_image_u32_2d_0001 %img %sampler
2922 %res1 = OpImageSampleProjDrefImplicitLod %u32 %simg %f32vec3_hhh %f32vec4_0000
2923 )";
2924 
2925   CompileSuccessfully(GenerateShaderCode(body).c_str());
2926   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2927   EXPECT_THAT(getDiagnosticString(),
2928               HasSubstr("Expected Dref to be of 32-bit float type"));
2929 }
2930 
TEST_F(ValidateImage,SampleProjDrefExplicitLodSuccess)2931 TEST_F(ValidateImage, SampleProjDrefExplicitLodSuccess) {
2932   const std::string body = R"(
2933 %img = OpLoad %type_image_f32_1d_0001 %uniform_image_f32_1d_0001
2934 %sampler = OpLoad %type_sampler %uniform_sampler
2935 %simg = OpSampledImage %type_sampled_image_f32_1d_0001 %img %sampler
2936 %res1 = OpImageSampleProjDrefExplicitLod %f32 %simg %f32vec2_hh %f32_0_5 Lod %f32_1
2937 %res2 = OpImageSampleProjDrefExplicitLod %f32 %simg %f32vec3_hhh %f32_0_5 Grad %f32_0_5 %f32_0_5
2938 %res3 = OpImageSampleProjDrefExplicitLod %f32 %simg %f32vec2_hh %f32_0_5 ConstOffset %s32_1
2939 %res4 = OpImageSampleProjDrefExplicitLod %f32 %simg %f32vec2_hh %f32_0_5 Offset %s32_1
2940 %res5 = OpImageSampleProjDrefExplicitLod %f32 %simg %f32vec2_hh %f32_0_5 Grad|Offset %f32_0_5 %f32_0_5 %s32_1
2941 %res6 = OpImageSampleProjDrefExplicitLod %f32 %simg %f32vec2_hh %f32_0_5 Lod|NonPrivateTexelKHR %f32_1
2942 )";
2943 
2944   const std::string extra = R"(
2945 OpCapability VulkanMemoryModelKHR
2946 OpExtension "SPV_KHR_vulkan_memory_model"
2947 )";
2948   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
2949                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
2950                           .c_str());
2951   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2952 }
2953 
TEST_F(ValidateImage,SampleProjDrefExplicitLodWrongResultType)2954 TEST_F(ValidateImage, SampleProjDrefExplicitLodWrongResultType) {
2955   const std::string body = R"(
2956 %img = OpLoad %type_image_f32_1d_0001 %uniform_image_f32_1d_0001
2957 %sampler = OpLoad %type_sampler %uniform_sampler
2958 %simg = OpSampledImage %type_sampled_image_f32_1d_0001 %img %sampler
2959 %res1 = OpImageSampleProjDrefExplicitLod %bool %simg %f32vec2_hh %f32_0_5 Lod %f32_1
2960 )";
2961 
2962   CompileSuccessfully(GenerateShaderCode(body).c_str());
2963   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2964   EXPECT_THAT(getDiagnosticString(),
2965               HasSubstr("Expected Result Type to be int or float scalar type"));
2966 }
2967 
TEST_F(ValidateImage,SampleProjDrefExplicitLodNotSampledImage)2968 TEST_F(ValidateImage, SampleProjDrefExplicitLodNotSampledImage) {
2969   const std::string body = R"(
2970 %img = OpLoad %type_image_f32_1d_0001 %uniform_image_f32_1d_0001
2971 %res1 = OpImageSampleProjDrefExplicitLod %f32 %img %f32vec2_hh %f32_0_5 Lod %f32_1
2972 )";
2973 
2974   CompileSuccessfully(GenerateShaderCode(body).c_str());
2975   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2976   EXPECT_THAT(
2977       getDiagnosticString(),
2978       HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage"));
2979 }
2980 
TEST_F(ValidateImage,SampleProjDrefExplicitLodMultisampleError)2981 TEST_F(ValidateImage, SampleProjDrefExplicitLodMultisampleError) {
2982   const std::string body = R"(
2983 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
2984 %sampler = OpLoad %type_sampler %uniform_sampler
2985 %simg = OpSampledImage %type_sampled_image_f32_2d_0011 %img %sampler
2986 %res1 = OpImageSampleDrefExplicitLod %f32 %simg %f32vec2_hh %f32_1 Lod|Sample %f32_1 %u32_1
2987 )";
2988 
2989   CompileSuccessfully(GenerateShaderCode(body).c_str());
2990   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2991   EXPECT_THAT(
2992       getDiagnosticString(),
2993       HasSubstr("Dref sampling operation is invalid for multisample image"));
2994 }
2995 
TEST_F(ValidateImage,SampleProjDrefExplicitLodWrongSampledType)2996 TEST_F(ValidateImage, SampleProjDrefExplicitLodWrongSampledType) {
2997   const std::string body = R"(
2998 %img = OpLoad %type_image_f32_1d_0001 %uniform_image_f32_1d_0001
2999 %sampler = OpLoad %type_sampler %uniform_sampler
3000 %simg = OpSampledImage %type_sampled_image_f32_1d_0001 %img %sampler
3001 %res1 = OpImageSampleProjDrefExplicitLod %u32 %simg %f32vec2_hh %f32_0_5 Lod %f32_1
3002 )";
3003 
3004   CompileSuccessfully(GenerateShaderCode(body).c_str());
3005   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3006   EXPECT_THAT(
3007       getDiagnosticString(),
3008       HasSubstr("Expected Image 'Sampled Type' to be the same as Result Type"));
3009 }
3010 
TEST_F(ValidateImage,SampleProjDrefExplicitLodVoidSampledType)3011 TEST_F(ValidateImage, SampleProjDrefExplicitLodVoidSampledType) {
3012   const std::string body = R"(
3013 %img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001
3014 %sampler = OpLoad %type_sampler %uniform_sampler
3015 %simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler
3016 %res1 = OpImageSampleProjDrefExplicitLod %u32 %simg %f32vec3_hhh %f32_0_5 Lod %f32_1
3017 )";
3018 
3019   CompileSuccessfully(GenerateShaderCode(body).c_str());
3020   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3021   EXPECT_THAT(
3022       getDiagnosticString(),
3023       HasSubstr("Expected Image 'Sampled Type' to be the same as Result Type"));
3024 }
3025 
TEST_F(ValidateImage,SampleProjDrefExplicitLodWrongCoordinateType)3026 TEST_F(ValidateImage, SampleProjDrefExplicitLodWrongCoordinateType) {
3027   const std::string body = R"(
3028 %img = OpLoad %type_image_f32_1d_0001 %uniform_image_f32_1d_0001
3029 %sampler = OpLoad %type_sampler %uniform_sampler
3030 %simg = OpSampledImage %type_sampled_image_f32_1d_0001 %img %sampler
3031 %res1 = OpImageSampleProjDrefExplicitLod %f32 %simg %img %f32_0_5 Lod %f32_1
3032 )";
3033 
3034   CompileSuccessfully(GenerateShaderCode(body).c_str());
3035   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3036   EXPECT_THAT(getDiagnosticString(),
3037               HasSubstr("Expected Coordinate to be float scalar or vector"));
3038 }
3039 
TEST_F(ValidateImage,SampleProjDrefExplicitLodCoordinateSizeTooSmall)3040 TEST_F(ValidateImage, SampleProjDrefExplicitLodCoordinateSizeTooSmall) {
3041   const std::string body = R"(
3042 %img = OpLoad %type_image_f32_1d_0001 %uniform_image_f32_1d_0001
3043 %sampler = OpLoad %type_sampler %uniform_sampler
3044 %simg = OpSampledImage %type_sampled_image_f32_1d_0001 %img %sampler
3045 %res1 = OpImageSampleProjDrefExplicitLod %f32 %simg %f32_0_5 %f32_0_5 Lod %f32_1
3046 )";
3047 
3048   CompileSuccessfully(GenerateShaderCode(body).c_str());
3049   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3050   EXPECT_THAT(getDiagnosticString(),
3051               HasSubstr("Expected Coordinate to have at least 2 components, "
3052                         "but given only 1"));
3053 }
3054 
TEST_F(ValidateImage,FetchSuccess)3055 TEST_F(ValidateImage, FetchSuccess) {
3056   const std::string body = R"(
3057 %img = OpLoad %type_image_f32_1d_0001 %uniform_image_f32_1d_0001
3058 %res1 = OpImageFetch %f32vec4 %img %u32vec2_01
3059 %res2 = OpImageFetch %f32vec4 %img %u32vec2_01 NonPrivateTexelKHR
3060 )";
3061 
3062   const std::string extra = R"(
3063 OpCapability VulkanMemoryModelKHR
3064 OpExtension "SPV_KHR_vulkan_memory_model"
3065 )";
3066   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
3067                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
3068                           .c_str());
3069   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
3070 }
3071 
TEST_F(ValidateImage,FetchMultisampledSuccess)3072 TEST_F(ValidateImage, FetchMultisampledSuccess) {
3073   const std::string body = R"(
3074 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
3075 %res1 = OpImageFetch %f32vec4 %img %u32vec2_01 Sample %u32_1
3076 %res2 = OpImageFetch %f32vec4 %img %u32vec2_01 Sample|NonPrivateTexelKHR %u32_1
3077 )";
3078 
3079   const std::string extra = R"(
3080 OpCapability VulkanMemoryModelKHR
3081 OpExtension "SPV_KHR_vulkan_memory_model"
3082 )";
3083   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
3084                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
3085                           .c_str());
3086   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
3087 }
3088 
TEST_F(ValidateImage,FetchWrongResultType)3089 TEST_F(ValidateImage, FetchWrongResultType) {
3090   const std::string body = R"(
3091 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
3092 %res1 = OpImageFetch %f32 %img %u32vec2_01
3093 )";
3094 
3095   CompileSuccessfully(GenerateShaderCode(body).c_str());
3096   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3097   EXPECT_THAT(getDiagnosticString(),
3098               HasSubstr("Expected Result Type to be int or float vector type"));
3099 }
3100 
TEST_F(ValidateImage,FetchWrongNumComponentsResultType)3101 TEST_F(ValidateImage, FetchWrongNumComponentsResultType) {
3102   const std::string body = R"(
3103 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
3104 %res1 = OpImageFetch %f32vec3 %img %u32vec2_01
3105 )";
3106 
3107   CompileSuccessfully(GenerateShaderCode(body).c_str());
3108   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3109   EXPECT_THAT(getDiagnosticString(),
3110               HasSubstr("Expected Result Type to have 4 components"));
3111 }
3112 
TEST_F(ValidateImage,FetchNotImage)3113 TEST_F(ValidateImage, FetchNotImage) {
3114   const std::string body = R"(
3115 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3116 %sampler = OpLoad %type_sampler %uniform_sampler
3117 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3118 %res1 = OpImageFetch %f32vec4 %sampler %u32vec2_01
3119 )";
3120 
3121   CompileSuccessfully(GenerateShaderCode(body).c_str());
3122   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3123   EXPECT_THAT(getDiagnosticString(),
3124               HasSubstr("Expected Image to be of type OpTypeImage"));
3125 }
3126 
TEST_F(ValidateImage,FetchSampledImageDirectly)3127 TEST_F(ValidateImage, FetchSampledImageDirectly) {
3128   const std::string body = R"(
3129 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3130 %sampler = OpLoad %type_sampler %uniform_sampler
3131 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3132 %res1 = OpImageFetch %f32vec4 %simg %u32vec2_01
3133 )";
3134 
3135   CompileSuccessfully(GenerateShaderCode(body).c_str());
3136   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3137   EXPECT_THAT(getDiagnosticString(),
3138               HasSubstr("OpSampledImage instruction must not appear as operand "
3139                         "for OpImageFetch"));
3140 }
3141 
TEST_F(ValidateImage,FetchNotSampled)3142 TEST_F(ValidateImage, FetchNotSampled) {
3143   const std::string body = R"(
3144 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
3145 %res1 = OpImageFetch %u32vec4 %img %u32vec2_01
3146 )";
3147 
3148   CompileSuccessfully(GenerateShaderCode(body).c_str());
3149   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3150   EXPECT_THAT(getDiagnosticString(),
3151               HasSubstr("Expected Image 'Sampled' parameter to be 1"));
3152 }
3153 
TEST_F(ValidateImage,FetchCube)3154 TEST_F(ValidateImage, FetchCube) {
3155   const std::string body = R"(
3156 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
3157 %res1 = OpImageFetch %f32vec4 %img %u32vec3_012
3158 )";
3159 
3160   CompileSuccessfully(GenerateShaderCode(body).c_str());
3161   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3162   EXPECT_THAT(getDiagnosticString(), HasSubstr("Image 'Dim' cannot be Cube"));
3163 }
3164 
TEST_F(ValidateImage,FetchWrongSampledType)3165 TEST_F(ValidateImage, FetchWrongSampledType) {
3166   const std::string body = R"(
3167 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
3168 %res1 = OpImageFetch %u32vec4 %img %u32vec2_01
3169 )";
3170 
3171   CompileSuccessfully(GenerateShaderCode(body).c_str());
3172   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3173   EXPECT_THAT(getDiagnosticString(),
3174               HasSubstr("Expected Image 'Sampled Type' to be the same as "
3175                         "Result Type components"));
3176 }
3177 
TEST_F(ValidateImage,FetchVoidSampledType)3178 TEST_F(ValidateImage, FetchVoidSampledType) {
3179   const std::string body = R"(
3180 %img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001
3181 %res1 = OpImageFetch %f32vec4 %img %u32vec2_01
3182 %res2 = OpImageFetch %u32vec4 %img %u32vec2_01
3183 %res3 = OpImageFetch %s32vec4 %img %u32vec2_01
3184 )";
3185 
3186   CompileSuccessfully(GenerateShaderCode(body).c_str());
3187   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3188 }
3189 
TEST_F(ValidateImage,FetchWrongCoordinateType)3190 TEST_F(ValidateImage, FetchWrongCoordinateType) {
3191   const std::string body = R"(
3192 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
3193 %res1 = OpImageFetch %f32vec4 %img %f32vec2_00
3194 )";
3195 
3196   CompileSuccessfully(GenerateShaderCode(body).c_str());
3197   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3198   EXPECT_THAT(getDiagnosticString(),
3199               HasSubstr("Expected Coordinate to be int scalar or vector"));
3200 }
3201 
TEST_F(ValidateImage,FetchCoordinateSizeTooSmall)3202 TEST_F(ValidateImage, FetchCoordinateSizeTooSmall) {
3203   const std::string body = R"(
3204 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
3205 %res1 = OpImageFetch %f32vec4 %img %u32_1
3206 )";
3207 
3208   CompileSuccessfully(GenerateShaderCode(body).c_str());
3209   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3210   EXPECT_THAT(getDiagnosticString(),
3211               HasSubstr("Expected Coordinate to have at least 2 components, "
3212                         "but given only 1"));
3213 }
3214 
TEST_F(ValidateImage,FetchLodNotInt)3215 TEST_F(ValidateImage, FetchLodNotInt) {
3216   const std::string body = R"(
3217 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3218 %res1 = OpImageFetch %f32vec4 %img %u32vec2_01 Lod %f32_1
3219 )";
3220 
3221   CompileSuccessfully(GenerateShaderCode(body).c_str());
3222   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3223   EXPECT_THAT(getDiagnosticString(),
3224               HasSubstr("Expected Image Operand Lod to be int scalar when used "
3225                         "with OpImageFetch"));
3226 }
3227 
TEST_F(ValidateImage,FetchMultisampledMissingSample)3228 TEST_F(ValidateImage, FetchMultisampledMissingSample) {
3229   const std::string body = R"(
3230 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
3231 %res1 = OpImageFetch %f32vec4 %img %u32vec2_01
3232 )";
3233 
3234   CompileSuccessfully(GenerateShaderCode(body).c_str());
3235   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions())
3236       << GenerateShaderCode(body);
3237   EXPECT_THAT(getDiagnosticString(),
3238               HasSubstr("Image Operand Sample is required for operation on "
3239                         "multi-sampled image"))
3240       << getDiagnosticString();
3241 }
3242 
TEST_F(ValidateImage,GatherSuccess)3243 TEST_F(ValidateImage, GatherSuccess) {
3244   const std::string body = R"(
3245 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3246 %sampler = OpLoad %type_sampler %uniform_sampler
3247 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3248 %res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1
3249 %res2 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 ConstOffsets %const_offsets
3250 %res3 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 NonPrivateTexelKHR
3251 )";
3252 
3253   const std::string extra = R"(
3254 OpCapability VulkanMemoryModelKHR
3255 OpExtension "SPV_KHR_vulkan_memory_model"
3256 )";
3257   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
3258                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
3259                           .c_str());
3260   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
3261 }
3262 
TEST_F(ValidateImage,GatherWrongResultType)3263 TEST_F(ValidateImage, GatherWrongResultType) {
3264   const std::string body = R"(
3265 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
3266 %sampler = OpLoad %type_sampler %uniform_sampler
3267 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
3268 %res1 = OpImageGather %f32 %simg %f32vec4_0000 %u32_1
3269 )";
3270 
3271   CompileSuccessfully(GenerateShaderCode(body).c_str());
3272   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3273   EXPECT_THAT(getDiagnosticString(),
3274               HasSubstr("Expected Result Type to be int or float vector type"));
3275 }
3276 
TEST_F(ValidateImage,GatherWrongNumComponentsResultType)3277 TEST_F(ValidateImage, GatherWrongNumComponentsResultType) {
3278   const std::string body = R"(
3279 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
3280 %sampler = OpLoad %type_sampler %uniform_sampler
3281 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
3282 %res1 = OpImageGather %f32vec3 %simg %f32vec4_0000 %u32_1
3283 )";
3284 
3285   CompileSuccessfully(GenerateShaderCode(body).c_str());
3286   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3287   EXPECT_THAT(getDiagnosticString(),
3288               HasSubstr("Expected Result Type to have 4 components"));
3289 }
3290 
TEST_F(ValidateImage,GatherNotSampledImage)3291 TEST_F(ValidateImage, GatherNotSampledImage) {
3292   const std::string body = R"(
3293 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
3294 %res1 = OpImageGather %f32vec4 %img %f32vec4_0000 %u32_1
3295 )";
3296 
3297   CompileSuccessfully(GenerateShaderCode(body).c_str());
3298   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3299   EXPECT_THAT(
3300       getDiagnosticString(),
3301       HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage"));
3302 }
3303 
TEST_F(ValidateImage,GatherMultisampleError)3304 TEST_F(ValidateImage, GatherMultisampleError) {
3305   const std::string body = R"(
3306 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
3307 %sampler = OpLoad %type_sampler %uniform_sampler
3308 %simg = OpSampledImage %type_sampled_image_f32_2d_0011 %img %sampler
3309 %res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 Sample %u32_1
3310 )";
3311 
3312   CompileSuccessfully(GenerateShaderCode(body).c_str());
3313   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3314   EXPECT_THAT(getDiagnosticString(),
3315               HasSubstr("Gather operation is invalid for multisample image"));
3316 }
3317 
TEST_F(ValidateImage,GatherWrongSampledType)3318 TEST_F(ValidateImage, GatherWrongSampledType) {
3319   const std::string body = R"(
3320 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
3321 %sampler = OpLoad %type_sampler %uniform_sampler
3322 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
3323 %res1 = OpImageGather %u32vec4 %simg %f32vec4_0000 %u32_1
3324 )";
3325 
3326   CompileSuccessfully(GenerateShaderCode(body).c_str());
3327   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3328   EXPECT_THAT(getDiagnosticString(),
3329               HasSubstr("Expected Image 'Sampled Type' to be the same as "
3330                         "Result Type components"));
3331 }
3332 
TEST_F(ValidateImage,GatherVoidSampledType)3333 TEST_F(ValidateImage, GatherVoidSampledType) {
3334   const std::string body = R"(
3335 %img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001
3336 %sampler = OpLoad %type_sampler %uniform_sampler
3337 %simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler
3338 %res1 = OpImageGather %u32vec4 %simg %f32vec2_00 %u32_1
3339 )";
3340 
3341   CompileSuccessfully(GenerateShaderCode(body).c_str());
3342   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3343 }
3344 
TEST_F(ValidateImage,GatherWrongCoordinateType)3345 TEST_F(ValidateImage, GatherWrongCoordinateType) {
3346   const std::string body = R"(
3347 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
3348 %sampler = OpLoad %type_sampler %uniform_sampler
3349 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
3350 %res1 = OpImageGather %f32vec4 %simg %u32vec4_0123 %u32_1
3351 )";
3352 
3353   CompileSuccessfully(GenerateShaderCode(body).c_str());
3354   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3355   EXPECT_THAT(getDiagnosticString(),
3356               HasSubstr("Expected Coordinate to be float scalar or vector"));
3357 }
3358 
TEST_F(ValidateImage,GatherCoordinateSizeTooSmall)3359 TEST_F(ValidateImage, GatherCoordinateSizeTooSmall) {
3360   const std::string body = R"(
3361 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
3362 %sampler = OpLoad %type_sampler %uniform_sampler
3363 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
3364 %res1 = OpImageGather %f32vec4 %simg %f32_0_5 %u32_1
3365 )";
3366 
3367   CompileSuccessfully(GenerateShaderCode(body).c_str());
3368   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3369   EXPECT_THAT(getDiagnosticString(),
3370               HasSubstr("Expected Coordinate to have at least 4 components, "
3371                         "but given only 1"));
3372 }
3373 
TEST_F(ValidateImage,GatherWrongComponentType)3374 TEST_F(ValidateImage, GatherWrongComponentType) {
3375   const std::string body = R"(
3376 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
3377 %sampler = OpLoad %type_sampler %uniform_sampler
3378 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
3379 %res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %f32_1
3380 )";
3381 
3382   CompileSuccessfully(GenerateShaderCode(body).c_str());
3383   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3384   EXPECT_THAT(getDiagnosticString(),
3385               HasSubstr("Expected Component to be 32-bit int scalar"));
3386 }
3387 
TEST_F(ValidateImage,GatherComponentNot32Bit)3388 TEST_F(ValidateImage, GatherComponentNot32Bit) {
3389   const std::string body = R"(
3390 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
3391 %sampler = OpLoad %type_sampler %uniform_sampler
3392 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
3393 %res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u64_0
3394 )";
3395 
3396   CompileSuccessfully(GenerateShaderCode(body).c_str());
3397   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3398   EXPECT_THAT(getDiagnosticString(),
3399               HasSubstr("Expected Component to be 32-bit int scalar"));
3400 }
3401 
TEST_F(ValidateImage,GatherComponentSuccessVulkan)3402 TEST_F(ValidateImage, GatherComponentSuccessVulkan) {
3403   const std::string body = R"(
3404 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
3405 %sampler = OpLoad %type_sampler %uniform_sampler
3406 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
3407 %res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_0
3408 )";
3409 
3410   spv_target_env env = SPV_ENV_VULKAN_1_0;
3411   CompileSuccessfully(GenerateShaderCode(body, "", "Fragment", "", env).c_str(),
3412                       env);
3413   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(env));
3414 }
3415 
TEST_F(ValidateImage,GatherComponentNotConstantVulkan)3416 TEST_F(ValidateImage, GatherComponentNotConstantVulkan) {
3417   const std::string body = R"(
3418 %input_u32 = OpLoad %u32 %input_flat_u32
3419 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
3420 %sampler = OpLoad %type_sampler %uniform_sampler
3421 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
3422 %res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %input_u32
3423 )";
3424 
3425   spv_target_env env = SPV_ENV_VULKAN_1_0;
3426   CompileSuccessfully(GenerateShaderCode(body, "", "Fragment", "", env).c_str(),
3427                       env);
3428   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
3429   EXPECT_THAT(getDiagnosticString(),
3430               AnyVUID("VUID-StandaloneSpirv-OpImageGather-04664"));
3431   EXPECT_THAT(getDiagnosticString(),
3432               HasSubstr("Expected Component Operand to be a const object for "
3433                         "Vulkan environment"));
3434 }
3435 
TEST_F(ValidateImage,GatherDimCube)3436 TEST_F(ValidateImage, GatherDimCube) {
3437   const std::string body = R"(
3438 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
3439 %sampler = OpLoad %type_sampler %uniform_sampler
3440 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
3441 %res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 ConstOffsets %const_offsets
3442 )";
3443 
3444   CompileSuccessfully(GenerateShaderCode(body).c_str());
3445   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3446   EXPECT_THAT(
3447       getDiagnosticString(),
3448       HasSubstr(
3449           "Image Operand ConstOffsets cannot be used with Cube Image 'Dim'"));
3450 }
3451 
TEST_F(ValidateImage,GatherConstOffsetsNotArray)3452 TEST_F(ValidateImage, GatherConstOffsetsNotArray) {
3453   const std::string body = R"(
3454 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3455 %sampler = OpLoad %type_sampler %uniform_sampler
3456 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3457 %res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 ConstOffsets %u32vec4_0123
3458 )";
3459 
3460   CompileSuccessfully(GenerateShaderCode(body).c_str());
3461   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3462   EXPECT_THAT(
3463       getDiagnosticString(),
3464       HasSubstr(
3465           "Expected Image Operand ConstOffsets to be an array of size 4"));
3466 }
3467 
TEST_F(ValidateImage,GatherConstOffsetsArrayWrongSize)3468 TEST_F(ValidateImage, GatherConstOffsetsArrayWrongSize) {
3469   const std::string body = R"(
3470 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3471 %sampler = OpLoad %type_sampler %uniform_sampler
3472 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3473 %res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 ConstOffsets %const_offsets3x2
3474 )";
3475 
3476   CompileSuccessfully(GenerateShaderCode(body).c_str());
3477   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3478   EXPECT_THAT(
3479       getDiagnosticString(),
3480       HasSubstr(
3481           "Expected Image Operand ConstOffsets to be an array of size 4"));
3482 }
3483 
TEST_F(ValidateImage,GatherConstOffsetsArrayNotVector)3484 TEST_F(ValidateImage, GatherConstOffsetsArrayNotVector) {
3485   const std::string body = R"(
3486 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3487 %sampler = OpLoad %type_sampler %uniform_sampler
3488 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3489 %res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 ConstOffsets %const_offsets4xu
3490 )";
3491 
3492   CompileSuccessfully(GenerateShaderCode(body).c_str());
3493   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3494   EXPECT_THAT(getDiagnosticString(),
3495               HasSubstr("Expected Image Operand ConstOffsets array components "
3496                         "to be int vectors of size 2"));
3497 }
3498 
TEST_F(ValidateImage,GatherConstOffsetsArrayVectorWrongSize)3499 TEST_F(ValidateImage, GatherConstOffsetsArrayVectorWrongSize) {
3500   const std::string body = R"(
3501 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3502 %sampler = OpLoad %type_sampler %uniform_sampler
3503 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3504 %res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 ConstOffsets %const_offsets4x3
3505 )";
3506 
3507   CompileSuccessfully(GenerateShaderCode(body).c_str());
3508   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3509   EXPECT_THAT(getDiagnosticString(),
3510               HasSubstr("Expected Image Operand ConstOffsets array components "
3511                         "to be int vectors of size 2"));
3512 }
3513 
TEST_F(ValidateImage,GatherConstOffsetsArrayNotConst)3514 TEST_F(ValidateImage, GatherConstOffsetsArrayNotConst) {
3515   const std::string body = R"(
3516 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3517 %sampler = OpLoad %type_sampler %uniform_sampler
3518 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3519 %offsets = OpUndef %u32vec2arr4
3520 %res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 ConstOffsets %offsets
3521 )";
3522 
3523   CompileSuccessfully(GenerateShaderCode(body).c_str());
3524   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3525   EXPECT_THAT(
3526       getDiagnosticString(),
3527       HasSubstr("Expected Image Operand ConstOffsets to be a const object"));
3528 }
3529 
TEST_F(ValidateImage,NotGatherWithConstOffsets)3530 TEST_F(ValidateImage, NotGatherWithConstOffsets) {
3531   const std::string body = R"(
3532 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3533 %sampler = OpLoad %type_sampler %uniform_sampler
3534 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3535 %res2 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh ConstOffsets %const_offsets
3536 )";
3537 
3538   CompileSuccessfully(GenerateShaderCode(body).c_str());
3539   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3540   EXPECT_THAT(
3541       getDiagnosticString(),
3542       HasSubstr(
3543           "Image Operand ConstOffsets can only be used with OpImageGather "
3544           "and OpImageDrefGather"));
3545 }
3546 
TEST_F(ValidateImage,DrefGatherSuccess)3547 TEST_F(ValidateImage, DrefGatherSuccess) {
3548   const std::string body = R"(
3549 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3550 %sampler = OpLoad %type_sampler %uniform_sampler
3551 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3552 %res1 = OpImageDrefGather %f32vec4 %simg %f32vec4_0000 %f32_0_5
3553 %res2 = OpImageDrefGather %f32vec4 %simg %f32vec4_0000 %f32_0_5 ConstOffsets %const_offsets
3554 %res3 = OpImageDrefGather %f32vec4 %simg %f32vec4_0000 %f32_0_5 NonPrivateTexelKHR
3555 )";
3556 
3557   const std::string extra = R"(
3558 OpCapability VulkanMemoryModelKHR
3559 OpExtension "SPV_KHR_vulkan_memory_model"
3560 )";
3561   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
3562                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
3563                           .c_str());
3564   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
3565 }
3566 
TEST_F(ValidateImage,DrefGatherMultisampleError)3567 TEST_F(ValidateImage, DrefGatherMultisampleError) {
3568   const std::string body = R"(
3569 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
3570 %sampler = OpLoad %type_sampler %uniform_sampler
3571 %simg = OpSampledImage %type_sampled_image_f32_2d_0011 %img %sampler
3572 %res1 = OpImageDrefGather %f32vec4 %simg %f32vec4_0000 %f32_1 Sample %u32_1
3573 )";
3574 
3575   CompileSuccessfully(GenerateShaderCode(body).c_str());
3576   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3577   EXPECT_THAT(getDiagnosticString(),
3578               HasSubstr("Gather operation is invalid for multisample image"));
3579 }
3580 
TEST_F(ValidateImage,DrefGatherVoidSampledType)3581 TEST_F(ValidateImage, DrefGatherVoidSampledType) {
3582   const std::string body = R"(
3583 %img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001
3584 %sampler = OpLoad %type_sampler %uniform_sampler
3585 %simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler
3586 %res1 = OpImageDrefGather %u32vec4 %simg %f32vec2_00 %f32_0_5
3587 )";
3588 
3589   CompileSuccessfully(GenerateShaderCode(body).c_str());
3590   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3591   EXPECT_THAT(getDiagnosticString(),
3592               HasSubstr("Expected Image 'Sampled Type' to be the same as "
3593                         "Result Type components"));
3594 }
3595 
TEST_F(ValidateImage,DrefGatherWrongDrefType)3596 TEST_F(ValidateImage, DrefGatherWrongDrefType) {
3597   const std::string body = R"(
3598 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
3599 %sampler = OpLoad %type_sampler %uniform_sampler
3600 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
3601 %res1 = OpImageDrefGather %f32vec4 %simg %f32vec4_0000 %u32_1
3602 )";
3603 
3604   CompileSuccessfully(GenerateShaderCode(body).c_str());
3605   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3606   EXPECT_THAT(getDiagnosticString(),
3607               HasSubstr("Expected Dref to be of 32-bit float type"));
3608 }
3609 
TEST_F(ValidateImage,DrefGatherWrongDimVulkan)3610 TEST_F(ValidateImage, DrefGatherWrongDimVulkan) {
3611   const std::string body = R"(
3612 %img = OpLoad %type_image_f32_3d_0001 %uniform_image_f32_3d_0001
3613 %sampler = OpLoad %type_sampler %uniform_sampler
3614 %simg = OpSampledImage %type_sampled_image_f32_3d_0001 %img %sampler
3615 %res1 = OpImageDrefGather %f32vec4 %simg %f32vec4_0000 %f32_0_5
3616 )";
3617 
3618   CompileSuccessfully(
3619       GenerateShaderCode(body, "", "Fragment", "", SPV_ENV_VULKAN_1_0).c_str());
3620   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
3621   EXPECT_THAT(getDiagnosticString(),
3622               AnyVUID("VUID-StandaloneSpirv-OpImage-04777"));
3623   EXPECT_THAT(getDiagnosticString(),
3624               HasSubstr("Expected Image 'Dim' to be 2D, Cube, or Rect"));
3625 }
3626 
TEST_F(ValidateImage,ReadSuccess1)3627 TEST_F(ValidateImage, ReadSuccess1) {
3628   const std::string body = R"(
3629 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
3630 %res1 = OpImageRead %u32vec4 %img %u32vec2_01
3631 )";
3632 
3633   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
3634   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3635   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3636 }
3637 
TEST_F(ValidateImage,ReadSuccess2)3638 TEST_F(ValidateImage, ReadSuccess2) {
3639   const std::string body = R"(
3640 %img = OpLoad %type_image_f32_1d_0002_rgba32f %uniform_image_f32_1d_0002_rgba32f
3641 %res1 = OpImageRead %f32vec4 %img %u32vec2_01
3642 )";
3643 
3644   const std::string extra = "\nOpCapability Image1D\n";
3645   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3646   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3647 }
3648 
TEST_F(ValidateImage,ReadSuccess3)3649 TEST_F(ValidateImage, ReadSuccess3) {
3650   const std::string body = R"(
3651 %img = OpLoad %type_image_f32_cube_0102_rgba32f %uniform_image_f32_cube_0102_rgba32f
3652 %res1 = OpImageRead %f32vec4 %img %u32vec3_012
3653 )";
3654 
3655   const std::string extra = "\nOpCapability ImageCubeArray\n";
3656   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3657   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3658 }
3659 
TEST_F(ValidateImage,ReadSuccess4)3660 TEST_F(ValidateImage, ReadSuccess4) {
3661   const std::string body = R"(
3662 %img = OpLoad %type_image_f32_spd_0002 %uniform_image_f32_spd_0002
3663 %res1 = OpImageRead %f32vec4 %img %u32vec2_01
3664 )";
3665 
3666   CompileSuccessfully(GenerateShaderCode(body).c_str());
3667   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3668 }
3669 
TEST_F(ValidateImage,ReadNeedCapabilityStorageImageReadWithoutFormat)3670 TEST_F(ValidateImage, ReadNeedCapabilityStorageImageReadWithoutFormat) {
3671   const std::string body = R"(
3672 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
3673 %res1 = OpImageRead %u32vec4 %img %u32vec2_01
3674 )";
3675 
3676   CompileSuccessfully(GenerateShaderCode(body).c_str());
3677   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3678 }
3679 
TEST_F(ValidateImage,ReadNeedCapabilityStorageImageReadWithoutFormatVulkan)3680 TEST_F(ValidateImage, ReadNeedCapabilityStorageImageReadWithoutFormatVulkan) {
3681   const std::string body = R"(
3682 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
3683 %res1 = OpImageRead %u32vec4 %img %u32vec2_01
3684 )";
3685 
3686   spv_target_env env = SPV_ENV_VULKAN_1_0;
3687   CompileSuccessfully(GenerateShaderCode(body, "", "Fragment", "", env).c_str(),
3688                       env);
3689   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
3690   EXPECT_THAT(getDiagnosticString(),
3691               HasSubstr("Capability StorageImageReadWithoutFormat is required "
3692                         "to read storage image"));
3693 }
3694 
TEST_F(ValidateImage,ReadNeedCapabilityImage1D)3695 TEST_F(ValidateImage, ReadNeedCapabilityImage1D) {
3696   const std::string body = R"(
3697 %img = OpLoad %type_image_f32_1d_0002_rgba32f %uniform_image_f32_1d_0002_rgba32f
3698 %res1 = OpImageRead %f32vec4 %img %u32vec2_01
3699 )";
3700 
3701   CompileSuccessfully(GenerateShaderCode(body).c_str());
3702   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3703   EXPECT_THAT(
3704       getDiagnosticString(),
3705       HasSubstr("Capability Image1D is required to access storage image"));
3706 }
3707 
TEST_F(ValidateImage,ReadNeedCapabilityImageCubeArray)3708 TEST_F(ValidateImage, ReadNeedCapabilityImageCubeArray) {
3709   const std::string body = R"(
3710 %img = OpLoad %type_image_f32_cube_0102_rgba32f %uniform_image_f32_cube_0102_rgba32f
3711 %res1 = OpImageRead %f32vec4 %img %u32vec3_012
3712 )";
3713 
3714   CompileSuccessfully(GenerateShaderCode(body).c_str());
3715   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3716   EXPECT_THAT(
3717       getDiagnosticString(),
3718       HasSubstr(
3719           "Capability ImageCubeArray is required to access storage image"));
3720 }
3721 
3722 // TODO([email protected]) Disabled until the spec is clarified.
TEST_F(ValidateImage,DISABLED_ReadWrongResultType)3723 TEST_F(ValidateImage, DISABLED_ReadWrongResultType) {
3724   const std::string body = R"(
3725 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
3726 %res1 = OpImageRead %f32 %img %u32vec2_01
3727 )";
3728 
3729   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
3730   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3731   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3732   EXPECT_THAT(getDiagnosticString(),
3733               HasSubstr("Expected Result Type to be int or float vector type"));
3734 }
3735 
TEST_F(ValidateImage,ReadScalarResultType_Universal)3736 TEST_F(ValidateImage, ReadScalarResultType_Universal) {
3737   const std::string body = R"(
3738 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
3739 %res1 = OpImageRead %u32 %img %u32vec2_01
3740 )";
3741 
3742   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
3743   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3744   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_0));
3745   EXPECT_THAT(getDiagnosticString(), Eq(""));
3746 }
3747 
TEST_F(ValidateImage,ReadUnusualNumComponentsResultType_Universal)3748 TEST_F(ValidateImage, ReadUnusualNumComponentsResultType_Universal) {
3749   const std::string body = R"(
3750 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
3751 %res1 = OpImageRead %u32vec3 %img %u32vec2_01
3752 )";
3753 
3754   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
3755   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3756   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_0));
3757   EXPECT_THAT(getDiagnosticString(), Eq(""));
3758 }
3759 
TEST_F(ValidateImage,ReadWrongNumComponentsResultType_Vulkan)3760 TEST_F(ValidateImage, ReadWrongNumComponentsResultType_Vulkan) {
3761   const std::string body = R"(
3762 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
3763 %res1 = OpImageRead %u32vec3 %img %u32vec2_01
3764 )";
3765 
3766   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
3767   CompileSuccessfully(
3768       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_VULKAN_1_0)
3769           .c_str());
3770   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
3771   EXPECT_THAT(getDiagnosticString(),
3772               AnyVUID("VUID-StandaloneSpirv-Result-04780"));
3773   EXPECT_THAT(getDiagnosticString(),
3774               HasSubstr("Expected Result Type to have 4 components"));
3775 }
3776 
TEST_F(ValidateImage,ReadNotImage)3777 TEST_F(ValidateImage, ReadNotImage) {
3778   const std::string body = R"(
3779 %sampler = OpLoad %type_sampler %uniform_sampler
3780 %res1 = OpImageRead %f32vec4 %sampler %u32vec2_01
3781 )";
3782 
3783   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
3784   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3785   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3786   EXPECT_THAT(getDiagnosticString(),
3787               HasSubstr("Expected Image to be of type OpTypeImage"));
3788 }
3789 
TEST_F(ValidateImage,ReadImageSampled)3790 TEST_F(ValidateImage, ReadImageSampled) {
3791   const std::string body = R"(
3792 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3793 %res1 = OpImageRead %f32vec4 %img %u32vec2_01
3794 )";
3795 
3796   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
3797   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3798   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3799   EXPECT_THAT(getDiagnosticString(),
3800               HasSubstr("Expected Image 'Sampled' parameter to be 0 or 2"));
3801 }
3802 
TEST_F(ValidateImage,ReadWrongSampledType)3803 TEST_F(ValidateImage, ReadWrongSampledType) {
3804   const std::string body = R"(
3805 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
3806 %res1 = OpImageRead %f32vec4 %img %u32vec2_01
3807 )";
3808 
3809   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
3810   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3811   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3812   EXPECT_THAT(getDiagnosticString(),
3813               HasSubstr("Expected Image 'Sampled Type' to be the same as "
3814                         "Result Type components"));
3815 }
3816 
TEST_F(ValidateImage,ReadVoidSampledType)3817 TEST_F(ValidateImage, ReadVoidSampledType) {
3818   const std::string body = R"(
3819 %img = OpLoad %type_image_void_2d_0002 %uniform_image_void_2d_0002
3820 %res1 = OpImageRead %f32vec4 %img %u32vec2_01
3821 %res2 = OpImageRead %u32vec4 %img %u32vec2_01
3822 %res3 = OpImageRead %s32vec4 %img %u32vec2_01
3823 )";
3824 
3825   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
3826   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3827   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3828 }
3829 
TEST_F(ValidateImage,ReadWrongCoordinateType)3830 TEST_F(ValidateImage, ReadWrongCoordinateType) {
3831   const std::string body = R"(
3832 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
3833 %res1 = OpImageRead %u32vec4 %img %f32vec2_00
3834 )";
3835 
3836   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
3837   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3838   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3839   EXPECT_THAT(getDiagnosticString(),
3840               HasSubstr("Expected Coordinate to be int scalar or vector"));
3841 }
3842 
TEST_F(ValidateImage,ReadCoordinateSizeTooSmall)3843 TEST_F(ValidateImage, ReadCoordinateSizeTooSmall) {
3844   const std::string body = R"(
3845 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
3846 %res1 = OpImageRead %u32vec4 %img %u32_1
3847 )";
3848 
3849   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
3850   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3851   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3852   EXPECT_THAT(getDiagnosticString(),
3853               HasSubstr("Expected Coordinate to have at least 2 components, "
3854                         "but given only 1"));
3855 }
3856 
TEST_F(ValidateImage,WriteSuccess1)3857 TEST_F(ValidateImage, WriteSuccess1) {
3858   const std::string body = R"(
3859 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
3860 OpImageWrite %img %u32vec2_01 %u32vec4_0123
3861 )";
3862 
3863   const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n";
3864   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3865   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3866 }
3867 
TEST_F(ValidateImage,WriteSuccess2)3868 TEST_F(ValidateImage, WriteSuccess2) {
3869   const std::string body = R"(
3870 %img = OpLoad %type_image_f32_1d_0002_rgba32f %uniform_image_f32_1d_0002_rgba32f
3871 OpImageWrite %img %u32_1 %f32vec4_0000
3872 )";
3873 
3874   const std::string extra = "\nOpCapability Image1D\n";
3875   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3876   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3877 }
3878 
TEST_F(ValidateImage,WriteSuccess3)3879 TEST_F(ValidateImage, WriteSuccess3) {
3880   const std::string body = R"(
3881 %img = OpLoad %type_image_f32_cube_0102_rgba32f %uniform_image_f32_cube_0102_rgba32f
3882 OpImageWrite %img %u32vec3_012 %f32vec4_0000
3883 )";
3884 
3885   const std::string extra = "\nOpCapability ImageCubeArray\n";
3886   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3887   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3888 }
3889 
TEST_F(ValidateImage,WriteSuccess4)3890 TEST_F(ValidateImage, WriteSuccess4) {
3891   const std::string body = R"(
3892 %img = OpLoad %type_image_f32_2d_0012 %uniform_image_f32_2d_0012
3893 OpImageWrite %img %u32vec2_01 %f32vec4_0000 Sample %u32_1
3894 )";
3895 
3896   const std::string extra = R"(
3897     OpCapability StorageImageWriteWithoutFormat
3898     OpCapability StorageImageMultisample
3899     )";
3900 
3901   const std::string declarations = R"(
3902 %type_image_f32_2d_0012 = OpTypeImage %f32 2D 0 0 1 2 Unknown
3903 %ptr_image_f32_2d_0012 = OpTypePointer UniformConstant %type_image_f32_2d_0012
3904 %uniform_image_f32_2d_0012 = OpVariable %ptr_image_f32_2d_0012 UniformConstant
3905     )";
3906   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
3907                                          SPV_ENV_UNIVERSAL_1_0, "GLSL450",
3908                                          declarations)
3909                           .c_str());
3910   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3911 }
3912 
TEST_F(ValidateImage,WriteSubpassData)3913 TEST_F(ValidateImage, WriteSubpassData) {
3914   const std::string body = R"(
3915 %img = OpLoad %type_image_f32_spd_0002 %uniform_image_f32_spd_0002
3916 OpImageWrite %img %u32vec2_01 %f32vec4_0000
3917 )";
3918 
3919   CompileSuccessfully(GenerateShaderCode(body).c_str());
3920   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3921   EXPECT_THAT(getDiagnosticString(),
3922               HasSubstr("Image 'Dim' cannot be SubpassData"));
3923 }
3924 
TEST_F(ValidateImage,WriteNeedCapabilityStorageImageWriteWithoutFormat)3925 TEST_F(ValidateImage, WriteNeedCapabilityStorageImageWriteWithoutFormat) {
3926   const std::string body = R"(
3927 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
3928 OpImageWrite %img %u32vec2_01 %u32vec4_0123
3929 )";
3930 
3931   CompileSuccessfully(GenerateShaderCode(body).c_str());
3932   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3933 }
3934 
TEST_F(ValidateImage,WriteNeedCapabilityStorageImageWriteWithoutFormatVulkan)3935 TEST_F(ValidateImage, WriteNeedCapabilityStorageImageWriteWithoutFormatVulkan) {
3936   const std::string body = R"(
3937 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
3938 OpImageWrite %img %u32vec2_01 %u32vec4_0123
3939 )";
3940 
3941   spv_target_env env = SPV_ENV_VULKAN_1_0;
3942   CompileSuccessfully(GenerateShaderCode(body, "", "Fragment", "", env).c_str(),
3943                       env);
3944   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
3945   EXPECT_THAT(
3946       getDiagnosticString(),
3947       HasSubstr(
3948           "Capability StorageImageWriteWithoutFormat is required to write to "
3949           "storage image"));
3950 }
3951 
TEST_F(ValidateImage,WriteNeedCapabilityImage1D)3952 TEST_F(ValidateImage, WriteNeedCapabilityImage1D) {
3953   const std::string body = R"(
3954 %img = OpLoad %type_image_f32_1d_0002_rgba32f %uniform_image_f32_1d_0002_rgba32f
3955 OpImageWrite %img %u32vec2_01 %f32vec4_0000
3956 )";
3957 
3958   CompileSuccessfully(GenerateShaderCode(body).c_str());
3959   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3960   EXPECT_THAT(getDiagnosticString(),
3961               HasSubstr("Capability Image1D is required to access storage "
3962                         "image"));
3963 }
3964 
TEST_F(ValidateImage,WriteNeedCapabilityImageCubeArray)3965 TEST_F(ValidateImage, WriteNeedCapabilityImageCubeArray) {
3966   const std::string body = R"(
3967 %img = OpLoad %type_image_f32_cube_0102_rgba32f %uniform_image_f32_cube_0102_rgba32f
3968 OpImageWrite %img %u32vec3_012 %f32vec4_0000
3969 )";
3970 
3971   CompileSuccessfully(GenerateShaderCode(body).c_str());
3972   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3973   EXPECT_THAT(
3974       getDiagnosticString(),
3975       HasSubstr(
3976           "Capability ImageCubeArray is required to access storage image"));
3977 }
3978 
TEST_F(ValidateImage,WriteNotImage)3979 TEST_F(ValidateImage, WriteNotImage) {
3980   const std::string body = R"(
3981 %sampler = OpLoad %type_sampler %uniform_sampler
3982 OpImageWrite %sampler %u32vec2_01 %f32vec4_0000
3983 )";
3984 
3985   CompileSuccessfully(GenerateShaderCode(body).c_str());
3986   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3987   EXPECT_THAT(getDiagnosticString(),
3988               HasSubstr("Expected Image to be of type OpTypeImage"));
3989 }
3990 
TEST_F(ValidateImage,WriteImageSampled)3991 TEST_F(ValidateImage, WriteImageSampled) {
3992   const std::string body = R"(
3993 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3994 OpImageWrite %img %u32vec2_01 %f32vec4_0000
3995 )";
3996 
3997   const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n";
3998   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3999   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4000   EXPECT_THAT(getDiagnosticString(),
4001               HasSubstr("Expected Image 'Sampled' parameter to be 0 or 2"));
4002 }
4003 
TEST_F(ValidateImage,WriteWrongCoordinateType)4004 TEST_F(ValidateImage, WriteWrongCoordinateType) {
4005   const std::string body = R"(
4006 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
4007 OpImageWrite %img %f32vec2_00 %u32vec4_0123
4008 )";
4009 
4010   const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n";
4011   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
4012   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4013   EXPECT_THAT(getDiagnosticString(),
4014               HasSubstr("Expected Coordinate to be int scalar or vector"));
4015 }
4016 
TEST_F(ValidateImage,WriteCoordinateSizeTooSmall)4017 TEST_F(ValidateImage, WriteCoordinateSizeTooSmall) {
4018   const std::string body = R"(
4019 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
4020 OpImageWrite %img %u32_1 %u32vec4_0123
4021 )";
4022 
4023   const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n";
4024   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
4025   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4026   EXPECT_THAT(getDiagnosticString(),
4027               HasSubstr("Expected Coordinate to have at least 2 components, "
4028                         "but given only 1"));
4029 }
4030 
TEST_F(ValidateImage,WriteTexelScalarSuccess)4031 TEST_F(ValidateImage, WriteTexelScalarSuccess) {
4032   const std::string body = R"(
4033 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
4034 OpImageWrite %img %u32vec2_01 %u32_2
4035 )";
4036 
4037   const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n";
4038   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
4039   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
4040 }
4041 
TEST_F(ValidateImage,WriteTexelWrongType)4042 TEST_F(ValidateImage, WriteTexelWrongType) {
4043   const std::string body = R"(
4044 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
4045 OpImageWrite %img %u32vec2_01 %img
4046 )";
4047 
4048   const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n";
4049   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
4050   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4051   EXPECT_THAT(getDiagnosticString(),
4052               HasSubstr("Expected Texel to be int or float vector or scalar"));
4053 }
4054 
TEST_F(ValidateImage,WriteTexelNonNumericalType)4055 TEST_F(ValidateImage, WriteTexelNonNumericalType) {
4056   const std::string body = R"(
4057 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
4058 OpImageWrite %img %u32vec2_01 %boolvec4_tttt
4059 )";
4060 
4061   const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n";
4062   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
4063   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4064   EXPECT_THAT(getDiagnosticString(),
4065               HasSubstr("Expected Texel to be int or float vector or scalar"));
4066 }
4067 
TEST_F(ValidateImage,WriteTexelWrongComponentType)4068 TEST_F(ValidateImage, WriteTexelWrongComponentType) {
4069   const std::string body = R"(
4070 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
4071 OpImageWrite %img %u32vec2_01 %f32vec4_0000
4072 )";
4073 
4074   const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n";
4075   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
4076   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4077   EXPECT_THAT(
4078       getDiagnosticString(),
4079       HasSubstr(
4080           "Expected Image 'Sampled Type' to be the same as Texel components"));
4081 }
4082 
TEST_F(ValidateImage,WriteSampleNotInteger)4083 TEST_F(ValidateImage, WriteSampleNotInteger) {
4084   const std::string body = R"(
4085 %img = OpLoad %type_image_f32_2d_0012 %uniform_image_f32_2d_0012
4086 OpImageWrite %img %u32vec2_01 %f32vec4_0000 Sample %f32_1
4087 )";
4088 
4089   const std::string extra = R"(
4090     OpCapability StorageImageWriteWithoutFormat
4091     OpCapability StorageImageMultisample
4092     )";
4093   const std::string declarations = R"(
4094 %type_image_f32_2d_0012 = OpTypeImage %f32 2D 0 0 1 2 Unknown
4095 %ptr_image_f32_2d_0012 = OpTypePointer UniformConstant %type_image_f32_2d_0012
4096 %uniform_image_f32_2d_0012 = OpVariable %ptr_image_f32_2d_0012 UniformConstant
4097     )";
4098   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
4099                                          SPV_ENV_UNIVERSAL_1_0, "GLSL450",
4100                                          declarations)
4101                           .c_str());
4102   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4103   EXPECT_THAT(getDiagnosticString(),
4104               HasSubstr("Expected Image Operand Sample to be int scalar"));
4105 }
4106 
TEST_F(ValidateImage,WriteSampleNotMultisampled)4107 TEST_F(ValidateImage, WriteSampleNotMultisampled) {
4108   const std::string body = R"(
4109 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
4110 OpImageWrite %img %u32vec2_01 %f32vec4_0000 Sample %u32_1
4111 )";
4112 
4113   const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n";
4114   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
4115   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4116   EXPECT_THAT(
4117       getDiagnosticString(),
4118       HasSubstr("Image Operand Sample requires non-zero 'MS' parameter"));
4119 }
4120 
TEST_F(ValidateImage,SampleWrongOpcode)4121 TEST_F(ValidateImage, SampleWrongOpcode) {
4122   const std::string body = R"(
4123 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
4124 %sampler = OpLoad %type_sampler %uniform_sampler
4125 %simg = OpSampledImage %type_sampled_image_f32_2d_0011 %img %sampler
4126 %res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_00 Sample %u32_1
4127 )";
4128 
4129   CompileSuccessfully(GenerateShaderCode(body).c_str());
4130   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4131   EXPECT_THAT(getDiagnosticString(),
4132               HasSubstr("Sampling operation is invalid for multisample image"));
4133 }
4134 
TEST_F(ValidateImage,SampleImageToImageSuccess)4135 TEST_F(ValidateImage, SampleImageToImageSuccess) {
4136   const std::string body = R"(
4137 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4138 %sampler = OpLoad %type_sampler %uniform_sampler
4139 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4140 %img2 = OpImage %type_image_f32_2d_0001 %simg
4141 )";
4142 
4143   CompileSuccessfully(GenerateShaderCode(body).c_str());
4144   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
4145 }
4146 
TEST_F(ValidateImage,SampleImageToImageWrongResultType)4147 TEST_F(ValidateImage, SampleImageToImageWrongResultType) {
4148   const std::string body = R"(
4149 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4150 %sampler = OpLoad %type_sampler %uniform_sampler
4151 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4152 %img2 = OpImage %type_sampled_image_f32_2d_0001 %simg
4153 )";
4154 
4155   CompileSuccessfully(GenerateShaderCode(body).c_str());
4156   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4157   EXPECT_THAT(getDiagnosticString(),
4158               HasSubstr("Expected Result Type to be OpTypeImage"));
4159 }
4160 
TEST_F(ValidateImage,SampleImageToImageNotSampledImage)4161 TEST_F(ValidateImage, SampleImageToImageNotSampledImage) {
4162   const std::string body = R"(
4163 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4164 %img2 = OpImage %type_image_f32_2d_0001 %img
4165 )";
4166 
4167   CompileSuccessfully(GenerateShaderCode(body).c_str());
4168   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4169   EXPECT_THAT(
4170       getDiagnosticString(),
4171       HasSubstr("Expected Sample Image to be of type OpTypeSampleImage"));
4172 }
4173 
TEST_F(ValidateImage,SampleImageToImageNotTheSameImageType)4174 TEST_F(ValidateImage, SampleImageToImageNotTheSameImageType) {
4175   const std::string body = R"(
4176 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4177 %sampler = OpLoad %type_sampler %uniform_sampler
4178 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4179 %img2 = OpImage %type_image_f32_2d_0002 %simg
4180 )";
4181 
4182   CompileSuccessfully(GenerateShaderCode(body).c_str());
4183   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4184   EXPECT_THAT(getDiagnosticString(),
4185               HasSubstr("Expected Sample Image image type to be equal to "
4186                         "Result Type"));
4187 }
4188 
TEST_F(ValidateImage,QueryFormatSuccess)4189 TEST_F(ValidateImage, QueryFormatSuccess) {
4190   const std::string body = R"(
4191 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4192 %res1 = OpImageQueryFormat %u32 %img
4193 )";
4194 
4195   CompileSuccessfully(GenerateKernelCode(body).c_str());
4196   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
4197 }
4198 
TEST_F(ValidateImage,QueryFormatWrongResultType)4199 TEST_F(ValidateImage, QueryFormatWrongResultType) {
4200   const std::string body = R"(
4201 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4202 %res1 = OpImageQueryFormat %bool %img
4203 )";
4204 
4205   CompileSuccessfully(GenerateKernelCode(body).c_str());
4206   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4207   EXPECT_THAT(getDiagnosticString(),
4208               HasSubstr("Expected Result Type to be int scalar type"));
4209 }
4210 
TEST_F(ValidateImage,QueryFormatNotImage)4211 TEST_F(ValidateImage, QueryFormatNotImage) {
4212   const std::string body = R"(
4213 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4214 %sampler = OpLoad %type_sampler %uniform_sampler
4215 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4216 %res1 = OpImageQueryFormat %u32 %sampler
4217 )";
4218 
4219   CompileSuccessfully(GenerateKernelCode(body).c_str());
4220   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4221   EXPECT_THAT(getDiagnosticString(),
4222               HasSubstr("Expected operand to be of type OpTypeImage"));
4223 }
4224 
TEST_F(ValidateImage,QueryOrderSuccess)4225 TEST_F(ValidateImage, QueryOrderSuccess) {
4226   const std::string body = R"(
4227 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4228 %res1 = OpImageQueryOrder %u32 %img
4229 )";
4230 
4231   CompileSuccessfully(GenerateKernelCode(body).c_str());
4232   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
4233 }
4234 
TEST_F(ValidateImage,QueryOrderWrongResultType)4235 TEST_F(ValidateImage, QueryOrderWrongResultType) {
4236   const std::string body = R"(
4237 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4238 %res1 = OpImageQueryOrder %bool %img
4239 )";
4240 
4241   CompileSuccessfully(GenerateKernelCode(body).c_str());
4242   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4243   EXPECT_THAT(getDiagnosticString(),
4244               HasSubstr("Expected Result Type to be int scalar type"));
4245 }
4246 
TEST_F(ValidateImage,QueryOrderNotImage)4247 TEST_F(ValidateImage, QueryOrderNotImage) {
4248   const std::string body = R"(
4249 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4250 %sampler = OpLoad %type_sampler %uniform_sampler
4251 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4252 %res1 = OpImageQueryOrder %u32 %sampler
4253 )";
4254 
4255   CompileSuccessfully(GenerateKernelCode(body).c_str());
4256   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4257   EXPECT_THAT(getDiagnosticString(),
4258               HasSubstr("Expected operand to be of type OpTypeImage"));
4259 }
4260 
TEST_F(ValidateImage,QuerySizeLodSuccess)4261 TEST_F(ValidateImage, QuerySizeLodSuccess) {
4262   const std::string body = R"(
4263 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4264 %res1 = OpImageQuerySizeLod %u32vec2 %img %u32_1
4265 )";
4266 
4267   CompileSuccessfully(GenerateKernelCode(body).c_str());
4268   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
4269 }
4270 
TEST_F(ValidateImage,QuerySizeLodWrongResultType)4271 TEST_F(ValidateImage, QuerySizeLodWrongResultType) {
4272   const std::string body = R"(
4273 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4274 %res1 = OpImageQuerySizeLod %f32vec2 %img %u32_1
4275 )";
4276 
4277   CompileSuccessfully(GenerateKernelCode(body).c_str());
4278   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4279   EXPECT_THAT(
4280       getDiagnosticString(),
4281       HasSubstr("Expected Result Type to be int scalar or vector type"));
4282 }
4283 
TEST_F(ValidateImage,QuerySizeLodResultTypeWrongSize)4284 TEST_F(ValidateImage, QuerySizeLodResultTypeWrongSize) {
4285   const std::string body = R"(
4286 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4287 %res1 = OpImageQuerySizeLod %u32 %img %u32_1
4288 )";
4289 
4290   CompileSuccessfully(GenerateKernelCode(body).c_str());
4291   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4292   EXPECT_THAT(getDiagnosticString(),
4293               HasSubstr("Result Type has 1 components, but 2 expected"));
4294 }
4295 
TEST_F(ValidateImage,QuerySizeLodNotImage)4296 TEST_F(ValidateImage, QuerySizeLodNotImage) {
4297   const std::string body = R"(
4298 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4299 %sampler = OpLoad %type_sampler %uniform_sampler
4300 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4301 %res1 = OpImageQuerySizeLod %u32vec2 %sampler %u32_1
4302 )";
4303 
4304   CompileSuccessfully(GenerateKernelCode(body).c_str());
4305   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4306   EXPECT_THAT(getDiagnosticString(),
4307               HasSubstr("Expected Image to be of type OpTypeImage"));
4308 }
4309 
TEST_F(ValidateImage,QuerySizeLodSampledImageDirectly)4310 TEST_F(ValidateImage, QuerySizeLodSampledImageDirectly) {
4311   const std::string body = R"(
4312 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4313 %sampler = OpLoad %type_sampler %uniform_sampler
4314 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4315 %res1 = OpImageQuerySizeLod %u32vec2 %simg %u32_1
4316 )";
4317 
4318   CompileSuccessfully(GenerateShaderCode(body).c_str());
4319   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4320   EXPECT_THAT(getDiagnosticString(),
4321               HasSubstr("OpSampledImage instruction must not appear as operand "
4322                         "for OpImageQuerySizeLod"));
4323 }
4324 
TEST_F(ValidateImage,QuerySizeLodMultisampledError)4325 TEST_F(ValidateImage, QuerySizeLodMultisampledError) {
4326   const std::string body = R"(
4327 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
4328 %res1 = OpImageQuerySizeLod %u32vec2 %img %u32_1
4329 )";
4330 
4331   CompileSuccessfully(GenerateKernelCode(body).c_str());
4332   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4333   EXPECT_THAT(getDiagnosticString(), HasSubstr("Image 'MS' must be 0"));
4334 }
4335 
TEST_F(ValidateImage,QuerySizeLodNonSampledUniversalSuccess)4336 TEST_F(ValidateImage, QuerySizeLodNonSampledUniversalSuccess) {
4337   const std::string body = R"(
4338 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
4339 %res1 = OpImageQuerySizeLod %u32vec2 %img %u32_1
4340 )";
4341 
4342   CompileSuccessfully(GenerateShaderCode(body).c_str());
4343   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
4344   EXPECT_EQ(getDiagnosticString(), "");
4345 }
4346 
TEST_F(ValidateImage,QuerySizeLodVulkanNonSampledError)4347 TEST_F(ValidateImage, QuerySizeLodVulkanNonSampledError) {
4348   // Create a whole shader module.  Avoid Vulkan incompatibility with
4349   // SampledRrect images inserted by helper function GenerateShaderCode.
4350   const std::string body = R"(
4351 OpCapability Shader
4352 OpCapability ImageQuery
4353 OpMemoryModel Logical Simple
4354 OpEntryPoint Fragment %main "main"
4355 OpExecutionMode %main OriginUpperLeft
4356 
4357 %f32 = OpTypeFloat 32
4358 %u32 = OpTypeInt 32 0
4359 %u32_0 = OpConstant %u32 0
4360 %u32vec2 = OpTypeVector %u32 2
4361 %void = OpTypeVoid
4362 %voidfn = OpTypeFunction %void
4363 
4364 ; Test with a storage image.
4365 %type_image_f32_2d_0002 = OpTypeImage %f32 2D 0 0 0 2 Rgba32f
4366 %ptr_image_f32_2d_0002 = OpTypePointer UniformConstant %type_image_f32_2d_0002
4367 %uniform_image_f32_2d_0002 = OpVariable %ptr_image_f32_2d_0002 UniformConstant
4368 
4369 %main = OpFunction %void None %voidfn
4370 %entry = OpLabel
4371 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
4372 %res1 = OpImageQuerySizeLod %u32vec2 %img %u32_0
4373 OpReturn
4374 OpFunctionEnd
4375 )";
4376 
4377   CompileSuccessfully(body.c_str());
4378   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
4379   EXPECT_THAT(getDiagnosticString(),
4380               AnyVUID("VUID-StandaloneSpirv-OpImageQuerySizeLod-04659"));
4381   EXPECT_THAT(
4382       getDiagnosticString(),
4383       HasSubstr(
4384           "OpImageQuerySizeLod must only consume an \"Image\" operand whose "
4385           "type has its \"Sampled\" operand set to 1"));
4386 }
4387 
TEST_F(ValidateImage,QuerySizeLodWrongImageDim)4388 TEST_F(ValidateImage, QuerySizeLodWrongImageDim) {
4389   const std::string body = R"(
4390 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
4391 %res1 = OpImageQuerySizeLod %u32vec2 %img %u32_1
4392 )";
4393 
4394   CompileSuccessfully(GenerateKernelCode(body).c_str());
4395   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4396   EXPECT_THAT(getDiagnosticString(),
4397               HasSubstr("Image 'Dim' must be 1D, 2D, 3D or Cube"));
4398 }
4399 
TEST_F(ValidateImage,QuerySizeLodWrongLodType)4400 TEST_F(ValidateImage, QuerySizeLodWrongLodType) {
4401   const std::string body = R"(
4402 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4403 %res1 = OpImageQuerySizeLod %u32vec2 %img %f32_0
4404 )";
4405 
4406   CompileSuccessfully(GenerateKernelCode(body).c_str());
4407   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4408   EXPECT_THAT(getDiagnosticString(),
4409               HasSubstr("Expected Level of Detail to be int scalar"));
4410 }
4411 
TEST_F(ValidateImage,QuerySizeSuccess)4412 TEST_F(ValidateImage, QuerySizeSuccess) {
4413   const std::string body = R"(
4414 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
4415 %res1 = OpImageQuerySize %u32vec2 %img
4416 )";
4417 
4418   CompileSuccessfully(GenerateKernelCode(body).c_str());
4419   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
4420 }
4421 
TEST_F(ValidateImage,QuerySizeWrongResultType)4422 TEST_F(ValidateImage, QuerySizeWrongResultType) {
4423   const std::string body = R"(
4424 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
4425 %res1 = OpImageQuerySize %f32vec2 %img
4426 )";
4427 
4428   CompileSuccessfully(GenerateKernelCode(body).c_str());
4429   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4430   EXPECT_THAT(
4431       getDiagnosticString(),
4432       HasSubstr("Expected Result Type to be int scalar or vector type"));
4433 }
4434 
TEST_F(ValidateImage,QuerySizeNotImage)4435 TEST_F(ValidateImage, QuerySizeNotImage) {
4436   const std::string body = R"(
4437 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
4438 %sampler = OpLoad %type_sampler %uniform_sampler
4439 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4440 %res1 = OpImageQuerySize %u32vec2 %sampler
4441 )";
4442 
4443   CompileSuccessfully(GenerateKernelCode(body).c_str());
4444   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4445   EXPECT_THAT(getDiagnosticString(),
4446               HasSubstr("Expected Image to be of type OpTypeImage"));
4447 }
4448 
TEST_F(ValidateImage,QuerySizeSampledImageDirectly)4449 TEST_F(ValidateImage, QuerySizeSampledImageDirectly) {
4450   const std::string body = R"(
4451 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
4452 %sampler = OpLoad %type_sampler %uniform_sampler
4453 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4454 %res1 = OpImageQuerySize %u32vec2 %simg
4455 )";
4456 
4457   CompileSuccessfully(GenerateShaderCode(body).c_str());
4458   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4459   EXPECT_THAT(getDiagnosticString(),
4460               HasSubstr("OpSampledImage instruction must not appear as operand "
4461                         "for OpImageQuerySize"));
4462 }
4463 
TEST_F(ValidateImage,QuerySizeDimSubpassDataBad)4464 TEST_F(ValidateImage, QuerySizeDimSubpassDataBad) {
4465   const std::string body = R"(
4466 %img = OpLoad %type_image_f32_spd_0002 %uniform_image_f32_spd_0002
4467 %res1 = OpImageQuerySize %u32vec2 %img
4468 )";
4469 
4470   CompileSuccessfully(GenerateShaderCode(body).c_str());
4471   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4472   EXPECT_THAT(
4473       getDiagnosticString(),
4474       HasSubstr("Image 'Dim' must be 1D, Buffer, 2D, Cube, 3D or Rect"));
4475 }
4476 
TEST_F(ValidateImage,QuerySizeWrongSampling)4477 TEST_F(ValidateImage, QuerySizeWrongSampling) {
4478   const std::string body = R"(
4479 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4480 %res1 = OpImageQuerySize %u32vec2 %img
4481 )";
4482 
4483   CompileSuccessfully(GenerateKernelCode(body).c_str());
4484   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4485   EXPECT_THAT(
4486       getDiagnosticString(),
4487       HasSubstr("Image must have either 'MS'=1 or 'Sampled'=0 or 'Sampled'=2"));
4488 }
4489 
TEST_F(ValidateImage,QuerySizeWrongNumberOfComponents)4490 TEST_F(ValidateImage, QuerySizeWrongNumberOfComponents) {
4491   const std::string body = R"(
4492 %img = OpLoad %type_image_f32_3d_0111 %uniform_image_f32_3d_0111
4493 %res1 = OpImageQuerySize %u32vec2 %img
4494 )";
4495 
4496   CompileSuccessfully(GenerateShaderCode(body).c_str());
4497   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4498   EXPECT_THAT(getDiagnosticString(),
4499               HasSubstr("Result Type has 2 components, but 4 expected"));
4500 }
4501 
TEST_F(ValidateImage,QueryLodSuccessKernel)4502 TEST_F(ValidateImage, QueryLodSuccessKernel) {
4503   const std::string body = R"(
4504 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4505 %sampler = OpLoad %type_sampler %uniform_sampler
4506 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4507 %res1 = OpImageQueryLod %f32vec2 %simg %f32vec2_hh
4508 %res2 = OpImageQueryLod %f32vec2 %simg %u32vec2_01
4509 )";
4510 
4511   CompileSuccessfully(GenerateKernelCode(body).c_str());
4512   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
4513 }
4514 
TEST_F(ValidateImage,QueryLodSuccessShader)4515 TEST_F(ValidateImage, QueryLodSuccessShader) {
4516   const std::string body = R"(
4517 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4518 %sampler = OpLoad %type_sampler %uniform_sampler
4519 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4520 %res1 = OpImageQueryLod %f32vec2 %simg %f32vec2_hh
4521 )";
4522 
4523   CompileSuccessfully(GenerateShaderCode(body).c_str());
4524   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
4525 }
4526 
TEST_F(ValidateImage,QueryLodWrongResultType)4527 TEST_F(ValidateImage, QueryLodWrongResultType) {
4528   const std::string body = R"(
4529 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4530 %sampler = OpLoad %type_sampler %uniform_sampler
4531 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4532 %res1 = OpImageQueryLod %u32vec2 %simg %f32vec2_hh
4533 )";
4534 
4535   CompileSuccessfully(GenerateKernelCode(body).c_str());
4536   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4537   EXPECT_THAT(getDiagnosticString(),
4538               HasSubstr("Expected Result Type to be float vector type"));
4539 }
4540 
TEST_F(ValidateImage,QueryLodResultTypeWrongSize)4541 TEST_F(ValidateImage, QueryLodResultTypeWrongSize) {
4542   const std::string body = R"(
4543 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4544 %sampler = OpLoad %type_sampler %uniform_sampler
4545 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4546 %res1 = OpImageQueryLod %f32vec3 %simg %f32vec2_hh
4547 )";
4548 
4549   CompileSuccessfully(GenerateKernelCode(body).c_str());
4550   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4551   EXPECT_THAT(getDiagnosticString(),
4552               HasSubstr("Expected Result Type to have 2 components"));
4553 }
4554 
TEST_F(ValidateImage,QueryLodNotSampledImage)4555 TEST_F(ValidateImage, QueryLodNotSampledImage) {
4556   const std::string body = R"(
4557 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4558 %res1 = OpImageQueryLod %f32vec2 %img %f32vec2_hh
4559 )";
4560 
4561   CompileSuccessfully(GenerateKernelCode(body).c_str());
4562   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4563   EXPECT_THAT(
4564       getDiagnosticString(),
4565       HasSubstr("Expected Image operand to be of type OpTypeSampledImage"));
4566 }
4567 
TEST_F(ValidateImage,QueryLodWrongDim)4568 TEST_F(ValidateImage, QueryLodWrongDim) {
4569   const std::string body = R"(
4570 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
4571 %sampler = OpLoad %type_sampler %uniform_sampler
4572 %simg = OpSampledImage %type_sampled_image_f32_rect_0001 %img %sampler
4573 %res1 = OpImageQueryLod %f32vec2 %simg %f32vec2_hh
4574 )";
4575 
4576   CompileSuccessfully(GenerateKernelCode(body).c_str());
4577   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4578   EXPECT_THAT(getDiagnosticString(),
4579               HasSubstr("Image 'Dim' must be 1D, 2D, 3D or Cube"));
4580 }
4581 
TEST_F(ValidateImage,QueryLodWrongCoordinateType)4582 TEST_F(ValidateImage, QueryLodWrongCoordinateType) {
4583   const std::string body = R"(
4584 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4585 %sampler = OpLoad %type_sampler %uniform_sampler
4586 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4587 %res1 = OpImageQueryLod %f32vec2 %simg %u32vec2_01
4588 )";
4589 
4590   CompileSuccessfully(GenerateShaderCode(body).c_str());
4591   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4592   EXPECT_THAT(getDiagnosticString(),
4593               HasSubstr("Expected Coordinate to be float scalar or vector"));
4594 }
4595 
TEST_F(ValidateImage,QueryLodCoordinateSizeTooSmall)4596 TEST_F(ValidateImage, QueryLodCoordinateSizeTooSmall) {
4597   const std::string body = R"(
4598 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4599 %sampler = OpLoad %type_sampler %uniform_sampler
4600 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4601 %res1 = OpImageQueryLod %f32vec2 %simg %f32_0
4602 )";
4603 
4604   CompileSuccessfully(GenerateShaderCode(body).c_str());
4605   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4606   EXPECT_THAT(getDiagnosticString(),
4607               HasSubstr("Expected Coordinate to have at least 2 components, "
4608                         "but given only 1"));
4609 }
4610 
TEST_F(ValidateImage,QueryLevelsSuccess)4611 TEST_F(ValidateImage, QueryLevelsSuccess) {
4612   const std::string body = R"(
4613 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4614 %res1 = OpImageQueryLevels %u32 %img
4615 )";
4616 
4617   CompileSuccessfully(GenerateKernelCode(body).c_str());
4618   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
4619 }
4620 
TEST_F(ValidateImage,QueryLevelsWrongResultType)4621 TEST_F(ValidateImage, QueryLevelsWrongResultType) {
4622   const std::string body = R"(
4623 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4624 %res1 = OpImageQueryLevels %f32 %img
4625 )";
4626 
4627   CompileSuccessfully(GenerateKernelCode(body).c_str());
4628   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4629   EXPECT_THAT(getDiagnosticString(),
4630               HasSubstr("Expected Result Type to be int scalar type"));
4631 }
4632 
TEST_F(ValidateImage,QueryLevelsNotImage)4633 TEST_F(ValidateImage, QueryLevelsNotImage) {
4634   const std::string body = R"(
4635 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4636 %sampler = OpLoad %type_sampler %uniform_sampler
4637 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4638 %res1 = OpImageQueryLevels %u32 %sampler
4639 )";
4640 
4641   CompileSuccessfully(GenerateKernelCode(body).c_str());
4642   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4643   EXPECT_THAT(getDiagnosticString(),
4644               HasSubstr("Expected Image to be of type OpTypeImage"));
4645 }
4646 
TEST_F(ValidateImage,QueryLevelsSampledImageDirectly)4647 TEST_F(ValidateImage, QueryLevelsSampledImageDirectly) {
4648   const std::string body = R"(
4649 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4650 %sampler = OpLoad %type_sampler %uniform_sampler
4651 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4652 %res1 = OpImageQueryLevels %u32 %simg
4653 )";
4654 
4655   CompileSuccessfully(GenerateShaderCode(body).c_str());
4656   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4657   EXPECT_THAT(getDiagnosticString(),
4658               HasSubstr("OpSampledImage instruction must not appear as operand "
4659                         "for OpImageQueryLevels"));
4660 }
4661 
TEST_F(ValidateImage,QueryLevelsWrongDim)4662 TEST_F(ValidateImage, QueryLevelsWrongDim) {
4663   const std::string body = R"(
4664 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
4665 %res1 = OpImageQueryLevels %u32 %img
4666 )";
4667 
4668   CompileSuccessfully(GenerateKernelCode(body).c_str());
4669   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4670   EXPECT_THAT(getDiagnosticString(),
4671               HasSubstr("Image 'Dim' must be 1D, 2D, 3D or Cube"));
4672 }
4673 
TEST_F(ValidateImage,QuerySizeLevelsNonSampledUniversalSuccess)4674 TEST_F(ValidateImage, QuerySizeLevelsNonSampledUniversalSuccess) {
4675   const std::string body = R"(
4676 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
4677 %res1 = OpImageQueryLevels %u32 %img
4678 )";
4679 
4680   CompileSuccessfully(GenerateShaderCode(body).c_str());
4681   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
4682   EXPECT_EQ(getDiagnosticString(), "");
4683 }
4684 
TEST_F(ValidateImage,QuerySizeLevelsVulkanNonSampledError)4685 TEST_F(ValidateImage, QuerySizeLevelsVulkanNonSampledError) {
4686   // Create a whole shader module.  Avoid Vulkan incompatibility with
4687   // SampledRrect images inserted by helper function GenerateShaderCode.
4688   const std::string body = R"(
4689 OpCapability Shader
4690 OpCapability ImageQuery
4691 OpMemoryModel Logical Simple
4692 OpEntryPoint Fragment %main "main"
4693 OpExecutionMode %main OriginUpperLeft
4694 
4695 %f32 = OpTypeFloat 32
4696 %u32 = OpTypeInt 32 0
4697 %void = OpTypeVoid
4698 %voidfn = OpTypeFunction %void
4699 
4700 ; Test with a storage image.
4701 %type_image_f32_2d_0002 = OpTypeImage %f32 2D 0 0 0 2 Rgba32f
4702 %ptr_image_f32_2d_0002 = OpTypePointer UniformConstant %type_image_f32_2d_0002
4703 %uniform_image_f32_2d_0002 = OpVariable %ptr_image_f32_2d_0002 UniformConstant
4704 
4705 %main = OpFunction %void None %voidfn
4706 %entry = OpLabel
4707 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
4708 %res1 = OpImageQueryLevels %u32 %img
4709 OpReturn
4710 OpFunctionEnd
4711 )";
4712 
4713   CompileSuccessfully(body.c_str());
4714   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
4715   EXPECT_THAT(getDiagnosticString(),
4716               AnyVUID("VUID-StandaloneSpirv-OpImageQuerySizeLod-04659"));
4717   EXPECT_THAT(
4718       getDiagnosticString(),
4719       HasSubstr("OpImageQueryLevels must only consume an \"Image\" operand "
4720                 "whose type has its \"Sampled\" operand set to 1"));
4721 }
4722 
TEST_F(ValidateImage,QuerySamplesSuccess)4723 TEST_F(ValidateImage, QuerySamplesSuccess) {
4724   const std::string body = R"(
4725 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
4726 %res1 = OpImageQuerySamples %u32 %img
4727 )";
4728 
4729   CompileSuccessfully(GenerateKernelCode(body).c_str());
4730   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
4731 }
4732 
TEST_F(ValidateImage,QuerySamplesNot2D)4733 TEST_F(ValidateImage, QuerySamplesNot2D) {
4734   const std::string body = R"(
4735 %img = OpLoad %type_image_f32_3d_0011 %uniform_image_f32_3d_0011
4736 %res1 = OpImageQuerySamples %u32 %img
4737 )";
4738 
4739   CompileSuccessfully(GenerateKernelCode(body).c_str());
4740   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4741   EXPECT_THAT(getDiagnosticString(), HasSubstr("Image 'Dim' must be 2D"));
4742 }
4743 
TEST_F(ValidateImage,QuerySamplesNotMultisampled)4744 TEST_F(ValidateImage, QuerySamplesNotMultisampled) {
4745   const std::string body = R"(
4746 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4747 %res1 = OpImageQuerySamples %u32 %img
4748 )";
4749 
4750   CompileSuccessfully(GenerateKernelCode(body).c_str());
4751   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4752   EXPECT_THAT(getDiagnosticString(), HasSubstr("Image 'MS' must be 1"));
4753 }
4754 
TEST_F(ValidateImage,QueryLodWrongExecutionModel)4755 TEST_F(ValidateImage, QueryLodWrongExecutionModel) {
4756   const std::string body = R"(
4757 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4758 %sampler = OpLoad %type_sampler %uniform_sampler
4759 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4760 %res1 = OpImageQueryLod %f32vec2 %simg %f32vec2_hh
4761 )";
4762 
4763   CompileSuccessfully(GenerateShaderCode(body, "", "Vertex").c_str());
4764   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4765   EXPECT_THAT(
4766       getDiagnosticString(),
4767       HasSubstr(
4768           "OpImageQueryLod requires Fragment or GLCompute execution model"));
4769 }
4770 
TEST_F(ValidateImage,QueryLodWrongExecutionModelWithFunc)4771 TEST_F(ValidateImage, QueryLodWrongExecutionModelWithFunc) {
4772   const std::string body = R"(
4773 %call_ret = OpFunctionCall %void %my_func
4774 OpReturn
4775 OpFunctionEnd
4776 %my_func = OpFunction %void None %func
4777 %my_func_entry = OpLabel
4778 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4779 %sampler = OpLoad %type_sampler %uniform_sampler
4780 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4781 %res1 = OpImageQueryLod %f32vec2 %simg %f32vec2_hh
4782 )";
4783 
4784   CompileSuccessfully(GenerateShaderCode(body, "", "Vertex").c_str());
4785   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4786   EXPECT_THAT(
4787       getDiagnosticString(),
4788       HasSubstr(
4789           "OpImageQueryLod requires Fragment or GLCompute execution model"));
4790 }
4791 
TEST_F(ValidateImage,QueryLodComputeShaderDerivatives)4792 TEST_F(ValidateImage, QueryLodComputeShaderDerivatives) {
4793   const std::string body = R"(
4794 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4795 %sampler = OpLoad %type_sampler %uniform_sampler
4796 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4797 %res1 = OpImageQueryLod %f32vec2 %simg %f32vec2_hh
4798 )";
4799 
4800   const std::string extra = R"(
4801 OpCapability ComputeDerivativeGroupLinearNV
4802 OpExtension "SPV_NV_compute_shader_derivatives"
4803 )";
4804   const std::string mode = R"(
4805 OpExecutionMode %main LocalSize 8 8 1
4806 OpExecutionMode %main DerivativeGroupLinearNV
4807 )";
4808   CompileSuccessfully(
4809       GenerateShaderCode(body, extra, "GLCompute", mode).c_str());
4810   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
4811 }
4812 
TEST_F(ValidateImage,QueryLodUniversalSuccess)4813 TEST_F(ValidateImage, QueryLodUniversalSuccess) {
4814   // Create a whole shader module.  Avoid Vulkan incompatibility with
4815   // SampledRrect images inserted by helper function GenerateShaderCode.
4816   const std::string body = R"(
4817 OpCapability Shader
4818 OpCapability ImageQuery
4819 OpMemoryModel Logical Simple
4820 OpEntryPoint Fragment %main "main"
4821 OpExecutionMode %main OriginUpperLeft
4822 
4823 OpDecorate %uniform_image_f32_2d_0000 DescriptorSet 0
4824 OpDecorate %uniform_image_f32_2d_0000 Binding 0
4825 OpDecorate %sampler DescriptorSet 0
4826 OpDecorate %sampler Binding 1
4827 
4828 %f32 = OpTypeFloat 32
4829 %f32vec2 = OpTypeVector %f32 2
4830 %f32vec2_null = OpConstantNull %f32vec2
4831 %u32 = OpTypeInt 32 0
4832 %u32vec2 = OpTypeVector %u32 2
4833 %void = OpTypeVoid
4834 %voidfn = OpTypeFunction %void
4835 
4836 ; Test with an image with sampled = 0
4837 %type_image_f32_2d_0000 = OpTypeImage %f32 2D 0 0 0 0 Rgba32f
4838 %ptr_image_f32_2d_0000 = OpTypePointer UniformConstant %type_image_f32_2d_0000
4839 %uniform_image_f32_2d_0000 = OpVariable %ptr_image_f32_2d_0000 UniformConstant
4840 %sampled_image_ty = OpTypeSampledImage %type_image_f32_2d_0000
4841 
4842 %sampler_ty = OpTypeSampler
4843 %ptr_sampler_ty = OpTypePointer UniformConstant %sampler_ty
4844 %sampler = OpVariable %ptr_sampler_ty UniformConstant
4845 
4846 
4847 %main = OpFunction %void None %voidfn
4848 %entry = OpLabel
4849 %img = OpLoad %type_image_f32_2d_0000 %uniform_image_f32_2d_0000
4850 %s = OpLoad %sampler_ty %sampler
4851 %simg = OpSampledImage %sampled_image_ty %img %s
4852 %res1 = OpImageQueryLod %f32vec2 %simg %f32vec2_null
4853 OpReturn
4854 OpFunctionEnd
4855 )";
4856 
4857   CompileSuccessfully(body.c_str());
4858   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
4859 }
4860 
TEST_F(ValidateImage,QueryLodVulkanNonSampledError)4861 TEST_F(ValidateImage, QueryLodVulkanNonSampledError) {
4862   // Create a whole shader module.  Avoid Vulkan incompatibility with
4863   // SampledRrect images inserted by helper function GenerateShaderCode.
4864   const std::string body = R"(
4865 OpCapability Shader
4866 OpCapability ImageQuery
4867 OpMemoryModel Logical Simple
4868 OpEntryPoint Fragment %main "main"
4869 OpExecutionMode %main OriginUpperLeft
4870 
4871 OpDecorate %sampled_image DescriptorSet 0
4872 OpDecorate %sampled_image Binding 0
4873 
4874 %f32 = OpTypeFloat 32
4875 %f32vec2 = OpTypeVector %f32 2
4876 %f32vec2_null = OpConstantNull %f32vec2
4877 %u32 = OpTypeInt 32 0
4878 %u32vec2 = OpTypeVector %u32 2
4879 %void = OpTypeVoid
4880 %voidfn = OpTypeFunction %void
4881 
4882 ; Test with an image with Sampled = 2
4883 ; In Vulkan it Sampled must be 1 or 2, checked in another part of the
4884 ; validation flow.
4885 %type_image_f32_2d_0002 = OpTypeImage %f32 2D 0 0 0 2 Rgba32f
4886 
4887 ; Expect to fail here.
4888 %sampled_image_ty = OpTypeSampledImage %type_image_f32_2d_0002
4889 %ptr_sampled_image_ty = OpTypePointer UniformConstant %sampled_image_ty
4890 %sampled_image = OpVariable %ptr_sampled_image_ty UniformConstant
4891 
4892 %main = OpFunction %void None %voidfn
4893 %entry = OpLabel
4894 %simg = OpLoad %sampled_image_ty %sampled_image
4895 %res1 = OpImageQueryLod %f32vec2 %simg %f32vec2_null
4896 OpReturn
4897 OpFunctionEnd
4898 )";
4899 
4900   CompileSuccessfully(body.c_str());
4901   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
4902   EXPECT_THAT(getDiagnosticString(),
4903               AnyVUID("VUID-StandaloneSpirv-OpTypeImage-04657"));
4904   EXPECT_THAT(getDiagnosticString(),
4905               HasSubstr("Sampled image type requires an image type with "
4906                         "\"Sampled\" operand set to 0 or 1"));
4907 }
4908 
TEST_F(ValidateImage,QueryLodComputeShaderDerivativesMissingMode)4909 TEST_F(ValidateImage, QueryLodComputeShaderDerivativesMissingMode) {
4910   const std::string body = R"(
4911 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4912 %sampler = OpLoad %type_sampler %uniform_sampler
4913 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4914 %res1 = OpImageQueryLod %f32vec2 %simg %f32vec2_hh
4915 )";
4916 
4917   const std::string extra = R"(
4918 OpCapability ComputeDerivativeGroupLinearNV
4919 OpExtension "SPV_NV_compute_shader_derivatives"
4920 )";
4921   const std::string mode = R"(
4922 OpExecutionMode %main LocalSize 8 8 1
4923 )";
4924   CompileSuccessfully(
4925       GenerateShaderCode(body, extra, "GLCompute", mode).c_str());
4926   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4927   EXPECT_THAT(getDiagnosticString(),
4928               HasSubstr("OpImageQueryLod requires DerivativeGroupQuadsNV or "
4929                         "DerivativeGroupLinearNV execution mode for GLCompute "
4930                         "execution model"));
4931 }
4932 
TEST_F(ValidateImage,ImplicitLodWrongExecutionModel)4933 TEST_F(ValidateImage, ImplicitLodWrongExecutionModel) {
4934   const std::string body = R"(
4935 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4936 %sampler = OpLoad %type_sampler %uniform_sampler
4937 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4938 %res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh
4939 )";
4940 
4941   CompileSuccessfully(GenerateShaderCode(body, "", "Vertex").c_str());
4942   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4943   EXPECT_THAT(getDiagnosticString(),
4944               HasSubstr("ImplicitLod instructions require Fragment or "
4945                         "GLCompute execution model"));
4946 }
4947 
TEST_F(ValidateImage,ImplicitLodComputeShaderDerivatives)4948 TEST_F(ValidateImage, ImplicitLodComputeShaderDerivatives) {
4949   const std::string body = R"(
4950 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4951 %sampler = OpLoad %type_sampler %uniform_sampler
4952 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4953 %res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh
4954 )";
4955 
4956   const std::string extra = R"(
4957 OpCapability ComputeDerivativeGroupLinearNV
4958 OpExtension "SPV_NV_compute_shader_derivatives"
4959 )";
4960   const std::string mode = R"(
4961 OpExecutionMode %main LocalSize 8 8 1
4962 OpExecutionMode %main DerivativeGroupLinearNV
4963 )";
4964   CompileSuccessfully(
4965       GenerateShaderCode(body, extra, "GLCompute", mode).c_str());
4966   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
4967 }
4968 
TEST_F(ValidateImage,ImplicitLodComputeShaderDerivativesMissingMode)4969 TEST_F(ValidateImage, ImplicitLodComputeShaderDerivativesMissingMode) {
4970   const std::string body = R"(
4971 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4972 %sampler = OpLoad %type_sampler %uniform_sampler
4973 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4974 %res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh
4975 )";
4976 
4977   const std::string extra = R"(
4978 OpCapability ComputeDerivativeGroupLinearNV
4979 OpExtension "SPV_NV_compute_shader_derivatives"
4980 )";
4981   const std::string mode = R"(
4982 OpExecutionMode %main LocalSize 8 8 1
4983 )";
4984   CompileSuccessfully(
4985       GenerateShaderCode(body, extra, "GLCompute", mode).c_str());
4986   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4987   EXPECT_THAT(
4988       getDiagnosticString(),
4989       HasSubstr("ImplicitLod instructions require DerivativeGroupQuadsNV or "
4990                 "DerivativeGroupLinearNV execution mode for GLCompute "
4991                 "execution model"));
4992 }
4993 
TEST_F(ValidateImage,ReadSubpassDataWrongExecutionModel)4994 TEST_F(ValidateImage, ReadSubpassDataWrongExecutionModel) {
4995   const std::string body = R"(
4996 %img = OpLoad %type_image_f32_spd_0002 %uniform_image_f32_spd_0002
4997 %res1 = OpImageRead %f32vec4 %img %u32vec2_01
4998 )";
4999 
5000   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
5001   CompileSuccessfully(GenerateShaderCode(body, extra, "Vertex").c_str());
5002   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5003   EXPECT_THAT(getDiagnosticString(),
5004               HasSubstr("Dim SubpassData requires Fragment execution model"));
5005 }
5006 
TEST_F(ValidateImage,SparseSampleImplicitLodSuccess)5007 TEST_F(ValidateImage, SparseSampleImplicitLodSuccess) {
5008   const std::string body = R"(
5009 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5010 %sampler = OpLoad %type_sampler %uniform_sampler
5011 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5012 %res1 = OpImageSparseSampleImplicitLod %struct_u32_f32vec4 %simg %f32vec2_hh
5013 %res2 = OpImageSparseSampleImplicitLod %struct_u32_f32vec4 %simg %f32vec2_hh Bias %f32_0_25
5014 %res4 = OpImageSparseSampleImplicitLod %struct_u32_f32vec4 %simg %f32vec2_hh ConstOffset %s32vec2_01
5015 %res5 = OpImageSparseSampleImplicitLod %struct_u32_f32vec4 %simg %f32vec2_hh Offset %s32vec2_01
5016 %res6 = OpImageSparseSampleImplicitLod %struct_u32_f32vec4 %simg %f32vec2_hh MinLod %f32_0_5
5017 %res7 = OpImageSparseSampleImplicitLod %struct_u64_f32vec4 %simg %f32vec2_hh Bias|Offset|MinLod %f32_0_25 %s32vec2_01 %f32_0_5
5018 %res8 = OpImageSparseSampleImplicitLod %struct_u32_f32vec4 %simg %f32vec2_hh NonPrivateTexelKHR
5019 )";
5020 
5021   const std::string extra = R"(
5022 OpCapability VulkanMemoryModelKHR
5023 OpExtension "SPV_KHR_vulkan_memory_model"
5024 )";
5025   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
5026                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
5027                           .c_str());
5028   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5029 }
5030 
TEST_F(ValidateImage,SparseSampleImplicitLodResultTypeNotStruct)5031 TEST_F(ValidateImage, SparseSampleImplicitLodResultTypeNotStruct) {
5032   const std::string body = R"(
5033 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5034 %sampler = OpLoad %type_sampler %uniform_sampler
5035 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5036 %res1 = OpImageSparseSampleImplicitLod %f32 %simg %f32vec2_hh
5037 )";
5038 
5039   CompileSuccessfully(GenerateShaderCode(body).c_str());
5040   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5041   EXPECT_THAT(getDiagnosticString(),
5042               HasSubstr("Expected Result Type to be OpTypeStruct"));
5043 }
5044 
TEST_F(ValidateImage,SparseSampleImplicitLodResultTypeNotTwoMembers1)5045 TEST_F(ValidateImage, SparseSampleImplicitLodResultTypeNotTwoMembers1) {
5046   const std::string body = R"(
5047 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5048 %sampler = OpLoad %type_sampler %uniform_sampler
5049 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5050 %res1 = OpImageSparseSampleImplicitLod %struct_u32 %simg %f32vec2_hh
5051 )";
5052 
5053   CompileSuccessfully(GenerateShaderCode(body).c_str());
5054   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5055   EXPECT_THAT(getDiagnosticString(),
5056               HasSubstr("Expected Result Type to be a struct containing an int "
5057                         "scalar and a texel"));
5058 }
5059 
TEST_F(ValidateImage,SparseSampleImplicitLodResultTypeNotTwoMembers2)5060 TEST_F(ValidateImage, SparseSampleImplicitLodResultTypeNotTwoMembers2) {
5061   const std::string body = R"(
5062 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5063 %sampler = OpLoad %type_sampler %uniform_sampler
5064 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5065 %res1 = OpImageSparseSampleImplicitLod %struct_u32_f32vec4_u32 %simg %f32vec2_hh
5066 )";
5067 
5068   CompileSuccessfully(GenerateShaderCode(body).c_str());
5069   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5070   EXPECT_THAT(getDiagnosticString(),
5071               HasSubstr("Expected Result Type to be a struct containing an "
5072                         "int scalar and a texel"));
5073 }
5074 
TEST_F(ValidateImage,SparseSampleImplicitLodResultTypeFirstMemberNotInt)5075 TEST_F(ValidateImage, SparseSampleImplicitLodResultTypeFirstMemberNotInt) {
5076   const std::string body = R"(
5077 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5078 %sampler = OpLoad %type_sampler %uniform_sampler
5079 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5080 %res1 = OpImageSparseSampleImplicitLod %struct_f32_f32vec4 %simg %f32vec2_hh
5081 )";
5082 
5083   CompileSuccessfully(GenerateShaderCode(body).c_str());
5084   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5085   EXPECT_THAT(getDiagnosticString(),
5086               HasSubstr("Expected Result Type to be a struct containing an "
5087                         "int scalar and a texel"));
5088 }
5089 
TEST_F(ValidateImage,SparseSampleImplicitLodResultTypeTexelNotVector)5090 TEST_F(ValidateImage, SparseSampleImplicitLodResultTypeTexelNotVector) {
5091   const std::string body = R"(
5092 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5093 %sampler = OpLoad %type_sampler %uniform_sampler
5094 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5095 %res1 = OpImageSparseSampleImplicitLod %struct_u32_u32 %simg %f32vec2_hh
5096 )";
5097 
5098   CompileSuccessfully(GenerateShaderCode(body).c_str());
5099   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5100   EXPECT_THAT(getDiagnosticString(),
5101               HasSubstr("Expected Result Type's second member to be int or "
5102                         "float vector type"));
5103 }
5104 
TEST_F(ValidateImage,SparseSampleImplicitLodWrongNumComponentsTexel)5105 TEST_F(ValidateImage, SparseSampleImplicitLodWrongNumComponentsTexel) {
5106   const std::string body = R"(
5107 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5108 %sampler = OpLoad %type_sampler %uniform_sampler
5109 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5110 %res1 = OpImageSparseSampleImplicitLod %struct_u32_f32vec3 %simg %f32vec2_hh
5111 )";
5112 
5113   CompileSuccessfully(GenerateShaderCode(body).c_str());
5114   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5115   EXPECT_THAT(getDiagnosticString(),
5116               HasSubstr("Expected Result Type's second member to have 4 "
5117                         "components"));
5118 }
5119 
TEST_F(ValidateImage,SparseSampleImplicitLodWrongComponentTypeTexel)5120 TEST_F(ValidateImage, SparseSampleImplicitLodWrongComponentTypeTexel) {
5121   const std::string body = R"(
5122 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5123 %sampler = OpLoad %type_sampler %uniform_sampler
5124 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5125 %res1 = OpImageSparseSampleImplicitLod %struct_u32_u32vec4 %simg %f32vec2_hh
5126 )";
5127 
5128   CompileSuccessfully(GenerateShaderCode(body).c_str());
5129   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5130   EXPECT_THAT(getDiagnosticString(),
5131               HasSubstr("Expected Image 'Sampled Type' to be the same as "
5132                         "Result Type's second member components"));
5133 }
5134 
TEST_F(ValidateImage,SparseSampleDrefImplicitLodSuccess)5135 TEST_F(ValidateImage, SparseSampleDrefImplicitLodSuccess) {
5136   const std::string body = R"(
5137 %img = OpLoad %type_image_u32_2d_0001 %uniform_image_u32_2d_0001
5138 %sampler = OpLoad %type_sampler %uniform_sampler
5139 %simg = OpSampledImage %type_sampled_image_u32_2d_0001 %img %sampler
5140 %res1 = OpImageSparseSampleDrefImplicitLod %struct_u32_u32 %simg %f32vec2_hh %f32_1
5141 %res2 = OpImageSparseSampleDrefImplicitLod %struct_u32_u32 %simg %f32vec2_hh %f32_1 Bias %f32_0_25
5142 %res4 = OpImageSparseSampleDrefImplicitLod %struct_u32_u32 %simg %f32vec2_hh %f32_1 ConstOffset %s32vec2_01
5143 %res5 = OpImageSparseSampleDrefImplicitLod %struct_u32_u32 %simg %f32vec2_hh %f32_1 Offset %s32vec2_01
5144 %res6 = OpImageSparseSampleDrefImplicitLod %struct_u32_u32 %simg %f32vec2_hh %f32_1 MinLod %f32_0_5
5145 %res7 = OpImageSparseSampleDrefImplicitLod %struct_u32_u32 %simg %f32vec2_hh %f32_1 Bias|Offset|MinLod %f32_0_25 %s32vec2_01 %f32_0_5
5146 %res8 = OpImageSparseSampleDrefImplicitLod %struct_u32_u32 %simg %f32vec2_hh %f32_1 NonPrivateTexelKHR
5147 )";
5148 
5149   const std::string extra = R"(
5150 OpCapability VulkanMemoryModelKHR
5151 OpExtension "SPV_KHR_vulkan_memory_model"
5152 )";
5153   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
5154                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
5155                           .c_str());
5156   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5157 }
5158 
TEST_F(ValidateImage,SparseSampleDrefImplicitLodResultTypeNotStruct)5159 TEST_F(ValidateImage, SparseSampleDrefImplicitLodResultTypeNotStruct) {
5160   const std::string body = R"(
5161 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5162 %sampler = OpLoad %type_sampler %uniform_sampler
5163 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5164 %res1 = OpImageSparseSampleDrefImplicitLod %f32 %simg %f32vec2_hh %f32_1
5165 )";
5166 
5167   CompileSuccessfully(GenerateShaderCode(body).c_str());
5168   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5169   EXPECT_THAT(getDiagnosticString(),
5170               HasSubstr("Expected Result Type to be OpTypeStruct"));
5171 }
5172 
TEST_F(ValidateImage,SparseSampleDrefImplicitLodResultTypeNotTwoMembers1)5173 TEST_F(ValidateImage, SparseSampleDrefImplicitLodResultTypeNotTwoMembers1) {
5174   const std::string body = R"(
5175 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5176 %sampler = OpLoad %type_sampler %uniform_sampler
5177 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5178 %res1 = OpImageSparseSampleDrefImplicitLod %struct_u32 %simg %f32vec2_hh %f32_1
5179 )";
5180 
5181   CompileSuccessfully(GenerateShaderCode(body).c_str());
5182   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5183   EXPECT_THAT(
5184       getDiagnosticString(),
5185       HasSubstr("Expected Result Type to be a struct containing an int scalar "
5186                 "and a texel"));
5187 }
5188 
TEST_F(ValidateImage,SparseSampleDrefImplicitLodResultTypeNotTwoMembers2)5189 TEST_F(ValidateImage, SparseSampleDrefImplicitLodResultTypeNotTwoMembers2) {
5190   const std::string body = R"(
5191 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5192 %sampler = OpLoad %type_sampler %uniform_sampler
5193 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5194 %res1 = OpImageSparseSampleDrefImplicitLod %struct_u32_f32_u32 %simg %f32vec2_hh %f32_1
5195 )";
5196 
5197   CompileSuccessfully(GenerateShaderCode(body).c_str());
5198   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5199   EXPECT_THAT(
5200       getDiagnosticString(),
5201       HasSubstr("Expected Result Type to be a struct containing an int scalar "
5202                 "and a texel"));
5203 }
5204 
TEST_F(ValidateImage,SparseSampleDrefImplicitLodResultTypeFirstMemberNotInt)5205 TEST_F(ValidateImage, SparseSampleDrefImplicitLodResultTypeFirstMemberNotInt) {
5206   const std::string body = R"(
5207 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5208 %sampler = OpLoad %type_sampler %uniform_sampler
5209 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5210 %res1 = OpImageSparseSampleDrefImplicitLod %struct_f32_f32 %simg %f32vec2_hh %f32_1
5211 )";
5212 
5213   CompileSuccessfully(GenerateShaderCode(body).c_str());
5214   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5215   EXPECT_THAT(
5216       getDiagnosticString(),
5217       HasSubstr("Expected Result Type to be a struct containing an int scalar "
5218                 "and a texel"));
5219 }
5220 
TEST_F(ValidateImage,SparseSampleDrefImplicitLodDifferentSampledType)5221 TEST_F(ValidateImage, SparseSampleDrefImplicitLodDifferentSampledType) {
5222   const std::string body = R"(
5223 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5224 %sampler = OpLoad %type_sampler %uniform_sampler
5225 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5226 %res1 = OpImageSparseSampleDrefImplicitLod %struct_u32_u32 %simg %f32vec2_hh %f32_1
5227 )";
5228 
5229   CompileSuccessfully(GenerateShaderCode(body).c_str());
5230   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5231   EXPECT_THAT(getDiagnosticString(),
5232               HasSubstr("Expected Image 'Sampled Type' to be the same as "
5233                         "Result Type's second member"));
5234 }
5235 
TEST_F(ValidateImage,SparseFetchSuccess)5236 TEST_F(ValidateImage, SparseFetchSuccess) {
5237   const std::string body = R"(
5238 %img = OpLoad %type_image_f32_1d_0001 %uniform_image_f32_1d_0001
5239 %res1 = OpImageSparseFetch %struct_u32_f32vec4 %img %u32vec2_01
5240 %res2 = OpImageSparseFetch %struct_u32_f32vec4 %img %u32vec2_01 NonPrivateTexelKHR
5241 )";
5242 
5243   const std::string extra = R"(
5244 OpCapability VulkanMemoryModelKHR
5245 OpExtension "SPV_KHR_vulkan_memory_model"
5246 )";
5247   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
5248                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
5249                           .c_str());
5250   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5251 }
5252 
TEST_F(ValidateImage,SparseFetchResultTypeNotStruct)5253 TEST_F(ValidateImage, SparseFetchResultTypeNotStruct) {
5254   const std::string body = R"(
5255 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
5256 %res1 = OpImageSparseFetch %f32 %img %u32vec2_01
5257 )";
5258 
5259   CompileSuccessfully(GenerateShaderCode(body).c_str());
5260   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5261   EXPECT_THAT(getDiagnosticString(),
5262               HasSubstr("Expected Result Type to be OpTypeStruct"));
5263 }
5264 
TEST_F(ValidateImage,SparseFetchResultTypeNotTwoMembers1)5265 TEST_F(ValidateImage, SparseFetchResultTypeNotTwoMembers1) {
5266   const std::string body = R"(
5267 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
5268 %res1 = OpImageSparseFetch %struct_u32 %img %u32vec2_01
5269 )";
5270 
5271   CompileSuccessfully(GenerateShaderCode(body).c_str());
5272   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5273   EXPECT_THAT(getDiagnosticString(),
5274               HasSubstr("Expected Result Type to be a struct containing an "
5275                         "int scalar and a texel"));
5276 }
5277 
TEST_F(ValidateImage,SparseFetchResultTypeNotTwoMembers2)5278 TEST_F(ValidateImage, SparseFetchResultTypeNotTwoMembers2) {
5279   const std::string body = R"(
5280 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
5281 %res1 = OpImageSparseFetch %struct_u32_f32vec4_u32 %img %u32vec2_01
5282 )";
5283 
5284   CompileSuccessfully(GenerateShaderCode(body).c_str());
5285   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5286   EXPECT_THAT(getDiagnosticString(),
5287               HasSubstr("Expected Result Type to be a struct containing an "
5288                         "int scalar and a texel"));
5289 }
5290 
TEST_F(ValidateImage,SparseFetchResultTypeFirstMemberNotInt)5291 TEST_F(ValidateImage, SparseFetchResultTypeFirstMemberNotInt) {
5292   const std::string body = R"(
5293 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
5294 %res1 = OpImageSparseFetch %struct_f32_f32vec4 %img %u32vec2_01
5295 )";
5296 
5297   CompileSuccessfully(GenerateShaderCode(body).c_str());
5298   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5299   EXPECT_THAT(getDiagnosticString(),
5300               HasSubstr("Expected Result Type to be a struct containing an "
5301                         "int scalar and a texel"));
5302 }
5303 
TEST_F(ValidateImage,SparseFetchResultTypeTexelNotVector)5304 TEST_F(ValidateImage, SparseFetchResultTypeTexelNotVector) {
5305   const std::string body = R"(
5306 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
5307 %res1 = OpImageSparseFetch %struct_u32_u32 %img %u32vec2_01
5308 )";
5309 
5310   CompileSuccessfully(GenerateShaderCode(body).c_str());
5311   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5312   EXPECT_THAT(getDiagnosticString(),
5313               HasSubstr("Expected Result Type's second member to be int or "
5314                         "float vector type"));
5315 }
5316 
TEST_F(ValidateImage,SparseFetchWrongNumComponentsTexel)5317 TEST_F(ValidateImage, SparseFetchWrongNumComponentsTexel) {
5318   const std::string body = R"(
5319 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
5320 %res1 = OpImageSparseFetch %struct_u32_f32vec3 %img %u32vec2_01
5321 )";
5322 
5323   CompileSuccessfully(GenerateShaderCode(body).c_str());
5324   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5325   EXPECT_THAT(getDiagnosticString(),
5326               HasSubstr("Expected Result Type's second member to have 4 "
5327                         "components"));
5328 }
5329 
TEST_F(ValidateImage,SparseFetchWrongComponentTypeTexel)5330 TEST_F(ValidateImage, SparseFetchWrongComponentTypeTexel) {
5331   const std::string body = R"(
5332 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
5333 %res1 = OpImageSparseFetch %struct_u32_u32vec4 %img %u32vec2_01
5334 )";
5335 
5336   CompileSuccessfully(GenerateShaderCode(body).c_str());
5337   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5338   EXPECT_THAT(getDiagnosticString(),
5339               HasSubstr("Expected Image 'Sampled Type' to be the same as "
5340                         "Result Type's second member components"));
5341 }
5342 
TEST_F(ValidateImage,SparseReadSuccess)5343 TEST_F(ValidateImage, SparseReadSuccess) {
5344   const std::string body = R"(
5345 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
5346 %res1 = OpImageSparseRead %struct_u32_f32vec4 %img %u32vec2_01
5347 )";
5348 
5349   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
5350   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
5351   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
5352 }
5353 
TEST_F(ValidateImage,SparseReadResultTypeNotStruct)5354 TEST_F(ValidateImage, SparseReadResultTypeNotStruct) {
5355   const std::string body = R"(
5356 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
5357 %res1 = OpImageSparseRead %f32 %img %u32vec2_01
5358 )";
5359 
5360   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
5361   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
5362   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5363   EXPECT_THAT(getDiagnosticString(),
5364               HasSubstr("Expected Result Type to be OpTypeStruct"));
5365 }
5366 
TEST_F(ValidateImage,SparseReadResultTypeNotTwoMembers1)5367 TEST_F(ValidateImage, SparseReadResultTypeNotTwoMembers1) {
5368   const std::string body = R"(
5369 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
5370 %res1 = OpImageSparseRead %struct_u32 %img %u32vec2_01
5371 )";
5372 
5373   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
5374   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
5375   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5376   EXPECT_THAT(getDiagnosticString(),
5377               HasSubstr("Expected Result Type to be a struct containing an "
5378                         "int scalar and a texel"));
5379 }
5380 
TEST_F(ValidateImage,SparseReadResultTypeNotTwoMembers2)5381 TEST_F(ValidateImage, SparseReadResultTypeNotTwoMembers2) {
5382   const std::string body = R"(
5383 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
5384 %res1 = OpImageSparseRead %struct_u32_f32vec4_u32 %img %u32vec2_01
5385 )";
5386 
5387   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
5388   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
5389   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5390   EXPECT_THAT(getDiagnosticString(),
5391               HasSubstr("Expected Result Type to be a struct containing an "
5392                         "int scalar and a texel"));
5393 }
5394 
TEST_F(ValidateImage,SparseReadResultTypeFirstMemberNotInt)5395 TEST_F(ValidateImage, SparseReadResultTypeFirstMemberNotInt) {
5396   const std::string body = R"(
5397 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
5398 %res1 = OpImageSparseRead %struct_f32_f32vec4 %img %u32vec2_01
5399 )";
5400 
5401   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
5402   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
5403   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5404   EXPECT_THAT(getDiagnosticString(),
5405               HasSubstr("Expected Result Type to be a struct containing an "
5406                         "int scalar and a texel"));
5407 }
5408 
TEST_F(ValidateImage,SparseReadResultTypeTexelWrongType)5409 TEST_F(ValidateImage, SparseReadResultTypeTexelWrongType) {
5410   const std::string body = R"(
5411 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
5412 %res1 = OpImageSparseRead %struct_u32_u32arr4 %img %u32vec2_01
5413 )";
5414 
5415   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
5416   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
5417   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5418   EXPECT_THAT(getDiagnosticString(),
5419               HasSubstr("Expected Result Type's second member to be int or "
5420                         "float scalar or vector type"));
5421 }
5422 
TEST_F(ValidateImage,SparseReadWrongComponentTypeTexel)5423 TEST_F(ValidateImage, SparseReadWrongComponentTypeTexel) {
5424   const std::string body = R"(
5425 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
5426 %res1 = OpImageSparseRead %struct_u32_u32vec4 %img %u32vec2_01
5427 )";
5428 
5429   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
5430   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
5431   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5432   EXPECT_THAT(getDiagnosticString(),
5433               HasSubstr("Expected Image 'Sampled Type' to be the same as "
5434                         "Result Type's second member components"));
5435 }
5436 
TEST_F(ValidateImage,SparseReadSubpassDataNotAllowed)5437 TEST_F(ValidateImage, SparseReadSubpassDataNotAllowed) {
5438   const std::string body = R"(
5439 %img = OpLoad %type_image_f32_spd_0002 %uniform_image_f32_spd_0002
5440 %res1 = OpImageSparseRead %struct_u32_f32vec4 %img %u32vec2_01
5441 )";
5442 
5443   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
5444   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment").c_str());
5445   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5446   EXPECT_THAT(
5447       getDiagnosticString(),
5448       HasSubstr("Image Dim SubpassData cannot be used with ImageSparseRead"));
5449 }
5450 
TEST_F(ValidateImage,SparseGatherSuccess)5451 TEST_F(ValidateImage, SparseGatherSuccess) {
5452   const std::string body = R"(
5453 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5454 %sampler = OpLoad %type_sampler %uniform_sampler
5455 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5456 %res1 = OpImageSparseGather %struct_u32_f32vec4 %simg %f32vec4_0000 %u32_1
5457 %res2 = OpImageSparseGather %struct_u32_f32vec4 %simg %f32vec4_0000 %u32_1 NonPrivateTexelKHR
5458 )";
5459 
5460   const std::string extra = R"(
5461 OpCapability VulkanMemoryModelKHR
5462 OpExtension "SPV_KHR_vulkan_memory_model"
5463 )";
5464   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
5465                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
5466                           .c_str());
5467   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5468 }
5469 
TEST_F(ValidateImage,SparseGatherResultTypeNotStruct)5470 TEST_F(ValidateImage, SparseGatherResultTypeNotStruct) {
5471   const std::string body = R"(
5472 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5473 %sampler = OpLoad %type_sampler %uniform_sampler
5474 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5475 %res1 = OpImageSparseGather %f32 %simg %f32vec2_hh %u32_1
5476 )";
5477 
5478   CompileSuccessfully(GenerateShaderCode(body).c_str());
5479   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5480   EXPECT_THAT(getDiagnosticString(),
5481               HasSubstr("Expected Result Type to be OpTypeStruct"));
5482 }
5483 
TEST_F(ValidateImage,SparseGatherResultTypeNotTwoMembers1)5484 TEST_F(ValidateImage, SparseGatherResultTypeNotTwoMembers1) {
5485   const std::string body = R"(
5486 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5487 %sampler = OpLoad %type_sampler %uniform_sampler
5488 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5489 %res1 = OpImageSparseGather %struct_u32 %simg %f32vec2_hh %u32_1
5490 )";
5491 
5492   CompileSuccessfully(GenerateShaderCode(body).c_str());
5493   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5494   EXPECT_THAT(getDiagnosticString(),
5495               HasSubstr("Expected Result Type to be a struct containing an int "
5496                         "scalar and a texel"));
5497 }
5498 
TEST_F(ValidateImage,SparseGatherResultTypeNotTwoMembers2)5499 TEST_F(ValidateImage, SparseGatherResultTypeNotTwoMembers2) {
5500   const std::string body = R"(
5501 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5502 %sampler = OpLoad %type_sampler %uniform_sampler
5503 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5504 %res1 = OpImageSparseGather %struct_u32_f32vec4_u32 %simg %f32vec2_hh %u32_1
5505 )";
5506 
5507   CompileSuccessfully(GenerateShaderCode(body).c_str());
5508   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5509   EXPECT_THAT(getDiagnosticString(),
5510               HasSubstr("Expected Result Type to be a struct containing an int "
5511                         "scalar and a texel"));
5512 }
5513 
TEST_F(ValidateImage,SparseGatherResultTypeFirstMemberNotInt)5514 TEST_F(ValidateImage, SparseGatherResultTypeFirstMemberNotInt) {
5515   const std::string body = R"(
5516 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5517 %sampler = OpLoad %type_sampler %uniform_sampler
5518 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5519 %res1 = OpImageSparseGather %struct_f32_f32vec4 %simg %f32vec2_hh %u32_1
5520 )";
5521 
5522   CompileSuccessfully(GenerateShaderCode(body).c_str());
5523   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5524   EXPECT_THAT(getDiagnosticString(),
5525               HasSubstr("Expected Result Type to be a struct containing an "
5526                         "int scalar and a texel"));
5527 }
5528 
TEST_F(ValidateImage,SparseGatherResultTypeTexelNotVector)5529 TEST_F(ValidateImage, SparseGatherResultTypeTexelNotVector) {
5530   const std::string body = R"(
5531 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5532 %sampler = OpLoad %type_sampler %uniform_sampler
5533 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5534 %res1 = OpImageSparseGather %struct_u32_u32 %simg %f32vec2_hh %u32_1
5535 )";
5536 
5537   CompileSuccessfully(GenerateShaderCode(body).c_str());
5538   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5539   EXPECT_THAT(getDiagnosticString(),
5540               HasSubstr("Expected Result Type's second member to be int or "
5541                         "float vector type"));
5542 }
5543 
TEST_F(ValidateImage,SparseGatherWrongNumComponentsTexel)5544 TEST_F(ValidateImage, SparseGatherWrongNumComponentsTexel) {
5545   const std::string body = R"(
5546 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5547 %sampler = OpLoad %type_sampler %uniform_sampler
5548 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5549 %res1 = OpImageSparseGather %struct_u32_f32vec3 %simg %f32vec2_hh %u32_1
5550 )";
5551 
5552   CompileSuccessfully(GenerateShaderCode(body).c_str());
5553   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5554   EXPECT_THAT(getDiagnosticString(),
5555               HasSubstr("Expected Result Type's second member to have 4 "
5556                         "components"));
5557 }
5558 
TEST_F(ValidateImage,SparseGatherWrongComponentTypeTexel)5559 TEST_F(ValidateImage, SparseGatherWrongComponentTypeTexel) {
5560   const std::string body = R"(
5561 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5562 %sampler = OpLoad %type_sampler %uniform_sampler
5563 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5564 %res1 = OpImageSparseGather %struct_u32_u32vec4 %simg %f32vec2_hh %u32_1
5565 )";
5566 
5567   CompileSuccessfully(GenerateShaderCode(body).c_str());
5568   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5569   EXPECT_THAT(getDiagnosticString(),
5570               HasSubstr("Expected Image 'Sampled Type' to be the same as "
5571                         "Result Type's second member components"));
5572 }
5573 
TEST_F(ValidateImage,SparseTexelsResidentSuccess)5574 TEST_F(ValidateImage, SparseTexelsResidentSuccess) {
5575   const std::string body = R"(
5576 %res1 = OpImageSparseTexelsResident %bool %u32_1
5577 )";
5578 
5579   CompileSuccessfully(GenerateShaderCode(body).c_str());
5580   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
5581 }
5582 
TEST_F(ValidateImage,SparseTexelsResidentResultTypeNotBool)5583 TEST_F(ValidateImage, SparseTexelsResidentResultTypeNotBool) {
5584   const std::string body = R"(
5585 %res1 = OpImageSparseTexelsResident %u32 %u32_1
5586 )";
5587 
5588   CompileSuccessfully(GenerateShaderCode(body).c_str());
5589   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5590   EXPECT_THAT(getDiagnosticString(),
5591               HasSubstr("Expected Result Type to be bool scalar type"));
5592 }
5593 
TEST_F(ValidateImage,MakeTexelVisibleKHRSuccessImageRead)5594 TEST_F(ValidateImage, MakeTexelVisibleKHRSuccessImageRead) {
5595   const std::string body = R"(
5596 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
5597 %res1 = OpImageRead %u32vec4 %img %u32vec2_01 MakeTexelVisibleKHR|NonPrivateTexelKHR %u32_2
5598 )";
5599 
5600   const std::string extra = R"(
5601 OpCapability StorageImageReadWithoutFormat
5602 OpCapability VulkanMemoryModelKHR
5603 OpExtension "SPV_KHR_vulkan_memory_model"
5604 )";
5605   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
5606                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
5607                           .c_str());
5608   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5609 }
5610 
TEST_F(ValidateImage,MakeTexelVisibleKHRSuccessImageSparseRead)5611 TEST_F(ValidateImage, MakeTexelVisibleKHRSuccessImageSparseRead) {
5612   const std::string body = R"(
5613 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
5614 %res1 = OpImageSparseRead %struct_u32_f32vec4 %img %u32vec2_01 MakeTexelVisibleKHR|NonPrivateTexelKHR %u32_2
5615 )";
5616 
5617   const std::string extra = R"(
5618 OpCapability StorageImageReadWithoutFormat
5619 OpCapability VulkanMemoryModelKHR
5620 OpExtension "SPV_KHR_vulkan_memory_model"
5621 )";
5622   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
5623                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
5624                           .c_str());
5625   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5626 }
5627 
TEST_F(ValidateImage,MakeTexelVisibleKHRFailureOpcode)5628 TEST_F(ValidateImage, MakeTexelVisibleKHRFailureOpcode) {
5629   const std::string body = R"(
5630 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5631 %sampler = OpLoad %type_sampler %uniform_sampler
5632 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5633 %res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh MakeTexelVisibleKHR|NonPrivateTexelKHR %u32_1
5634 )";
5635 
5636   const std::string extra = R"(
5637 OpCapability StorageImageReadWithoutFormat
5638 OpCapability VulkanMemoryModelKHR
5639 OpExtension "SPV_KHR_vulkan_memory_model"
5640 )";
5641   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
5642                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
5643                           .c_str());
5644   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
5645             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5646   EXPECT_THAT(
5647       getDiagnosticString(),
5648       HasSubstr("Image Operand MakeTexelVisibleKHR can only be used with "
5649                 "OpImageRead or OpImageSparseRead: OpImageSampleImplicitLod"));
5650 }
5651 
TEST_F(ValidateImage,MakeTexelVisibleKHRFailureMissingNonPrivate)5652 TEST_F(ValidateImage, MakeTexelVisibleKHRFailureMissingNonPrivate) {
5653   const std::string body = R"(
5654 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
5655 %res1 = OpImageRead %u32vec4 %img %u32vec2_01 MakeTexelVisibleKHR %u32_1
5656 )";
5657 
5658   const std::string extra = R"(
5659 OpCapability StorageImageReadWithoutFormat
5660 OpCapability VulkanMemoryModelKHR
5661 OpExtension "SPV_KHR_vulkan_memory_model"
5662 )";
5663   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
5664                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
5665                           .c_str());
5666   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
5667             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5668   EXPECT_THAT(getDiagnosticString(),
5669               HasSubstr("Image Operand MakeTexelVisibleKHR requires "
5670                         "NonPrivateTexelKHR is also specified: OpImageRead"));
5671 }
5672 
TEST_F(ValidateImage,MakeTexelAvailableKHRSuccessImageWrite)5673 TEST_F(ValidateImage, MakeTexelAvailableKHRSuccessImageWrite) {
5674   const std::string body = R"(
5675 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
5676 OpImageWrite %img %u32vec2_01 %u32vec4_0123 MakeTexelAvailableKHR|NonPrivateTexelKHR %u32_2
5677 )";
5678 
5679   const std::string extra = R"(
5680 OpCapability StorageImageWriteWithoutFormat
5681 OpCapability VulkanMemoryModelKHR
5682 OpExtension "SPV_KHR_vulkan_memory_model"
5683 )";
5684   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
5685                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
5686                           .c_str());
5687   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5688 }
5689 
TEST_F(ValidateImage,MakeTexelAvailableKHRFailureOpcode)5690 TEST_F(ValidateImage, MakeTexelAvailableKHRFailureOpcode) {
5691   const std::string body = R"(
5692 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5693 %sampler = OpLoad %type_sampler %uniform_sampler
5694 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5695 %res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh MakeTexelAvailableKHR|NonPrivateTexelKHR %u32_1
5696 )";
5697 
5698   const std::string extra = R"(
5699 OpCapability StorageImageReadWithoutFormat
5700 OpCapability VulkanMemoryModelKHR
5701 OpExtension "SPV_KHR_vulkan_memory_model"
5702 )";
5703   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
5704                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
5705                           .c_str());
5706   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
5707             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5708   EXPECT_THAT(getDiagnosticString(),
5709               HasSubstr("Image Operand MakeTexelAvailableKHR can only be used "
5710                         "with OpImageWrite: OpImageSampleImplicitLod"));
5711 }
5712 
TEST_F(ValidateImage,MakeTexelAvailableKHRFailureMissingNonPrivate)5713 TEST_F(ValidateImage, MakeTexelAvailableKHRFailureMissingNonPrivate) {
5714   const std::string body = R"(
5715 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
5716 OpImageWrite %img %u32vec2_01 %u32vec4_0123 MakeTexelAvailableKHR %u32_1
5717 )";
5718 
5719   const std::string extra = R"(
5720 OpCapability StorageImageWriteWithoutFormat
5721 OpCapability VulkanMemoryModelKHR
5722 OpExtension "SPV_KHR_vulkan_memory_model"
5723 )";
5724   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
5725                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
5726                           .c_str());
5727   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
5728             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5729   EXPECT_THAT(getDiagnosticString(),
5730               HasSubstr("Image Operand MakeTexelAvailableKHR requires "
5731                         "NonPrivateTexelKHR is also specified: OpImageWrite"));
5732 }
5733 
TEST_F(ValidateImage,VulkanMemoryModelDeviceScopeImageWriteBad)5734 TEST_F(ValidateImage, VulkanMemoryModelDeviceScopeImageWriteBad) {
5735   const std::string body = R"(
5736 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
5737 OpImageWrite %img %u32vec2_01 %u32vec4_0123 MakeTexelAvailableKHR|NonPrivateTexelKHR %u32_1
5738 )";
5739 
5740   const std::string extra = R"(
5741 OpCapability StorageImageWriteWithoutFormat
5742 OpCapability VulkanMemoryModelKHR
5743 OpExtension "SPV_KHR_vulkan_memory_model"
5744 )";
5745   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
5746                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
5747                           .c_str());
5748   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
5749             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5750   EXPECT_THAT(
5751       getDiagnosticString(),
5752       HasSubstr("Use of device scope with VulkanKHR memory model requires the "
5753                 "VulkanMemoryModelDeviceScopeKHR capability"));
5754 }
5755 
TEST_F(ValidateImage,VulkanMemoryModelDeviceScopeImageWriteGood)5756 TEST_F(ValidateImage, VulkanMemoryModelDeviceScopeImageWriteGood) {
5757   const std::string body = R"(
5758 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
5759 OpImageWrite %img %u32vec2_01 %u32vec4_0123 MakeTexelAvailableKHR|NonPrivateTexelKHR %u32_1
5760 )";
5761 
5762   const std::string extra = R"(
5763 OpCapability StorageImageWriteWithoutFormat
5764 OpCapability VulkanMemoryModelKHR
5765 OpCapability VulkanMemoryModelDeviceScopeKHR
5766 OpExtension "SPV_KHR_vulkan_memory_model"
5767 )";
5768   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
5769                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
5770                           .c_str());
5771   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5772 }
5773 
TEST_F(ValidateImage,VulkanMemoryModelDeviceScopeImageReadBad)5774 TEST_F(ValidateImage, VulkanMemoryModelDeviceScopeImageReadBad) {
5775   const std::string body = R"(
5776 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
5777 %res1 = OpImageRead %u32vec4 %img %u32vec2_01 MakeTexelVisibleKHR|NonPrivateTexelKHR %u32_1
5778 )";
5779 
5780   const std::string extra = R"(
5781 OpCapability StorageImageReadWithoutFormat
5782 OpCapability VulkanMemoryModelKHR
5783 OpExtension "SPV_KHR_vulkan_memory_model"
5784 )";
5785   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
5786                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
5787                           .c_str());
5788   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
5789             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5790   EXPECT_THAT(
5791       getDiagnosticString(),
5792       HasSubstr("Use of device scope with VulkanKHR memory model requires the "
5793                 "VulkanMemoryModelDeviceScopeKHR capability"));
5794 }
5795 
TEST_F(ValidateImage,VulkanMemoryModelDeviceScopeImageReadGood)5796 TEST_F(ValidateImage, VulkanMemoryModelDeviceScopeImageReadGood) {
5797   const std::string body = R"(
5798 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
5799 %res1 = OpImageRead %u32vec4 %img %u32vec2_01 MakeTexelVisibleKHR|NonPrivateTexelKHR %u32_1
5800 )";
5801 
5802   const std::string extra = R"(
5803 OpCapability StorageImageReadWithoutFormat
5804 OpCapability VulkanMemoryModelKHR
5805 OpCapability VulkanMemoryModelDeviceScopeKHR
5806 OpExtension "SPV_KHR_vulkan_memory_model"
5807 )";
5808   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
5809                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
5810                           .c_str());
5811   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5812 }
5813 
5814 // This example used to cause a seg fault on OpReturnValue, verifying it doesn't
5815 // anymore.
TEST_F(ValidateImage,Issue2463NoSegFault)5816 TEST_F(ValidateImage, Issue2463NoSegFault) {
5817   const std::string spirv = R"(
5818                OpCapability Linkage
5819                OpCapability Shader
5820           %1 = OpExtInstImport "GLSL.std.450"
5821                OpMemoryModel Logical GLSL450
5822        %void = OpTypeVoid
5823           %6 = OpTypeFunction %void
5824       %float = OpTypeFloat 32
5825           %8 = OpTypeImage %float 3D 0 0 0 1 Unknown
5826 %_ptr_UniformConstant_8 = OpTypePointer UniformConstant %8
5827          %10 = OpTypeSampler
5828 %_ptr_UniformConstant_10 = OpTypePointer UniformConstant %10
5829          %12 = OpTypeSampledImage %8
5830          %13 = OpTypeFunction %12 %_ptr_UniformConstant_8 %_ptr_UniformConstant_10
5831          %23 = OpFunction %12 None %13
5832          %24 = OpFunctionParameter %_ptr_UniformConstant_8
5833          %25 = OpFunctionParameter %_ptr_UniformConstant_10
5834          %26 = OpLabel
5835          %27 = OpLoad %8 %24
5836          %28 = OpLoad %10 %25
5837          %29 = OpSampledImage %12 %27 %28
5838                OpReturnValue %29
5839                OpFunctionEnd
5840 )";
5841 
5842   CompileSuccessfully(spirv);
5843   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5844   EXPECT_THAT(getDiagnosticString(),
5845               HasSubstr("OpSampledImage instruction must not appear as operand "
5846                         "for OpReturnValue"));
5847 }
5848 
TEST_F(ValidateImage,SignExtendV13Bad)5849 TEST_F(ValidateImage, SignExtendV13Bad) {
5850   const std::string body = R"(
5851 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
5852 %res1 = OpImageRead %u32vec4 %img %u32vec2_01 SignExtend
5853 )";
5854 
5855   CompileSuccessfully(
5856       GenerateShaderCode(body, "", "Fragment", "", SPV_ENV_UNIVERSAL_1_3));
5857   ASSERT_EQ(SPV_ERROR_WRONG_VERSION, ValidateInstructions());
5858   EXPECT_THAT(
5859       getDiagnosticString(),
5860       HasSubstr("SignExtend(4096) requires SPIR-V version 1.4 or later"));
5861 }
5862 
TEST_F(ValidateImage,ZeroExtendV13Bad)5863 TEST_F(ValidateImage, ZeroExtendV13Bad) {
5864   const std::string body = R"(
5865 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
5866 %res1 = OpImageRead %u32vec4 %img %u32vec2_01 ZeroExtend
5867 )";
5868 
5869   CompileSuccessfully(
5870       GenerateShaderCode(body, "", "Fragment", "", SPV_ENV_UNIVERSAL_1_3));
5871   ASSERT_EQ(SPV_ERROR_WRONG_VERSION, ValidateInstructions());
5872   EXPECT_THAT(
5873       getDiagnosticString(),
5874       HasSubstr("ZeroExtend(8192) requires SPIR-V version 1.4 or later"));
5875 }
5876 
TEST_F(ValidateImage,SignExtendScalarUIntTexelV14Good)5877 TEST_F(ValidateImage, SignExtendScalarUIntTexelV14Good) {
5878   // Unsigned int sampled type
5879   const std::string body = R"(
5880 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
5881 %res1 = OpImageRead %u32 %img %u32vec2_01 SignExtend
5882 )";
5883   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
5884 
5885   CompileSuccessfully(
5886       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4),
5887       SPV_ENV_UNIVERSAL_1_4);
5888   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
5889   EXPECT_THAT(getDiagnosticString(), Eq(""));
5890 }
5891 
TEST_F(ValidateImage,SignExtendScalarSIntTexelV14Good)5892 TEST_F(ValidateImage, SignExtendScalarSIntTexelV14Good) {
5893   // Signed int sampled type
5894   const std::string body = R"(
5895 %img = OpLoad %type_image_s32_2d_0002 %uniform_image_s32_2d_0002
5896 %res1 = OpImageRead %s32 %img %u32vec2_01 SignExtend
5897 )";
5898   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
5899 
5900   CompileSuccessfully(
5901       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4),
5902       SPV_ENV_UNIVERSAL_1_4);
5903   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
5904   EXPECT_THAT(getDiagnosticString(), Eq(""));
5905 }
5906 
TEST_F(ValidateImage,SignExtendScalarVectorUIntTexelV14Good)5907 TEST_F(ValidateImage, SignExtendScalarVectorUIntTexelV14Good) {
5908   const std::string body = R"(
5909 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
5910 %res1 = OpImageRead %u32vec4 %img %u32vec2_01 SignExtend
5911 )";
5912   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
5913 
5914   CompileSuccessfully(
5915       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4),
5916       SPV_ENV_UNIVERSAL_1_4);
5917   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
5918   EXPECT_THAT(getDiagnosticString(), Eq(""));
5919 }
5920 
TEST_F(ValidateImage,SignExtendVectorSIntTexelV14Good)5921 TEST_F(ValidateImage, SignExtendVectorSIntTexelV14Good) {
5922   const std::string body = R"(
5923 %img = OpLoad %type_image_s32_2d_0002 %uniform_image_s32_2d_0002
5924 %res1 = OpImageRead %s32vec4 %img %u32vec2_01 SignExtend
5925 )";
5926   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
5927 
5928   CompileSuccessfully(
5929       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4),
5930       SPV_ENV_UNIVERSAL_1_4);
5931   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
5932   EXPECT_THAT(getDiagnosticString(), Eq(""));
5933 }
5934 
5935 // No negative tests for SignExtend since we don't truly know the
5936 // texel format.
5937 
TEST_F(ValidateImage,ZeroExtendScalarUIntTexelV14Good)5938 TEST_F(ValidateImage, ZeroExtendScalarUIntTexelV14Good) {
5939   // Unsigned int sampled type
5940   const std::string body = R"(
5941 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
5942 %res1 = OpImageRead %u32 %img %u32vec2_01 ZeroExtend
5943 )";
5944   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
5945 
5946   CompileSuccessfully(
5947       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4),
5948       SPV_ENV_UNIVERSAL_1_4);
5949   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
5950   EXPECT_THAT(getDiagnosticString(), Eq(""));
5951 }
5952 
TEST_F(ValidateImage,ZeroExtendScalarSIntTexelV14Good)5953 TEST_F(ValidateImage, ZeroExtendScalarSIntTexelV14Good) {
5954   // Zeroed int sampled type
5955   const std::string body = R"(
5956 %img = OpLoad %type_image_s32_2d_0002 %uniform_image_s32_2d_0002
5957 %res1 = OpImageRead %s32 %img %u32vec2_01 ZeroExtend
5958 )";
5959   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
5960 
5961   CompileSuccessfully(
5962       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4),
5963       SPV_ENV_UNIVERSAL_1_4);
5964   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
5965   EXPECT_THAT(getDiagnosticString(), Eq(""));
5966 }
5967 
TEST_F(ValidateImage,ZeroExtendScalarVectorUIntTexelV14Good)5968 TEST_F(ValidateImage, ZeroExtendScalarVectorUIntTexelV14Good) {
5969   const std::string body = R"(
5970 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
5971 %res1 = OpImageRead %u32vec4 %img %u32vec2_01 ZeroExtend
5972 )";
5973   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
5974 
5975   CompileSuccessfully(
5976       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4),
5977       SPV_ENV_UNIVERSAL_1_4);
5978   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
5979   EXPECT_THAT(getDiagnosticString(), Eq(""));
5980 }
5981 
TEST_F(ValidateImage,ZeroExtendVectorSIntTexelV14Good)5982 TEST_F(ValidateImage, ZeroExtendVectorSIntTexelV14Good) {
5983   const std::string body = R"(
5984 %img = OpLoad %type_image_s32_2d_0002 %uniform_image_s32_2d_0002
5985 %res1 = OpImageRead %s32vec4 %img %u32vec2_01 ZeroExtend
5986 )";
5987   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
5988 
5989   CompileSuccessfully(
5990       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4),
5991       SPV_ENV_UNIVERSAL_1_4);
5992   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
5993   EXPECT_THAT(getDiagnosticString(), Eq(""));
5994 }
5995 
TEST_F(ValidateImage,ReadLodAMDSuccess1)5996 TEST_F(ValidateImage, ReadLodAMDSuccess1) {
5997   const std::string body = R"(
5998 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
5999 %res1 = OpImageRead %u32vec4 %img %u32vec2_01 Lod %u32_0
6000 )";
6001 
6002   const std::string extra =
6003       "\nOpCapability StorageImageReadWithoutFormat\n"
6004       "OpCapability ImageReadWriteLodAMD\n"
6005       "OpExtension \"SPV_AMD_shader_image_load_store_lod\"\n";
6006   CompileSuccessfully(
6007       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_1),
6008       SPV_ENV_UNIVERSAL_1_1);
6009   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
6010 }
6011 
TEST_F(ValidateImage,ReadLodAMDSuccess2)6012 TEST_F(ValidateImage, ReadLodAMDSuccess2) {
6013   const std::string body = R"(
6014 %img = OpLoad %type_image_f32_1d_0002_rgba32f %uniform_image_f32_1d_0002_rgba32f
6015 %res1 = OpImageRead %f32vec4 %img %u32vec2_01 Lod %u32_0
6016 )";
6017 
6018   const std::string extra =
6019       "\nOpCapability Image1D\n"
6020       "OpCapability ImageReadWriteLodAMD\n"
6021       "OpExtension \"SPV_AMD_shader_image_load_store_lod\"\n";
6022   CompileSuccessfully(
6023       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_1),
6024       SPV_ENV_UNIVERSAL_1_1);
6025   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
6026 }
6027 
TEST_F(ValidateImage,ReadLodAMDSuccess3)6028 TEST_F(ValidateImage, ReadLodAMDSuccess3) {
6029   const std::string body = R"(
6030 %img = OpLoad %type_image_f32_cube_0102_rgba32f %uniform_image_f32_cube_0102_rgba32f
6031 %res1 = OpImageRead %f32vec4 %img %u32vec3_012 Lod %u32_0
6032 )";
6033 
6034   const std::string extra =
6035       "\nOpCapability ImageCubeArray\n"
6036       "OpCapability ImageReadWriteLodAMD\n"
6037       "OpExtension \"SPV_AMD_shader_image_load_store_lod\"\n";
6038   CompileSuccessfully(
6039       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_1),
6040       SPV_ENV_UNIVERSAL_1_1);
6041   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
6042 }
6043 
TEST_F(ValidateImage,ReadLodAMDNeedCapability)6044 TEST_F(ValidateImage, ReadLodAMDNeedCapability) {
6045   const std::string body = R"(
6046 %img = OpLoad %type_image_f32_cube_0102_rgba32f %uniform_image_f32_cube_0102_rgba32f
6047 %res1 = OpImageRead %f32vec4 %img %u32vec3_012 Lod %u32_0
6048 )";
6049 
6050   const std::string extra = "\nOpCapability ImageCubeArray\n";
6051   CompileSuccessfully(
6052       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_1),
6053       SPV_ENV_UNIVERSAL_1_1);
6054   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
6055             ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
6056   EXPECT_THAT(getDiagnosticString(),
6057               HasSubstr("Image Operand Lod can only be used with ExplicitLod "
6058                         "opcodes and OpImageFetch"));
6059 }
6060 
TEST_F(ValidateImage,WriteLodAMDSuccess1)6061 TEST_F(ValidateImage, WriteLodAMDSuccess1) {
6062   const std::string body = R"(
6063 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
6064 OpImageWrite %img %u32vec2_01 %u32vec4_0123 Lod %u32_0
6065 )";
6066 
6067   const std::string extra =
6068       "\nOpCapability StorageImageWriteWithoutFormat\n"
6069       "OpCapability ImageReadWriteLodAMD\n"
6070       "OpExtension \"SPV_AMD_shader_image_load_store_lod\"\n";
6071   CompileSuccessfully(
6072       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_1),
6073       SPV_ENV_UNIVERSAL_1_1);
6074   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
6075 }
6076 
TEST_F(ValidateImage,WriteLodAMDSuccess2)6077 TEST_F(ValidateImage, WriteLodAMDSuccess2) {
6078   const std::string body = R"(
6079 %img = OpLoad %type_image_f32_1d_0002_rgba32f %uniform_image_f32_1d_0002_rgba32f
6080 OpImageWrite %img %u32_1 %f32vec4_0000 Lod %u32_0
6081 )";
6082 
6083   const std::string extra =
6084       "\nOpCapability Image1D\n"
6085       "OpCapability ImageReadWriteLodAMD\n"
6086       "OpExtension \"SPV_AMD_shader_image_load_store_lod\"\n";
6087   CompileSuccessfully(
6088       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_1),
6089       SPV_ENV_UNIVERSAL_1_1);
6090   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
6091 }
6092 
TEST_F(ValidateImage,WriteLodAMDSuccess3)6093 TEST_F(ValidateImage, WriteLodAMDSuccess3) {
6094   const std::string body = R"(
6095 %img = OpLoad %type_image_f32_cube_0102_rgba32f %uniform_image_f32_cube_0102_rgba32f
6096 OpImageWrite %img %u32vec3_012 %f32vec4_0000 Lod %u32_0
6097 )";
6098 
6099   const std::string extra =
6100       "\nOpCapability ImageCubeArray\n"
6101       "OpCapability ImageReadWriteLodAMD\n"
6102       "OpExtension \"SPV_AMD_shader_image_load_store_lod\"\n";
6103   CompileSuccessfully(
6104       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_1),
6105       SPV_ENV_UNIVERSAL_1_1);
6106   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
6107 }
6108 
TEST_F(ValidateImage,WriteLodAMDNeedCapability)6109 TEST_F(ValidateImage, WriteLodAMDNeedCapability) {
6110   const std::string body = R"(
6111 %img = OpLoad %type_image_f32_cube_0102_rgba32f %uniform_image_f32_cube_0102_rgba32f
6112 OpImageWrite %img %u32vec3_012 %f32vec4_0000 Lod %u32_0
6113 )";
6114 
6115   const std::string extra = "\nOpCapability ImageCubeArray\n";
6116   CompileSuccessfully(
6117       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_1),
6118       SPV_ENV_UNIVERSAL_1_1);
6119   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
6120             ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
6121   EXPECT_THAT(getDiagnosticString(),
6122               HasSubstr("Image Operand Lod can only be used with ExplicitLod "
6123                         "opcodes and OpImageFetch"));
6124 }
6125 
TEST_F(ValidateImage,SparseReadLodAMDSuccess)6126 TEST_F(ValidateImage, SparseReadLodAMDSuccess) {
6127   const std::string body = R"(
6128 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
6129 %res1 = OpImageSparseRead %struct_u32_f32vec4 %img %u32vec2_01 Lod %u32_0
6130 )";
6131 
6132   const std::string extra =
6133       "\nOpCapability StorageImageReadWithoutFormat\n"
6134       "OpCapability ImageReadWriteLodAMD\n"
6135       "OpExtension \"SPV_AMD_shader_image_load_store_lod\"\n";
6136   CompileSuccessfully(
6137       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_1),
6138       SPV_ENV_UNIVERSAL_1_1);
6139   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
6140 }
6141 
TEST_F(ValidateImage,SparseReadLodAMDNeedCapability)6142 TEST_F(ValidateImage, SparseReadLodAMDNeedCapability) {
6143   const std::string body = R"(
6144 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
6145 %res1 = OpImageSparseRead %struct_u32_f32vec4 %img %u32vec2_01 Lod %u32_0
6146 )";
6147 
6148   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
6149   CompileSuccessfully(
6150       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_1),
6151       SPV_ENV_UNIVERSAL_1_1);
6152   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
6153             ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
6154   EXPECT_THAT(getDiagnosticString(),
6155               HasSubstr("Image Operand Lod can only be used with ExplicitLod "
6156                         "opcodes and OpImageFetch"));
6157 }
6158 
TEST_F(ValidateImage,GatherBiasAMDSuccess)6159 TEST_F(ValidateImage, GatherBiasAMDSuccess) {
6160   const std::string body = R"(
6161 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
6162 %sampler = OpLoad %type_sampler %uniform_sampler
6163 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
6164 %res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 Bias %f32_1
6165 )";
6166 
6167   const std::string extra = R"(
6168 OpCapability ImageGatherBiasLodAMD
6169 OpExtension "SPV_AMD_texture_gather_bias_lod"
6170 )";
6171   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
6172   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
6173 }
6174 
TEST_F(ValidateImage,GatherLodAMDSuccess)6175 TEST_F(ValidateImage, GatherLodAMDSuccess) {
6176   const std::string body = R"(
6177 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
6178 %sampler = OpLoad %type_sampler %uniform_sampler
6179 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
6180 %res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 Lod %f32_1
6181 )";
6182 
6183   const std::string extra = R"(
6184 OpCapability ImageGatherBiasLodAMD
6185 OpExtension "SPV_AMD_texture_gather_bias_lod"
6186 )";
6187   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
6188   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
6189 }
6190 
TEST_F(ValidateImage,SparseGatherBiasAMDSuccess)6191 TEST_F(ValidateImage, SparseGatherBiasAMDSuccess) {
6192   const std::string body = R"(
6193 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
6194 %sampler = OpLoad %type_sampler %uniform_sampler
6195 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
6196 %res1 = OpImageSparseGather %struct_u32_f32vec4 %simg %f32vec4_0000 %u32_1 Bias %f32_1
6197 )";
6198 
6199   const std::string extra = R"(
6200 OpCapability ImageGatherBiasLodAMD
6201 OpExtension "SPV_AMD_texture_gather_bias_lod"
6202 )";
6203   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
6204   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
6205 }
6206 
TEST_F(ValidateImage,SparseGatherLodAMDSuccess)6207 TEST_F(ValidateImage, SparseGatherLodAMDSuccess) {
6208   const std::string body = R"(
6209 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
6210 %sampler = OpLoad %type_sampler %uniform_sampler
6211 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
6212 %res1 = OpImageSparseGather %struct_u32_f32vec4 %simg %f32vec4_0000 %u32_1 Lod %f32_1
6213 )";
6214 
6215   const std::string extra = R"(
6216 OpCapability ImageGatherBiasLodAMD
6217 OpExtension "SPV_AMD_texture_gather_bias_lod"
6218 )";
6219   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
6220   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
6221 }
6222 
6223 // No negative tests for ZeroExtend since we don't truly know the
6224 // texel format.
6225 
6226 // Tests for 64-bit images
6227 static const std::string capabilities_and_extensions_image64 = R"(
6228 OpCapability Int64ImageEXT
6229 OpExtension "SPV_EXT_shader_image_int64"
6230 )";
6231 static const std::string capabilities_and_extensions_image64_atomic = R"(
6232 OpCapability Int64Atomics
6233 OpCapability Int64ImageEXT
6234 OpExtension "SPV_EXT_shader_image_int64"
6235 )";
6236 static const std::string declarations_image64 = R"(
6237 %type_image_u64_buffer_0002_r64ui = OpTypeImage %u64 Buffer 0 0 0 2 R64ui
6238 %ptr_Image_u64 = OpTypePointer Image %u64
6239 %ptr_image_u64_buffer_0002_r64ui = OpTypePointer Private %type_image_u64_buffer_0002_r64ui
6240 %private_image_u64_buffer_0002_r64ui = OpVariable %ptr_image_u64_buffer_0002_r64ui Private
6241 )";
6242 static const std::string declarations_image64i = R"(
6243 %type_image_s64_buffer_0002_r64i = OpTypeImage %s64 Buffer 0 0 0 2 R64i
6244 %ptr_Image_s64 = OpTypePointer Image %s64
6245 %ptr_image_s64_buffer_0002_r64i = OpTypePointer Private %type_image_s64_buffer_0002_r64i
6246 %private_image_s64_buffer_0002_r64i = OpVariable %ptr_image_s64_buffer_0002_r64i Private
6247 )";
6248 
TEST_F(ValidateImage,Image64MissingCapability)6249 TEST_F(ValidateImage, Image64MissingCapability) {
6250   CompileSuccessfully(GenerateShaderCode("", "", "Fragment", "",
6251                                          SPV_ENV_UNIVERSAL_1_3, "GLSL450",
6252                                          declarations_image64)
6253                           .c_str());
6254   ASSERT_EQ(SPV_ERROR_INVALID_CAPABILITY, ValidateInstructions());
6255 }
6256 
TEST_F(ValidateImage,Image64MissingExtension)6257 TEST_F(ValidateImage, Image64MissingExtension) {
6258   const std::string extra = R"(
6259 OpCapability Int64ImageEXT
6260 )";
6261 
6262   CompileSuccessfully(GenerateShaderCode("", extra, "Fragment", "",
6263                                          SPV_ENV_UNIVERSAL_1_3, "GLSL450",
6264                                          declarations_image64)
6265                           .c_str());
6266   ASSERT_EQ(SPV_ERROR_MISSING_EXTENSION, ValidateInstructions());
6267 }
6268 
TEST_F(ValidateImage,ImageTexelPointer64Success)6269 TEST_F(ValidateImage, ImageTexelPointer64Success) {
6270   const std::string body = R"(
6271 %texel_ptr = OpImageTexelPointer %ptr_Image_u64 %private_image_u64_buffer_0002_r64ui %u32_0 %u32_0
6272 %sum = OpAtomicIAdd %u64 %texel_ptr %u32_1 %u32_0 %u64_1
6273 )";
6274 
6275   CompileSuccessfully(
6276       GenerateShaderCode(body, capabilities_and_extensions_image64_atomic,
6277                          "Fragment", "", SPV_ENV_UNIVERSAL_1_3, "GLSL450",
6278                          declarations_image64)
6279           .c_str());
6280   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
6281 }
6282 
TEST_F(ValidateImage,ImageTexelPointer64ResultTypeNotPointer)6283 TEST_F(ValidateImage, ImageTexelPointer64ResultTypeNotPointer) {
6284   const std::string body = R"(
6285 %texel_ptr = OpImageTexelPointer %type_image_u64_buffer_0002_r64ui %private_image_u64_buffer_0002_r64ui %u32_0 %u32_0
6286 %sum = OpAtomicIAdd %u64 %texel_ptr %u32_1 %u32_0 %u64_1
6287 )";
6288 
6289   CompileSuccessfully(
6290       GenerateShaderCode(body, capabilities_and_extensions_image64_atomic,
6291                          "Fragment", "", SPV_ENV_UNIVERSAL_1_3, "GLSL450",
6292                          declarations_image64)
6293           .c_str());
6294   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
6295   EXPECT_THAT(getDiagnosticString(),
6296               HasSubstr("Expected Result Type to be OpTypePointer"));
6297 }
6298 
TEST_F(ValidateImage,ImageTexelPointer64ResultTypeNotImageClass)6299 TEST_F(ValidateImage, ImageTexelPointer64ResultTypeNotImageClass) {
6300   const std::string body = R"(
6301 %texel_ptr = OpImageTexelPointer %ptr_image_f32_cube_0101 %private_image_u64_buffer_0002_r64ui %u32_0 %u32_0
6302 %sum = OpAtomicIAdd %u64 %texel_ptr %u32_1 %u32_0 %u64_1
6303 )";
6304 
6305   CompileSuccessfully(
6306       GenerateShaderCode(body, capabilities_and_extensions_image64_atomic,
6307                          "Fragment", "", SPV_ENV_UNIVERSAL_1_3, "GLSL450",
6308                          declarations_image64)
6309           .c_str());
6310   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
6311   EXPECT_THAT(getDiagnosticString(),
6312               HasSubstr("Expected Result Type to be OpTypePointer whose "
6313                         "Storage Class operand is Image"));
6314 }
6315 
TEST_F(ValidateImage,ImageTexelPointer64SampleNotZeroForImageWithMSZero)6316 TEST_F(ValidateImage, ImageTexelPointer64SampleNotZeroForImageWithMSZero) {
6317   const std::string body = R"(
6318 %texel_ptr = OpImageTexelPointer %ptr_Image_u64 %private_image_u64_buffer_0002_r64ui %u32_0 %u32_1
6319 %sum = OpAtomicIAdd %u64 %texel_ptr %u32_1 %u32_0 %u64_1
6320 )";
6321 
6322   CompileSuccessfully(
6323       GenerateShaderCode(body, capabilities_and_extensions_image64_atomic,
6324                          "Fragment", "", SPV_ENV_UNIVERSAL_1_3, "GLSL450",
6325                          declarations_image64)
6326           .c_str());
6327   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
6328   EXPECT_THAT(getDiagnosticString(),
6329               HasSubstr("Expected Sample for Image with MS 0 to be a valid "
6330                         "<id> for the value 0"));
6331 }
6332 
TEST_F(ValidateImage,ImageTexelPointerR32uiSuccessVulkan)6333 TEST_F(ValidateImage, ImageTexelPointerR32uiSuccessVulkan) {
6334   const std::string body = R"(
6335 %texel_ptr = OpImageTexelPointer %ptr_Image_u32 %private_image_u32_buffer_0002_r32ui %u32_0 %u32_0
6336 )";
6337 
6338   spv_target_env env = SPV_ENV_VULKAN_1_0;
6339   CompileSuccessfully(GenerateShaderCode(body, "", "Fragment", "", env).c_str(),
6340                       env);
6341   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(env));
6342 }
6343 
TEST_F(ValidateImage,ImageTexelPointerR32iSuccessVulkan)6344 TEST_F(ValidateImage, ImageTexelPointerR32iSuccessVulkan) {
6345   const std::string& declarations = R"(
6346 %type_image_s32_buffer_0002_r32i = OpTypeImage %s32 Buffer 0 0 0 2 R32i
6347 %ptr_Image_s32 = OpTypePointer Image %s32
6348 %ptr_image_s32_buffer_0002_r32i = OpTypePointer Private %type_image_s32_buffer_0002_r32i
6349 %private_image_s32_buffer_0002_r32i = OpVariable %ptr_image_s32_buffer_0002_r32i Private
6350 )";
6351 
6352   const std::string body = R"(
6353 %texel_ptr = OpImageTexelPointer %ptr_Image_s32 %private_image_s32_buffer_0002_r32i %u32_0 %u32_0
6354 )";
6355 
6356   spv_target_env env = SPV_ENV_VULKAN_1_0;
6357   CompileSuccessfully(
6358       GenerateShaderCode(body, "", "Fragment", "", env, "GLSL450", declarations)
6359           .c_str(),
6360       env);
6361   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(env));
6362 }
6363 
TEST_F(ValidateImage,ImageTexelPointerR64uiSuccessVulkan)6364 TEST_F(ValidateImage, ImageTexelPointerR64uiSuccessVulkan) {
6365   const std::string body = R"(
6366 %texel_ptr = OpImageTexelPointer %ptr_Image_u64 %private_image_u64_buffer_0002_r64ui %u32_0 %u32_0
6367 )";
6368 
6369   spv_target_env env = SPV_ENV_VULKAN_1_0;
6370   CompileSuccessfully(
6371       GenerateShaderCode(body, capabilities_and_extensions_image64, "Fragment",
6372                          "", env, "GLSL450", declarations_image64)
6373           .c_str(),
6374       env);
6375   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(env));
6376 }
6377 
TEST_F(ValidateImage,ImageTexelPointerR64iSuccessVulkan)6378 TEST_F(ValidateImage, ImageTexelPointerR64iSuccessVulkan) {
6379   const std::string body = R"(
6380 %texel_ptr = OpImageTexelPointer %ptr_Image_s64 %private_image_s64_buffer_0002_r64i %u32_0 %u32_0
6381 )";
6382 
6383   spv_target_env env = SPV_ENV_VULKAN_1_0;
6384   CompileSuccessfully(
6385       GenerateShaderCode(body, capabilities_and_extensions_image64, "Fragment",
6386                          "", env, "GLSL450", declarations_image64i)
6387           .c_str(),
6388       env);
6389   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(env));
6390 }
6391 
TEST_F(ValidateImage,ImageTexelPointerR32fSuccessVulkan)6392 TEST_F(ValidateImage, ImageTexelPointerR32fSuccessVulkan) {
6393   const std::string& declarations = R"(
6394 %type_image_f32_buffer_0002_r32f = OpTypeImage %f32 Buffer 0 0 0 2 R32f
6395 %ptr_image_f32_buffer_0002_r32f = OpTypePointer Private %type_image_f32_buffer_0002_r32f
6396 %private_image_f32_buffer_0002_r32f = OpVariable %ptr_image_f32_buffer_0002_r32f Private
6397 )";
6398 
6399   const std::string body = R"(
6400 %texel_ptr = OpImageTexelPointer %ptr_Image_f32 %private_image_f32_buffer_0002_r32f %u32_0 %u32_0
6401 )";
6402 
6403   spv_target_env env = SPV_ENV_VULKAN_1_0;
6404   CompileSuccessfully(
6405       GenerateShaderCode(body, "", "Fragment", "", env, "GLSL450", declarations)
6406           .c_str(),
6407       env);
6408   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(env));
6409 }
6410 
TEST_F(ValidateImage,ImageTexelPointerRgba32iVulkan)6411 TEST_F(ValidateImage, ImageTexelPointerRgba32iVulkan) {
6412   const std::string& declarations = R"(
6413 %type_image_s32_buffer_0002_rgba32i = OpTypeImage %s32 Buffer 0 0 0 2 Rgba32i
6414 %ptr_Image_s32 = OpTypePointer Image %s32
6415 %ptr_image_s32_buffer_0002_rgba32i = OpTypePointer Private %type_image_s32_buffer_0002_rgba32i
6416 %private_image_s32_buffer_0002_rgba32i = OpVariable %ptr_image_s32_buffer_0002_rgba32i Private
6417 )";
6418 
6419   const std::string body = R"(
6420 %texel_ptr = OpImageTexelPointer %ptr_Image_s32 %private_image_s32_buffer_0002_rgba32i %u32_0 %u32_0
6421 )";
6422 
6423   spv_target_env env = SPV_ENV_VULKAN_1_0;
6424   CompileSuccessfully(
6425       GenerateShaderCode(body, "", "Fragment", "", env, "GLSL450", declarations)
6426           .c_str(),
6427       env);
6428   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
6429   EXPECT_THAT(getDiagnosticString(),
6430               AnyVUID("VUID-StandaloneSpirv-OpImageTexelPointer-04658"));
6431   EXPECT_THAT(getDiagnosticString(),
6432               HasSubstr("Expected the Image Format in Image to be R64i, R64ui, "
6433                         "R32f, R32i, or R32ui for Vulkan environment"));
6434 }
6435 
TEST_F(ValidateImage,ImageTexelPointerRgba16fVulkan)6436 TEST_F(ValidateImage, ImageTexelPointerRgba16fVulkan) {
6437   const std::string& declarations = R"(
6438 %type_image_s32_buffer_0002_rgba16f = OpTypeImage %s32 Buffer 0 0 0 2 Rgba16f
6439 %ptr_Image_s32 = OpTypePointer Image %s32
6440 %ptr_image_s32_buffer_0002_rgba16f = OpTypePointer Private %type_image_s32_buffer_0002_rgba16f
6441 %private_image_s32_buffer_0002_rgba16f = OpVariable %ptr_image_s32_buffer_0002_rgba16f Private
6442 )";
6443 
6444   const std::string body = R"(
6445 %texel_ptr = OpImageTexelPointer %ptr_Image_s32 %private_image_s32_buffer_0002_rgba16f %u32_0 %u32_0
6446 )";
6447 
6448   spv_target_env env = SPV_ENV_VULKAN_1_0;
6449   CompileSuccessfully(
6450       GenerateShaderCode(body, "", "Fragment", "", env, "GLSL450", declarations)
6451           .c_str(),
6452       env);
6453   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
6454   EXPECT_THAT(getDiagnosticString(),
6455               AnyVUID("VUID-StandaloneSpirv-OpImageTexelPointer-04658"));
6456   EXPECT_THAT(getDiagnosticString(),
6457               HasSubstr("Expected the Image Format in Image to be R64i, R64ui, "
6458                         "R32f, R32i, or R32ui for Vulkan environment"));
6459 }
6460 
TEST_F(ValidateImage,ImageExecutionModeLimitationNoMode)6461 TEST_F(ValidateImage, ImageExecutionModeLimitationNoMode) {
6462   const std::string text = R"(
6463 OpCapability Shader
6464 OpMemoryModel Logical GLSL450
6465 OpEntryPoint GLCompute %2 " " %4
6466 %void = OpTypeVoid
6467 %8 = OpTypeFunction %void
6468 %float = OpTypeFloat 32
6469 %v4float = OpTypeVector %float 4
6470 %12 = OpTypeImage %float 2D 0 0 0 1 Rgba8ui
6471 %13 = OpTypeSampledImage %12
6472 %_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
6473 %5 = OpVariable %_ptr_UniformConstant_13 UniformConstant
6474 %_ptr_Input_v4float = OpTypePointer Input %v4float
6475 %4 = OpVariable %_ptr_Input_v4float Input
6476 %v2float = OpTypeVector %float 2
6477 %float_1_35631564en19 = OpConstant %float 1.35631564e-19
6478 %2 = OpFunction %void None %8
6479 %8224 = OpLabel
6480 %6 = OpLoad %13 %5
6481 %19 = OpLoad %v4float %4
6482 %20 = OpVectorShuffle %v2float %19 %19 0 1
6483 %21 = OpVectorTimesScalar %v2float %20 %float_1_35631564en19
6484 %65312 = OpImageSampleImplicitLod %v4float %6 %21
6485 OpUnreachable
6486 OpFunctionEnd
6487 )";
6488 
6489   CompileSuccessfully(text);
6490   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6491   EXPECT_THAT(getDiagnosticString(),
6492               HasSubstr("ImplicitLod instructions require "
6493                         "DerivativeGroupQuadsNV or DerivativeGroupLinearNV "
6494                         "execution mode for GLCompute execution model"));
6495 }
6496 
TEST_F(ValidateImage,TypeSampledImageNotBufferPost1p6)6497 TEST_F(ValidateImage, TypeSampledImageNotBufferPost1p6) {
6498   const std::string text = R"(
6499 OpCapability Shader
6500 OpCapability Linkage
6501 OpCapability SampledBuffer
6502 OpMemoryModel Logical GLSL450
6503 %float = OpTypeFloat 32
6504 %image = OpTypeImage %float Buffer 0 0 0 1 Unknown
6505 %sampled = OpTypeSampledImage %image
6506 )";
6507 
6508   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_6);
6509   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_6));
6510   EXPECT_THAT(getDiagnosticString(),
6511               HasSubstr("In SPIR-V 1.6 or later, sampled image dimension must "
6512                         "not be Buffer"));
6513 }
6514 
TEST_F(ValidateImage,NonTemporalImage)6515 TEST_F(ValidateImage, NonTemporalImage) {
6516   const std::string text = R"(
6517 OpCapability Shader
6518 OpMemoryModel Logical GLSL450
6519 OpEntryPoint Fragment %2 " " %4 %5
6520 OpExecutionMode %2 OriginUpperLeft
6521 %void = OpTypeVoid
6522 %8 = OpTypeFunction %void
6523 %float = OpTypeFloat 32
6524 %v4float = OpTypeVector %float 4
6525 %12 = OpTypeImage %float 2D 0 0 0 1 Rgba8ui
6526 %13 = OpTypeSampledImage %12
6527 %_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
6528 %5 = OpVariable %_ptr_UniformConstant_13 UniformConstant
6529 %_ptr_Input_v4float = OpTypePointer Input %v4float
6530 %4 = OpVariable %_ptr_Input_v4float Input
6531 %v2float = OpTypeVector %float 2
6532 %float_1_35631564en19 = OpConstant %float 1.35631564e-19
6533 %2 = OpFunction %void None %8
6534 %8224 = OpLabel
6535 %6 = OpLoad %13 %5
6536 %19 = OpLoad %v4float %4
6537 %20 = OpVectorShuffle %v2float %19 %19 0 1
6538 %21 = OpVectorTimesScalar %v2float %20 %float_1_35631564en19
6539 %65312 = OpImageSampleImplicitLod %v4float %6 %21 Nontemporal
6540 OpReturn
6541 OpFunctionEnd
6542 )";
6543 
6544   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_6);
6545   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_6));
6546 }
6547 
TEST_F(ValidateImage,NVBindlessSamplerBuiltins)6548 TEST_F(ValidateImage, NVBindlessSamplerBuiltins) {
6549   const std::string text = R"(
6550               OpCapability Shader
6551               OpCapability Int64
6552               OpCapability Image1D
6553               OpCapability BindlessTextureNV
6554               OpExtension "SPV_NV_bindless_texture"
6555          %1 = OpExtInstImport "GLSL.std.450"
6556               OpMemoryModel Logical GLSL450
6557               OpSamplerImageAddressingModeNV 64
6558               OpEntryPoint Fragment %main "main"
6559               OpExecutionMode %main OriginUpperLeft
6560               OpSource GLSL 450
6561               OpName %main "main"
6562               OpName %s2D "s2D"
6563               OpName %textureHandle "textureHandle"
6564               OpName %i1D "i1D"
6565               OpName %s "s"
6566               OpName %temp "temp"
6567       %void = OpTypeVoid
6568          %3 = OpTypeFunction %void
6569      %float = OpTypeFloat 32
6570          %7 = OpTypeImage %float 2D 0 0 0 1 Unknown
6571          %8 = OpTypeSampledImage %7
6572 %_ptr_Function_8 = OpTypePointer Function %8
6573      %ulong = OpTypeInt 64 0
6574 %_ptr_Private_ulong = OpTypePointer Private %ulong
6575 %textureHandle = OpVariable %_ptr_Private_ulong Private
6576         %16 = OpTypeImage %float 1D 0 0 0 2 Rgba32f
6577 %_ptr_Function_16 = OpTypePointer Function %16
6578         %21 = OpTypeSampler
6579 %_ptr_Function_21 = OpTypePointer Function %21
6580 %_ptr_Function_ulong = OpTypePointer Function %ulong
6581       %main = OpFunction %void None %3
6582          %5 = OpLabel
6583        %s2D = OpVariable %_ptr_Function_8 Function
6584        %i1D = OpVariable %_ptr_Function_16 Function
6585          %s = OpVariable %_ptr_Function_21 Function
6586       %temp = OpVariable %_ptr_Function_ulong Function
6587         %14 = OpLoad %ulong %textureHandle
6588         %15 = OpConvertUToSampledImageNV %8 %14
6589               OpStore %s2D %15
6590         %19 = OpLoad %ulong %textureHandle
6591         %20 = OpConvertUToImageNV %16 %19
6592               OpStore %i1D %20
6593         %24 = OpLoad %ulong %textureHandle
6594         %25 = OpConvertUToSamplerNV %21 %24
6595               OpStore %s %25
6596         %28 = OpLoad %8 %s2D
6597         %29 = OpConvertSampledImageToUNV %ulong %28
6598               OpStore %temp %29
6599         %30 = OpLoad %16 %i1D
6600         %31 = OpConvertImageToUNV %ulong %30
6601               OpStore %temp %31
6602         %32 = OpLoad %21 %s
6603         %33 = OpConvertSamplerToUNV %ulong %32
6604               OpStore %temp %33
6605               OpReturn
6606               OpFunctionEnd
6607 )";
6608 
6609   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
6610   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6611 }
6612 
TEST_F(ValidateImage,NVBindlessAddressingMode64)6613 TEST_F(ValidateImage, NVBindlessAddressingMode64) {
6614   std::string text = R"(
6615          OpCapability Shader
6616          OpCapability BindlessTextureNV
6617          OpExtension "SPV_NV_bindless_texture"
6618          OpMemoryModel Logical GLSL450
6619          OpSamplerImageAddressingModeNV 64
6620          OpEntryPoint GLCompute %func "main"
6621 %voidt = OpTypeVoid
6622 %uintt = OpTypeInt 32 0
6623 %funct = OpTypeFunction %voidt
6624 %func  = OpFunction %voidt None %funct
6625 %entry = OpLabel
6626 %udef  = OpUndef %uintt
6627          OpReturn
6628          OpFunctionEnd
6629 )";
6630   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
6631   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6632 }
6633 
TEST_F(ValidateImage,NVBindlessAddressingMode32)6634 TEST_F(ValidateImage, NVBindlessAddressingMode32) {
6635   std::string text = R"(
6636          OpCapability Shader
6637          OpCapability BindlessTextureNV
6638          OpExtension "SPV_NV_bindless_texture"
6639          OpMemoryModel Logical GLSL450
6640          OpSamplerImageAddressingModeNV 32
6641          OpEntryPoint GLCompute %func "main"
6642 %voidt = OpTypeVoid
6643 %uintt = OpTypeInt 32 0
6644 %funct = OpTypeFunction %voidt
6645 %func  = OpFunction %voidt None %funct
6646 %entry = OpLabel
6647 %udef  = OpUndef %uintt
6648          OpReturn
6649          OpFunctionEnd
6650 )";
6651   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
6652   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6653 }
6654 
TEST_F(ValidateImage,NVBindlessInvalidAddressingMode)6655 TEST_F(ValidateImage, NVBindlessInvalidAddressingMode) {
6656   std::string text = R"(
6657          OpCapability Shader
6658          OpCapability BindlessTextureNV
6659          OpExtension "SPV_NV_bindless_texture"
6660          OpMemoryModel Logical GLSL450
6661          OpSamplerImageAddressingModeNV 0
6662          OpEntryPoint GLCompute %func "main"
6663 %voidt = OpTypeVoid
6664 %uintt = OpTypeInt 32 0
6665 %funct = OpTypeFunction %voidt
6666 %func  = OpFunction %voidt None %funct
6667 %entry = OpLabel
6668 %udef  = OpUndef %uintt
6669          OpReturn
6670          OpFunctionEnd
6671 )";
6672   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
6673   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
6674             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6675   EXPECT_THAT(
6676       getDiagnosticString(),
6677       HasSubstr("OpSamplerImageAddressingModeNV bitwidth should be 64 or 32"));
6678 }
6679 
TEST_F(ValidateImage,QCOMImageProcessingBlockMatchSADNoDecorationA)6680 TEST_F(ValidateImage, QCOMImageProcessingBlockMatchSADNoDecorationA) {
6681   std::string text = R"(
6682            OpCapability Shader
6683            OpCapability TextureBlockMatchQCOM
6684            OpExtension "SPV_QCOM_image_processing"
6685       %1 = OpExtInstImport "GLSL.std.450"
6686            OpMemoryModel Logical GLSL450
6687            OpEntryPoint Fragment %2 "main" %3 %4 %5 %6
6688            OpExecutionMode %2 OriginUpperLeft
6689            OpDecorate %3 Location 0
6690            OpDecorate %4 DescriptorSet 0
6691            OpDecorate %4 Binding 1
6692            OpDecorate %5 DescriptorSet 0
6693            OpDecorate %5 Binding 3
6694            OpDecorate %6 DescriptorSet 0
6695            OpDecorate %6 Binding 2
6696            OpDecorate %6 BlockMatchTextureQCOM
6697    %void = OpTypeVoid
6698       %8 = OpTypeFunction %void
6699    %uint = OpTypeInt 32 0
6700  %v2uint = OpTypeVector %uint 2
6701 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
6702   %float = OpTypeFloat 32
6703 %v4float = OpTypeVector %float 4
6704 %_ptr_Input_float = OpTypePointer Input %float
6705 %_ptr_Function_uint = OpTypePointer Function %uint
6706 %uint_4 = OpConstant %uint 4
6707     %17 = OpConstantComposite %v2uint %uint_4 %uint_4
6708 %_ptr_Output_v4float = OpTypePointer Output %v4float
6709      %3 = OpVariable %_ptr_Output_v4float Output
6710     %19 = OpTypeImage %float 2D 0 0 0 1 Unknown
6711 %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19
6712      %4 = OpVariable %_ptr_UniformConstant_19 UniformConstant
6713     %21 = OpTypeSampler
6714 %_ptr_UniformConstant_21 = OpTypePointer UniformConstant %21
6715     %5 = OpVariable %_ptr_UniformConstant_21 UniformConstant
6716    %23 = OpTypeSampledImage %19
6717     %6 = OpVariable %_ptr_UniformConstant_19 UniformConstant
6718     %2 = OpFunction %void None %8
6719    %24 = OpLabel
6720    %25 = OpVariable %_ptr_Function_v2uint Function
6721    %26 = OpLoad %19 %4
6722    %27 = OpLoad %21 %5
6723    %28 = OpSampledImage %23 %26 %27
6724    %29 = OpLoad %v2uint %25
6725    %30 = OpLoad %19 %6
6726    %31 = OpLoad %21 %5
6727    %32 = OpSampledImage %23 %30 %31
6728    %33 = OpImageBlockMatchSADQCOM %v4float %28 %29 %32 %29 %29
6729          OpStore %3 %33
6730          OpReturn
6731          OpFunctionEnd
6732 )";
6733   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
6734   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
6735             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
6736   EXPECT_THAT(getDiagnosticString(), HasSubstr("Missing decoration"));
6737 }
6738 
TEST_F(ValidateImage,QCOMImageProcessingBlockMatchSADNoDecorationB)6739 TEST_F(ValidateImage, QCOMImageProcessingBlockMatchSADNoDecorationB) {
6740   std::string text = R"(
6741            OpCapability Shader
6742            OpCapability TextureBlockMatchQCOM
6743            OpExtension "SPV_QCOM_image_processing"
6744       %1 = OpExtInstImport "GLSL.std.450"
6745            OpMemoryModel Logical GLSL450
6746            OpEntryPoint Fragment %2 "main" %3 %4 %5 %6
6747            OpExecutionMode %2 OriginUpperLeft
6748            OpDecorate %3 Location 0
6749            OpDecorate %4 DescriptorSet 0
6750            OpDecorate %4 Binding 1
6751            OpDecorate %5 DescriptorSet 0
6752            OpDecorate %5 Binding 3
6753            OpDecorate %5 BlockMatchTextureQCOM
6754            OpDecorate %6 DescriptorSet 0
6755            OpDecorate %6 Binding 2
6756    %void = OpTypeVoid
6757       %8 = OpTypeFunction %void
6758    %uint = OpTypeInt 32 0
6759  %v2uint = OpTypeVector %uint 2
6760 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
6761   %float = OpTypeFloat 32
6762 %v4float = OpTypeVector %float 4
6763 %_ptr_Input_float = OpTypePointer Input %float
6764 %_ptr_Function_uint = OpTypePointer Function %uint
6765 %uint_4 = OpConstant %uint 4
6766     %17 = OpConstantComposite %v2uint %uint_4 %uint_4
6767 %_ptr_Output_v4float = OpTypePointer Output %v4float
6768      %3 = OpVariable %_ptr_Output_v4float Output
6769     %19 = OpTypeImage %float 2D 0 0 0 1 Unknown
6770 %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19
6771      %4 = OpVariable %_ptr_UniformConstant_19 UniformConstant
6772     %21 = OpTypeSampler
6773 %_ptr_UniformConstant_21 = OpTypePointer UniformConstant %21
6774     %5 = OpVariable %_ptr_UniformConstant_21 UniformConstant
6775    %23 = OpTypeSampledImage %19
6776     %6 = OpVariable %_ptr_UniformConstant_19 UniformConstant
6777     %2 = OpFunction %void None %8
6778    %24 = OpLabel
6779    %25 = OpVariable %_ptr_Function_v2uint Function
6780    %26 = OpLoad %19 %4
6781    %27 = OpLoad %21 %5
6782    %28 = OpSampledImage %23 %26 %27
6783    %29 = OpLoad %v2uint %25
6784    %30 = OpLoad %19 %6
6785    %31 = OpLoad %21 %5
6786    %32 = OpSampledImage %23 %30 %31
6787    %33 = OpImageBlockMatchSADQCOM %v4float %28 %29 %32 %29 %29
6788          OpStore %3 %33
6789          OpReturn
6790          OpFunctionEnd
6791 )";
6792   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
6793   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
6794             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
6795   EXPECT_THAT(getDiagnosticString(), HasSubstr("Missing decoration"));
6796 }
6797 
TEST_F(ValidateImage,QCOMImageProcessingBlockMatchSADNoDecorationC)6798 TEST_F(ValidateImage, QCOMImageProcessingBlockMatchSADNoDecorationC) {
6799   std::string text = R"(
6800                OpCapability Shader
6801                OpCapability TextureBlockMatchQCOM
6802                OpExtension "SPV_QCOM_image_processing"
6803           %1 = OpExtInstImport "GLSL.std.450"
6804                OpMemoryModel Logical GLSL450
6805                OpEntryPoint Fragment %2 "main" %3 %4 %5
6806                OpExecutionMode %2 OriginUpperLeft
6807                OpDecorate %3 Location 0
6808                OpDecorate %4 DescriptorSet 0
6809                OpDecorate %4 Binding 4
6810                OpDecorate %5 DescriptorSet 0
6811                OpDecorate %5 Binding 5
6812                OpDecorate %5 BlockMatchTextureQCOM
6813        %void = OpTypeVoid
6814           %7 = OpTypeFunction %void
6815        %uint = OpTypeInt 32 0
6816      %v2uint = OpTypeVector %uint 2
6817 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
6818       %float = OpTypeFloat 32
6819     %v4float = OpTypeVector %float 4
6820 %_ptr_Input_v4float = OpTypePointer Input %v4float
6821 %_ptr_Input_float = OpTypePointer Input %float
6822 %_ptr_Function_uint = OpTypePointer Function %uint
6823 %_ptr_Output_v4float = OpTypePointer Output %v4float
6824           %3 = OpVariable %_ptr_Output_v4float Output
6825          %18 = OpTypeImage %float 2D 0 0 0 1 Unknown
6826          %19 = OpTypeSampledImage %18
6827 %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19
6828           %4 = OpVariable %_ptr_UniformConstant_19 UniformConstant
6829           %5 = OpVariable %_ptr_UniformConstant_19 UniformConstant
6830          %21 = OpTypeImage %float 2D 0 1 0 1 Unknown
6831           %2 = OpFunction %void None %7
6832          %22 = OpLabel
6833          %23 = OpVariable %_ptr_Function_v2uint Function
6834          %24 = OpLoad %19 %4
6835          %25 = OpLoad %v2uint %23
6836          %26 = OpLoad %19 %5
6837          %27 = OpLoad %v2uint %23
6838          %28 = OpLoad %v2uint %23
6839          %29 = OpImageBlockMatchSADQCOM %v4float %24 %25 %26 %27 %28
6840                OpStore %3 %29
6841                OpReturn
6842                OpFunctionEnd
6843 )";
6844   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
6845   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
6846             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
6847   EXPECT_THAT(getDiagnosticString(), HasSubstr("Missing decoration"));
6848 }
6849 
TEST_F(ValidateImage,QCOMImageProcessingBlockMatchSADNoDecorationD)6850 TEST_F(ValidateImage, QCOMImageProcessingBlockMatchSADNoDecorationD) {
6851   std::string text = R"(
6852                OpCapability Shader
6853                OpCapability TextureBlockMatchQCOM
6854                OpExtension "SPV_QCOM_image_processing"
6855           %1 = OpExtInstImport "GLSL.std.450"
6856                OpMemoryModel Logical GLSL450
6857                OpEntryPoint Fragment %2 "main" %3 %4 %5
6858                OpExecutionMode %2 OriginUpperLeft
6859                OpDecorate %3 Location 0
6860                OpDecorate %4 DescriptorSet 0
6861                OpDecorate %4 Binding 4
6862                OpDecorate %4 BlockMatchTextureQCOM
6863                OpDecorate %5 DescriptorSet 0
6864                OpDecorate %5 Binding 5
6865        %void = OpTypeVoid
6866           %7 = OpTypeFunction %void
6867        %uint = OpTypeInt 32 0
6868      %v2uint = OpTypeVector %uint 2
6869 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
6870       %float = OpTypeFloat 32
6871     %v4float = OpTypeVector %float 4
6872 %_ptr_Input_v4float = OpTypePointer Input %v4float
6873 %_ptr_Input_float = OpTypePointer Input %float
6874 %_ptr_Function_uint = OpTypePointer Function %uint
6875 %_ptr_Output_v4float = OpTypePointer Output %v4float
6876           %3 = OpVariable %_ptr_Output_v4float Output
6877          %18 = OpTypeImage %float 2D 0 0 0 1 Unknown
6878          %19 = OpTypeSampledImage %18
6879 %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19
6880           %4 = OpVariable %_ptr_UniformConstant_19 UniformConstant
6881           %5 = OpVariable %_ptr_UniformConstant_19 UniformConstant
6882          %21 = OpTypeImage %float 2D 0 1 0 1 Unknown
6883           %2 = OpFunction %void None %7
6884          %22 = OpLabel
6885          %23 = OpVariable %_ptr_Function_v2uint Function
6886          %24 = OpLoad %19 %4
6887          %25 = OpLoad %v2uint %23
6888          %26 = OpLoad %19 %5
6889          %27 = OpLoad %v2uint %23
6890          %28 = OpLoad %v2uint %23
6891          %29 = OpImageBlockMatchSADQCOM %v4float %24 %25 %26 %27 %28
6892                OpStore %3 %29
6893                OpReturn
6894                OpFunctionEnd
6895 )";
6896   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
6897   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
6898             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
6899   EXPECT_THAT(getDiagnosticString(), HasSubstr("Missing decoration"));
6900 }
6901 
TEST_F(ValidateImage,QCOMImageProcessingBlockMatchSSDNoDecorationA)6902 TEST_F(ValidateImage, QCOMImageProcessingBlockMatchSSDNoDecorationA) {
6903   std::string text = R"(
6904            OpCapability Shader
6905            OpCapability TextureBlockMatchQCOM
6906            OpExtension "SPV_QCOM_image_processing"
6907       %1 = OpExtInstImport "GLSL.std.450"
6908            OpMemoryModel Logical GLSL450
6909            OpEntryPoint Fragment %2 "main" %3 %4 %5 %6
6910            OpExecutionMode %2 OriginUpperLeft
6911            OpDecorate %3 Location 0
6912            OpDecorate %4 DescriptorSet 0
6913            OpDecorate %4 Binding 1
6914            OpDecorate %5 DescriptorSet 0
6915            OpDecorate %5 Binding 3
6916            OpDecorate %6 DescriptorSet 0
6917            OpDecorate %6 Binding 2
6918            OpDecorate %6 BlockMatchTextureQCOM
6919    %void = OpTypeVoid
6920       %8 = OpTypeFunction %void
6921    %uint = OpTypeInt 32 0
6922  %v2uint = OpTypeVector %uint 2
6923 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
6924   %float = OpTypeFloat 32
6925 %v4float = OpTypeVector %float 4
6926 %_ptr_Input_float = OpTypePointer Input %float
6927 %_ptr_Function_uint = OpTypePointer Function %uint
6928 %uint_4 = OpConstant %uint 4
6929     %17 = OpConstantComposite %v2uint %uint_4 %uint_4
6930 %_ptr_Output_v4float = OpTypePointer Output %v4float
6931      %3 = OpVariable %_ptr_Output_v4float Output
6932     %19 = OpTypeImage %float 2D 0 0 0 1 Unknown
6933 %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19
6934      %4 = OpVariable %_ptr_UniformConstant_19 UniformConstant
6935     %21 = OpTypeSampler
6936 %_ptr_UniformConstant_21 = OpTypePointer UniformConstant %21
6937     %5 = OpVariable %_ptr_UniformConstant_21 UniformConstant
6938    %23 = OpTypeSampledImage %19
6939     %6 = OpVariable %_ptr_UniformConstant_19 UniformConstant
6940     %2 = OpFunction %void None %8
6941    %24 = OpLabel
6942    %25 = OpVariable %_ptr_Function_v2uint Function
6943    %26 = OpLoad %19 %4
6944    %27 = OpLoad %21 %5
6945    %28 = OpSampledImage %23 %26 %27
6946    %29 = OpLoad %v2uint %25
6947    %30 = OpLoad %19 %6
6948    %31 = OpLoad %21 %5
6949    %32 = OpSampledImage %23 %30 %31
6950    %33 = OpImageBlockMatchSSDQCOM %v4float %28 %29 %32 %29 %29
6951          OpStore %3 %33
6952          OpReturn
6953          OpFunctionEnd
6954 )";
6955   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
6956   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
6957             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
6958   EXPECT_THAT(getDiagnosticString(), HasSubstr("Missing decoration"));
6959 }
6960 
TEST_F(ValidateImage,QCOMImageProcessingBlockMatchSSDNoDecorationB)6961 TEST_F(ValidateImage, QCOMImageProcessingBlockMatchSSDNoDecorationB) {
6962   std::string text = R"(
6963            OpCapability Shader
6964            OpCapability TextureBlockMatchQCOM
6965            OpExtension "SPV_QCOM_image_processing"
6966       %1 = OpExtInstImport "GLSL.std.450"
6967            OpMemoryModel Logical GLSL450
6968            OpEntryPoint Fragment %2 "main" %3 %4 %5 %6
6969            OpExecutionMode %2 OriginUpperLeft
6970            OpDecorate %3 Location 0
6971            OpDecorate %4 DescriptorSet 0
6972            OpDecorate %4 Binding 1
6973            OpDecorate %5 DescriptorSet 0
6974            OpDecorate %5 Binding 3
6975            OpDecorate %5 BlockMatchTextureQCOM
6976            OpDecorate %6 DescriptorSet 0
6977            OpDecorate %6 Binding 2
6978    %void = OpTypeVoid
6979       %8 = OpTypeFunction %void
6980    %uint = OpTypeInt 32 0
6981  %v2uint = OpTypeVector %uint 2
6982 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
6983   %float = OpTypeFloat 32
6984 %v4float = OpTypeVector %float 4
6985 %_ptr_Input_float = OpTypePointer Input %float
6986 %_ptr_Function_uint = OpTypePointer Function %uint
6987 %uint_4 = OpConstant %uint 4
6988     %17 = OpConstantComposite %v2uint %uint_4 %uint_4
6989 %_ptr_Output_v4float = OpTypePointer Output %v4float
6990      %3 = OpVariable %_ptr_Output_v4float Output
6991     %19 = OpTypeImage %float 2D 0 0 0 1 Unknown
6992 %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19
6993      %4 = OpVariable %_ptr_UniformConstant_19 UniformConstant
6994     %21 = OpTypeSampler
6995 %_ptr_UniformConstant_21 = OpTypePointer UniformConstant %21
6996     %5 = OpVariable %_ptr_UniformConstant_21 UniformConstant
6997    %23 = OpTypeSampledImage %19
6998     %6 = OpVariable %_ptr_UniformConstant_19 UniformConstant
6999     %2 = OpFunction %void None %8
7000    %24 = OpLabel
7001    %25 = OpVariable %_ptr_Function_v2uint Function
7002    %26 = OpLoad %19 %4
7003    %27 = OpLoad %21 %5
7004    %28 = OpSampledImage %23 %26 %27
7005    %29 = OpLoad %v2uint %25
7006    %30 = OpLoad %19 %6
7007    %31 = OpLoad %21 %5
7008    %32 = OpSampledImage %23 %30 %31
7009    %33 = OpImageBlockMatchSSDQCOM %v4float %28 %29 %32 %29 %29
7010          OpStore %3 %33
7011          OpReturn
7012          OpFunctionEnd
7013 )";
7014   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
7015   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
7016             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
7017   EXPECT_THAT(getDiagnosticString(), HasSubstr("Missing decoration"));
7018 }
7019 
TEST_F(ValidateImage,QCOMImageProcessingBlockMatchSSDNoDecorationC)7020 TEST_F(ValidateImage, QCOMImageProcessingBlockMatchSSDNoDecorationC) {
7021   std::string text = R"(
7022                OpCapability Shader
7023                OpCapability TextureBlockMatchQCOM
7024                OpExtension "SPV_QCOM_image_processing"
7025           %1 = OpExtInstImport "GLSL.std.450"
7026                OpMemoryModel Logical GLSL450
7027                OpEntryPoint Fragment %2 "main" %3 %4 %5
7028                OpExecutionMode %2 OriginUpperLeft
7029                OpDecorate %3 Location 0
7030                OpDecorate %4 DescriptorSet 0
7031                OpDecorate %4 Binding 4
7032                OpDecorate %5 DescriptorSet 0
7033                OpDecorate %5 Binding 5
7034                OpDecorate %5 BlockMatchTextureQCOM
7035        %void = OpTypeVoid
7036           %7 = OpTypeFunction %void
7037        %uint = OpTypeInt 32 0
7038      %v2uint = OpTypeVector %uint 2
7039 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
7040       %float = OpTypeFloat 32
7041     %v4float = OpTypeVector %float 4
7042 %_ptr_Input_v4float = OpTypePointer Input %v4float
7043 %_ptr_Input_float = OpTypePointer Input %float
7044 %_ptr_Function_uint = OpTypePointer Function %uint
7045 %_ptr_Output_v4float = OpTypePointer Output %v4float
7046           %3 = OpVariable %_ptr_Output_v4float Output
7047          %18 = OpTypeImage %float 2D 0 0 0 1 Unknown
7048          %19 = OpTypeSampledImage %18
7049 %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19
7050           %4 = OpVariable %_ptr_UniformConstant_19 UniformConstant
7051           %5 = OpVariable %_ptr_UniformConstant_19 UniformConstant
7052          %21 = OpTypeImage %float 2D 0 1 0 1 Unknown
7053           %2 = OpFunction %void None %7
7054          %22 = OpLabel
7055          %23 = OpVariable %_ptr_Function_v2uint Function
7056          %24 = OpLoad %19 %4
7057          %25 = OpLoad %v2uint %23
7058          %26 = OpLoad %19 %5
7059          %27 = OpLoad %v2uint %23
7060          %28 = OpLoad %v2uint %23
7061          %29 = OpImageBlockMatchSSDQCOM %v4float %24 %25 %26 %27 %28
7062                OpStore %3 %29
7063                OpReturn
7064                OpFunctionEnd
7065 )";
7066   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
7067   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
7068             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
7069   EXPECT_THAT(getDiagnosticString(), HasSubstr("Missing decoration"));
7070 }
7071 
TEST_F(ValidateImage,QCOMImageProcessingBlockMatchSSDNoDecorationD)7072 TEST_F(ValidateImage, QCOMImageProcessingBlockMatchSSDNoDecorationD) {
7073   std::string text = R"(
7074                OpCapability Shader
7075                OpCapability TextureBlockMatchQCOM
7076                OpExtension "SPV_QCOM_image_processing"
7077           %1 = OpExtInstImport "GLSL.std.450"
7078                OpMemoryModel Logical GLSL450
7079                OpEntryPoint Fragment %2 "main" %3 %4 %5
7080                OpExecutionMode %2 OriginUpperLeft
7081                OpDecorate %3 Location 0
7082                OpDecorate %4 DescriptorSet 0
7083                OpDecorate %4 Binding 4
7084                OpDecorate %4 BlockMatchTextureQCOM
7085                OpDecorate %5 DescriptorSet 0
7086                OpDecorate %5 Binding 5
7087        %void = OpTypeVoid
7088           %7 = OpTypeFunction %void
7089        %uint = OpTypeInt 32 0
7090      %v2uint = OpTypeVector %uint 2
7091 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
7092       %float = OpTypeFloat 32
7093     %v4float = OpTypeVector %float 4
7094 %_ptr_Input_v4float = OpTypePointer Input %v4float
7095 %_ptr_Input_float = OpTypePointer Input %float
7096 %_ptr_Function_uint = OpTypePointer Function %uint
7097 %_ptr_Output_v4float = OpTypePointer Output %v4float
7098           %3 = OpVariable %_ptr_Output_v4float Output
7099          %18 = OpTypeImage %float 2D 0 0 0 1 Unknown
7100          %19 = OpTypeSampledImage %18
7101 %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19
7102           %4 = OpVariable %_ptr_UniformConstant_19 UniformConstant
7103           %5 = OpVariable %_ptr_UniformConstant_19 UniformConstant
7104          %21 = OpTypeImage %float 2D 0 1 0 1 Unknown
7105           %2 = OpFunction %void None %7
7106          %22 = OpLabel
7107          %23 = OpVariable %_ptr_Function_v2uint Function
7108          %24 = OpLoad %19 %4
7109          %25 = OpLoad %v2uint %23
7110          %26 = OpLoad %19 %5
7111          %27 = OpLoad %v2uint %23
7112          %28 = OpLoad %v2uint %23
7113          %29 = OpImageBlockMatchSSDQCOM %v4float %24 %25 %26 %27 %28
7114                OpStore %3 %29
7115                OpReturn
7116                OpFunctionEnd
7117 )";
7118   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
7119   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
7120             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
7121   EXPECT_THAT(getDiagnosticString(), HasSubstr("Missing decoration"));
7122 }
7123 
TEST_F(ValidateImage,QCOMImageProcessingSampleWeightedNoDecorationA)7124 TEST_F(ValidateImage, QCOMImageProcessingSampleWeightedNoDecorationA) {
7125   std::string text = R"(
7126                OpCapability Shader
7127                OpCapability TextureSampleWeightedQCOM
7128                OpExtension "SPV_QCOM_image_processing"
7129           %1 = OpExtInstImport "GLSL.std.450"
7130                OpMemoryModel Logical GLSL450
7131                OpEntryPoint Fragment %2 "main" %3 %4 %5 %6 %7
7132                OpExecutionMode %2 OriginUpperLeft
7133                OpDecorate %3 Location 0
7134                OpDecorate %4 DescriptorSet 0
7135                OpDecorate %4 Binding 1
7136                OpDecorate %5 DescriptorSet 0
7137                OpDecorate %5 Binding 3
7138                OpDecorate %6 Location 0
7139                OpDecorate %7 DescriptorSet 0
7140                OpDecorate %7 Binding 0
7141        %void = OpTypeVoid
7142           %9 = OpTypeFunction %void
7143       %float = OpTypeFloat 32
7144     %v4float = OpTypeVector %float 4
7145 %_ptr_Output_v4float = OpTypePointer Output %v4float
7146           %3 = OpVariable %_ptr_Output_v4float Output
7147          %13 = OpTypeImage %float 2D 0 0 0 1 Unknown
7148 %_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
7149           %4 = OpVariable %_ptr_UniformConstant_13 UniformConstant
7150          %15 = OpTypeSampler
7151 %_ptr_UniformConstant_15 = OpTypePointer UniformConstant %15
7152           %5 = OpVariable %_ptr_UniformConstant_15 UniformConstant
7153          %17 = OpTypeSampledImage %13
7154 %_ptr_Input_v4float = OpTypePointer Input %v4float
7155           %6 = OpVariable %_ptr_Input_v4float Input
7156     %v2float = OpTypeVector %float 2
7157          %20 = OpTypeImage %float 2D 0 1 0 1 Unknown
7158 %_ptr_UniformConstant_20 = OpTypePointer UniformConstant %20
7159           %7 = OpVariable %_ptr_UniformConstant_20 UniformConstant
7160          %22 = OpTypeSampledImage %20
7161 %_ptr_UniformConstant_17 = OpTypePointer UniformConstant %17
7162           %2 = OpFunction %void None %9
7163          %24 = OpLabel
7164          %25 = OpLoad %13 %4
7165          %26 = OpLoad %15 %5
7166          %27 = OpSampledImage %17 %25 %26
7167          %28 = OpLoad %v4float %6
7168          %29 = OpVectorShuffle %v2float %28 %28 0 1
7169          %30 = OpLoad %20 %7
7170          %31 = OpLoad %15 %5
7171          %32 = OpSampledImage %22 %30 %31
7172          %33 = OpImageSampleWeightedQCOM %v4float %27 %29 %32
7173                OpStore %3 %33
7174                OpReturn
7175                OpFunctionEnd
7176 )";
7177   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
7178   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
7179             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
7180   EXPECT_THAT(getDiagnosticString(), HasSubstr("Missing decoration"));
7181 }
7182 
TEST_F(ValidateImage,QCOMImageProcessingSampleWeightedNoDecorationB)7183 TEST_F(ValidateImage, QCOMImageProcessingSampleWeightedNoDecorationB) {
7184   std::string text = R"(
7185                OpCapability Shader
7186                OpCapability TextureSampleWeightedQCOM
7187                OpExtension "SPV_QCOM_image_processing"
7188           %1 = OpExtInstImport "GLSL.std.450"
7189                OpMemoryModel Logical GLSL450
7190                OpEntryPoint Fragment %2 "main" %3 %4 %5 %6
7191                OpExecutionMode %2 OriginUpperLeft
7192                OpDecorate %3 Location 0
7193                OpDecorate %4 Location 0
7194                OpDecorate %5 DescriptorSet 0
7195                OpDecorate %5 Binding 4
7196                OpDecorate %6 DescriptorSet 0
7197                OpDecorate %6 Binding 5
7198        %void = OpTypeVoid
7199           %8 = OpTypeFunction %void
7200       %float = OpTypeFloat 32
7201     %v4float = OpTypeVector %float 4
7202 %_ptr_Output_v4float = OpTypePointer Output %v4float
7203           %3 = OpVariable %_ptr_Output_v4float Output
7204          %12 = OpTypeImage %float 2D 0 0 0 1 Unknown
7205 %_ptr_UniformConstant_12 = OpTypePointer UniformConstant %12
7206          %14 = OpTypeSampler
7207 %_ptr_UniformConstant_14 = OpTypePointer UniformConstant %14
7208          %16 = OpTypeSampledImage %12
7209 %_ptr_Input_v4float = OpTypePointer Input %v4float
7210           %4 = OpVariable %_ptr_Input_v4float Input
7211     %v2float = OpTypeVector %float 2
7212          %19 = OpTypeImage %float 2D 0 1 0 1 Unknown
7213 %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19
7214          %21 = OpTypeSampledImage %19
7215 %_ptr_UniformConstant_16 = OpTypePointer UniformConstant %16
7216           %5 = OpVariable %_ptr_UniformConstant_16 UniformConstant
7217 %_ptr_UniformConstant_21 = OpTypePointer UniformConstant %21
7218           %6 = OpVariable %_ptr_UniformConstant_21 UniformConstant
7219           %2 = OpFunction %void None %8
7220          %24 = OpLabel
7221          %25 = OpLoad %16 %5
7222          %26 = OpLoad %v4float %4
7223          %27 = OpVectorShuffle %v2float %26 %26 0 1
7224          %28 = OpLoad %21 %6
7225          %29 = OpImageSampleWeightedQCOM %v4float %25 %27 %28
7226                OpStore %3 %29
7227                OpReturn
7228                OpFunctionEnd
7229 )";
7230   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
7231   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
7232             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
7233   EXPECT_THAT(getDiagnosticString(), HasSubstr("Missing decoration"));
7234 }
7235 
TEST_F(ValidateImage,QCOMImageProcessingBlockMatchSADInvalidUseA)7236 TEST_F(ValidateImage, QCOMImageProcessingBlockMatchSADInvalidUseA) {
7237   std::string text = R"(
7238 ; SPIR-V
7239 ; Version: 1.0
7240 ; Generator: Khronos Glslang Reference Front End; 11
7241 ; Bound: 79
7242 ; Schema: 0
7243                OpCapability Shader
7244                OpCapability TextureBlockMatchQCOM
7245                OpExtension "SPV_QCOM_image_processing"
7246           %1 = OpExtInstImport "GLSL.std.450"
7247                OpMemoryModel Logical GLSL450
7248                OpEntryPoint Fragment %main "main" %100 %101 %102 %103 %104
7249                OpExecutionMode %main OriginUpperLeft
7250                OpDecorate %100 Location 0
7251                OpDecorate %101 Location 0
7252                OpDecorate %102 DescriptorSet 0
7253                OpDecorate %102 Binding 1
7254                OpDecorate %103 DescriptorSet 0
7255                OpDecorate %103 Binding 3
7256                OpDecorate %104 DescriptorSet 0
7257                OpDecorate %104 Binding 2
7258                OpDecorate %102 BlockMatchTextureQCOM
7259                OpDecorate %104 BlockMatchTextureQCOM
7260        %void = OpTypeVoid
7261           %3 = OpTypeFunction %void
7262        %uint = OpTypeInt 32 0
7263      %v2uint = OpTypeVector %uint 2
7264 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
7265       %float = OpTypeFloat 32
7266     %v4float = OpTypeVector %float 4
7267 %_ptr_Input_v4float = OpTypePointer Input %v4float
7268  %100 = OpVariable %_ptr_Input_v4float Input
7269 %_ptr_Output_v4float = OpTypePointer Output %v4float
7270   %101 = OpVariable %_ptr_Output_v4float Output
7271          %42 = OpTypeImage %float 2D 0 0 0 1 Unknown
7272 %_ptr_UniformConstant_42 = OpTypePointer UniformConstant %42
7273  %102 = OpVariable %_ptr_UniformConstant_42 UniformConstant
7274          %46 = OpTypeSampler
7275 %_ptr_UniformConstant_46 = OpTypePointer UniformConstant %46
7276        %103 = OpVariable %_ptr_UniformConstant_46 UniformConstant
7277          %50 = OpTypeSampledImage %42
7278  %104 = OpVariable %_ptr_UniformConstant_42 UniformConstant
7279     %v2float = OpTypeVector %float 2
7280        %main = OpFunction %void None %3
7281           %5 = OpLabel
7282          %15 = OpVariable %_ptr_Function_v2uint Function
7283          %45 = OpLoad %42 %102
7284          %49 = OpLoad %46 %103
7285          %51 = OpSampledImage %50 %45 %49
7286          %52 = OpLoad %v2uint %15
7287          %54 = OpLoad %42 %104
7288          %55 = OpLoad %46 %103
7289          %56 = OpSampledImage %50 %54 %55
7290          %57 = OpLoad %v2uint %15
7291          %58 = OpLoad %v2uint %15
7292          %59 = OpImageBlockMatchSADQCOM %v4float %51 %52 %56 %57 %58
7293                OpStore %101 %59
7294          %69 = OpLoad %42 %102
7295          %70 = OpLoad %46 %103
7296          %71 = OpSampledImage %50 %69 %70
7297          %73 = OpLoad %v4float %100
7298          %74 = OpVectorShuffle %v2float %73 %73 0 0
7299          %75 = OpImageSampleImplicitLod %v4float %71 %74
7300                OpStore %101 %75
7301                OpReturn
7302                OpFunctionEnd
7303 )";
7304   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
7305   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
7306             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
7307   EXPECT_THAT(
7308       getDiagnosticString(),
7309       HasSubstr("Illegal use of QCOM image processing decorated texture"));
7310 }
7311 
TEST_F(ValidateImage,QCOMImageProcessingBlockMatchSADInvalidUseB)7312 TEST_F(ValidateImage, QCOMImageProcessingBlockMatchSADInvalidUseB) {
7313   std::string text = R"(
7314 ; SPIR-V
7315 ; Version: 1.0
7316 ; Generator: Khronos Glslang Reference Front End; 11
7317 ; Bound: 79
7318 ; Schema: 0
7319                OpCapability Shader
7320                OpCapability TextureBlockMatchQCOM
7321                OpExtension "SPV_QCOM_image_processing"
7322           %1 = OpExtInstImport "GLSL.std.450"
7323                OpMemoryModel Logical GLSL450
7324                OpEntryPoint Fragment %main "main" %100 %101 %102 %103 %104
7325                OpExecutionMode %main OriginUpperLeft
7326                OpDecorate %100 Location 0
7327                OpDecorate %101 Location 0
7328                OpDecorate %102 DescriptorSet 0
7329                OpDecorate %102 Binding 1
7330                OpDecorate %103 DescriptorSet 0
7331                OpDecorate %103 Binding 3
7332                OpDecorate %104 DescriptorSet 0
7333                OpDecorate %104 Binding 2
7334                OpDecorate %102 BlockMatchTextureQCOM
7335                OpDecorate %104 BlockMatchTextureQCOM
7336        %void = OpTypeVoid
7337           %3 = OpTypeFunction %void
7338        %uint = OpTypeInt 32 0
7339      %v2uint = OpTypeVector %uint 2
7340 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
7341       %float = OpTypeFloat 32
7342     %v4float = OpTypeVector %float 4
7343 %_ptr_Input_v4float = OpTypePointer Input %v4float
7344  %100 = OpVariable %_ptr_Input_v4float Input
7345 %_ptr_Output_v4float = OpTypePointer Output %v4float
7346   %101 = OpVariable %_ptr_Output_v4float Output
7347          %42 = OpTypeImage %float 2D 0 0 0 1 Unknown
7348 %_ptr_UniformConstant_42 = OpTypePointer UniformConstant %42
7349  %102 = OpVariable %_ptr_UniformConstant_42 UniformConstant
7350          %46 = OpTypeSampler
7351 %_ptr_UniformConstant_46 = OpTypePointer UniformConstant %46
7352        %103 = OpVariable %_ptr_UniformConstant_46 UniformConstant
7353          %50 = OpTypeSampledImage %42
7354  %104 = OpVariable %_ptr_UniformConstant_42 UniformConstant
7355     %v2float = OpTypeVector %float 2
7356        %main = OpFunction %void None %3
7357           %5 = OpLabel
7358          %15 = OpVariable %_ptr_Function_v2uint Function
7359          %45 = OpLoad %42 %102
7360          %49 = OpLoad %46 %103
7361          %51 = OpSampledImage %50 %45 %49
7362          %52 = OpLoad %v2uint %15
7363          %54 = OpLoad %42 %104
7364          %55 = OpLoad %46 %103
7365          %56 = OpSampledImage %50 %54 %55
7366          %57 = OpLoad %v2uint %15
7367          %58 = OpLoad %v2uint %15
7368          %59 = OpImageBlockMatchSADQCOM %v4float %51 %52 %56 %57 %58
7369                OpStore %101 %59
7370          %69 = OpLoad %42 %104
7371          %70 = OpLoad %46 %103
7372          %71 = OpSampledImage %50 %69 %70
7373          %73 = OpLoad %v4float %100
7374          %74 = OpVectorShuffle %v2float %73 %73 0 0
7375          %75 = OpImageSampleImplicitLod %v4float %71 %74
7376                OpStore %101 %75
7377                OpReturn
7378                OpFunctionEnd
7379 )";
7380   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
7381   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
7382             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
7383   EXPECT_THAT(
7384       getDiagnosticString(),
7385       HasSubstr("Illegal use of QCOM image processing decorated texture"));
7386 }
7387 
TEST_F(ValidateImage,QCOMImageProcessingBlockMatchSADInvalidUseC)7388 TEST_F(ValidateImage, QCOMImageProcessingBlockMatchSADInvalidUseC) {
7389   std::string text = R"(
7390                OpCapability Shader
7391                OpCapability TextureBlockMatchQCOM
7392                OpExtension "SPV_QCOM_image_processing"
7393           %1 = OpExtInstImport "GLSL.std.450"
7394                OpMemoryModel Logical GLSL450
7395                OpEntryPoint Fragment %2 "main" %3 %4 %5 %6
7396                OpExecutionMode %2 OriginUpperLeft
7397                OpDecorate %3 Location 0
7398                OpDecorate %4 Location 0
7399                OpDecorate %5 DescriptorSet 0
7400                OpDecorate %5 Binding 4
7401                OpDecorate %6 DescriptorSet 0
7402                OpDecorate %6 Binding 5
7403                OpDecorate %5 BlockMatchTextureQCOM
7404                OpDecorate %6 BlockMatchTextureQCOM
7405        %void = OpTypeVoid
7406           %8 = OpTypeFunction %void
7407        %uint = OpTypeInt 32 0
7408      %v2uint = OpTypeVector %uint 2
7409 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
7410       %float = OpTypeFloat 32
7411     %v4float = OpTypeVector %float 4
7412 %_ptr_Input_v4float = OpTypePointer Input %v4float
7413           %3 = OpVariable %_ptr_Input_v4float Input
7414      %uint_4 = OpConstant %uint 4
7415          %16 = OpConstantComposite %v2uint %uint_4 %uint_4
7416 %_ptr_Output_v4float = OpTypePointer Output %v4float
7417           %4 = OpVariable %_ptr_Output_v4float Output
7418          %18 = OpTypeImage %float 2D 0 0 0 1 Unknown
7419 %_ptr_UniformConstant_18 = OpTypePointer UniformConstant %18
7420          %20 = OpTypeSampledImage %18
7421 %_ptr_UniformConstant_20 = OpTypePointer UniformConstant %20
7422           %5 = OpVariable %_ptr_UniformConstant_20 UniformConstant
7423           %6 = OpVariable %_ptr_UniformConstant_20 UniformConstant
7424     %v2float = OpTypeVector %float 2
7425          %23 = OpTypeImage %float 2D 0 1 0 1 Unknown
7426           %2 = OpFunction %void None %8
7427          %24 = OpLabel
7428          %25 = OpVariable %_ptr_Function_v2uint Function
7429                OpStore %25 %16
7430          %26 = OpLoad %20 %5
7431          %27 = OpLoad %v2uint %25
7432          %28 = OpLoad %20 %6
7433          %29 = OpLoad %v2uint %25
7434          %30 = OpLoad %v2uint %25
7435          %31 = OpImageBlockMatchSADQCOM %v4float %26 %27 %28 %29 %30
7436                OpStore %4 %31
7437          %32 = OpLoad %20 %5
7438          %33 = OpLoad %v4float %3
7439          %34 = OpVectorShuffle %v2float %33 %33 0 2
7440          %35 = OpImageSampleImplicitLod %v4float %32 %34
7441                OpStore %4 %35
7442                OpReturn
7443                OpFunctionEnd
7444 )";
7445   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
7446   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
7447             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
7448   EXPECT_THAT(
7449       getDiagnosticString(),
7450       HasSubstr("Illegal use of QCOM image processing decorated texture"));
7451 }
7452 
TEST_F(ValidateImage,QCOMImageProcessingBlockMatchSADInvalidUseD)7453 TEST_F(ValidateImage, QCOMImageProcessingBlockMatchSADInvalidUseD) {
7454   std::string text = R"(
7455                OpCapability Shader
7456                OpCapability TextureBlockMatchQCOM
7457                OpExtension "SPV_QCOM_image_processing"
7458           %1 = OpExtInstImport "GLSL.std.450"
7459                OpMemoryModel Logical GLSL450
7460                OpEntryPoint Fragment %2 "main" %3 %4 %5 %6
7461                OpExecutionMode %2 OriginUpperLeft
7462                OpDecorate %3 Location 0
7463                OpDecorate %4 Location 0
7464                OpDecorate %5 DescriptorSet 0
7465                OpDecorate %5 Binding 4
7466                OpDecorate %6 DescriptorSet 0
7467                OpDecorate %6 Binding 5
7468                OpDecorate %5 BlockMatchTextureQCOM
7469                OpDecorate %6 BlockMatchTextureQCOM
7470        %void = OpTypeVoid
7471           %8 = OpTypeFunction %void
7472        %uint = OpTypeInt 32 0
7473      %v2uint = OpTypeVector %uint 2
7474 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
7475       %float = OpTypeFloat 32
7476     %v4float = OpTypeVector %float 4
7477 %_ptr_Input_v4float = OpTypePointer Input %v4float
7478           %3 = OpVariable %_ptr_Input_v4float Input
7479      %uint_4 = OpConstant %uint 4
7480          %16 = OpConstantComposite %v2uint %uint_4 %uint_4
7481 %_ptr_Output_v4float = OpTypePointer Output %v4float
7482           %4 = OpVariable %_ptr_Output_v4float Output
7483          %18 = OpTypeImage %float 2D 0 0 0 1 Unknown
7484 %_ptr_UniformConstant_18 = OpTypePointer UniformConstant %18
7485          %20 = OpTypeSampledImage %18
7486 %_ptr_UniformConstant_20 = OpTypePointer UniformConstant %20
7487           %5 = OpVariable %_ptr_UniformConstant_20 UniformConstant
7488           %6 = OpVariable %_ptr_UniformConstant_20 UniformConstant
7489     %v2float = OpTypeVector %float 2
7490          %23 = OpTypeImage %float 2D 0 1 0 1 Unknown
7491           %2 = OpFunction %void None %8
7492          %24 = OpLabel
7493          %25 = OpVariable %_ptr_Function_v2uint Function
7494                OpStore %25 %16
7495          %26 = OpLoad %20 %5
7496          %27 = OpLoad %v2uint %25
7497          %28 = OpLoad %20 %6
7498          %29 = OpLoad %v2uint %25
7499          %30 = OpLoad %v2uint %25
7500          %31 = OpImageBlockMatchSADQCOM %v4float %26 %27 %28 %29 %30
7501                OpStore %4 %31
7502          %32 = OpLoad %20 %6
7503          %33 = OpLoad %v4float %3
7504          %34 = OpVectorShuffle %v2float %33 %33 0 2
7505          %35 = OpImageSampleImplicitLod %v4float %32 %34
7506                OpStore %4 %35
7507                OpReturn
7508                OpFunctionEnd
7509 )";
7510   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
7511   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
7512             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
7513   EXPECT_THAT(
7514       getDiagnosticString(),
7515       HasSubstr("Illegal use of QCOM image processing decorated texture"));
7516 }
7517 
TEST_F(ValidateImage,QCOMImageProcessingBlockMatchSSDInvalidUseA)7518 TEST_F(ValidateImage, QCOMImageProcessingBlockMatchSSDInvalidUseA) {
7519   std::string text = R"(
7520 ; SPIR-V
7521 ; Version: 1.0
7522 ; Generator: Khronos Glslang Reference Front End; 11
7523 ; Bound: 79
7524 ; Schema: 0
7525                OpCapability Shader
7526                OpCapability TextureBlockMatchQCOM
7527                OpExtension "SPV_QCOM_image_processing"
7528           %1 = OpExtInstImport "GLSL.std.450"
7529                OpMemoryModel Logical GLSL450
7530                OpEntryPoint Fragment %main "main" %100 %101 %102 %103 %104
7531                OpExecutionMode %main OriginUpperLeft
7532                OpDecorate %100 Location 0
7533                OpDecorate %101 Location 0
7534                OpDecorate %102 DescriptorSet 0
7535                OpDecorate %102 Binding 1
7536                OpDecorate %103 DescriptorSet 0
7537                OpDecorate %103 Binding 3
7538                OpDecorate %104 DescriptorSet 0
7539                OpDecorate %104 Binding 2
7540                OpDecorate %102 BlockMatchTextureQCOM
7541                OpDecorate %104 BlockMatchTextureQCOM
7542        %void = OpTypeVoid
7543           %3 = OpTypeFunction %void
7544        %uint = OpTypeInt 32 0
7545      %v2uint = OpTypeVector %uint 2
7546 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
7547       %float = OpTypeFloat 32
7548     %v4float = OpTypeVector %float 4
7549 %_ptr_Input_v4float = OpTypePointer Input %v4float
7550  %100 = OpVariable %_ptr_Input_v4float Input
7551 %_ptr_Output_v4float = OpTypePointer Output %v4float
7552   %101 = OpVariable %_ptr_Output_v4float Output
7553          %42 = OpTypeImage %float 2D 0 0 0 1 Unknown
7554 %_ptr_UniformConstant_42 = OpTypePointer UniformConstant %42
7555  %102 = OpVariable %_ptr_UniformConstant_42 UniformConstant
7556          %46 = OpTypeSampler
7557 %_ptr_UniformConstant_46 = OpTypePointer UniformConstant %46
7558        %103 = OpVariable %_ptr_UniformConstant_46 UniformConstant
7559          %50 = OpTypeSampledImage %42
7560  %104 = OpVariable %_ptr_UniformConstant_42 UniformConstant
7561     %v2float = OpTypeVector %float 2
7562        %main = OpFunction %void None %3
7563           %5 = OpLabel
7564          %15 = OpVariable %_ptr_Function_v2uint Function
7565          %45 = OpLoad %42 %102
7566          %49 = OpLoad %46 %103
7567          %51 = OpSampledImage %50 %45 %49
7568          %52 = OpLoad %v2uint %15
7569          %54 = OpLoad %42 %104
7570          %55 = OpLoad %46 %103
7571          %56 = OpSampledImage %50 %54 %55
7572          %57 = OpLoad %v2uint %15
7573          %58 = OpLoad %v2uint %15
7574          %59 = OpImageBlockMatchSSDQCOM %v4float %51 %52 %56 %57 %58
7575                OpStore %101 %59
7576          %69 = OpLoad %42 %102
7577          %70 = OpLoad %46 %103
7578          %71 = OpSampledImage %50 %69 %70
7579          %73 = OpLoad %v4float %100
7580          %74 = OpVectorShuffle %v2float %73 %73 0 0
7581          %75 = OpImageSampleImplicitLod %v4float %71 %74
7582                OpStore %101 %75
7583                OpReturn
7584                OpFunctionEnd
7585 )";
7586   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
7587   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
7588             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
7589   EXPECT_THAT(
7590       getDiagnosticString(),
7591       HasSubstr("Illegal use of QCOM image processing decorated texture"));
7592 }
7593 
TEST_F(ValidateImage,QCOMImageProcessingBlockMatchSSDInvalidUseB)7594 TEST_F(ValidateImage, QCOMImageProcessingBlockMatchSSDInvalidUseB) {
7595   std::string text = R"(
7596 ; SPIR-V
7597 ; Version: 1.0
7598 ; Generator: Khronos Glslang Reference Front End; 11
7599 ; Bound: 79
7600 ; Schema: 0
7601                OpCapability Shader
7602                OpCapability TextureBlockMatchQCOM
7603                OpExtension "SPV_QCOM_image_processing"
7604           %1 = OpExtInstImport "GLSL.std.450"
7605                OpMemoryModel Logical GLSL450
7606                OpEntryPoint Fragment %main "main" %100 %101 %102 %103 %104
7607                OpExecutionMode %main OriginUpperLeft
7608                OpDecorate %100 Location 0
7609                OpDecorate %101 Location 0
7610                OpDecorate %102 DescriptorSet 0
7611                OpDecorate %102 Binding 1
7612                OpDecorate %103 DescriptorSet 0
7613                OpDecorate %103 Binding 3
7614                OpDecorate %104 DescriptorSet 0
7615                OpDecorate %104 Binding 2
7616                OpDecorate %102 BlockMatchTextureQCOM
7617                OpDecorate %104 BlockMatchTextureQCOM
7618        %void = OpTypeVoid
7619           %3 = OpTypeFunction %void
7620        %uint = OpTypeInt 32 0
7621      %v2uint = OpTypeVector %uint 2
7622 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
7623       %float = OpTypeFloat 32
7624     %v4float = OpTypeVector %float 4
7625 %_ptr_Input_v4float = OpTypePointer Input %v4float
7626  %100 = OpVariable %_ptr_Input_v4float Input
7627 %_ptr_Output_v4float = OpTypePointer Output %v4float
7628   %101 = OpVariable %_ptr_Output_v4float Output
7629          %42 = OpTypeImage %float 2D 0 0 0 1 Unknown
7630 %_ptr_UniformConstant_42 = OpTypePointer UniformConstant %42
7631  %102 = OpVariable %_ptr_UniformConstant_42 UniformConstant
7632          %46 = OpTypeSampler
7633 %_ptr_UniformConstant_46 = OpTypePointer UniformConstant %46
7634        %103 = OpVariable %_ptr_UniformConstant_46 UniformConstant
7635          %50 = OpTypeSampledImage %42
7636  %104 = OpVariable %_ptr_UniformConstant_42 UniformConstant
7637     %v2float = OpTypeVector %float 2
7638        %main = OpFunction %void None %3
7639           %5 = OpLabel
7640          %15 = OpVariable %_ptr_Function_v2uint Function
7641          %45 = OpLoad %42 %102
7642          %49 = OpLoad %46 %103
7643          %51 = OpSampledImage %50 %45 %49
7644          %52 = OpLoad %v2uint %15
7645          %54 = OpLoad %42 %104
7646          %55 = OpLoad %46 %103
7647          %56 = OpSampledImage %50 %54 %55
7648          %57 = OpLoad %v2uint %15
7649          %58 = OpLoad %v2uint %15
7650          %59 = OpImageBlockMatchSSDQCOM %v4float %51 %52 %56 %57 %58
7651                OpStore %101 %59
7652          %69 = OpLoad %42 %104
7653          %70 = OpLoad %46 %103
7654          %71 = OpSampledImage %50 %69 %70
7655          %73 = OpLoad %v4float %100
7656          %74 = OpVectorShuffle %v2float %73 %73 0 0
7657          %75 = OpImageSampleImplicitLod %v4float %71 %74
7658                OpStore %101 %75
7659                OpReturn
7660                OpFunctionEnd
7661 )";
7662   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
7663   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
7664             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
7665   EXPECT_THAT(
7666       getDiagnosticString(),
7667       HasSubstr("Illegal use of QCOM image processing decorated texture"));
7668 }
7669 
TEST_F(ValidateImage,QCOMImageProcessingBlockMatchSSDInvalidUseC)7670 TEST_F(ValidateImage, QCOMImageProcessingBlockMatchSSDInvalidUseC) {
7671   std::string text = R"(
7672                OpCapability Shader
7673                OpCapability TextureBlockMatchQCOM
7674                OpExtension "SPV_QCOM_image_processing"
7675           %1 = OpExtInstImport "GLSL.std.450"
7676                OpMemoryModel Logical GLSL450
7677                OpEntryPoint Fragment %2 "main" %3 %4 %5 %6
7678                OpExecutionMode %2 OriginUpperLeft
7679                OpDecorate %3 Location 0
7680                OpDecorate %4 Location 0
7681                OpDecorate %5 DescriptorSet 0
7682                OpDecorate %5 Binding 4
7683                OpDecorate %6 DescriptorSet 0
7684                OpDecorate %6 Binding 5
7685                OpDecorate %5 BlockMatchTextureQCOM
7686                OpDecorate %6 BlockMatchTextureQCOM
7687        %void = OpTypeVoid
7688           %8 = OpTypeFunction %void
7689        %uint = OpTypeInt 32 0
7690      %v2uint = OpTypeVector %uint 2
7691 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
7692       %float = OpTypeFloat 32
7693     %v4float = OpTypeVector %float 4
7694 %_ptr_Input_v4float = OpTypePointer Input %v4float
7695           %3 = OpVariable %_ptr_Input_v4float Input
7696      %uint_4 = OpConstant %uint 4
7697          %16 = OpConstantComposite %v2uint %uint_4 %uint_4
7698 %_ptr_Output_v4float = OpTypePointer Output %v4float
7699           %4 = OpVariable %_ptr_Output_v4float Output
7700          %18 = OpTypeImage %float 2D 0 0 0 1 Unknown
7701 %_ptr_UniformConstant_18 = OpTypePointer UniformConstant %18
7702          %20 = OpTypeSampledImage %18
7703 %_ptr_UniformConstant_20 = OpTypePointer UniformConstant %20
7704           %5 = OpVariable %_ptr_UniformConstant_20 UniformConstant
7705           %6 = OpVariable %_ptr_UniformConstant_20 UniformConstant
7706     %v2float = OpTypeVector %float 2
7707          %23 = OpTypeImage %float 2D 0 1 0 1 Unknown
7708           %2 = OpFunction %void None %8
7709          %24 = OpLabel
7710          %25 = OpVariable %_ptr_Function_v2uint Function
7711                OpStore %25 %16
7712          %26 = OpLoad %20 %5
7713          %27 = OpLoad %v2uint %25
7714          %28 = OpLoad %20 %6
7715          %29 = OpLoad %v2uint %25
7716          %30 = OpLoad %v2uint %25
7717          %31 = OpImageBlockMatchSSDQCOM %v4float %26 %27 %28 %29 %30
7718                OpStore %4 %31
7719          %32 = OpLoad %20 %5
7720          %33 = OpLoad %v4float %3
7721          %34 = OpVectorShuffle %v2float %33 %33 0 2
7722          %35 = OpImageSampleImplicitLod %v4float %32 %34
7723                OpStore %4 %35
7724                OpReturn
7725                OpFunctionEnd
7726 )";
7727   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
7728   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
7729             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
7730   EXPECT_THAT(
7731       getDiagnosticString(),
7732       HasSubstr("Illegal use of QCOM image processing decorated texture"));
7733 }
7734 
TEST_F(ValidateImage,QCOMImageProcessingBlockMatchSSDInvalidUseD)7735 TEST_F(ValidateImage, QCOMImageProcessingBlockMatchSSDInvalidUseD) {
7736   std::string text = R"(
7737                OpCapability Shader
7738                OpCapability TextureBlockMatchQCOM
7739                OpExtension "SPV_QCOM_image_processing"
7740           %1 = OpExtInstImport "GLSL.std.450"
7741                OpMemoryModel Logical GLSL450
7742                OpEntryPoint Fragment %2 "main" %3 %4 %5 %6
7743                OpExecutionMode %2 OriginUpperLeft
7744                OpDecorate %3 Location 0
7745                OpDecorate %4 Location 0
7746                OpDecorate %5 DescriptorSet 0
7747                OpDecorate %5 Binding 4
7748                OpDecorate %6 DescriptorSet 0
7749                OpDecorate %6 Binding 5
7750                OpDecorate %5 BlockMatchTextureQCOM
7751                OpDecorate %6 BlockMatchTextureQCOM
7752        %void = OpTypeVoid
7753           %8 = OpTypeFunction %void
7754        %uint = OpTypeInt 32 0
7755      %v2uint = OpTypeVector %uint 2
7756 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
7757       %float = OpTypeFloat 32
7758     %v4float = OpTypeVector %float 4
7759 %_ptr_Input_v4float = OpTypePointer Input %v4float
7760           %3 = OpVariable %_ptr_Input_v4float Input
7761      %uint_4 = OpConstant %uint 4
7762          %16 = OpConstantComposite %v2uint %uint_4 %uint_4
7763 %_ptr_Output_v4float = OpTypePointer Output %v4float
7764           %4 = OpVariable %_ptr_Output_v4float Output
7765          %18 = OpTypeImage %float 2D 0 0 0 1 Unknown
7766 %_ptr_UniformConstant_18 = OpTypePointer UniformConstant %18
7767          %20 = OpTypeSampledImage %18
7768 %_ptr_UniformConstant_20 = OpTypePointer UniformConstant %20
7769           %5 = OpVariable %_ptr_UniformConstant_20 UniformConstant
7770           %6 = OpVariable %_ptr_UniformConstant_20 UniformConstant
7771     %v2float = OpTypeVector %float 2
7772          %23 = OpTypeImage %float 2D 0 1 0 1 Unknown
7773           %2 = OpFunction %void None %8
7774          %24 = OpLabel
7775          %25 = OpVariable %_ptr_Function_v2uint Function
7776                OpStore %25 %16
7777          %26 = OpLoad %20 %5
7778          %27 = OpLoad %v2uint %25
7779          %28 = OpLoad %20 %6
7780          %29 = OpLoad %v2uint %25
7781          %30 = OpLoad %v2uint %25
7782          %31 = OpImageBlockMatchSSDQCOM %v4float %26 %27 %28 %29 %30
7783                OpStore %4 %31
7784          %32 = OpLoad %20 %6
7785          %33 = OpLoad %v4float %3
7786          %34 = OpVectorShuffle %v2float %33 %33 0 2
7787          %35 = OpImageSampleImplicitLod %v4float %32 %34
7788                OpStore %4 %35
7789                OpReturn
7790                OpFunctionEnd
7791 )";
7792   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
7793   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
7794             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
7795   EXPECT_THAT(
7796       getDiagnosticString(),
7797       HasSubstr("Illegal use of QCOM image processing decorated texture"));
7798 }
7799 
TEST_F(ValidateImage,QCOMImageProcessingSampleWeightedInvalidUseA)7800 TEST_F(ValidateImage, QCOMImageProcessingSampleWeightedInvalidUseA) {
7801   std::string text = R"(
7802                OpCapability Shader
7803                OpCapability TextureSampleWeightedQCOM
7804                OpExtension "SPV_QCOM_image_processing"
7805           %1 = OpExtInstImport "GLSL.std.450"
7806                OpMemoryModel Logical GLSL450
7807                OpEntryPoint Fragment %2 "main" %3 %4 %5 %6
7808                OpExecutionMode %2 OriginUpperLeft
7809                OpDecorate %3 Location 0
7810                OpDecorate %4 Location 0
7811                OpDecorate %5 DescriptorSet 0
7812                OpDecorate %5 Binding 4
7813                OpDecorate %6 DescriptorSet 0
7814                OpDecorate %6 Binding 5
7815                OpDecorate %6 WeightTextureQCOM
7816        %void = OpTypeVoid
7817           %8 = OpTypeFunction %void
7818       %float = OpTypeFloat 32
7819     %v4float = OpTypeVector %float 4
7820 %_ptr_Output_v4float = OpTypePointer Output %v4float
7821           %3 = OpVariable %_ptr_Output_v4float Output
7822          %12 = OpTypeImage %float 2D 0 0 0 1 Unknown
7823 %_ptr_UniformConstant_12 = OpTypePointer UniformConstant %12
7824          %14 = OpTypeSampledImage %12
7825 %_ptr_Input_v4float = OpTypePointer Input %v4float
7826           %4 = OpVariable %_ptr_Input_v4float Input
7827     %v2float = OpTypeVector %float 2
7828          %17 = OpTypeImage %float 2D 0 1 0 1 Unknown
7829 %_ptr_UniformConstant_17 = OpTypePointer UniformConstant %17
7830          %19 = OpTypeSampledImage %17
7831 %_ptr_UniformConstant_14 = OpTypePointer UniformConstant %14
7832           %5 = OpVariable %_ptr_UniformConstant_14 UniformConstant
7833 %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19
7834           %6 = OpVariable %_ptr_UniformConstant_19 UniformConstant
7835     %v3float = OpTypeVector %float 3
7836           %2 = OpFunction %void None %8
7837          %23 = OpLabel
7838          %24 = OpLoad %v4float %4
7839          %25 = OpVectorShuffle %v2float %24 %24 0 1
7840          %26 = OpLoad %14 %5
7841          %27 = OpLoad %v4float %4
7842          %28 = OpVectorShuffle %v2float %27 %27 0 1
7843          %29 = OpLoad %19 %6
7844          %30 = OpImageSampleWeightedQCOM %v4float %26 %28 %29
7845                OpStore %3 %30
7846          %31 = OpLoad %19 %6
7847          %32 = OpLoad %v4float %4
7848          %33 = OpVectorShuffle %v3float %32 %32 0 1 0
7849          %34 = OpCompositeExtract %float %33 0
7850          %35 = OpCompositeExtract %float %33 1
7851          %36 = OpCompositeExtract %float %33 2
7852          %37 = OpCompositeConstruct %v3float %34 %35 %36
7853          %38 = OpImageSampleImplicitLod %v4float %31 %37
7854                OpStore %3 %38
7855                OpReturn
7856                OpFunctionEnd
7857 )";
7858   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
7859   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
7860             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
7861   EXPECT_THAT(
7862       getDiagnosticString(),
7863       HasSubstr("Illegal use of QCOM image processing decorated texture"));
7864 }
7865 
TEST_F(ValidateImage,QCOMImageProcessingSampleWeightedInvalidUseB)7866 TEST_F(ValidateImage, QCOMImageProcessingSampleWeightedInvalidUseB) {
7867   std::string text = R"(
7868                OpCapability Shader
7869                OpCapability TextureSampleWeightedQCOM
7870                OpExtension "SPV_QCOM_image_processing"
7871           %1 = OpExtInstImport "GLSL.std.450"
7872                OpMemoryModel Logical GLSL450
7873                OpEntryPoint Fragment %2 "main" %3 %4 %5 %6 %7
7874                OpExecutionMode %2 OriginUpperLeft
7875                OpDecorate %3 Location 0
7876                OpDecorate %5 DescriptorSet 0
7877                OpDecorate %5 Binding 1
7878                OpDecorate %6 DescriptorSet 0
7879                OpDecorate %6 Binding 3
7880                OpDecorate %4 Location 0
7881                OpDecorate %7 DescriptorSet 0
7882                OpDecorate %7 Binding 0
7883                OpDecorate %7 WeightTextureQCOM
7884        %void = OpTypeVoid
7885           %9 = OpTypeFunction %void
7886       %float = OpTypeFloat 32
7887     %v4float = OpTypeVector %float 4
7888 %_ptr_Output_v4float = OpTypePointer Output %v4float
7889           %3 = OpVariable %_ptr_Output_v4float Output
7890          %13 = OpTypeImage %float 2D 0 0 0 1 Unknown
7891 %_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
7892           %5 = OpVariable %_ptr_UniformConstant_13 UniformConstant
7893          %15 = OpTypeSampler
7894 %_ptr_UniformConstant_15 = OpTypePointer UniformConstant %15
7895           %6 = OpVariable %_ptr_UniformConstant_15 UniformConstant
7896          %17 = OpTypeSampledImage %13
7897 %_ptr_Input_v4float = OpTypePointer Input %v4float
7898           %4 = OpVariable %_ptr_Input_v4float Input
7899     %v2float = OpTypeVector %float 2
7900          %20 = OpTypeImage %float 2D 0 1 0 1 Unknown
7901 %_ptr_UniformConstant_20 = OpTypePointer UniformConstant %20
7902           %7 = OpVariable %_ptr_UniformConstant_20 UniformConstant
7903          %22 = OpTypeSampledImage %20
7904     %v3float = OpTypeVector %float 3
7905           %2 = OpFunction %void None %9
7906          %24 = OpLabel
7907          %25 = OpLoad %13 %5
7908          %26 = OpLoad %15 %6
7909          %27 = OpSampledImage %17 %25 %26
7910          %28 = OpLoad %v4float %4
7911          %29 = OpVectorShuffle %v2float %28 %28 0 1
7912          %30 = OpLoad %20 %7
7913          %31 = OpLoad %15 %6
7914          %32 = OpSampledImage %22 %30 %31
7915          %33 = OpImageSampleWeightedQCOM %v4float %27 %29 %32
7916                OpStore %3 %33
7917          %34 = OpLoad %20 %7
7918          %35 = OpLoad %15 %6
7919          %36 = OpSampledImage %22 %34 %35
7920          %37 = OpLoad %v4float %4
7921          %38 = OpVectorShuffle %v3float %37 %37 0 1 0
7922          %39 = OpCompositeExtract %float %38 0
7923          %40 = OpCompositeExtract %float %38 1
7924          %41 = OpCompositeExtract %float %38 2
7925          %42 = OpCompositeConstruct %v3float %39 %40 %41
7926          %43 = OpImageSampleImplicitLod %v4float %36 %42
7927                OpStore %3 %43
7928                OpReturn
7929                OpFunctionEnd
7930 )";
7931   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
7932   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
7933             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
7934   EXPECT_THAT(
7935       getDiagnosticString(),
7936       HasSubstr("Illegal use of QCOM image processing decorated texture"));
7937 }
7938 
TEST_F(ValidateImage,ImageMSArray_ArrayedSampledTypeRequiresCapability)7939 TEST_F(ValidateImage, ImageMSArray_ArrayedSampledTypeRequiresCapability) {
7940   const std::string code = R"(
7941                OpCapability Shader
7942                OpCapability StorageImageMultisample
7943                OpCapability StorageImageReadWithoutFormat
7944                OpMemoryModel Logical GLSL450
7945                OpEntryPoint Fragment %main "main"
7946                OpExecutionMode %main OriginUpperLeft
7947                OpDecorate %var_image DescriptorSet 0
7948                OpDecorate %var_image Binding 1
7949        %void = OpTypeVoid
7950        %func = OpTypeFunction %void
7951         %f32 = OpTypeFloat 32
7952         %u32 = OpTypeInt 32 0
7953      %uint_2 = OpConstant %u32 2
7954      %uint_1 = OpConstant %u32 1
7955      %v2uint = OpTypeVector %u32 2
7956     %v4float = OpTypeVector %f32 4
7957     %image = OpTypeImage %f32 2D 2 1 1 2 Unknown
7958 %ptr_image = OpTypePointer UniformConstant %image
7959        %10 = OpConstantComposite %v2uint %uint_1 %uint_2
7960 %var_image = OpVariable %ptr_image UniformConstant
7961      %main = OpFunction %void None %func
7962  %main_lab = OpLabel
7963        %18 = OpLoad %image %var_image
7964        %19 = OpImageRead %v4float %18 %10 Sample %uint_2
7965              OpReturn
7966              OpFunctionEnd
7967 )";
7968 
7969   const spv_target_env env = SPV_ENV_VULKAN_1_0;
7970   CompileSuccessfully(code, env);
7971   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
7972   EXPECT_THAT(
7973       getDiagnosticString(),
7974       HasSubstr("Capability ImageMSArray is required to access storage image"));
7975 }
7976 
TEST_F(ValidateImage,ImageMSArray_SampledTypeDoesNotRequireCapability)7977 TEST_F(ValidateImage, ImageMSArray_SampledTypeDoesNotRequireCapability) {
7978   const std::string code = R"(
7979                OpCapability Shader
7980                OpCapability StorageImageMultisample
7981                OpCapability StorageImageReadWithoutFormat
7982                OpMemoryModel Logical GLSL450
7983                OpEntryPoint Fragment %main "main"
7984                OpExecutionMode %main OriginUpperLeft
7985                OpDecorate %var_image DescriptorSet 0
7986                OpDecorate %var_image Binding 1
7987        %void = OpTypeVoid
7988        %func = OpTypeFunction %void
7989         %f32 = OpTypeFloat 32
7990         %u32 = OpTypeInt 32 0
7991      %uint_2 = OpConstant %u32 2
7992      %uint_1 = OpConstant %u32 1
7993      %v2uint = OpTypeVector %u32 2
7994     %v4float = OpTypeVector %f32 4
7995     %image = OpTypeImage %f32 2D 2 0 1 2 Unknown
7996 %ptr_image = OpTypePointer UniformConstant %image
7997        %10 = OpConstantComposite %v2uint %uint_1 %uint_2
7998 %var_image = OpVariable %ptr_image UniformConstant
7999      %main = OpFunction %void None %func
8000  %main_lab = OpLabel
8001        %18 = OpLoad %image %var_image
8002        %19 = OpImageRead %v4float %18 %10 Sample %uint_2
8003              OpReturn
8004              OpFunctionEnd
8005 )";
8006 
8007   const spv_target_env env = SPV_ENV_VULKAN_1_0;
8008   CompileSuccessfully(code, env);
8009   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(env));
8010   EXPECT_THAT(getDiagnosticString(), Eq(""));
8011 }
8012 
TEST_F(ValidateImage,ImageMSArray_ArrayedTypeDoesNotRequireCapability)8013 TEST_F(ValidateImage, ImageMSArray_ArrayedTypeDoesNotRequireCapability) {
8014   const std::string code = R"(
8015                OpCapability Shader
8016                OpCapability StorageImageReadWithoutFormat
8017                OpMemoryModel Logical GLSL450
8018                OpEntryPoint Fragment %main "main"
8019                OpExecutionMode %main OriginUpperLeft
8020                OpDecorate %var_image DescriptorSet 0
8021                OpDecorate %var_image Binding 1
8022        %void = OpTypeVoid
8023        %func = OpTypeFunction %void
8024         %f32 = OpTypeFloat 32
8025         %u32 = OpTypeInt 32 0
8026      %uint_3 = OpConstant %u32 3
8027      %uint_2 = OpConstant %u32 2
8028      %uint_1 = OpConstant %u32 1
8029      %v3uint = OpTypeVector %u32 3
8030     %v4float = OpTypeVector %f32 4
8031     %image = OpTypeImage %f32 2D 2 1 0 2 Unknown
8032 %ptr_image = OpTypePointer UniformConstant %image
8033        %10 = OpConstantComposite %v3uint %uint_1 %uint_2 %uint_3
8034 %var_image = OpVariable %ptr_image UniformConstant
8035      %main = OpFunction %void None %func
8036  %main_lab = OpLabel
8037        %18 = OpLoad %image %var_image
8038        %19 = OpImageRead %v4float %18 %10
8039              OpReturn
8040              OpFunctionEnd
8041 )";
8042 
8043   const spv_target_env env = SPV_ENV_VULKAN_1_0;
8044   CompileSuccessfully(code, env);
8045   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(env));
8046   EXPECT_THAT(getDiagnosticString(), Eq(""));
8047 }
8048 
8049 }  // namespace
8050 }  // namespace val
8051 }  // namespace spvtools
8052