• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2017 Google Inc.
2 // Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights
3 // reserved.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 
17 // Tests for unique type declaration rules validator.
18 
19 #include <sstream>
20 #include <string>
21 
22 #include "gmock/gmock.h"
23 #include "test/unit_spirv.h"
24 #include "test/val/val_fixtures.h"
25 
26 namespace spvtools {
27 namespace val {
28 namespace {
29 
30 using ::testing::Eq;
31 using ::testing::HasSubstr;
32 using ::testing::Not;
33 
34 using ValidateImage = spvtest::ValidateBase<bool>;
35 
GenerateShaderCode(const std::string & body,const std::string & capabilities_and_extensions="",const std::string & execution_model="Fragment",const std::string & execution_mode="",const spv_target_env env=SPV_ENV_UNIVERSAL_1_0,const std::string & memory_model="GLSL450",const std::string & declarations="")36 std::string GenerateShaderCode(
37     const std::string& body,
38     const std::string& capabilities_and_extensions = "",
39     const std::string& execution_model = "Fragment",
40     const std::string& execution_mode = "",
41     const spv_target_env env = SPV_ENV_UNIVERSAL_1_0,
42     const std::string& memory_model = "GLSL450",
43     const std::string& declarations = "") {
44   std::ostringstream ss;
45   ss << R"(
46 OpCapability Shader
47 OpCapability InputAttachment
48 OpCapability ImageGatherExtended
49 OpCapability MinLod
50 OpCapability Sampled1D
51 OpCapability ImageQuery
52 OpCapability Int64
53 OpCapability Float64
54 OpCapability SparseResidency
55 OpCapability ImageBuffer
56 )";
57 
58   if (env == SPV_ENV_UNIVERSAL_1_0) {
59     ss << "OpCapability SampledRect\n";
60   }
61 
62   // In 1.4, the entry point must list all module-scope variables used.  Just
63   // list all of them.
64   //
65   // For Vulkan, anything Location decoration needs to be an interface variable
66   std::string interface_vars =
67       (env != SPV_ENV_UNIVERSAL_1_4) ? "%input_flat_u32" :
68                                      R"(
69 %uniform_image_f32_1d_0001
70 %uniform_image_f32_1d_0002_rgba32f
71 %uniform_image_f32_2d_0001
72 %uniform_image_f32_2d_0011 ; multisampled sampled
73 %uniform_image_u32_2d_0001
74 %uniform_image_u32_2d_0002
75 %uniform_image_s32_3d_0001
76 %uniform_image_f32_2d_0002
77 %uniform_image_s32_2d_0002
78 %uniform_image_f32_spd_0002
79 %uniform_image_f32_3d_0111
80 %uniform_image_f32_cube_0101
81 %uniform_image_f32_cube_0102_rgba32f
82 %uniform_sampler
83 %private_image_u32_buffer_0002_r32ui
84 %private_image_u32_spd_0002
85 %private_image_f32_buffer_0002_r32ui
86 %input_flat_u32
87 )";
88 
89   ss << capabilities_and_extensions;
90   ss << "OpMemoryModel Logical " << memory_model << "\n";
91   ss << "OpEntryPoint " << execution_model
92      << " %main \"main\" " + interface_vars + "\n";
93   if (execution_model == "Fragment") {
94     ss << "OpExecutionMode %main OriginUpperLeft\n";
95   }
96   ss << execution_mode;
97 
98   if (env == SPV_ENV_VULKAN_1_0) {
99     ss << R"(
100 OpDecorate %uniform_image_f32_1d_0001 DescriptorSet 0
101 OpDecorate %uniform_image_f32_1d_0001 Binding 0
102 OpDecorate %uniform_image_f32_1d_0002_rgba32f DescriptorSet 0
103 OpDecorate %uniform_image_f32_1d_0002_rgba32f Binding 1
104 OpDecorate %uniform_image_f32_2d_0001 DescriptorSet 0
105 OpDecorate %uniform_image_f32_2d_0001 Binding 2
106 OpDecorate %uniform_image_f32_2d_0011 DescriptorSet 0
107 OpDecorate %uniform_image_f32_2d_0011 Binding 3
108 OpDecorate %uniform_image_u32_2d_0001 DescriptorSet 1
109 OpDecorate %uniform_image_u32_2d_0001 Binding 0
110 OpDecorate %uniform_image_u32_2d_0002 DescriptorSet 1
111 OpDecorate %uniform_image_u32_2d_0002 Binding 1
112 OpDecorate %uniform_image_s32_3d_0001 DescriptorSet 1
113 OpDecorate %uniform_image_s32_3d_0001 Binding 2
114 OpDecorate %uniform_image_f32_2d_0002 DescriptorSet 1
115 OpDecorate %uniform_image_f32_2d_0002 Binding 3
116 OpDecorate %uniform_image_s32_2d_0002 DescriptorSet 1
117 OpDecorate %uniform_image_s32_2d_0002 Binding 4
118 OpDecorate %uniform_image_f32_spd_0002 DescriptorSet 2
119 OpDecorate %uniform_image_f32_spd_0002 Binding 0
120 OpDecorate %uniform_image_f32_3d_0111 DescriptorSet 2
121 OpDecorate %uniform_image_f32_3d_0111 Binding 1
122 OpDecorate %uniform_image_f32_cube_0101 DescriptorSet 2
123 OpDecorate %uniform_image_f32_cube_0101 Binding 2
124 OpDecorate %uniform_image_f32_cube_0102_rgba32f DescriptorSet 2
125 OpDecorate %uniform_image_f32_cube_0102_rgba32f Binding 3
126 OpDecorate %uniform_sampler DescriptorSet 3
127 OpDecorate %uniform_sampler Binding 0
128 OpDecorate %input_flat_u32 Flat
129 OpDecorate %input_flat_u32 Location 0
130 )";
131   }
132 
133   ss << R"(
134 %void = OpTypeVoid
135 %func = OpTypeFunction %void
136 %bool = OpTypeBool
137 %f32 = OpTypeFloat 32
138 %f64 = OpTypeFloat 64
139 %u32 = OpTypeInt 32 0
140 %s32 = OpTypeInt 32 1
141 %u64 = OpTypeInt 64 0
142 %s64 = OpTypeInt 64 1
143 %s32vec2 = OpTypeVector %s32 2
144 %u32vec2 = OpTypeVector %u32 2
145 %f32vec2 = OpTypeVector %f32 2
146 %u32vec3 = OpTypeVector %u32 3
147 %s32vec3 = OpTypeVector %s32 3
148 %f32vec3 = OpTypeVector %f32 3
149 %u32vec4 = OpTypeVector %u32 4
150 %s32vec4 = OpTypeVector %s32 4
151 %f32vec4 = OpTypeVector %f32 4
152 %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,TypeImageDimRectVulkan)789 TEST_F(ValidateImage, TypeImageDimRectVulkan) {
790   const std::string code = GetShaderHeader("OpCapability InputAttachment\n") +
791                            R"(
792 %img_type = OpTypeImage %f32 Rect 0 1 0 2 Unknown
793 )" + TrivialMain();
794 
795   CompileSuccessfully(code.c_str());
796   ASSERT_EQ(SPV_ERROR_INVALID_CAPABILITY,
797             ValidateInstructions(SPV_ENV_VULKAN_1_0));
798   // Can't actually hit VUID-StandaloneSpirv-OpTypeImage-09638
799   EXPECT_THAT(
800       getDiagnosticString(),
801       AnyVUID("TypeImage requires one of these capabilities: SampledRect"));
802 }
803 
TEST_F(ValidateImage,TypeImageWrongSampledTypeForTileImageDataEXT)804 TEST_F(ValidateImage, TypeImageWrongSampledTypeForTileImageDataEXT) {
805   const std::string code = GetShaderHeader(
806                                "OpCapability TileImageColorReadAccessEXT\n"
807                                "OpExtension \"SPV_EXT_shader_tile_image\"\n",
808                                false) +
809                            R"(
810 %img_type = OpTypeImage %void TileImageDataEXT 0 0 0 2 Unknown
811 )";
812 
813   CompileSuccessfully(code.c_str());
814   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
815   EXPECT_THAT(
816       getDiagnosticString(),
817       HasSubstr(
818           "Dim TileImageDataEXT requires Sampled Type to be not OpTypeVoid"));
819 }
820 
TEST_F(ValidateImage,TypeImageWrongSampledForTileImageDataEXT)821 TEST_F(ValidateImage, TypeImageWrongSampledForTileImageDataEXT) {
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 1 Unknown
828 )";
829 
830   CompileSuccessfully(code.c_str());
831   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
832   EXPECT_THAT(getDiagnosticString(),
833               HasSubstr("Dim TileImageDataEXT requires Sampled to be 2"));
834 }
835 
TEST_F(ValidateImage,TypeImageWrongFormatForTileImageDataEXT)836 TEST_F(ValidateImage, TypeImageWrongFormatForTileImageDataEXT) {
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 0 0 0 2 Rgba32f
843 )";
844 
845   CompileSuccessfully(code.c_str());
846   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
847   EXPECT_THAT(getDiagnosticString(),
848               HasSubstr("Dim TileImageDataEXT requires format Unknown"));
849 }
850 
TEST_F(ValidateImage,TypeImageWrongDepthForTileImageDataEXT)851 TEST_F(ValidateImage, TypeImageWrongDepthForTileImageDataEXT) {
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 1 0 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 Depth to be 0"));
864 }
865 
TEST_F(ValidateImage,TypeImageWrongArrayedForTileImageDataEXT)866 TEST_F(ValidateImage, TypeImageWrongArrayedForTileImageDataEXT) {
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 1 0 2 Unknown
873 )";
874 
875   CompileSuccessfully(code.c_str());
876   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
877   EXPECT_THAT(getDiagnosticString(),
878               HasSubstr("Dim TileImageDataEXT requires Arrayed to be 0"));
879 }
880 
TEST_F(ValidateImage,TypeSampledImage_TileImageDataEXT_Error)881 TEST_F(ValidateImage, TypeSampledImage_TileImageDataEXT_Error) {
882   const std::string code = GetShaderHeader(
883                                "OpCapability TileImageColorReadAccessEXT\n"
884                                "OpExtension \"SPV_EXT_shader_tile_image\"\n",
885                                false) +
886                            R"(
887 %img_type = OpTypeImage %f32 TileImageDataEXT 0 0 0 2 Unknown
888 %simg_type = OpTypeSampledImage %img_type
889 )";
890 
891   CompileSuccessfully(code.c_str());
892   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
893   EXPECT_THAT(getDiagnosticString(),
894               HasSubstr("Sampled image type requires an image type with "
895                         "\"Sampled\" operand set to 0 or 1"));
896 }
897 
TEST_F(ValidateImage,ImageTexelPointerImageDimTileImageDataEXTBad)898 TEST_F(ValidateImage, ImageTexelPointerImageDimTileImageDataEXTBad) {
899   const std::string body = R"(
900 %texel_ptr = OpImageTexelPointer %ptr_Image_u32 %tile_image_u32_tid_0002 %u32_0 %u32_0
901 %sum = OpAtomicIAdd %u32 %texel_ptr %u32_1 %u32_0 %u32_1
902 )";
903   const std::string decl = R"(
904 %type_image_u32_tid_0002 = OpTypeImage %u32 TileImageDataEXT 0 0 0 2 Unknown
905 %ptr_image_u32_tid_0002 = OpTypePointer TileImageEXT %type_image_u32_tid_0002
906 %tile_image_u32_tid_0002 = OpVariable %ptr_image_u32_tid_0002 TileImageEXT
907 )";
908 
909   const std::string extra = R"(
910 OpCapability TileImageColorReadAccessEXT
911 OpExtension "SPV_EXT_shader_tile_image"
912 )";
913 
914   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
915                                          SPV_ENV_UNIVERSAL_1_5, "GLSL450", decl)
916                           .c_str());
917   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
918   EXPECT_THAT(getDiagnosticString(),
919               HasSubstr("Image Dim TileImageDataEXT cannot be used with "
920                         "OpImageTexelPointer"));
921 }
922 
TEST_F(ValidateImage,ReadTileImageDataEXT)923 TEST_F(ValidateImage, ReadTileImageDataEXT) {
924   const std::string body = R"(
925 %img = OpLoad %type_image_f32_tid_0002 %uniform_image_f32_tid_0002
926 %res1 = OpImageRead %f32vec4 %img %u32vec2_01
927 )";
928 
929   const std::string decl = R"(
930 %type_image_f32_tid_0002 = OpTypeImage %f32 TileImageDataEXT 0 0 0 2 Unknown
931 %ptr_image_f32_tid_0002 = OpTypePointer UniformConstant %type_image_f32_tid_0002
932 %uniform_image_f32_tid_0002 = OpVariable %ptr_image_f32_tid_0002 UniformConstant
933 )";
934 
935   const std::string extra = R"(
936 OpCapability StorageImageReadWithoutFormat
937 OpCapability TileImageColorReadAccessEXT
938 OpExtension "SPV_EXT_shader_tile_image"
939 )";
940 
941   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
942                                          SPV_ENV_UNIVERSAL_1_5, "GLSL450", decl)
943                           .c_str());
944   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
945   EXPECT_THAT(
946       getDiagnosticString(),
947       HasSubstr("Image Dim TileImageDataEXT cannot be used with ImageRead"));
948 }
949 
TEST_F(ValidateImage,WriteTileImageDataEXT)950 TEST_F(ValidateImage, WriteTileImageDataEXT) {
951   const std::string body = R"(
952 %img = OpLoad %type_image_f32_tid_0002 %uniform_image_f32_tid_0002
953 OpImageWrite %img %u32vec2_01 %f32vec4_0000
954 )";
955 
956   const std::string decl = R"(
957 %type_image_f32_tid_0002 = OpTypeImage %f32 TileImageDataEXT 0 0 0 2 Unknown
958 %ptr_image_f32_tid_0002 = OpTypePointer UniformConstant %type_image_f32_tid_0002
959 %uniform_image_f32_tid_0002 = OpVariable %ptr_image_f32_tid_0002 UniformConstant
960 )";
961 
962   const std::string extra = R"(
963 OpCapability TileImageColorReadAccessEXT
964 OpExtension "SPV_EXT_shader_tile_image"
965 )";
966 
967   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
968                                          SPV_ENV_UNIVERSAL_1_5, "GLSL450", decl)
969                           .c_str());
970   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
971   EXPECT_THAT(getDiagnosticString(),
972               HasSubstr("Image 'Dim' cannot be TileImageDataEXT"));
973 }
974 
TEST_F(ValidateImage,QueryFormatTileImageDataEXT)975 TEST_F(ValidateImage, QueryFormatTileImageDataEXT) {
976   const std::string body = R"(
977 %img = OpLoad %type_image_f32_tid_0002 %uniform_image_f32_tid_0002
978 %res1 = OpImageQueryFormat %u32 %img
979 )";
980 
981   const std::string decl = R"(
982 %type_image_f32_tid_0002 = OpTypeImage %f32 TileImageDataEXT 0 0 0 2 Unknown
983 %ptr_image_f32_tid_0002 = OpTypePointer UniformConstant %type_image_f32_tid_0002
984 %uniform_image_f32_tid_0002 = OpVariable %ptr_image_f32_tid_0002 UniformConstant
985 )";
986 
987   const std::string extra = R"(
988 OpCapability TileImageColorReadAccessEXT
989 OpExtension "SPV_EXT_shader_tile_image"
990 )";
991 
992   CompileSuccessfully(GenerateKernelCode(body, extra, decl).c_str());
993 
994   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
995   EXPECT_THAT(getDiagnosticString(),
996               HasSubstr("Image 'Dim' cannot be TileImageDataEXT"));
997 }
998 
TEST_F(ValidateImage,QueryOrderTileImageDataEXT)999 TEST_F(ValidateImage, QueryOrderTileImageDataEXT) {
1000   const std::string body = R"(
1001 %img = OpLoad %type_image_f32_tid_0002 %uniform_image_f32_tid_0002
1002 %res1 = OpImageQueryOrder %u32 %img
1003 )";
1004 
1005   const std::string decl = R"(
1006 %type_image_f32_tid_0002 = OpTypeImage %f32 TileImageDataEXT 0 0 0 2 Unknown
1007 %ptr_image_f32_tid_0002 = OpTypePointer UniformConstant %type_image_f32_tid_0002
1008 %uniform_image_f32_tid_0002 = OpVariable %ptr_image_f32_tid_0002 UniformConstant
1009 )";
1010 
1011   const std::string extra = R"(
1012 OpCapability TileImageColorReadAccessEXT
1013 OpExtension "SPV_EXT_shader_tile_image"
1014 )";
1015 
1016   CompileSuccessfully(GenerateKernelCode(body, extra, decl).c_str());
1017 
1018   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1019   EXPECT_THAT(getDiagnosticString(),
1020               HasSubstr("Image 'Dim' cannot be TileImageDataEXT"));
1021 }
1022 
TEST_F(ValidateImage,SparseFetchTileImageDataEXT)1023 TEST_F(ValidateImage, SparseFetchTileImageDataEXT) {
1024   const std::string body = R"(
1025 %img = OpLoad %type_image_f32_tid_0002 %uniform_image_f32_tid_0002
1026 %res1 = OpImageSparseFetch %struct_u32_f32vec4 %img %u32vec2_01
1027 )";
1028 
1029   const std::string decl = R"(
1030 %type_image_f32_tid_0002 = OpTypeImage %f32 TileImageDataEXT 0 0 0 2 Unknown
1031 %ptr_image_f32_tid_0002 = OpTypePointer UniformConstant %type_image_f32_tid_0002
1032 %uniform_image_f32_tid_0002 = OpVariable %ptr_image_f32_tid_0002 UniformConstant
1033 )";
1034 
1035   const std::string extra = R"(
1036 OpCapability StorageImageReadWithoutFormat
1037 OpCapability TileImageColorReadAccessEXT
1038 OpExtension "SPV_EXT_shader_tile_image"
1039 )";
1040 
1041   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
1042                                          SPV_ENV_UNIVERSAL_1_5, "GLSL450", decl)
1043                           .c_str());
1044   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1045   EXPECT_THAT(getDiagnosticString(),
1046               HasSubstr("Expected Image 'Sampled' parameter to be 1"));
1047 }
1048 
TEST_F(ValidateImage,SparseReadTileImageDataEXT)1049 TEST_F(ValidateImage, SparseReadTileImageDataEXT) {
1050   const std::string body = R"(
1051 %img = OpLoad %type_image_f32_tid_0002 %uniform_image_f32_tid_0002
1052 %res1 = OpImageSparseRead %struct_u32_f32vec4 %img %u32vec2_01
1053 )";
1054 
1055   const std::string decl = R"(
1056 %type_image_f32_tid_0002 = OpTypeImage %f32 TileImageDataEXT 0 0 0 2 Unknown
1057 %ptr_image_f32_tid_0002 = OpTypePointer UniformConstant %type_image_f32_tid_0002
1058 %uniform_image_f32_tid_0002 = OpVariable %ptr_image_f32_tid_0002 UniformConstant
1059 )";
1060 
1061   const std::string extra = R"(
1062 OpCapability StorageImageReadWithoutFormat
1063 OpCapability TileImageColorReadAccessEXT
1064 OpExtension "SPV_EXT_shader_tile_image"
1065 )";
1066 
1067   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
1068                                          SPV_ENV_UNIVERSAL_1_5, "GLSL450", decl)
1069                           .c_str());
1070   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1071   EXPECT_THAT(
1072       getDiagnosticString(),
1073       HasSubstr(
1074           "Image Dim TileImageDataEXT cannot be used with ImageSparseRead"));
1075 }
1076 
TEST_F(ValidateImage,TypeImage_OpenCL_Sampled0_OK)1077 TEST_F(ValidateImage, TypeImage_OpenCL_Sampled0_OK) {
1078   const std::string code = GetKernelHeader() + R"(
1079 %img_type = OpTypeImage %void 2D 0 0 0 0 Unknown ReadOnly
1080 )";
1081 
1082   CompileSuccessfully(code.c_str());
1083   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_OPENCL_2_1));
1084   EXPECT_THAT(getDiagnosticString(), Eq(""));
1085 }
1086 
TEST_F(ValidateImage,TypeImage_OpenCL_Sampled1_Invalid)1087 TEST_F(ValidateImage, TypeImage_OpenCL_Sampled1_Invalid) {
1088   const std::string code = GetKernelHeader() + R"(
1089 %img_type = OpTypeImage %void 2D 0 0 0 1 Unknown ReadOnly
1090 )";
1091 
1092   CompileSuccessfully(code.c_str());
1093   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_2_1));
1094   EXPECT_THAT(getDiagnosticString(),
1095               HasSubstr("Sampled must be 0 in the OpenCL environment."));
1096 }
1097 
TEST_F(ValidateImage,TypeImage_OpenCL_Sampled2_Invalid)1098 TEST_F(ValidateImage, TypeImage_OpenCL_Sampled2_Invalid) {
1099   const std::string code = GetKernelHeader() + R"(
1100 %img_type = OpTypeImage %void 2D 0 0 0 2 Unknown ReadOnly
1101 )";
1102 
1103   CompileSuccessfully(code.c_str());
1104   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_2_1));
1105   EXPECT_THAT(getDiagnosticString(),
1106               HasSubstr("Sampled must be 0 in the OpenCL environment."));
1107 }
1108 
TEST_F(ValidateImage,TypeImage_OpenCL_AccessQualifierMissing)1109 TEST_F(ValidateImage, TypeImage_OpenCL_AccessQualifierMissing) {
1110   const std::string code = GetKernelHeader() + R"(
1111 %img_type = OpTypeImage %void 2D 0 0 0 0 Unknown
1112 )";
1113 
1114   CompileSuccessfully(code.c_str());
1115   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_2_1));
1116   EXPECT_THAT(getDiagnosticString(),
1117               HasSubstr("In the OpenCL environment, the optional Access "
1118                         "Qualifier must be present"));
1119 }
1120 
TEST_F(ValidateImage,TypeImage_Vulkan_Sampled1_OK)1121 TEST_F(ValidateImage, TypeImage_Vulkan_Sampled1_OK) {
1122   const std::string code = GetShaderHeader() + R"(
1123 %img_type = OpTypeImage %f32 2D 0 0 0 1 Unknown
1124 )" + TrivialMain();
1125 
1126   CompileSuccessfully(code.c_str());
1127   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1128   EXPECT_THAT(getDiagnosticString(), Eq(""));
1129 }
1130 
TEST_F(ValidateImage,TypeImage_Vulkan_Sampled2_OK)1131 TEST_F(ValidateImage, TypeImage_Vulkan_Sampled2_OK) {
1132   const std::string code = GetShaderHeader() + R"(
1133 %img_type = OpTypeImage %f32 2D 0 0 0 2 Rgba32f
1134 )" + TrivialMain();
1135 
1136   CompileSuccessfully(code.c_str());
1137   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1138   EXPECT_THAT(getDiagnosticString(), Eq(""));
1139 }
1140 
TEST_F(ValidateImage,TypeImage_Vulkan_Sampled0_Invalid)1141 TEST_F(ValidateImage, TypeImage_Vulkan_Sampled0_Invalid) {
1142   const std::string code = GetShaderHeader() + R"(
1143 %img_type = OpTypeImage %f32 2D 0 0 0 0 Unknown
1144 )" + TrivialMain();
1145 
1146   CompileSuccessfully(code.c_str());
1147   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1148   EXPECT_THAT(getDiagnosticString(),
1149               AnyVUID("VUID-StandaloneSpirv-OpTypeImage-04657"));
1150   EXPECT_THAT(getDiagnosticString(),
1151               HasSubstr("Sampled must be 1 or 2 in the Vulkan environment."));
1152 }
1153 
TEST_F(ValidateImage,TypeImageWrongFormatForSubpassData)1154 TEST_F(ValidateImage, TypeImageWrongFormatForSubpassData) {
1155   const std::string code =
1156       GetShaderHeader("OpCapability InputAttachment\n", false) +
1157       R"(
1158 %img_type = OpTypeImage %f32 SubpassData 0 0 0 2 Rgba32f
1159 )";
1160 
1161   CompileSuccessfully(code.c_str());
1162   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1163   EXPECT_THAT(getDiagnosticString(),
1164               HasSubstr("Dim SubpassData requires format Unknown"));
1165 }
1166 
TEST_F(ValidateImage,TypeImageMultisampleStorageImage_MissingCapability)1167 TEST_F(ValidateImage, TypeImageMultisampleStorageImage_MissingCapability) {
1168   const std::string code = GetShaderHeader("", false) +
1169                            R"(
1170 %img_type = OpTypeImage %f32 2D 0 0 1 2 Rgba32f
1171 )";
1172 
1173   CompileSuccessfully(code.c_str());
1174   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()) << code;
1175   EXPECT_THAT(getDiagnosticString(),
1176               HasSubstr("Capability StorageImageMultisample is required when "
1177                         "using multisampled storage image"));
1178 }
1179 
TEST_F(ValidateImage,TypeImageMultisampleStorageImage_UsesCapability)1180 TEST_F(ValidateImage, TypeImageMultisampleStorageImage_UsesCapability) {
1181   const std::string code =
1182       GetShaderHeader("OpCapability StorageImageMultisample\n", false) +
1183       R"(
1184 %img_type = OpTypeImage %f32 2D 0 0 1 2 Rgba32f
1185 )";
1186 
1187   CompileSuccessfully(code.c_str());
1188   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()) << code;
1189   EXPECT_THAT(getDiagnosticString(), Eq(""));
1190 }
1191 
TEST_F(ValidateImage,TypeImageMultisampleSubpassData_OK)1192 TEST_F(ValidateImage, TypeImageMultisampleSubpassData_OK) {
1193   const std::string code =
1194       GetShaderHeader("OpCapability InputAttachment\n", false) +
1195       R"(
1196 %img_type = OpTypeImage %f32 SubpassData 0 0 1 2 Unknown
1197 )";
1198 
1199   CompileSuccessfully(code.c_str());
1200   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()) << code;
1201   EXPECT_THAT(getDiagnosticString(), Eq(""));
1202 }
1203 
TEST_F(ValidateImage,TypeSampledImage_NotImage_Error)1204 TEST_F(ValidateImage, TypeSampledImage_NotImage_Error) {
1205   const std::string code = GetShaderHeader("", false) + R"(
1206 %simg_type = OpTypeSampledImage %f32
1207 )";
1208 
1209   CompileSuccessfully(code.c_str());
1210   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1211   EXPECT_THAT(getDiagnosticString(),
1212               HasSubstr("Expected Image to be of type OpTypeImage"));
1213 }
1214 
TEST_F(ValidateImage,TypeSampledImage_Sampled0_Success)1215 TEST_F(ValidateImage, TypeSampledImage_Sampled0_Success) {
1216   // This is ok in the OpenCL and universal environments.
1217   // Vulkan will reject an OpTypeImage with Sampled=0, checked elsewhere.
1218   const std::string code = GetShaderHeader() + R"(
1219 %imty = OpTypeImage %f32 2D 0 0 0 0 Unknown
1220 %simg_type = OpTypeSampledImage %imty
1221 )" + TrivialMain();
1222 
1223   CompileSuccessfully(code.c_str());
1224   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1225   EXPECT_EQ(getDiagnosticString(), "");
1226 }
1227 
TEST_F(ValidateImage,TypeSampledImage_Sampled2_Error)1228 TEST_F(ValidateImage, TypeSampledImage_Sampled2_Error) {
1229   const std::string code = GetShaderHeader() + R"(
1230 %storage_image = OpTypeImage %f32 2D 0 0 0 2 Rgba32f
1231 %simg_type = OpTypeSampledImage %storage_image
1232 )" + TrivialMain();
1233 
1234   CompileSuccessfully(code.c_str());
1235   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1236   EXPECT_THAT(getDiagnosticString(),
1237               HasSubstr("Sampled image type requires an image type with "
1238                         "\"Sampled\" operand set to 0 or 1"));
1239 }
1240 
TEST_F(ValidateImage,TypeSampledImage_Sampled1_Success)1241 TEST_F(ValidateImage, TypeSampledImage_Sampled1_Success) {
1242   const std::string code = GetShaderHeader() + R"(
1243 %im = OpTypeImage %f32 2D 0 0 0 1 Unknown
1244 %simg_type = OpTypeSampledImage %im
1245 )" + TrivialMain();
1246 
1247   CompileSuccessfully(code.c_str());
1248   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1249   EXPECT_EQ(getDiagnosticString(), "");
1250 }
1251 
TEST_F(ValidateImage,SampledImageSuccess)1252 TEST_F(ValidateImage, SampledImageSuccess) {
1253   const std::string body = R"(
1254 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1255 %sampler = OpLoad %type_sampler %uniform_sampler
1256 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1257 )";
1258 
1259   CompileSuccessfully(GenerateShaderCode(body).c_str());
1260   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1261 }
1262 
TEST_F(ValidateImage,SampledImageVulkanSuccess)1263 TEST_F(ValidateImage, SampledImageVulkanSuccess) {
1264   const std::string body = R"(
1265 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1266 %sampler = OpLoad %type_sampler %uniform_sampler
1267 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1268 )";
1269 
1270   const spv_target_env env = SPV_ENV_VULKAN_1_0;
1271   CompileSuccessfully(GenerateShaderCode(body, "", "Fragment", "", env), env);
1272   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(env));
1273 }
1274 
TEST_F(ValidateImage,SampledImageWrongResultType)1275 TEST_F(ValidateImage, SampledImageWrongResultType) {
1276   const std::string body = R"(
1277 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1278 %sampler = OpLoad %type_sampler %uniform_sampler
1279 %simg = OpSampledImage %type_image_f32_2d_0001 %img %sampler
1280 )";
1281 
1282   CompileSuccessfully(GenerateShaderCode(body).c_str());
1283   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1284   EXPECT_THAT(getDiagnosticString(),
1285               HasSubstr("Expected Result Type to be OpTypeSampledImage"));
1286 }
1287 
TEST_F(ValidateImage,SampledImageNotImage)1288 TEST_F(ValidateImage, SampledImageNotImage) {
1289   const std::string body = R"(
1290 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1291 %sampler = OpLoad %type_sampler %uniform_sampler
1292 %simg1 = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1293 %simg2 = OpSampledImage %type_sampled_image_f32_2d_0001 %simg1 %sampler
1294 )";
1295 
1296   CompileSuccessfully(GenerateShaderCode(body).c_str());
1297   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1298   EXPECT_THAT(getDiagnosticString(),
1299               HasSubstr("Expected Image to be of type OpTypeImage"));
1300 }
1301 
TEST_F(ValidateImage,SampledImageImageNotForSampling)1302 TEST_F(ValidateImage, SampledImageImageNotForSampling) {
1303   const std::string code = GetShaderHeader() + R"(
1304 %im_ty = OpTypeImage %f32 2D 0 0 0 2 Unknown
1305 %sampler_ty = OpTypeSampler
1306 %sampled_image_ty = OpTypeSampledImage %im_ty ; will fail here first!
1307 
1308 %ptr_im_ty = OpTypePointer UniformConstant %im_ty
1309 %var_im = OpVariable %ptr_im_ty UniformConstant
1310 
1311 %ptr_sampler_ty = OpTypePointer UniformConstant %sampler_ty
1312 %var_sampler = OpVariable %ptr_sampler_ty UniformConstant
1313 
1314 %main = OpFunction %void None %func
1315 %entry = OpLabel
1316 %im = OpLoad %im_ty %var_im
1317 %sampler = OpLoad %sampler_ty %var_sampler
1318 %sampled_image = OpSampledImage %sampled_image_ty %im %sampler
1319 OpReturn
1320 OpFunctionEnd
1321 )";
1322 
1323   CompileSuccessfully(code.c_str());
1324   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1325   EXPECT_THAT(getDiagnosticString(),
1326               HasSubstr("Sampled image type requires an image type with "
1327                         "\"Sampled\" operand set to 0 or 1"))
1328       << code;
1329 }
1330 
TEST_F(ValidateImage,SampledImageNotSampler)1331 TEST_F(ValidateImage, SampledImageNotSampler) {
1332   const std::string body = R"(
1333 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1334 %sampler = OpLoad %type_sampler %uniform_sampler
1335 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %img
1336 )";
1337 
1338   CompileSuccessfully(GenerateShaderCode(body).c_str());
1339   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1340   EXPECT_THAT(getDiagnosticString(),
1341               HasSubstr("Expected Sampler to be of type OpTypeSampler"));
1342 }
1343 
TEST_F(ValidateImage,SampledImageIsStorage)1344 TEST_F(ValidateImage, SampledImageIsStorage) {
1345   const std::string declarations = R"(
1346 %type_sampled_image_f32_2d_0002 = OpTypeSampledImage %type_image_f32_2d_0002
1347 )";
1348   const std::string body = R"(
1349 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
1350 %sampler = OpLoad %type_sampler %uniform_sampler
1351 %simg = OpSampledImage %type_sampled_image_f32_2d_0002 %img %sampler
1352 )";
1353 
1354   CompileSuccessfully(GenerateShaderCode(body, "", "Fragment", "",
1355                                          SPV_ENV_UNIVERSAL_1_0, "GLSL450",
1356                                          declarations)
1357                           .c_str());
1358   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1359   EXPECT_THAT(getDiagnosticString(),
1360               HasSubstr("Sampled image type requires an image type with "
1361                         "\"Sampled\" operand set to 0 or 1"));
1362 }
1363 
TEST_F(ValidateImage,ImageTexelPointerSuccess)1364 TEST_F(ValidateImage, ImageTexelPointerSuccess) {
1365   const std::string body = R"(
1366 %texel_ptr = OpImageTexelPointer %ptr_Image_u32 %private_image_u32_buffer_0002_r32ui %u32_0 %u32_0
1367 %sum = OpAtomicIAdd %u32 %texel_ptr %u32_1 %u32_0 %u32_1
1368 )";
1369 
1370   CompileSuccessfully(GenerateShaderCode(body).c_str());
1371   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1372 }
1373 
TEST_F(ValidateImage,ImageTexelPointerResultTypeNotPointer)1374 TEST_F(ValidateImage, ImageTexelPointerResultTypeNotPointer) {
1375   const std::string body = R"(
1376 %texel_ptr = OpImageTexelPointer %type_image_u32_buffer_0002_r32ui %private_image_u32_buffer_0002_r32ui %u32_0 %u32_0
1377 %sum = OpAtomicIAdd %u32 %texel_ptr %u32_1 %u32_0 %u32_1
1378 )";
1379 
1380   CompileSuccessfully(GenerateShaderCode(body).c_str());
1381   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1382   EXPECT_THAT(getDiagnosticString(),
1383               HasSubstr("Expected Result Type to be OpTypePointer"));
1384 }
1385 
TEST_F(ValidateImage,ImageTexelPointerResultTypeNotImageClass)1386 TEST_F(ValidateImage, ImageTexelPointerResultTypeNotImageClass) {
1387   const std::string body = R"(
1388 %texel_ptr = OpImageTexelPointer %ptr_image_f32_cube_0101 %private_image_u32_buffer_0002_r32ui %u32_0 %u32_0
1389 %sum = OpAtomicIAdd %u32 %texel_ptr %u32_1 %u32_0 %u32_1
1390 )";
1391 
1392   CompileSuccessfully(GenerateShaderCode(body).c_str());
1393   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1394   EXPECT_THAT(getDiagnosticString(),
1395               HasSubstr("Expected Result Type to be OpTypePointer whose "
1396                         "Storage Class operand is Image"));
1397 }
1398 
TEST_F(ValidateImage,ImageTexelPointerResultTypeNotNumericNorVoid)1399 TEST_F(ValidateImage, ImageTexelPointerResultTypeNotNumericNorVoid) {
1400   const std::string body = R"(
1401 %texel_ptr = OpImageTexelPointer %ptr_Image_u32arr4 %private_image_u32_buffer_0002_r32ui %u32_0 %u32_0
1402 %sum = OpAtomicIAdd %u32 %texel_ptr %u32_1 %u32_0 %u32_1
1403 )";
1404 
1405   CompileSuccessfully(GenerateShaderCode(body).c_str());
1406   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1407   EXPECT_THAT(
1408       getDiagnosticString(),
1409       HasSubstr("Expected Result Type to be OpTypePointer whose Type operand "
1410                 "must be a scalar numerical type or OpTypeVoid"));
1411 }
1412 
TEST_F(ValidateImage,ImageTexelPointerImageNotResultTypePointer)1413 TEST_F(ValidateImage, ImageTexelPointerImageNotResultTypePointer) {
1414   const std::string body = R"(
1415 %texel_ptr = OpImageTexelPointer %ptr_Image_u32 %type_image_f32_buffer_0002_r32ui %u32_0 %u32_0
1416 %sum = OpAtomicIAdd %u32 %texel_ptr %u32_1 %u32_0 %u32_1
1417 )";
1418 
1419   CompileSuccessfully(GenerateShaderCode(body).c_str());
1420   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1421   EXPECT_THAT(getDiagnosticString(),
1422               HasSubstr("Operand '148[%148]' cannot be a "
1423                         "type"));
1424 }
1425 
TEST_F(ValidateImage,ImageTexelPointerImageNotImage)1426 TEST_F(ValidateImage, ImageTexelPointerImageNotImage) {
1427   const std::string body = R"(
1428 %texel_ptr = OpImageTexelPointer %ptr_Image_u32 %uniform_sampler %u32_0 %u32_0
1429 %sum = OpAtomicIAdd %u32 %texel_ptr %u32_1 %u32_0 %u32_1
1430 )";
1431 
1432   CompileSuccessfully(GenerateShaderCode(body).c_str());
1433   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1434   EXPECT_THAT(
1435       getDiagnosticString(),
1436       HasSubstr("Expected Image to be OpTypePointer with Type OpTypeImage"));
1437 }
1438 
TEST_F(ValidateImage,ImageTexelPointerImageSampledNotResultType)1439 TEST_F(ValidateImage, ImageTexelPointerImageSampledNotResultType) {
1440   const std::string body = R"(
1441 %texel_ptr = OpImageTexelPointer %ptr_Image_u32 %uniform_image_f32_cube_0101 %u32_0 %u32_0
1442 %sum = OpAtomicIAdd %u32 %texel_ptr %u32_1 %u32_0 %u32_1
1443 )";
1444 
1445   CompileSuccessfully(GenerateShaderCode(body).c_str());
1446   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1447   EXPECT_THAT(getDiagnosticString(),
1448               HasSubstr("Expected Image 'Sampled Type' to be the same as the "
1449                         "Type pointed to by Result Type"));
1450 }
1451 
TEST_F(ValidateImage,ImageTexelPointerImageDimSubpassDataBad)1452 TEST_F(ValidateImage, ImageTexelPointerImageDimSubpassDataBad) {
1453   const std::string body = R"(
1454 %texel_ptr = OpImageTexelPointer %ptr_Image_u32 %private_image_u32_spd_0002 %u32_0 %u32_0
1455 %sum = OpAtomicIAdd %u32 %texel_ptr %u32_1 %u32_0 %u32_1
1456 )";
1457 
1458   CompileSuccessfully(GenerateShaderCode(body).c_str());
1459   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1460   EXPECT_THAT(
1461       getDiagnosticString(),
1462       HasSubstr(
1463           "Image Dim SubpassData cannot be used with OpImageTexelPointer"));
1464 }
1465 
TEST_F(ValidateImage,ImageTexelPointerImageCoordTypeBad)1466 TEST_F(ValidateImage, ImageTexelPointerImageCoordTypeBad) {
1467   const std::string body = R"(
1468 %texel_ptr = OpImageTexelPointer %ptr_Image_f32 %private_image_f32_buffer_0002_r32ui %f32_0 %f32_0
1469 %sum = OpAtomicIAdd %f32 %texel_ptr %f32_1 %f32_0 %f32_1
1470 )";
1471 
1472   CompileSuccessfully(GenerateShaderCode(body).c_str());
1473   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1474   EXPECT_THAT(getDiagnosticString(),
1475               HasSubstr("Expected Coordinate to be integer scalar or vector"));
1476 }
1477 
TEST_F(ValidateImage,ImageTexelPointerImageCoordSizeBad)1478 TEST_F(ValidateImage, ImageTexelPointerImageCoordSizeBad) {
1479   const std::string body = R"(
1480 %texel_ptr = OpImageTexelPointer %ptr_Image_u32 %uniform_image_u32_2d_0002 %u32vec3_012 %u32_0
1481 %sum = OpAtomicIAdd %u32 %texel_ptr %u32_1 %u32_0 %u32_1
1482 )";
1483 
1484   CompileSuccessfully(GenerateShaderCode(body).c_str());
1485   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1486   EXPECT_THAT(
1487       getDiagnosticString(),
1488       HasSubstr("Expected Coordinate to have 2 components, but given 3"));
1489 }
1490 
TEST_F(ValidateImage,ImageTexelPointerSampleNotIntScalar)1491 TEST_F(ValidateImage, ImageTexelPointerSampleNotIntScalar) {
1492   const std::string body = R"(
1493 %texel_ptr = OpImageTexelPointer %ptr_Image_u32 %private_image_u32_buffer_0002_r32ui %u32_0 %f32_0
1494 %sum = OpAtomicIAdd %u32 %texel_ptr %u32_1 %u32_0 %u32_1
1495 )";
1496 
1497   CompileSuccessfully(GenerateShaderCode(body).c_str());
1498   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1499   EXPECT_THAT(getDiagnosticString(),
1500               HasSubstr("Expected Sample to be integer scalar"));
1501 }
1502 
TEST_F(ValidateImage,ImageTexelPointerSampleNotZeroForImageWithMSZero)1503 TEST_F(ValidateImage, ImageTexelPointerSampleNotZeroForImageWithMSZero) {
1504   const std::string body = R"(
1505 %texel_ptr = OpImageTexelPointer %ptr_Image_u32 %private_image_u32_buffer_0002_r32ui %u32_0 %u32_1
1506 %sum = OpAtomicIAdd %u32 %texel_ptr %u32_1 %u32_0 %u32_1
1507 )";
1508 
1509   CompileSuccessfully(GenerateShaderCode(body).c_str());
1510   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1511   EXPECT_THAT(getDiagnosticString(),
1512               HasSubstr("Expected Sample for Image with MS 0 to be a valid "
1513                         "<id> for the value 0"));
1514 }
1515 
TEST_F(ValidateImage,SampleImplicitLodSuccess)1516 TEST_F(ValidateImage, SampleImplicitLodSuccess) {
1517   const std::string body = R"(
1518 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1519 %sampler = OpLoad %type_sampler %uniform_sampler
1520 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1521 %res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh
1522 %res2 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh Bias %f32_0_25
1523 %res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh ConstOffset %s32vec2_01
1524 %res5 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh Offset %s32vec2_01
1525 %res6 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh MinLod %f32_0_5
1526 %res7 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh Bias|Offset|MinLod %f32_0_25 %s32vec2_01 %f32_0_5
1527 %res8 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh NonPrivateTexelKHR
1528 )";
1529 
1530   const std::string extra = R"(
1531 OpCapability VulkanMemoryModelKHR
1532 OpExtension "SPV_KHR_vulkan_memory_model"
1533 )";
1534   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
1535                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
1536                           .c_str());
1537   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1538 }
1539 
TEST_F(ValidateImage,SampleImplicitLodWrongResultType)1540 TEST_F(ValidateImage, SampleImplicitLodWrongResultType) {
1541   const std::string body = R"(
1542 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1543 %sampler = OpLoad %type_sampler %uniform_sampler
1544 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1545 %res1 = OpImageSampleImplicitLod %f32 %simg %f32vec2_hh
1546 )";
1547 
1548   CompileSuccessfully(GenerateShaderCode(body).c_str());
1549   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1550   EXPECT_THAT(getDiagnosticString(),
1551               HasSubstr("Expected Result Type to be int or float vector type"));
1552 }
1553 
TEST_F(ValidateImage,SampleImplicitLodWrongNumComponentsResultType)1554 TEST_F(ValidateImage, SampleImplicitLodWrongNumComponentsResultType) {
1555   const std::string body = R"(
1556 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1557 %sampler = OpLoad %type_sampler %uniform_sampler
1558 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1559 %res1 = OpImageSampleImplicitLod %f32vec3 %simg %f32vec2_hh
1560 )";
1561 
1562   CompileSuccessfully(GenerateShaderCode(body).c_str());
1563   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1564   EXPECT_THAT(getDiagnosticString(),
1565               HasSubstr("Expected Result Type to have 4 components"));
1566 }
1567 
TEST_F(ValidateImage,SampleImplicitLodNotSampledImage)1568 TEST_F(ValidateImage, SampleImplicitLodNotSampledImage) {
1569   const std::string body = R"(
1570 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1571 %res1 = OpImageSampleImplicitLod %f32vec4 %img %f32vec2_hh
1572 )";
1573 
1574   CompileSuccessfully(GenerateShaderCode(body).c_str());
1575   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1576   EXPECT_THAT(
1577       getDiagnosticString(),
1578       HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage"));
1579 }
1580 
TEST_F(ValidateImage,SampleImplicitLodMultisampleError)1581 TEST_F(ValidateImage, SampleImplicitLodMultisampleError) {
1582   const std::string body = R"(
1583 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
1584 %sampler = OpLoad %type_sampler %uniform_sampler
1585 %simg = OpSampledImage %type_sampled_image_f32_2d_0011 %img %sampler
1586 %res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_hh Sample %u32_1
1587 )";
1588 
1589   CompileSuccessfully(GenerateShaderCode(body).c_str());
1590   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1591   EXPECT_THAT(getDiagnosticString(),
1592               HasSubstr("Sampling operation is invalid for multisample image"));
1593 }
1594 
TEST_F(ValidateImage,SampleImplicitLodWrongSampledType)1595 TEST_F(ValidateImage, SampleImplicitLodWrongSampledType) {
1596   const std::string body = R"(
1597 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1598 %sampler = OpLoad %type_sampler %uniform_sampler
1599 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1600 %res1 = OpImageSampleImplicitLod %u32vec4 %simg %f32vec2_00
1601 )";
1602 
1603   CompileSuccessfully(GenerateShaderCode(body).c_str());
1604   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1605   EXPECT_THAT(getDiagnosticString(),
1606               HasSubstr("Expected Image 'Sampled Type' to be the same as "
1607                         "Result Type components"));
1608 }
1609 
TEST_F(ValidateImage,SampleImplicitLodVoidSampledType)1610 TEST_F(ValidateImage, SampleImplicitLodVoidSampledType) {
1611   const std::string body = R"(
1612 %img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001
1613 %sampler = OpLoad %type_sampler %uniform_sampler
1614 %simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler
1615 %res1 = OpImageSampleImplicitLod %u32vec4 %simg %f32vec2_00
1616 )";
1617 
1618   CompileSuccessfully(GenerateShaderCode(body).c_str());
1619   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1620 }
1621 
TEST_F(ValidateImage,SampleImplicitLodWrongCoordinateType)1622 TEST_F(ValidateImage, SampleImplicitLodWrongCoordinateType) {
1623   const std::string body = R"(
1624 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1625 %sampler = OpLoad %type_sampler %uniform_sampler
1626 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1627 %res1 = OpImageSampleImplicitLod %f32vec4 %simg %img
1628 )";
1629 
1630   CompileSuccessfully(GenerateShaderCode(body).c_str());
1631   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1632   EXPECT_THAT(getDiagnosticString(),
1633               HasSubstr("Expected Coordinate to be float scalar or vector"));
1634 }
1635 
TEST_F(ValidateImage,SampleImplicitLodCoordinateSizeTooSmall)1636 TEST_F(ValidateImage, SampleImplicitLodCoordinateSizeTooSmall) {
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 = OpImageSampleImplicitLod %f32vec4 %simg %f32_0_5
1642 )";
1643 
1644   CompileSuccessfully(GenerateShaderCode(body).c_str());
1645   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1646   EXPECT_THAT(getDiagnosticString(),
1647               HasSubstr("Expected Coordinate to have at least 2 components, "
1648                         "but given only 1"));
1649 }
1650 
TEST_F(ValidateImage,SampleExplicitLodSuccessShader)1651 TEST_F(ValidateImage, SampleExplicitLodSuccessShader) {
1652   const std::string body = R"(
1653 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1654 %sampler = OpLoad %type_sampler %uniform_sampler
1655 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1656 %res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec4_0000 Lod %f32_1
1657 %res2 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_hh Grad %f32vec2_10 %f32vec2_01
1658 %res3 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_hh ConstOffset %s32vec2_01
1659 %res4 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec3_hhh Offset %s32vec2_01
1660 %res5 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_hh Grad|Offset|MinLod %f32vec2_10 %f32vec2_01 %s32vec2_01 %f32_0_5
1661 %res6 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec4_0000 Lod|NonPrivateTexelKHR %f32_1
1662 )";
1663 
1664   const std::string extra = R"(
1665 OpCapability VulkanMemoryModelKHR
1666 OpExtension "SPV_KHR_vulkan_memory_model"
1667 )";
1668   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
1669                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
1670                           .c_str());
1671   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1672 }
1673 
TEST_F(ValidateImage,SampleExplicitLodSuccessKernel)1674 TEST_F(ValidateImage, SampleExplicitLodSuccessKernel) {
1675   const std::string body = R"(
1676 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1677 %sampler = OpLoad %type_sampler %uniform_sampler
1678 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1679 %res1 = OpImageSampleExplicitLod %f32vec4 %simg %u32vec4_0123 Lod %f32_1
1680 %res2 = OpImageSampleExplicitLod %f32vec4 %simg %u32vec2_01 Grad %f32vec2_10 %f32vec2_01
1681 %res3 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_hh ConstOffset %u32vec2_01
1682 %res4 = OpImageSampleExplicitLod %f32vec4 %simg %u32vec2_01 Offset %u32vec2_01
1683 %res5 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_hh Grad|Offset %f32vec2_10 %f32vec2_01 %u32vec2_01
1684 )";
1685 
1686   CompileSuccessfully(GenerateKernelCode(body).c_str());
1687   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1688 }
1689 
TEST_F(ValidateImage,SampleExplicitLodSuccessCubeArrayed)1690 TEST_F(ValidateImage, SampleExplicitLodSuccessCubeArrayed) {
1691   const std::string body = R"(
1692 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
1693 %sampler = OpLoad %type_sampler %uniform_sampler
1694 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
1695 %res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec4_0000 Grad %f32vec3_hhh %f32vec3_hhh
1696 )";
1697 
1698   CompileSuccessfully(GenerateShaderCode(body).c_str());
1699   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1700 }
1701 
TEST_F(ValidateImage,SampleExplicitLodWrongResultType)1702 TEST_F(ValidateImage, SampleExplicitLodWrongResultType) {
1703   const std::string body = R"(
1704 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1705 %sampler = OpLoad %type_sampler %uniform_sampler
1706 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1707 %res1 = OpImageSampleExplicitLod %f32 %simg %f32vec2_hh Lod %f32_1
1708 )";
1709 
1710   CompileSuccessfully(GenerateShaderCode(body).c_str());
1711   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1712   EXPECT_THAT(getDiagnosticString(),
1713               HasSubstr("Expected Result Type to be int or float vector type"));
1714 }
1715 
TEST_F(ValidateImage,SampleExplicitLodWrongNumComponentsResultType)1716 TEST_F(ValidateImage, SampleExplicitLodWrongNumComponentsResultType) {
1717   const std::string body = R"(
1718 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1719 %sampler = OpLoad %type_sampler %uniform_sampler
1720 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1721 %res1 = OpImageSampleExplicitLod %f32vec3 %simg %f32vec2_hh Lod %f32_1
1722 )";
1723 
1724   CompileSuccessfully(GenerateShaderCode(body).c_str());
1725   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1726   EXPECT_THAT(getDiagnosticString(),
1727               HasSubstr("Expected Result Type to have 4 components"));
1728 }
1729 
TEST_F(ValidateImage,SampleExplicitLodNotSampledImage)1730 TEST_F(ValidateImage, SampleExplicitLodNotSampledImage) {
1731   const std::string body = R"(
1732 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1733 %res1 = OpImageSampleExplicitLod %f32vec4 %img %f32vec2_hh Lod %f32_1
1734 )";
1735 
1736   CompileSuccessfully(GenerateShaderCode(body).c_str());
1737   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1738   EXPECT_THAT(
1739       getDiagnosticString(),
1740       HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage"));
1741 }
1742 
TEST_F(ValidateImage,SampleExplicitLodMultisampleError)1743 TEST_F(ValidateImage, SampleExplicitLodMultisampleError) {
1744   const std::string body = R"(
1745 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
1746 %sampler = OpLoad %type_sampler %uniform_sampler
1747 %simg = OpSampledImage %type_sampled_image_f32_2d_0011 %img %sampler
1748 %res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh Lod|Sample %f32_0 %u32_1
1749 )";
1750 
1751   CompileSuccessfully(GenerateShaderCode(body).c_str());
1752   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1753   EXPECT_THAT(getDiagnosticString(),
1754               HasSubstr("Sampling operation is invalid for multisample image"));
1755 }
1756 
TEST_F(ValidateImage,SampleExplicitLodWrongSampledType)1757 TEST_F(ValidateImage, SampleExplicitLodWrongSampledType) {
1758   const std::string body = R"(
1759 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1760 %sampler = OpLoad %type_sampler %uniform_sampler
1761 %simg = OpSampledImage %type_sampled_image_f32_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_ERROR_INVALID_DATA, ValidateInstructions());
1767   EXPECT_THAT(getDiagnosticString(),
1768               HasSubstr("Expected Image 'Sampled Type' to be the same as "
1769                         "Result Type components"));
1770 }
1771 
TEST_F(ValidateImage,SampleExplicitLodVoidSampledType)1772 TEST_F(ValidateImage, SampleExplicitLodVoidSampledType) {
1773   const std::string body = R"(
1774 %img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001
1775 %sampler = OpLoad %type_sampler %uniform_sampler
1776 %simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler
1777 %res1 = OpImageSampleExplicitLod %u32vec4 %simg %f32vec2_00 Lod %f32_1
1778 )";
1779 
1780   CompileSuccessfully(GenerateShaderCode(body).c_str());
1781   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1782 }
1783 
TEST_F(ValidateImage,SampleExplicitLodWrongCoordinateType)1784 TEST_F(ValidateImage, SampleExplicitLodWrongCoordinateType) {
1785   const std::string body = R"(
1786 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1787 %sampler = OpLoad %type_sampler %uniform_sampler
1788 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1789 %res1 = OpImageSampleExplicitLod %f32vec4 %simg %img Lod %f32_1
1790 )";
1791 
1792   CompileSuccessfully(GenerateShaderCode(body).c_str());
1793   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1794   EXPECT_THAT(getDiagnosticString(),
1795               HasSubstr("Expected Coordinate to be float scalar or vector"));
1796 }
1797 
TEST_F(ValidateImage,SampleExplicitLodCoordinateSizeTooSmall)1798 TEST_F(ValidateImage, SampleExplicitLodCoordinateSizeTooSmall) {
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 %f32_0_5 Lod %f32_1
1804 )";
1805 
1806   CompileSuccessfully(GenerateShaderCode(body).c_str());
1807   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1808   EXPECT_THAT(getDiagnosticString(),
1809               HasSubstr("Expected Coordinate to have at least 2 components, "
1810                         "but given only 1"));
1811 }
1812 
TEST_F(ValidateImage,SampleExplicitLodBias)1813 TEST_F(ValidateImage, SampleExplicitLodBias) {
1814   const std::string body = R"(
1815 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1816 %sampler = OpLoad %type_sampler %uniform_sampler
1817 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1818 %res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_00 Bias|Lod %f32_1 %f32_1
1819 )";
1820 
1821   CompileSuccessfully(GenerateShaderCode(body).c_str());
1822   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1823   EXPECT_THAT(
1824       getDiagnosticString(),
1825       HasSubstr(
1826           "Image Operand Bias can only be used with ImplicitLod opcodes"));
1827 }
1828 
TEST_F(ValidateImage,LodAndGrad)1829 TEST_F(ValidateImage, LodAndGrad) {
1830   const std::string body = R"(
1831 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1832 %sampler = OpLoad %type_sampler %uniform_sampler
1833 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1834 %res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_00 Lod|Grad %f32_1 %f32vec2_hh %f32vec2_hh
1835 )";
1836 
1837   CompileSuccessfully(GenerateShaderCode(body).c_str());
1838   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1839   EXPECT_THAT(
1840       getDiagnosticString(),
1841       HasSubstr(
1842           "Image Operand bits Lod and Grad cannot be set at the same time"));
1843 }
1844 
TEST_F(ValidateImage,ImplicitLodWithLod)1845 TEST_F(ValidateImage, ImplicitLodWithLod) {
1846   const std::string body = R"(
1847 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1848 %sampler = OpLoad %type_sampler %uniform_sampler
1849 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1850 %res2 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh Lod %f32_0_5
1851 )";
1852 
1853   CompileSuccessfully(GenerateShaderCode(body).c_str());
1854   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1855   EXPECT_THAT(
1856       getDiagnosticString(),
1857       HasSubstr("Image Operand Lod can only be used with ExplicitLod opcodes "
1858                 "and OpImageFetch"));
1859 }
1860 
TEST_F(ValidateImage,LodWrongType)1861 TEST_F(ValidateImage, LodWrongType) {
1862   const std::string body = R"(
1863 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1864 %sampler = OpLoad %type_sampler %uniform_sampler
1865 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1866 %res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_00 Lod %f32vec2_hh)";
1867 
1868   CompileSuccessfully(GenerateShaderCode(body).c_str());
1869   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1870   EXPECT_THAT(getDiagnosticString(),
1871               HasSubstr("Expected Image Operand Lod to be float scalar when "
1872                         "used with ExplicitLod"));
1873 }
1874 
TEST_F(ValidateImage,LodWrongDim)1875 TEST_F(ValidateImage, LodWrongDim) {
1876   const std::string body = R"(
1877 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
1878 %sampler = OpLoad %type_sampler %uniform_sampler
1879 %simg = OpSampledImage %type_sampled_image_f32_rect_0001 %img %sampler
1880 %res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_00 Lod %f32_0)";
1881 
1882   CompileSuccessfully(GenerateShaderCode(body).c_str());
1883   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1884   EXPECT_THAT(getDiagnosticString(),
1885               HasSubstr("Image Operand Lod requires 'Dim' parameter to be 1D, "
1886                         "2D, 3D or Cube"));
1887 }
1888 
TEST_F(ValidateImage,MinLodIncompatible)1889 TEST_F(ValidateImage, MinLodIncompatible) {
1890   const std::string body = R"(
1891 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1892 %sampler = OpLoad %type_sampler %uniform_sampler
1893 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1894 %res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_00 Lod|MinLod %f32_0 %f32_0)";
1895 
1896   CompileSuccessfully(GenerateShaderCode(body).c_str());
1897   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1898   EXPECT_THAT(
1899       getDiagnosticString(),
1900       HasSubstr(
1901           "Image Operand MinLod can only be used with ImplicitLod opcodes or "
1902           "together with Image Operand Grad"));
1903 }
1904 
TEST_F(ValidateImage,ImplicitLodWithGrad)1905 TEST_F(ValidateImage, ImplicitLodWithGrad) {
1906   const std::string body = R"(
1907 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1908 %sampler = OpLoad %type_sampler %uniform_sampler
1909 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1910 %res2 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh Grad %f32vec2_hh %f32vec2_hh
1911 )";
1912 
1913   CompileSuccessfully(GenerateShaderCode(body).c_str());
1914   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1915   EXPECT_THAT(
1916       getDiagnosticString(),
1917       HasSubstr(
1918           "Image Operand Grad can only be used with ExplicitLod opcodes"));
1919 }
1920 
TEST_F(ValidateImage,SampleImplicitLodCubeArrayedSuccess)1921 TEST_F(ValidateImage, SampleImplicitLodCubeArrayedSuccess) {
1922   const std::string body = R"(
1923 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
1924 %sampler = OpLoad %type_sampler %uniform_sampler
1925 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
1926 %res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000
1927 %res2 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 Bias %f32_0_25
1928 %res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 MinLod %f32_0_5
1929 %res5 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 Bias|MinLod %f32_0_25 %f32_0_5
1930 )";
1931 
1932   CompileSuccessfully(GenerateShaderCode(body).c_str());
1933   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1934 }
1935 
TEST_F(ValidateImage,SampleImplicitLodBiasWrongType)1936 TEST_F(ValidateImage, SampleImplicitLodBiasWrongType) {
1937   const std::string body = R"(
1938 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
1939 %sampler = OpLoad %type_sampler %uniform_sampler
1940 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
1941 %res2 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh Bias %u32_0
1942 )";
1943 
1944   CompileSuccessfully(GenerateShaderCode(body).c_str());
1945   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1946   EXPECT_THAT(getDiagnosticString(),
1947               HasSubstr("Expected Image Operand Bias to be float scalar"));
1948 }
1949 
TEST_F(ValidateImage,SampleImplicitLodBiasWrongDim)1950 TEST_F(ValidateImage, SampleImplicitLodBiasWrongDim) {
1951   const std::string body = R"(
1952 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
1953 %sampler = OpLoad %type_sampler %uniform_sampler
1954 %simg = OpSampledImage %type_sampled_image_f32_rect_0001 %img %sampler
1955 %res2 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh Bias %f32_0
1956 )";
1957 
1958   CompileSuccessfully(GenerateShaderCode(body).c_str());
1959   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1960   EXPECT_THAT(getDiagnosticString(),
1961               HasSubstr("Image Operand Bias requires 'Dim' parameter to be 1D, "
1962                         "2D, 3D or Cube"));
1963 }
1964 
TEST_F(ValidateImage,SampleExplicitLodGradDxWrongType)1965 TEST_F(ValidateImage, SampleExplicitLodGradDxWrongType) {
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 %s32vec3_012 %f32vec3_hhh
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,SampleExplicitLodGradDyWrongType)1980 TEST_F(ValidateImage, SampleExplicitLodGradDyWrongType) {
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  %f32vec3_hhh %s32vec3_012
1986 )";
1987 
1988   CompileSuccessfully(GenerateShaderCode(body).c_str());
1989   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1990   EXPECT_THAT(getDiagnosticString(),
1991               HasSubstr("Expected both Image Operand Grad ids to be float "
1992                         "scalars or vectors"));
1993 }
1994 
TEST_F(ValidateImage,SampleExplicitLodGradDxWrongSize)1995 TEST_F(ValidateImage, SampleExplicitLodGradDxWrongSize) {
1996   const std::string body = R"(
1997 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
1998 %sampler = OpLoad %type_sampler %uniform_sampler
1999 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
2000 %res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec4_0000 Grad %f32vec2_00 %f32vec3_hhh
2001 )";
2002 
2003   CompileSuccessfully(GenerateShaderCode(body).c_str());
2004   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2005   EXPECT_THAT(
2006       getDiagnosticString(),
2007       HasSubstr(
2008           "Expected Image Operand Grad dx to have 3 components, but given 2"));
2009 }
2010 
TEST_F(ValidateImage,SampleExplicitLodGradDyWrongSize)2011 TEST_F(ValidateImage, SampleExplicitLodGradDyWrongSize) {
2012   const std::string body = R"(
2013 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
2014 %sampler = OpLoad %type_sampler %uniform_sampler
2015 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
2016 %res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec4_0000 Grad %f32vec3_hhh %f32vec2_00
2017 )";
2018 
2019   CompileSuccessfully(GenerateShaderCode(body).c_str());
2020   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2021   EXPECT_THAT(
2022       getDiagnosticString(),
2023       HasSubstr(
2024           "Expected Image Operand Grad dy to have 3 components, but given 2"));
2025 }
2026 
TEST_F(ValidateImage,SampleImplicitLodConstOffsetCubeDim)2027 TEST_F(ValidateImage, SampleImplicitLodConstOffsetCubeDim) {
2028   const std::string body = R"(
2029 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
2030 %sampler = OpLoad %type_sampler %uniform_sampler
2031 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
2032 %res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 ConstOffset %s32vec3_012
2033 )";
2034 
2035   CompileSuccessfully(GenerateShaderCode(body).c_str());
2036   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2037   EXPECT_THAT(
2038       getDiagnosticString(),
2039       HasSubstr(
2040           "Image Operand ConstOffset cannot be used with Cube Image 'Dim'"));
2041 }
2042 
TEST_F(ValidateImage,SampleImplicitLodConstOffsetWrongType)2043 TEST_F(ValidateImage, SampleImplicitLodConstOffsetWrongType) {
2044   const std::string body = R"(
2045 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2046 %sampler = OpLoad %type_sampler %uniform_sampler
2047 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2048 %res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_00 ConstOffset %f32vec2_00
2049 )";
2050 
2051   CompileSuccessfully(GenerateShaderCode(body).c_str());
2052   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2053   EXPECT_THAT(
2054       getDiagnosticString(),
2055       HasSubstr(
2056           "Expected Image Operand ConstOffset to be int scalar or vector"));
2057 }
2058 
TEST_F(ValidateImage,SampleImplicitLodConstOffsetWrongSize)2059 TEST_F(ValidateImage, SampleImplicitLodConstOffsetWrongSize) {
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 %res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_00 ConstOffset %s32vec3_012
2065 )";
2066 
2067   CompileSuccessfully(GenerateShaderCode(body).c_str());
2068   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2069   EXPECT_THAT(getDiagnosticString(),
2070               HasSubstr("Expected Image Operand ConstOffset to have 2 "
2071                         "components, but given 3"));
2072 }
2073 
TEST_F(ValidateImage,SampleImplicitLodConstOffsetNotConst)2074 TEST_F(ValidateImage, SampleImplicitLodConstOffsetNotConst) {
2075   const std::string body = R"(
2076 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2077 %sampler = OpLoad %type_sampler %uniform_sampler
2078 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2079 %offset = OpSNegate %s32vec3 %s32vec3_012
2080 %res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_00 ConstOffset %offset
2081 )";
2082 
2083   CompileSuccessfully(GenerateShaderCode(body).c_str());
2084   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2085   EXPECT_THAT(
2086       getDiagnosticString(),
2087       HasSubstr("Expected Image Operand ConstOffset to be a const object"));
2088 }
2089 
TEST_F(ValidateImage,SampleImplicitLodOffsetCubeDim)2090 TEST_F(ValidateImage, SampleImplicitLodOffsetCubeDim) {
2091   const std::string body = R"(
2092 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
2093 %sampler = OpLoad %type_sampler %uniform_sampler
2094 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
2095 %res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 Offset %s32vec3_012
2096 )";
2097 
2098   CompileSuccessfully(GenerateShaderCode(body).c_str());
2099   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2100   EXPECT_THAT(
2101       getDiagnosticString(),
2102       HasSubstr("Image Operand Offset cannot be used with Cube Image 'Dim'"));
2103 }
2104 
TEST_F(ValidateImage,SampleImplicitLodOffsetWrongType)2105 TEST_F(ValidateImage, SampleImplicitLodOffsetWrongType) {
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 %f32vec2_00
2111 )";
2112 
2113   CompileSuccessfully(GenerateShaderCode(body).c_str());
2114   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2115   EXPECT_THAT(
2116       getDiagnosticString(),
2117       HasSubstr("Expected Image Operand Offset to be int scalar or vector"));
2118 }
2119 
TEST_F(ValidateImage,SampleImplicitLodOffsetWrongSize)2120 TEST_F(ValidateImage, SampleImplicitLodOffsetWrongSize) {
2121   const std::string body = R"(
2122 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2123 %sampler = OpLoad %type_sampler %uniform_sampler
2124 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2125 %res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 Offset %s32vec3_012
2126 )";
2127 
2128   CompileSuccessfully(GenerateShaderCode(body).c_str());
2129   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2130   EXPECT_THAT(
2131       getDiagnosticString(),
2132       HasSubstr(
2133           "Expected Image Operand Offset to have 2 components, but given 3"));
2134 }
2135 
TEST_F(ValidateImage,SampleImplicitLodVulkanOffsetWrongSize)2136 TEST_F(ValidateImage, SampleImplicitLodVulkanOffsetWrongSize) {
2137   const std::string body = R"(
2138 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2139 %sampler = OpLoad %type_sampler %uniform_sampler
2140 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2141 %res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 Offset %s32vec2_01
2142 )";
2143 
2144   CompileSuccessfully(
2145       GenerateShaderCode(body, "", "Fragment", "", SPV_ENV_VULKAN_1_0).c_str());
2146   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
2147   EXPECT_THAT(getDiagnosticString(),
2148               AnyVUID("VUID-StandaloneSpirv-Offset-04663"));
2149   EXPECT_THAT(getDiagnosticString(),
2150               HasSubstr("Image Operand Offset can only be used with "
2151                         "OpImage*Gather operations"));
2152 }
2153 
TEST_F(ValidateImage,SampleImplicitLodVulkanOffsetWrongBeforeLegalization)2154 TEST_F(ValidateImage, SampleImplicitLodVulkanOffsetWrongBeforeLegalization) {
2155   const std::string body = R"(
2156 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2157 %sampler = OpLoad %type_sampler %uniform_sampler
2158 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2159 %res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 Offset %s32vec2_01
2160 )";
2161 
2162   CompileSuccessfully(
2163       GenerateShaderCode(body, "", "Fragment", "", SPV_ENV_VULKAN_1_0).c_str());
2164   getValidatorOptions()->before_hlsl_legalization = true;
2165   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
2166 }
2167 
TEST_F(ValidateImage,SampleImplicitLodMoreThanOneOffset)2168 TEST_F(ValidateImage, SampleImplicitLodMoreThanOneOffset) {
2169   const std::string body = R"(
2170 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2171 %sampler = OpLoad %type_sampler %uniform_sampler
2172 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2173 %res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 ConstOffset|Offset %s32vec2_01 %s32vec2_01
2174 )";
2175 
2176   CompileSuccessfully(GenerateShaderCode(body).c_str());
2177   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2178   EXPECT_THAT(
2179       getDiagnosticString(),
2180       HasSubstr("Image Operands Offset, ConstOffset, ConstOffsets, Offsets "
2181                 "cannot be used together"));
2182 }
2183 
TEST_F(ValidateImage,SampleImplicitLodVulkanMoreThanOneOffset)2184 TEST_F(ValidateImage, SampleImplicitLodVulkanMoreThanOneOffset) {
2185   const std::string body = R"(
2186 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2187 %sampler = OpLoad %type_sampler %uniform_sampler
2188 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2189 %res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 ConstOffset|Offset %s32vec2_01 %s32vec2_01
2190 )";
2191 
2192   CompileSuccessfully(
2193       GenerateShaderCode(body, "", "Fragment", "", SPV_ENV_VULKAN_1_0).c_str());
2194   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
2195   EXPECT_THAT(
2196       getDiagnosticString(),
2197       HasSubstr("Image Operands Offset, ConstOffset, ConstOffsets, Offsets "
2198                 "cannot be used together"));
2199 }
2200 
TEST_F(ValidateImage,SampleImplicitLodMinLodWrongType)2201 TEST_F(ValidateImage, SampleImplicitLodMinLodWrongType) {
2202   const std::string body = R"(
2203 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
2204 %sampler = OpLoad %type_sampler %uniform_sampler
2205 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
2206 %res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 MinLod %s32_0
2207 )";
2208 
2209   CompileSuccessfully(GenerateShaderCode(body).c_str());
2210   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2211   EXPECT_THAT(getDiagnosticString(),
2212               HasSubstr("Expected Image Operand MinLod to be float scalar"));
2213 }
2214 
TEST_F(ValidateImage,SampleImplicitLodMinLodWrongDim)2215 TEST_F(ValidateImage, SampleImplicitLodMinLodWrongDim) {
2216   const std::string body = R"(
2217 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
2218 %sampler = OpLoad %type_sampler %uniform_sampler
2219 %simg = OpSampledImage %type_sampled_image_f32_rect_0001 %img %sampler
2220 %res2 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh MinLod %f32_0_25
2221 )";
2222 
2223   CompileSuccessfully(GenerateShaderCode(body).c_str());
2224   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2225   EXPECT_THAT(getDiagnosticString(),
2226               HasSubstr("Image Operand MinLod requires 'Dim' parameter to be "
2227                         "1D, 2D, 3D or Cube"));
2228 }
2229 
TEST_F(ValidateImage,SampleProjExplicitLodSuccess2D)2230 TEST_F(ValidateImage, SampleProjExplicitLodSuccess2D) {
2231   const std::string body = R"(
2232 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2233 %sampler = OpLoad %type_sampler %uniform_sampler
2234 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2235 %res1 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec3_hhh Lod %f32_1
2236 %res3 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec3_hhh Grad %f32vec2_10 %f32vec2_01
2237 %res4 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec3_hhh ConstOffset %s32vec2_01
2238 %res5 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec3_hhh Offset %s32vec2_01
2239 %res7 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec3_hhh Grad|Offset %f32vec2_10 %f32vec2_01 %s32vec2_01
2240 %res8 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec3_hhh Lod|NonPrivateTexelKHR %f32_1
2241 )";
2242 
2243   const std::string extra = R"(
2244 OpCapability VulkanMemoryModelKHR
2245 OpExtension "SPV_KHR_vulkan_memory_model"
2246 )";
2247   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
2248                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
2249                           .c_str());
2250   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2251 }
2252 
TEST_F(ValidateImage,SampleProjExplicitLodSuccessRect)2253 TEST_F(ValidateImage, SampleProjExplicitLodSuccessRect) {
2254   const std::string body = R"(
2255 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
2256 %sampler = OpLoad %type_sampler %uniform_sampler
2257 %simg = OpSampledImage %type_sampled_image_f32_rect_0001 %img %sampler
2258 %res1 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec3_hhh Grad %f32vec2_10 %f32vec2_01
2259 %res2 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec3_hhh Grad|Offset %f32vec2_10 %f32vec2_01 %s32vec2_01
2260 )";
2261 
2262   CompileSuccessfully(GenerateShaderCode(body).c_str());
2263   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
2264 }
2265 
TEST_F(ValidateImage,SampleProjExplicitLodWrongResultType)2266 TEST_F(ValidateImage, SampleProjExplicitLodWrongResultType) {
2267   const std::string body = R"(
2268 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2269 %sampler = OpLoad %type_sampler %uniform_sampler
2270 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2271 %res1 = OpImageSampleProjExplicitLod %f32 %simg %f32vec3_hhh Lod %f32_1
2272 )";
2273 
2274   CompileSuccessfully(GenerateShaderCode(body).c_str());
2275   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2276   EXPECT_THAT(getDiagnosticString(),
2277               HasSubstr("Expected Result Type to be int or float vector type"));
2278 }
2279 
TEST_F(ValidateImage,SampleProjExplicitLodWrongNumComponentsResultType)2280 TEST_F(ValidateImage, SampleProjExplicitLodWrongNumComponentsResultType) {
2281   const std::string body = R"(
2282 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2283 %sampler = OpLoad %type_sampler %uniform_sampler
2284 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2285 %res1 = OpImageSampleProjExplicitLod %f32vec3 %simg %f32vec3_hhh Lod %f32_1
2286 )";
2287 
2288   CompileSuccessfully(GenerateShaderCode(body).c_str());
2289   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2290   EXPECT_THAT(getDiagnosticString(),
2291               HasSubstr("Expected Result Type to have 4 components"));
2292 }
2293 
TEST_F(ValidateImage,SampleProjExplicitLodNotSampledImage)2294 TEST_F(ValidateImage, SampleProjExplicitLodNotSampledImage) {
2295   const std::string body = R"(
2296 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2297 %res1 = OpImageSampleProjExplicitLod %f32vec4 %img %f32vec3_hhh Lod %f32_1
2298 )";
2299 
2300   CompileSuccessfully(GenerateShaderCode(body).c_str());
2301   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2302   EXPECT_THAT(
2303       getDiagnosticString(),
2304       HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage"));
2305 }
2306 
TEST_F(ValidateImage,SampleProjExplicitLodMultisampleError)2307 TEST_F(ValidateImage, SampleProjExplicitLodMultisampleError) {
2308   const std::string body = R"(
2309 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
2310 %sampler = OpLoad %type_sampler %uniform_sampler
2311 %simg = OpSampledImage %type_sampled_image_f32_2d_0011 %img %sampler
2312 %res1 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec2_hh Lod|Sample %f32_1 %u32_1
2313 )";
2314 
2315   CompileSuccessfully(GenerateShaderCode(body).c_str());
2316   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2317   EXPECT_THAT(getDiagnosticString(),
2318               HasSubstr("Expected Image 'MS' parameter to be 0"));
2319 }
2320 
TEST_F(ValidateImage,SampleProjExplicitLodWrongSampledType)2321 TEST_F(ValidateImage, SampleProjExplicitLodWrongSampledType) {
2322   const std::string body = R"(
2323 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2324 %sampler = OpLoad %type_sampler %uniform_sampler
2325 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2326 %res1 = OpImageSampleProjExplicitLod %u32vec4 %simg %f32vec3_hhh Lod %f32_1
2327 )";
2328 
2329   CompileSuccessfully(GenerateShaderCode(body).c_str());
2330   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2331   EXPECT_THAT(getDiagnosticString(),
2332               HasSubstr("Expected Image 'Sampled Type' to be the same as "
2333                         "Result Type components"));
2334 }
2335 
TEST_F(ValidateImage,SampleProjExplicitLodVoidSampledType)2336 TEST_F(ValidateImage, SampleProjExplicitLodVoidSampledType) {
2337   const std::string body = R"(
2338 %img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001
2339 %sampler = OpLoad %type_sampler %uniform_sampler
2340 %simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler
2341 %res1 = OpImageSampleProjExplicitLod %u32vec4 %simg %f32vec3_hhh Lod %f32_1
2342 )";
2343 
2344   CompileSuccessfully(GenerateShaderCode(body).c_str());
2345   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
2346 }
2347 
TEST_F(ValidateImage,SampleProjExplicitLodWrongCoordinateType)2348 TEST_F(ValidateImage, SampleProjExplicitLodWrongCoordinateType) {
2349   const std::string body = R"(
2350 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2351 %sampler = OpLoad %type_sampler %uniform_sampler
2352 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2353 %res1 = OpImageSampleProjExplicitLod %f32vec4 %simg %img Lod %f32_1
2354 )";
2355 
2356   CompileSuccessfully(GenerateShaderCode(body).c_str());
2357   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2358   EXPECT_THAT(getDiagnosticString(),
2359               HasSubstr("Expected Coordinate to be float scalar or vector"));
2360 }
2361 
TEST_F(ValidateImage,SampleProjExplicitLodCoordinateSizeTooSmall)2362 TEST_F(ValidateImage, SampleProjExplicitLodCoordinateSizeTooSmall) {
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 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec2_hh Lod %f32_1
2368 )";
2369 
2370   CompileSuccessfully(GenerateShaderCode(body).c_str());
2371   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2372   EXPECT_THAT(getDiagnosticString(),
2373               HasSubstr("Expected Coordinate to have at least 3 components, "
2374                         "but given only 2"));
2375 }
2376 
TEST_F(ValidateImage,SampleProjImplicitLodSuccess)2377 TEST_F(ValidateImage, SampleProjImplicitLodSuccess) {
2378   const std::string body = R"(
2379 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2380 %sampler = OpLoad %type_sampler %uniform_sampler
2381 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2382 %res1 = OpImageSampleProjImplicitLod %f32vec4 %simg %f32vec3_hhh
2383 %res2 = OpImageSampleProjImplicitLod %f32vec4 %simg %f32vec3_hhh Bias %f32_0_25
2384 %res4 = OpImageSampleProjImplicitLod %f32vec4 %simg %f32vec3_hhh ConstOffset %s32vec2_01
2385 %res5 = OpImageSampleProjImplicitLod %f32vec4 %simg %f32vec3_hhh Offset %s32vec2_01
2386 %res6 = OpImageSampleProjImplicitLod %f32vec4 %simg %f32vec3_hhh MinLod %f32_0_5
2387 %res7 = OpImageSampleProjImplicitLod %f32vec4 %simg %f32vec3_hhh Bias|Offset|MinLod %f32_0_25 %s32vec2_01 %f32_0_5
2388 %res8 = OpImageSampleProjImplicitLod %f32vec4 %simg %f32vec3_hhh NonPrivateTexelKHR
2389 )";
2390 
2391   const std::string extra = R"(
2392 OpCapability VulkanMemoryModelKHR
2393 OpExtension "SPV_KHR_vulkan_memory_model"
2394 )";
2395   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
2396                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
2397                           .c_str());
2398   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2399 }
2400 
TEST_F(ValidateImage,SampleProjImplicitLodWrongResultType)2401 TEST_F(ValidateImage, SampleProjImplicitLodWrongResultType) {
2402   const std::string body = R"(
2403 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2404 %sampler = OpLoad %type_sampler %uniform_sampler
2405 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2406 %res1 = OpImageSampleProjImplicitLod %f32 %simg %f32vec3_hhh
2407 )";
2408 
2409   CompileSuccessfully(GenerateShaderCode(body).c_str());
2410   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2411   EXPECT_THAT(getDiagnosticString(),
2412               HasSubstr("Expected Result Type to be int or float vector type"));
2413 }
2414 
TEST_F(ValidateImage,SampleProjImplicitLodWrongNumComponentsResultType)2415 TEST_F(ValidateImage, SampleProjImplicitLodWrongNumComponentsResultType) {
2416   const std::string body = R"(
2417 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2418 %sampler = OpLoad %type_sampler %uniform_sampler
2419 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2420 %res1 = OpImageSampleProjImplicitLod %f32vec3 %simg %f32vec3_hhh
2421 )";
2422 
2423   CompileSuccessfully(GenerateShaderCode(body).c_str());
2424   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2425   EXPECT_THAT(getDiagnosticString(),
2426               HasSubstr("Expected Result Type to have 4 components"));
2427 }
2428 
TEST_F(ValidateImage,SampleProjImplicitLodNotSampledImage)2429 TEST_F(ValidateImage, SampleProjImplicitLodNotSampledImage) {
2430   const std::string body = R"(
2431 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2432 %res1 = OpImageSampleProjImplicitLod %f32vec4 %img %f32vec3_hhh
2433 )";
2434 
2435   CompileSuccessfully(GenerateShaderCode(body).c_str());
2436   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2437   EXPECT_THAT(
2438       getDiagnosticString(),
2439       HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage"));
2440 }
2441 
TEST_F(ValidateImage,SampleProjImplicitLodMultisampleError)2442 TEST_F(ValidateImage, SampleProjImplicitLodMultisampleError) {
2443   const std::string body = R"(
2444 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
2445 %sampler = OpLoad %type_sampler %uniform_sampler
2446 %simg = OpSampledImage %type_sampled_image_f32_2d_0011 %img %sampler
2447 %res1 = OpImageSampleProjImplicitLod %f32vec4 %simg %f32vec2_hh Sample %u32_1
2448 )";
2449 
2450   CompileSuccessfully(GenerateShaderCode(body).c_str());
2451   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2452   EXPECT_THAT(getDiagnosticString(),
2453               HasSubstr("Expected Image 'MS' parameter to be 0"));
2454 }
2455 
TEST_F(ValidateImage,SampleProjImplicitLodWrongSampledType)2456 TEST_F(ValidateImage, SampleProjImplicitLodWrongSampledType) {
2457   const std::string body = R"(
2458 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2459 %sampler = OpLoad %type_sampler %uniform_sampler
2460 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2461 %res1 = OpImageSampleProjImplicitLod %u32vec4 %simg %f32vec3_hhh
2462 )";
2463 
2464   CompileSuccessfully(GenerateShaderCode(body).c_str());
2465   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2466   EXPECT_THAT(getDiagnosticString(),
2467               HasSubstr("Expected Image 'Sampled Type' to be the same as "
2468                         "Result Type components"));
2469 }
2470 
TEST_F(ValidateImage,SampleProjImplicitLodVoidSampledType)2471 TEST_F(ValidateImage, SampleProjImplicitLodVoidSampledType) {
2472   const std::string body = R"(
2473 %img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001
2474 %sampler = OpLoad %type_sampler %uniform_sampler
2475 %simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler
2476 %res1 = OpImageSampleProjImplicitLod %u32vec4 %simg %f32vec3_hhh
2477 )";
2478 
2479   CompileSuccessfully(GenerateShaderCode(body).c_str());
2480   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
2481 }
2482 
TEST_F(ValidateImage,SampleProjImplicitLodWrongCoordinateType)2483 TEST_F(ValidateImage, SampleProjImplicitLodWrongCoordinateType) {
2484   const std::string body = R"(
2485 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2486 %sampler = OpLoad %type_sampler %uniform_sampler
2487 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2488 %res1 = OpImageSampleProjImplicitLod %f32vec4 %simg %img
2489 )";
2490 
2491   CompileSuccessfully(GenerateShaderCode(body).c_str());
2492   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2493   EXPECT_THAT(getDiagnosticString(),
2494               HasSubstr("Expected Coordinate to be float scalar or vector"));
2495 }
2496 
TEST_F(ValidateImage,SampleProjImplicitLodCoordinateSizeTooSmall)2497 TEST_F(ValidateImage, SampleProjImplicitLodCoordinateSizeTooSmall) {
2498   const std::string body = R"(
2499 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2500 %sampler = OpLoad %type_sampler %uniform_sampler
2501 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2502 %res1 = OpImageSampleProjImplicitLod %f32vec4 %simg %f32vec2_hh
2503 )";
2504 
2505   CompileSuccessfully(GenerateShaderCode(body).c_str());
2506   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2507   EXPECT_THAT(getDiagnosticString(),
2508               HasSubstr("Expected Coordinate to have at least 3 components, "
2509                         "but given only 2"));
2510 }
2511 
TEST_F(ValidateImage,SampleDrefImplicitLodSuccess)2512 TEST_F(ValidateImage, SampleDrefImplicitLodSuccess) {
2513   const std::string body = R"(
2514 %img = OpLoad %type_image_u32_2d_0001 %uniform_image_u32_2d_0001
2515 %sampler = OpLoad %type_sampler %uniform_sampler
2516 %simg = OpSampledImage %type_sampled_image_u32_2d_0001 %img %sampler
2517 %res1 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec2_hh %f32_1
2518 %res2 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec2_hh %f32_1 Bias %f32_0_25
2519 %res4 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec2_hh %f32_1 ConstOffset %s32vec2_01
2520 %res5 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec2_hh %f32_1 Offset %s32vec2_01
2521 %res6 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec2_hh %f32_1 MinLod %f32_0_5
2522 %res7 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec2_hh %f32_1 Bias|Offset|MinLod %f32_0_25 %s32vec2_01 %f32_0_5
2523 %res8 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec2_hh %f32_1 NonPrivateTexelKHR
2524 )";
2525 
2526   const std::string extra = R"(
2527 OpCapability VulkanMemoryModelKHR
2528 OpExtension "SPV_KHR_vulkan_memory_model"
2529 )";
2530   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
2531                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
2532                           .c_str());
2533   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2534 }
2535 
TEST_F(ValidateImage,SampleDrefImplicitLodWrongResultType)2536 TEST_F(ValidateImage, SampleDrefImplicitLodWrongResultType) {
2537   const std::string body = R"(
2538 %img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001
2539 %sampler = OpLoad %type_sampler %uniform_sampler
2540 %simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler
2541 %res1 = OpImageSampleDrefImplicitLod %void %simg %f32vec2_hh %u32_1
2542 )";
2543 
2544   CompileSuccessfully(GenerateShaderCode(body).c_str());
2545   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2546   EXPECT_THAT(getDiagnosticString(),
2547               HasSubstr("Expected Result Type to be int or float scalar type"));
2548 }
2549 
TEST_F(ValidateImage,SampleDrefImplicitLodNotSampledImage)2550 TEST_F(ValidateImage, SampleDrefImplicitLodNotSampledImage) {
2551   const std::string body = R"(
2552 %img = OpLoad %type_image_u32_2d_0001 %uniform_image_u32_2d_0001
2553 %res1 = OpImageSampleDrefImplicitLod %u32 %img %f32vec2_hh %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("Expected Sampled Image to be of type OpTypeSampledImage"));
2561 }
2562 
TEST_F(ValidateImage,SampleDrefImplicitLodMultisampleError)2563 TEST_F(ValidateImage, SampleDrefImplicitLodMultisampleError) {
2564   const std::string body = R"(
2565 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
2566 %sampler = OpLoad %type_sampler %uniform_sampler
2567 %simg = OpSampledImage %type_sampled_image_f32_2d_0011 %img %sampler
2568 %res1 = OpImageSampleDrefImplicitLod %f32 %simg %f32vec2_hh %f32_1 Sample %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("Dref sampling operation is invalid for multisample image"));
2576 }
2577 
TEST_F(ValidateImage,SampleDrefImplicitLodWrongSampledType)2578 TEST_F(ValidateImage, SampleDrefImplicitLodWrongSampledType) {
2579   const std::string body = R"(
2580 %img = OpLoad %type_image_u32_2d_0001 %uniform_image_u32_2d_0001
2581 %sampler = OpLoad %type_sampler %uniform_sampler
2582 %simg = OpSampledImage %type_sampled_image_u32_2d_0001 %img %sampler
2583 %res1 = OpImageSampleDrefImplicitLod %f32 %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,SampleDrefImplicitLodVoidSampledType)2593 TEST_F(ValidateImage, SampleDrefImplicitLodVoidSampledType) {
2594   const std::string body = R"(
2595 %img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001
2596 %sampler = OpLoad %type_sampler %uniform_sampler
2597 %simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler
2598 %res1 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec2_00 %u32_1
2599 )";
2600 
2601   CompileSuccessfully(GenerateShaderCode(body).c_str());
2602   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2603   EXPECT_THAT(
2604       getDiagnosticString(),
2605       HasSubstr("Expected Image 'Sampled Type' to be the same as Result Type"));
2606 }
2607 
TEST_F(ValidateImage,SampleDrefImplicitLodWrongCoordinateType)2608 TEST_F(ValidateImage, SampleDrefImplicitLodWrongCoordinateType) {
2609   const std::string body = R"(
2610 %img = OpLoad %type_image_u32_2d_0001 %uniform_image_u32_2d_0001
2611 %sampler = OpLoad %type_sampler %uniform_sampler
2612 %simg = OpSampledImage %type_sampled_image_u32_2d_0001 %img %sampler
2613 %res1 = OpImageSampleDrefImplicitLod %u32 %simg %img %u32_1
2614 )";
2615 
2616   CompileSuccessfully(GenerateShaderCode(body).c_str());
2617   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2618   EXPECT_THAT(getDiagnosticString(),
2619               HasSubstr("Expected Coordinate to be float scalar or vector"));
2620 }
2621 
TEST_F(ValidateImage,SampleDrefImplicitLodCoordinateSizeTooSmall)2622 TEST_F(ValidateImage, SampleDrefImplicitLodCoordinateSizeTooSmall) {
2623   const std::string body = R"(
2624 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2625 %sampler = OpLoad %type_sampler %uniform_sampler
2626 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2627 %res1 = OpImageSampleDrefImplicitLod %f32 %simg %f32_0_5 %f32_0_5
2628 )";
2629 
2630   CompileSuccessfully(GenerateShaderCode(body).c_str());
2631   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2632   EXPECT_THAT(getDiagnosticString(),
2633               HasSubstr("Expected Coordinate to have at least 2 components, "
2634                         "but given only 1"));
2635 }
2636 
TEST_F(ValidateImage,SampleDrefImplicitLodWrongDrefType)2637 TEST_F(ValidateImage, SampleDrefImplicitLodWrongDrefType) {
2638   const std::string body = R"(
2639 %img = OpLoad %type_image_u32_2d_0001 %uniform_image_u32_2d_0001
2640 %sampler = OpLoad %type_sampler %uniform_sampler
2641 %simg = OpSampledImage %type_sampled_image_u32_2d_0001 %img %sampler
2642 %res1 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec2_00 %f64_1
2643 )";
2644 
2645   CompileSuccessfully(GenerateShaderCode(body).c_str());
2646   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2647   EXPECT_THAT(getDiagnosticString(),
2648               HasSubstr("Expected Dref to be of 32-bit float type"));
2649 }
2650 
TEST_F(ValidateImage,SampleDrefImplicitLodWrongDimVulkan)2651 TEST_F(ValidateImage, SampleDrefImplicitLodWrongDimVulkan) {
2652   const std::string body = R"(
2653 %img = OpLoad %type_image_u32_3d_0001 %uniform_image_u32_3d_0001
2654 %sampler = OpLoad %type_sampler %uniform_sampler
2655 %simg = OpSampledImage %type_sampled_image_u32_3d_0001 %img %sampler
2656 %res1 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec3_hhh %f32_1
2657 )";
2658 
2659   CompileSuccessfully(
2660       GenerateShaderCode(body, "", "Fragment", "", SPV_ENV_VULKAN_1_0).c_str());
2661   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
2662   EXPECT_THAT(getDiagnosticString(),
2663               AnyVUID("VUID-StandaloneSpirv-OpImage-04777"));
2664   EXPECT_THAT(getDiagnosticString(),
2665               HasSubstr("In Vulkan, OpImage*Dref* instructions must not use "
2666                         "images with a 3D Dim"));
2667 }
2668 
TEST_F(ValidateImage,SampleDrefExplicitLodSuccess)2669 TEST_F(ValidateImage, SampleDrefExplicitLodSuccess) {
2670   const std::string body = R"(
2671 %img = OpLoad %type_image_s32_3d_0001 %uniform_image_s32_3d_0001
2672 %sampler = OpLoad %type_sampler %uniform_sampler
2673 %simg = OpSampledImage %type_sampled_image_s32_3d_0001 %img %sampler
2674 %res1 = OpImageSampleDrefExplicitLod %s32 %simg %f32vec4_0000 %f32_1 Lod %f32_1
2675 %res3 = OpImageSampleDrefExplicitLod %s32 %simg %f32vec3_hhh %f32_1 Grad %f32vec3_hhh %f32vec3_hhh
2676 %res4 = OpImageSampleDrefExplicitLod %s32 %simg %f32vec3_hhh %f32_1 ConstOffset %s32vec3_012
2677 %res5 = OpImageSampleDrefExplicitLod %s32 %simg %f32vec4_0000 %f32_1 Offset %s32vec3_012
2678 %res7 = OpImageSampleDrefExplicitLod %s32 %simg %f32vec3_hhh %f32_1 Grad|Offset %f32vec3_hhh %f32vec3_hhh %s32vec3_012
2679 %res8 = OpImageSampleDrefExplicitLod %s32 %simg %f32vec4_0000 %f32_1 Lod|NonPrivateTexelKHR %f32_1
2680 )";
2681 
2682   const std::string extra = R"(
2683 OpCapability VulkanMemoryModelKHR
2684 OpExtension "SPV_KHR_vulkan_memory_model"
2685 )";
2686   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
2687                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
2688                           .c_str());
2689   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2690 }
2691 
TEST_F(ValidateImage,SampleDrefExplicitLodWrongResultType)2692 TEST_F(ValidateImage, SampleDrefExplicitLodWrongResultType) {
2693   const std::string body = R"(
2694 %img = OpLoad %type_image_s32_3d_0001 %uniform_image_s32_3d_0001
2695 %sampler = OpLoad %type_sampler %uniform_sampler
2696 %simg = OpSampledImage %type_sampled_image_s32_3d_0001 %img %sampler
2697 %res1 = OpImageSampleDrefExplicitLod %bool %simg %f32vec3_hhh %s32_1 Lod %f32_1
2698 )";
2699 
2700   CompileSuccessfully(GenerateShaderCode(body).c_str());
2701   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2702   EXPECT_THAT(getDiagnosticString(),
2703               HasSubstr("Expected Result Type to be int or float scalar type"));
2704 }
2705 
TEST_F(ValidateImage,SampleDrefExplicitLodNotSampledImage)2706 TEST_F(ValidateImage, SampleDrefExplicitLodNotSampledImage) {
2707   const std::string body = R"(
2708 %img = OpLoad %type_image_s32_3d_0001 %uniform_image_s32_3d_0001
2709 %res1 = OpImageSampleDrefExplicitLod %s32 %img %f32vec3_hhh %s32_1 Lod %f32_1
2710 )";
2711 
2712   CompileSuccessfully(GenerateShaderCode(body).c_str());
2713   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2714   EXPECT_THAT(
2715       getDiagnosticString(),
2716       HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage"));
2717 }
2718 
TEST_F(ValidateImage,SampleDrefExplicitLodMultisampleError)2719 TEST_F(ValidateImage, SampleDrefExplicitLodMultisampleError) {
2720   const std::string body = R"(
2721 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
2722 %sampler = OpLoad %type_sampler %uniform_sampler
2723 %simg = OpSampledImage %type_sampled_image_f32_2d_0011 %img %sampler
2724 %res1 = OpImageSampleDrefExplicitLod %f32 %simg %f32vec2_hh %f32_1 Lod|Sample %f32_1 %u32_1
2725 )";
2726 
2727   CompileSuccessfully(GenerateShaderCode(body).c_str());
2728   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2729   EXPECT_THAT(
2730       getDiagnosticString(),
2731       HasSubstr("Dref sampling operation is invalid for multisample image"));
2732 }
2733 
TEST_F(ValidateImage,SampleDrefExplicitLodWrongSampledType)2734 TEST_F(ValidateImage, SampleDrefExplicitLodWrongSampledType) {
2735   const std::string body = R"(
2736 %img = OpLoad %type_image_s32_3d_0001 %uniform_image_s32_3d_0001
2737 %sampler = OpLoad %type_sampler %uniform_sampler
2738 %simg = OpSampledImage %type_sampled_image_s32_3d_0001 %img %sampler
2739 %res1 = OpImageSampleDrefExplicitLod %f32 %simg %f32vec3_hhh %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,SampleDrefExplicitLodVoidSampledType)2749 TEST_F(ValidateImage, SampleDrefExplicitLodVoidSampledType) {
2750   const std::string body = R"(
2751 %img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001
2752 %sampler = OpLoad %type_sampler %uniform_sampler
2753 %simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler
2754 %res1 = OpImageSampleDrefExplicitLod %u32 %simg %f32vec2_00 %s32_1 Lod %f32_1
2755 )";
2756 
2757   CompileSuccessfully(GenerateShaderCode(body).c_str());
2758   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2759   EXPECT_THAT(
2760       getDiagnosticString(),
2761       HasSubstr("Expected Image 'Sampled Type' to be the same as Result Type"));
2762 }
2763 
TEST_F(ValidateImage,SampleDrefExplicitLodWrongCoordinateType)2764 TEST_F(ValidateImage, SampleDrefExplicitLodWrongCoordinateType) {
2765   const std::string body = R"(
2766 %img = OpLoad %type_image_s32_3d_0001 %uniform_image_s32_3d_0001
2767 %sampler = OpLoad %type_sampler %uniform_sampler
2768 %simg = OpSampledImage %type_sampled_image_s32_3d_0001 %img %sampler
2769 %res1 = OpImageSampleDrefExplicitLod %s32 %simg %img %s32_1 Lod %f32_1
2770 )";
2771 
2772   CompileSuccessfully(GenerateShaderCode(body).c_str());
2773   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2774   EXPECT_THAT(getDiagnosticString(),
2775               HasSubstr("Expected Coordinate to be float scalar or vector"));
2776 }
2777 
TEST_F(ValidateImage,SampleDrefExplicitLodCoordinateSizeTooSmall)2778 TEST_F(ValidateImage, SampleDrefExplicitLodCoordinateSizeTooSmall) {
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 %f32vec2_hh %s32_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 Coordinate to have at least 3 components, "
2790                         "but given only 2"));
2791 }
2792 
TEST_F(ValidateImage,SampleDrefExplicitLodWrongDrefType)2793 TEST_F(ValidateImage, SampleDrefExplicitLodWrongDrefType) {
2794   const std::string body = R"(
2795 %img = OpLoad %type_image_s32_3d_0001 %uniform_image_s32_3d_0001
2796 %sampler = OpLoad %type_sampler %uniform_sampler
2797 %simg = OpSampledImage %type_sampled_image_s32_3d_0001 %img %sampler
2798 %res1 = OpImageSampleDrefExplicitLod %s32 %simg %f32vec3_hhh %u32_1 Lod %f32_1
2799 )";
2800 
2801   CompileSuccessfully(GenerateShaderCode(body).c_str());
2802   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2803   EXPECT_THAT(getDiagnosticString(),
2804               HasSubstr("Expected Dref to be of 32-bit float type"));
2805 }
2806 
TEST_F(ValidateImage,SampleProjDrefImplicitLodSuccess)2807 TEST_F(ValidateImage, SampleProjDrefImplicitLodSuccess) {
2808   const std::string body = R"(
2809 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2810 %sampler = OpLoad %type_sampler %uniform_sampler
2811 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2812 %res1 = OpImageSampleProjDrefImplicitLod %f32 %simg %f32vec3_hhh %f32_0_5
2813 %res2 = OpImageSampleProjDrefImplicitLod %f32 %simg %f32vec3_hhh %f32_0_5 Bias %f32_0_25
2814 %res4 = OpImageSampleProjDrefImplicitLod %f32 %simg %f32vec3_hhh %f32_0_5 ConstOffset %s32vec2_01
2815 %res5 = OpImageSampleProjDrefImplicitLod %f32 %simg %f32vec3_hhh %f32_0_5 Offset %s32vec2_01
2816 %res6 = OpImageSampleProjDrefImplicitLod %f32 %simg %f32vec3_hhh %f32_0_5 MinLod %f32_0_5
2817 %res7 = OpImageSampleProjDrefImplicitLod %f32 %simg %f32vec3_hhh %f32_0_5 Bias|Offset|MinLod %f32_0_25 %s32vec2_01 %f32_0_5
2818 %res8 = OpImageSampleProjDrefImplicitLod %f32 %simg %f32vec3_hhh %f32_0_5 NonPrivateTexelKHR
2819 )";
2820 
2821   const std::string extra = R"(
2822 OpCapability VulkanMemoryModelKHR
2823 OpExtension "SPV_KHR_vulkan_memory_model"
2824 )";
2825   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
2826                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
2827                           .c_str());
2828   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2829 }
2830 
TEST_F(ValidateImage,SampleProjDrefImplicitLodWrongResultType)2831 TEST_F(ValidateImage, SampleProjDrefImplicitLodWrongResultType) {
2832   const std::string body = R"(
2833 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2834 %sampler = OpLoad %type_sampler %uniform_sampler
2835 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2836 %res1 = OpImageSampleProjDrefImplicitLod %void %simg %f32vec3_hhh %f32_0_5
2837 )";
2838 
2839   CompileSuccessfully(GenerateShaderCode(body).c_str());
2840   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2841   EXPECT_THAT(getDiagnosticString(),
2842               HasSubstr("Expected Result Type to be int or float scalar type"));
2843 }
2844 
TEST_F(ValidateImage,SampleProjDrefImplicitLodNotSampledImage)2845 TEST_F(ValidateImage, SampleProjDrefImplicitLodNotSampledImage) {
2846   const std::string body = R"(
2847 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2848 %res1 = OpImageSampleProjDrefImplicitLod %f32 %img %f32vec3_hhh %f32_0_5
2849 )";
2850 
2851   CompileSuccessfully(GenerateShaderCode(body).c_str());
2852   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2853   EXPECT_THAT(
2854       getDiagnosticString(),
2855       HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage"));
2856 }
2857 
TEST_F(ValidateImage,SampleProjDrefImplicitLodMultisampleError)2858 TEST_F(ValidateImage, SampleProjDrefImplicitLodMultisampleError) {
2859   const std::string body = R"(
2860 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
2861 %sampler = OpLoad %type_sampler %uniform_sampler
2862 %simg = OpSampledImage %type_sampled_image_f32_2d_0011 %img %sampler
2863 %res1 = OpImageSampleDrefExplicitLod %f32 %simg %f32vec2_hh %f32_1 Sample %u32_1
2864 )";
2865 
2866   CompileSuccessfully(GenerateShaderCode(body).c_str());
2867   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2868   EXPECT_THAT(
2869       getDiagnosticString(),
2870       HasSubstr("Dref sampling operation is invalid for multisample image"));
2871 }
2872 
TEST_F(ValidateImage,SampleProjDrefImplicitLodWrongSampledType)2873 TEST_F(ValidateImage, SampleProjDrefImplicitLodWrongSampledType) {
2874   const std::string body = R"(
2875 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2876 %sampler = OpLoad %type_sampler %uniform_sampler
2877 %simg = OpSampledImage %type_sampled_image_f32_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,SampleProjDrefImplicitLodVoidSampledType)2888 TEST_F(ValidateImage, SampleProjDrefImplicitLodVoidSampledType) {
2889   const std::string body = R"(
2890 %img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001
2891 %sampler = OpLoad %type_sampler %uniform_sampler
2892 %simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler
2893 %res1 = OpImageSampleProjDrefImplicitLod %u32 %simg %f32vec3_hhh %f32_0_5
2894 )";
2895 
2896   CompileSuccessfully(GenerateShaderCode(body).c_str());
2897   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2898   EXPECT_THAT(
2899       getDiagnosticString(),
2900       HasSubstr("Expected Image 'Sampled Type' to be the same as Result Type"));
2901 }
2902 
TEST_F(ValidateImage,SampleProjDrefImplicitLodWrongCoordinateType)2903 TEST_F(ValidateImage, SampleProjDrefImplicitLodWrongCoordinateType) {
2904   const std::string body = R"(
2905 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2906 %sampler = OpLoad %type_sampler %uniform_sampler
2907 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2908 %res1 = OpImageSampleProjDrefImplicitLod %f32 %simg %img %f32_0_5
2909 )";
2910 
2911   CompileSuccessfully(GenerateShaderCode(body).c_str());
2912   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2913   EXPECT_THAT(getDiagnosticString(),
2914               HasSubstr("Expected Coordinate to be float scalar or vector"));
2915 }
2916 
TEST_F(ValidateImage,SampleProjDrefImplicitLodCoordinateSizeTooSmall)2917 TEST_F(ValidateImage, SampleProjDrefImplicitLodCoordinateSizeTooSmall) {
2918   const std::string body = R"(
2919 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
2920 %sampler = OpLoad %type_sampler %uniform_sampler
2921 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
2922 %res1 = OpImageSampleProjDrefImplicitLod %f32 %simg %f32vec2_hh %f32_0_5
2923 )";
2924 
2925   CompileSuccessfully(GenerateShaderCode(body).c_str());
2926   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2927   EXPECT_THAT(getDiagnosticString(),
2928               HasSubstr("Expected Coordinate to have at least 3 components, "
2929                         "but given only 2"));
2930 }
2931 
TEST_F(ValidateImage,SampleProjDrefImplicitLodWrongDrefType)2932 TEST_F(ValidateImage, SampleProjDrefImplicitLodWrongDrefType) {
2933   const std::string body = R"(
2934 %img = OpLoad %type_image_u32_2d_0001 %uniform_image_u32_2d_0001
2935 %sampler = OpLoad %type_sampler %uniform_sampler
2936 %simg = OpSampledImage %type_sampled_image_u32_2d_0001 %img %sampler
2937 %res1 = OpImageSampleProjDrefImplicitLod %u32 %simg %f32vec3_hhh %f32vec4_0000
2938 )";
2939 
2940   CompileSuccessfully(GenerateShaderCode(body).c_str());
2941   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2942   EXPECT_THAT(getDiagnosticString(),
2943               HasSubstr("Expected Dref to be of 32-bit float type"));
2944 }
2945 
TEST_F(ValidateImage,SampleProjDrefExplicitLodSuccess)2946 TEST_F(ValidateImage, SampleProjDrefExplicitLodSuccess) {
2947   const std::string body = R"(
2948 %img = OpLoad %type_image_f32_1d_0001 %uniform_image_f32_1d_0001
2949 %sampler = OpLoad %type_sampler %uniform_sampler
2950 %simg = OpSampledImage %type_sampled_image_f32_1d_0001 %img %sampler
2951 %res1 = OpImageSampleProjDrefExplicitLod %f32 %simg %f32vec2_hh %f32_0_5 Lod %f32_1
2952 %res2 = OpImageSampleProjDrefExplicitLod %f32 %simg %f32vec3_hhh %f32_0_5 Grad %f32_0_5 %f32_0_5
2953 %res3 = OpImageSampleProjDrefExplicitLod %f32 %simg %f32vec2_hh %f32_0_5 ConstOffset %s32_1
2954 %res4 = OpImageSampleProjDrefExplicitLod %f32 %simg %f32vec2_hh %f32_0_5 Offset %s32_1
2955 %res5 = OpImageSampleProjDrefExplicitLod %f32 %simg %f32vec2_hh %f32_0_5 Grad|Offset %f32_0_5 %f32_0_5 %s32_1
2956 %res6 = OpImageSampleProjDrefExplicitLod %f32 %simg %f32vec2_hh %f32_0_5 Lod|NonPrivateTexelKHR %f32_1
2957 )";
2958 
2959   const std::string extra = R"(
2960 OpCapability VulkanMemoryModelKHR
2961 OpExtension "SPV_KHR_vulkan_memory_model"
2962 )";
2963   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
2964                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
2965                           .c_str());
2966   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2967 }
2968 
TEST_F(ValidateImage,SampleProjDrefExplicitLodWrongResultType)2969 TEST_F(ValidateImage, SampleProjDrefExplicitLodWrongResultType) {
2970   const std::string body = R"(
2971 %img = OpLoad %type_image_f32_1d_0001 %uniform_image_f32_1d_0001
2972 %sampler = OpLoad %type_sampler %uniform_sampler
2973 %simg = OpSampledImage %type_sampled_image_f32_1d_0001 %img %sampler
2974 %res1 = OpImageSampleProjDrefExplicitLod %bool %simg %f32vec2_hh %f32_0_5 Lod %f32_1
2975 )";
2976 
2977   CompileSuccessfully(GenerateShaderCode(body).c_str());
2978   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2979   EXPECT_THAT(getDiagnosticString(),
2980               HasSubstr("Expected Result Type to be int or float scalar type"));
2981 }
2982 
TEST_F(ValidateImage,SampleProjDrefExplicitLodNotSampledImage)2983 TEST_F(ValidateImage, SampleProjDrefExplicitLodNotSampledImage) {
2984   const std::string body = R"(
2985 %img = OpLoad %type_image_f32_1d_0001 %uniform_image_f32_1d_0001
2986 %res1 = OpImageSampleProjDrefExplicitLod %f32 %img %f32vec2_hh %f32_0_5 Lod %f32_1
2987 )";
2988 
2989   CompileSuccessfully(GenerateShaderCode(body).c_str());
2990   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2991   EXPECT_THAT(
2992       getDiagnosticString(),
2993       HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage"));
2994 }
2995 
TEST_F(ValidateImage,SampleProjDrefExplicitLodMultisampleError)2996 TEST_F(ValidateImage, SampleProjDrefExplicitLodMultisampleError) {
2997   const std::string body = R"(
2998 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
2999 %sampler = OpLoad %type_sampler %uniform_sampler
3000 %simg = OpSampledImage %type_sampled_image_f32_2d_0011 %img %sampler
3001 %res1 = OpImageSampleDrefExplicitLod %f32 %simg %f32vec2_hh %f32_1 Lod|Sample %f32_1 %u32_1
3002 )";
3003 
3004   CompileSuccessfully(GenerateShaderCode(body).c_str());
3005   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3006   EXPECT_THAT(
3007       getDiagnosticString(),
3008       HasSubstr("Dref sampling operation is invalid for multisample image"));
3009 }
3010 
TEST_F(ValidateImage,SampleProjDrefExplicitLodWrongSampledType)3011 TEST_F(ValidateImage, SampleProjDrefExplicitLodWrongSampledType) {
3012   const std::string body = R"(
3013 %img = OpLoad %type_image_f32_1d_0001 %uniform_image_f32_1d_0001
3014 %sampler = OpLoad %type_sampler %uniform_sampler
3015 %simg = OpSampledImage %type_sampled_image_f32_1d_0001 %img %sampler
3016 %res1 = OpImageSampleProjDrefExplicitLod %u32 %simg %f32vec2_hh %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,SampleProjDrefExplicitLodVoidSampledType)3026 TEST_F(ValidateImage, SampleProjDrefExplicitLodVoidSampledType) {
3027   const std::string body = R"(
3028 %img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001
3029 %sampler = OpLoad %type_sampler %uniform_sampler
3030 %simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler
3031 %res1 = OpImageSampleProjDrefExplicitLod %u32 %simg %f32vec3_hhh %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(
3037       getDiagnosticString(),
3038       HasSubstr("Expected Image 'Sampled Type' to be the same as Result Type"));
3039 }
3040 
TEST_F(ValidateImage,SampleProjDrefExplicitLodWrongCoordinateType)3041 TEST_F(ValidateImage, SampleProjDrefExplicitLodWrongCoordinateType) {
3042   const std::string body = R"(
3043 %img = OpLoad %type_image_f32_1d_0001 %uniform_image_f32_1d_0001
3044 %sampler = OpLoad %type_sampler %uniform_sampler
3045 %simg = OpSampledImage %type_sampled_image_f32_1d_0001 %img %sampler
3046 %res1 = OpImageSampleProjDrefExplicitLod %f32 %simg %img %f32_0_5 Lod %f32_1
3047 )";
3048 
3049   CompileSuccessfully(GenerateShaderCode(body).c_str());
3050   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3051   EXPECT_THAT(getDiagnosticString(),
3052               HasSubstr("Expected Coordinate to be float scalar or vector"));
3053 }
3054 
TEST_F(ValidateImage,SampleProjDrefExplicitLodCoordinateSizeTooSmall)3055 TEST_F(ValidateImage, SampleProjDrefExplicitLodCoordinateSizeTooSmall) {
3056   const std::string body = R"(
3057 %img = OpLoad %type_image_f32_1d_0001 %uniform_image_f32_1d_0001
3058 %sampler = OpLoad %type_sampler %uniform_sampler
3059 %simg = OpSampledImage %type_sampled_image_f32_1d_0001 %img %sampler
3060 %res1 = OpImageSampleProjDrefExplicitLod %f32 %simg %f32_0_5 %f32_0_5 Lod %f32_1
3061 )";
3062 
3063   CompileSuccessfully(GenerateShaderCode(body).c_str());
3064   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3065   EXPECT_THAT(getDiagnosticString(),
3066               HasSubstr("Expected Coordinate to have at least 2 components, "
3067                         "but given only 1"));
3068 }
3069 
TEST_F(ValidateImage,FetchSuccess)3070 TEST_F(ValidateImage, FetchSuccess) {
3071   const std::string body = R"(
3072 %img = OpLoad %type_image_f32_1d_0001 %uniform_image_f32_1d_0001
3073 %res1 = OpImageFetch %f32vec4 %img %u32vec2_01
3074 %res2 = OpImageFetch %f32vec4 %img %u32vec2_01 NonPrivateTexelKHR
3075 )";
3076 
3077   const std::string extra = R"(
3078 OpCapability VulkanMemoryModelKHR
3079 OpExtension "SPV_KHR_vulkan_memory_model"
3080 )";
3081   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
3082                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
3083                           .c_str());
3084   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
3085 }
3086 
TEST_F(ValidateImage,FetchMultisampledSuccess)3087 TEST_F(ValidateImage, FetchMultisampledSuccess) {
3088   const std::string body = R"(
3089 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
3090 %res1 = OpImageFetch %f32vec4 %img %u32vec2_01 Sample %u32_1
3091 %res2 = OpImageFetch %f32vec4 %img %u32vec2_01 Sample|NonPrivateTexelKHR %u32_1
3092 )";
3093 
3094   const std::string extra = R"(
3095 OpCapability VulkanMemoryModelKHR
3096 OpExtension "SPV_KHR_vulkan_memory_model"
3097 )";
3098   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
3099                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
3100                           .c_str());
3101   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
3102 }
3103 
TEST_F(ValidateImage,FetchWrongResultType)3104 TEST_F(ValidateImage, FetchWrongResultType) {
3105   const std::string body = R"(
3106 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
3107 %res1 = OpImageFetch %f32 %img %u32vec2_01
3108 )";
3109 
3110   CompileSuccessfully(GenerateShaderCode(body).c_str());
3111   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3112   EXPECT_THAT(getDiagnosticString(),
3113               HasSubstr("Expected Result Type to be int or float vector type"));
3114 }
3115 
TEST_F(ValidateImage,FetchWrongNumComponentsResultType)3116 TEST_F(ValidateImage, FetchWrongNumComponentsResultType) {
3117   const std::string body = R"(
3118 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
3119 %res1 = OpImageFetch %f32vec3 %img %u32vec2_01
3120 )";
3121 
3122   CompileSuccessfully(GenerateShaderCode(body).c_str());
3123   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3124   EXPECT_THAT(getDiagnosticString(),
3125               HasSubstr("Expected Result Type to have 4 components"));
3126 }
3127 
TEST_F(ValidateImage,FetchNotImage)3128 TEST_F(ValidateImage, FetchNotImage) {
3129   const std::string body = R"(
3130 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3131 %sampler = OpLoad %type_sampler %uniform_sampler
3132 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3133 %res1 = OpImageFetch %f32vec4 %sampler %u32vec2_01
3134 )";
3135 
3136   CompileSuccessfully(GenerateShaderCode(body).c_str());
3137   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3138   EXPECT_THAT(getDiagnosticString(),
3139               HasSubstr("Expected Image to be of type OpTypeImage"));
3140 }
3141 
TEST_F(ValidateImage,FetchSampledImageDirectly)3142 TEST_F(ValidateImage, FetchSampledImageDirectly) {
3143   const std::string body = R"(
3144 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3145 %sampler = OpLoad %type_sampler %uniform_sampler
3146 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3147 %res1 = OpImageFetch %f32vec4 %simg %u32vec2_01
3148 )";
3149 
3150   CompileSuccessfully(GenerateShaderCode(body).c_str());
3151   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3152   EXPECT_THAT(getDiagnosticString(),
3153               HasSubstr("OpSampledImage instruction must not appear as operand "
3154                         "for OpImageFetch"));
3155 }
3156 
TEST_F(ValidateImage,FetchNotSampled)3157 TEST_F(ValidateImage, FetchNotSampled) {
3158   const std::string body = R"(
3159 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
3160 %res1 = OpImageFetch %u32vec4 %img %u32vec2_01
3161 )";
3162 
3163   CompileSuccessfully(GenerateShaderCode(body).c_str());
3164   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3165   EXPECT_THAT(getDiagnosticString(),
3166               HasSubstr("Expected Image 'Sampled' parameter to be 1"));
3167 }
3168 
TEST_F(ValidateImage,FetchCube)3169 TEST_F(ValidateImage, FetchCube) {
3170   const std::string body = R"(
3171 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
3172 %res1 = OpImageFetch %f32vec4 %img %u32vec3_012
3173 )";
3174 
3175   CompileSuccessfully(GenerateShaderCode(body).c_str());
3176   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3177   EXPECT_THAT(getDiagnosticString(), HasSubstr("Image 'Dim' cannot be Cube"));
3178 }
3179 
TEST_F(ValidateImage,FetchWrongSampledType)3180 TEST_F(ValidateImage, FetchWrongSampledType) {
3181   const std::string body = R"(
3182 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
3183 %res1 = OpImageFetch %u32vec4 %img %u32vec2_01
3184 )";
3185 
3186   CompileSuccessfully(GenerateShaderCode(body).c_str());
3187   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3188   EXPECT_THAT(getDiagnosticString(),
3189               HasSubstr("Expected Image 'Sampled Type' to be the same as "
3190                         "Result Type components"));
3191 }
3192 
TEST_F(ValidateImage,FetchVoidSampledType)3193 TEST_F(ValidateImage, FetchVoidSampledType) {
3194   const std::string body = R"(
3195 %img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001
3196 %res1 = OpImageFetch %f32vec4 %img %u32vec2_01
3197 %res2 = OpImageFetch %u32vec4 %img %u32vec2_01
3198 %res3 = OpImageFetch %s32vec4 %img %u32vec2_01
3199 )";
3200 
3201   CompileSuccessfully(GenerateShaderCode(body).c_str());
3202   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3203 }
3204 
TEST_F(ValidateImage,FetchWrongCoordinateType)3205 TEST_F(ValidateImage, FetchWrongCoordinateType) {
3206   const std::string body = R"(
3207 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
3208 %res1 = OpImageFetch %f32vec4 %img %f32vec2_00
3209 )";
3210 
3211   CompileSuccessfully(GenerateShaderCode(body).c_str());
3212   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3213   EXPECT_THAT(getDiagnosticString(),
3214               HasSubstr("Expected Coordinate to be int scalar or vector"));
3215 }
3216 
TEST_F(ValidateImage,FetchCoordinateSizeTooSmall)3217 TEST_F(ValidateImage, FetchCoordinateSizeTooSmall) {
3218   const std::string body = R"(
3219 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
3220 %res1 = OpImageFetch %f32vec4 %img %u32_1
3221 )";
3222 
3223   CompileSuccessfully(GenerateShaderCode(body).c_str());
3224   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3225   EXPECT_THAT(getDiagnosticString(),
3226               HasSubstr("Expected Coordinate to have at least 2 components, "
3227                         "but given only 1"));
3228 }
3229 
TEST_F(ValidateImage,FetchLodNotInt)3230 TEST_F(ValidateImage, FetchLodNotInt) {
3231   const std::string body = R"(
3232 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3233 %res1 = OpImageFetch %f32vec4 %img %u32vec2_01 Lod %f32_1
3234 )";
3235 
3236   CompileSuccessfully(GenerateShaderCode(body).c_str());
3237   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3238   EXPECT_THAT(getDiagnosticString(),
3239               HasSubstr("Expected Image Operand Lod to be int scalar when used "
3240                         "with OpImageFetch"));
3241 }
3242 
TEST_F(ValidateImage,FetchMultisampledMissingSample)3243 TEST_F(ValidateImage, FetchMultisampledMissingSample) {
3244   const std::string body = R"(
3245 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
3246 %res1 = OpImageFetch %f32vec4 %img %u32vec2_01
3247 )";
3248 
3249   CompileSuccessfully(GenerateShaderCode(body).c_str());
3250   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions())
3251       << GenerateShaderCode(body);
3252   EXPECT_THAT(getDiagnosticString(),
3253               HasSubstr("Image Operand Sample is required for operation on "
3254                         "multi-sampled image"))
3255       << getDiagnosticString();
3256 }
3257 
TEST_F(ValidateImage,GatherSuccess)3258 TEST_F(ValidateImage, GatherSuccess) {
3259   const std::string body = R"(
3260 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3261 %sampler = OpLoad %type_sampler %uniform_sampler
3262 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3263 %res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1
3264 %res2 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 ConstOffsets %const_offsets
3265 %res3 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 NonPrivateTexelKHR
3266 )";
3267 
3268   const std::string extra = R"(
3269 OpCapability VulkanMemoryModelKHR
3270 OpExtension "SPV_KHR_vulkan_memory_model"
3271 )";
3272   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
3273                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
3274                           .c_str());
3275   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
3276 }
3277 
TEST_F(ValidateImage,GatherWrongResultType)3278 TEST_F(ValidateImage, GatherWrongResultType) {
3279   const std::string body = R"(
3280 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
3281 %sampler = OpLoad %type_sampler %uniform_sampler
3282 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
3283 %res1 = OpImageGather %f32 %simg %f32vec4_0000 %u32_1
3284 )";
3285 
3286   CompileSuccessfully(GenerateShaderCode(body).c_str());
3287   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3288   EXPECT_THAT(getDiagnosticString(),
3289               HasSubstr("Expected Result Type to be int or float vector type"));
3290 }
3291 
TEST_F(ValidateImage,GatherWrongNumComponentsResultType)3292 TEST_F(ValidateImage, GatherWrongNumComponentsResultType) {
3293   const std::string body = R"(
3294 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
3295 %sampler = OpLoad %type_sampler %uniform_sampler
3296 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
3297 %res1 = OpImageGather %f32vec3 %simg %f32vec4_0000 %u32_1
3298 )";
3299 
3300   CompileSuccessfully(GenerateShaderCode(body).c_str());
3301   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3302   EXPECT_THAT(getDiagnosticString(),
3303               HasSubstr("Expected Result Type to have 4 components"));
3304 }
3305 
TEST_F(ValidateImage,GatherNotSampledImage)3306 TEST_F(ValidateImage, GatherNotSampledImage) {
3307   const std::string body = R"(
3308 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
3309 %res1 = OpImageGather %f32vec4 %img %f32vec4_0000 %u32_1
3310 )";
3311 
3312   CompileSuccessfully(GenerateShaderCode(body).c_str());
3313   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3314   EXPECT_THAT(
3315       getDiagnosticString(),
3316       HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage"));
3317 }
3318 
TEST_F(ValidateImage,GatherMultisampleError)3319 TEST_F(ValidateImage, GatherMultisampleError) {
3320   const std::string body = R"(
3321 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
3322 %sampler = OpLoad %type_sampler %uniform_sampler
3323 %simg = OpSampledImage %type_sampled_image_f32_2d_0011 %img %sampler
3324 %res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 Sample %u32_1
3325 )";
3326 
3327   CompileSuccessfully(GenerateShaderCode(body).c_str());
3328   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3329   EXPECT_THAT(getDiagnosticString(),
3330               HasSubstr("Gather operation is invalid for multisample image"));
3331 }
3332 
TEST_F(ValidateImage,GatherWrongSampledType)3333 TEST_F(ValidateImage, GatherWrongSampledType) {
3334   const std::string body = R"(
3335 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
3336 %sampler = OpLoad %type_sampler %uniform_sampler
3337 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
3338 %res1 = OpImageGather %u32vec4 %simg %f32vec4_0000 %u32_1
3339 )";
3340 
3341   CompileSuccessfully(GenerateShaderCode(body).c_str());
3342   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3343   EXPECT_THAT(getDiagnosticString(),
3344               HasSubstr("Expected Image 'Sampled Type' to be the same as "
3345                         "Result Type components"));
3346 }
3347 
TEST_F(ValidateImage,GatherVoidSampledType)3348 TEST_F(ValidateImage, GatherVoidSampledType) {
3349   const std::string body = R"(
3350 %img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001
3351 %sampler = OpLoad %type_sampler %uniform_sampler
3352 %simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler
3353 %res1 = OpImageGather %u32vec4 %simg %f32vec2_00 %u32_1
3354 )";
3355 
3356   CompileSuccessfully(GenerateShaderCode(body).c_str());
3357   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3358 }
3359 
TEST_F(ValidateImage,GatherWrongCoordinateType)3360 TEST_F(ValidateImage, GatherWrongCoordinateType) {
3361   const std::string body = R"(
3362 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
3363 %sampler = OpLoad %type_sampler %uniform_sampler
3364 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
3365 %res1 = OpImageGather %f32vec4 %simg %u32vec4_0123 %u32_1
3366 )";
3367 
3368   CompileSuccessfully(GenerateShaderCode(body).c_str());
3369   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3370   EXPECT_THAT(getDiagnosticString(),
3371               HasSubstr("Expected Coordinate to be float scalar or vector"));
3372 }
3373 
TEST_F(ValidateImage,GatherCoordinateSizeTooSmall)3374 TEST_F(ValidateImage, GatherCoordinateSizeTooSmall) {
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 %f32_0_5 %u32_1
3380 )";
3381 
3382   CompileSuccessfully(GenerateShaderCode(body).c_str());
3383   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3384   EXPECT_THAT(getDiagnosticString(),
3385               HasSubstr("Expected Coordinate to have at least 4 components, "
3386                         "but given only 1"));
3387 }
3388 
TEST_F(ValidateImage,GatherWrongComponentType)3389 TEST_F(ValidateImage, GatherWrongComponentType) {
3390   const std::string body = R"(
3391 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
3392 %sampler = OpLoad %type_sampler %uniform_sampler
3393 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
3394 %res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %f32_1
3395 )";
3396 
3397   CompileSuccessfully(GenerateShaderCode(body).c_str());
3398   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3399   EXPECT_THAT(getDiagnosticString(),
3400               HasSubstr("Expected Component to be 32-bit int scalar"));
3401 }
3402 
TEST_F(ValidateImage,GatherComponentNot32Bit)3403 TEST_F(ValidateImage, GatherComponentNot32Bit) {
3404   const std::string body = R"(
3405 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
3406 %sampler = OpLoad %type_sampler %uniform_sampler
3407 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
3408 %res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u64_0
3409 )";
3410 
3411   CompileSuccessfully(GenerateShaderCode(body).c_str());
3412   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3413   EXPECT_THAT(getDiagnosticString(),
3414               HasSubstr("Expected Component to be 32-bit int scalar"));
3415 }
3416 
TEST_F(ValidateImage,GatherComponentSuccessVulkan)3417 TEST_F(ValidateImage, GatherComponentSuccessVulkan) {
3418   const std::string body = R"(
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 %u32_0
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_SUCCESS, ValidateInstructions(env));
3429 }
3430 
TEST_F(ValidateImage,GatherComponentNotConstantVulkan)3431 TEST_F(ValidateImage, GatherComponentNotConstantVulkan) {
3432   const std::string body = R"(
3433 %input_u32 = OpLoad %u32 %input_flat_u32
3434 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
3435 %sampler = OpLoad %type_sampler %uniform_sampler
3436 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
3437 %res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %input_u32
3438 )";
3439 
3440   spv_target_env env = SPV_ENV_VULKAN_1_0;
3441   CompileSuccessfully(GenerateShaderCode(body, "", "Fragment", "", env).c_str(),
3442                       env);
3443   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
3444   EXPECT_THAT(getDiagnosticString(),
3445               AnyVUID("VUID-StandaloneSpirv-OpImageGather-04664"));
3446   EXPECT_THAT(getDiagnosticString(),
3447               HasSubstr("Expected Component Operand to be a const object for "
3448                         "Vulkan environment"));
3449 }
3450 
TEST_F(ValidateImage,GatherDimCube)3451 TEST_F(ValidateImage, GatherDimCube) {
3452   const std::string body = R"(
3453 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
3454 %sampler = OpLoad %type_sampler %uniform_sampler
3455 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
3456 %res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 ConstOffsets %const_offsets
3457 )";
3458 
3459   CompileSuccessfully(GenerateShaderCode(body).c_str());
3460   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3461   EXPECT_THAT(
3462       getDiagnosticString(),
3463       HasSubstr(
3464           "Image Operand ConstOffsets cannot be used with Cube Image 'Dim'"));
3465 }
3466 
TEST_F(ValidateImage,GatherConstOffsetsNotArray)3467 TEST_F(ValidateImage, GatherConstOffsetsNotArray) {
3468   const std::string body = R"(
3469 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3470 %sampler = OpLoad %type_sampler %uniform_sampler
3471 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3472 %res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 ConstOffsets %u32vec4_0123
3473 )";
3474 
3475   CompileSuccessfully(GenerateShaderCode(body).c_str());
3476   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3477   EXPECT_THAT(
3478       getDiagnosticString(),
3479       HasSubstr(
3480           "Expected Image Operand ConstOffsets to be an array of size 4"));
3481 }
3482 
TEST_F(ValidateImage,GatherConstOffsetsArrayWrongSize)3483 TEST_F(ValidateImage, GatherConstOffsetsArrayWrongSize) {
3484   const std::string body = R"(
3485 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3486 %sampler = OpLoad %type_sampler %uniform_sampler
3487 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3488 %res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 ConstOffsets %const_offsets3x2
3489 )";
3490 
3491   CompileSuccessfully(GenerateShaderCode(body).c_str());
3492   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3493   EXPECT_THAT(
3494       getDiagnosticString(),
3495       HasSubstr(
3496           "Expected Image Operand ConstOffsets to be an array of size 4"));
3497 }
3498 
TEST_F(ValidateImage,GatherConstOffsetsArrayNotVector)3499 TEST_F(ValidateImage, GatherConstOffsetsArrayNotVector) {
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_offsets4xu
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,GatherConstOffsetsArrayVectorWrongSize)3514 TEST_F(ValidateImage, GatherConstOffsetsArrayVectorWrongSize) {
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 %res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 ConstOffsets %const_offsets4x3
3520 )";
3521 
3522   CompileSuccessfully(GenerateShaderCode(body).c_str());
3523   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3524   EXPECT_THAT(getDiagnosticString(),
3525               HasSubstr("Expected Image Operand ConstOffsets array components "
3526                         "to be int vectors of size 2"));
3527 }
3528 
TEST_F(ValidateImage,GatherConstOffsetsArrayNotConst)3529 TEST_F(ValidateImage, GatherConstOffsetsArrayNotConst) {
3530   const std::string body = R"(
3531 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3532 %sampler = OpLoad %type_sampler %uniform_sampler
3533 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3534 %offsets = OpUndef %u32vec2arr4
3535 %res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 ConstOffsets %offsets
3536 )";
3537 
3538   CompileSuccessfully(GenerateShaderCode(body).c_str());
3539   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3540   EXPECT_THAT(
3541       getDiagnosticString(),
3542       HasSubstr("Expected Image Operand ConstOffsets to be a const object"));
3543 }
3544 
TEST_F(ValidateImage,NotGatherWithConstOffsets)3545 TEST_F(ValidateImage, NotGatherWithConstOffsets) {
3546   const std::string body = R"(
3547 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3548 %sampler = OpLoad %type_sampler %uniform_sampler
3549 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3550 %res2 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh ConstOffsets %const_offsets
3551 )";
3552 
3553   CompileSuccessfully(GenerateShaderCode(body).c_str());
3554   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3555   EXPECT_THAT(
3556       getDiagnosticString(),
3557       HasSubstr(
3558           "Image Operand ConstOffsets can only be used with OpImageGather "
3559           "and OpImageDrefGather"));
3560 }
3561 
TEST_F(ValidateImage,DrefGatherSuccess)3562 TEST_F(ValidateImage, DrefGatherSuccess) {
3563   const std::string body = R"(
3564 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3565 %sampler = OpLoad %type_sampler %uniform_sampler
3566 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
3567 %res1 = OpImageDrefGather %f32vec4 %simg %f32vec4_0000 %f32_0_5
3568 %res2 = OpImageDrefGather %f32vec4 %simg %f32vec4_0000 %f32_0_5 ConstOffsets %const_offsets
3569 %res3 = OpImageDrefGather %f32vec4 %simg %f32vec4_0000 %f32_0_5 NonPrivateTexelKHR
3570 )";
3571 
3572   const std::string extra = R"(
3573 OpCapability VulkanMemoryModelKHR
3574 OpExtension "SPV_KHR_vulkan_memory_model"
3575 )";
3576   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
3577                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
3578                           .c_str());
3579   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
3580 }
3581 
TEST_F(ValidateImage,DrefGatherMultisampleError)3582 TEST_F(ValidateImage, DrefGatherMultisampleError) {
3583   const std::string body = R"(
3584 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
3585 %sampler = OpLoad %type_sampler %uniform_sampler
3586 %simg = OpSampledImage %type_sampled_image_f32_2d_0011 %img %sampler
3587 %res1 = OpImageDrefGather %f32vec4 %simg %f32vec4_0000 %f32_1 Sample %u32_1
3588 )";
3589 
3590   CompileSuccessfully(GenerateShaderCode(body).c_str());
3591   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3592   EXPECT_THAT(getDiagnosticString(),
3593               HasSubstr("Gather operation is invalid for multisample image"));
3594 }
3595 
TEST_F(ValidateImage,DrefGatherVoidSampledType)3596 TEST_F(ValidateImage, DrefGatherVoidSampledType) {
3597   const std::string body = R"(
3598 %img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001
3599 %sampler = OpLoad %type_sampler %uniform_sampler
3600 %simg = OpSampledImage %type_sampled_image_void_2d_0001 %img %sampler
3601 %res1 = OpImageDrefGather %u32vec4 %simg %f32vec2_00 %f32_0_5
3602 )";
3603 
3604   CompileSuccessfully(GenerateShaderCode(body).c_str());
3605   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3606   EXPECT_THAT(getDiagnosticString(),
3607               HasSubstr("Expected Image 'Sampled Type' to be the same as "
3608                         "Result Type components"));
3609 }
3610 
TEST_F(ValidateImage,DrefGatherWrongDrefType)3611 TEST_F(ValidateImage, DrefGatherWrongDrefType) {
3612   const std::string body = R"(
3613 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
3614 %sampler = OpLoad %type_sampler %uniform_sampler
3615 %simg = OpSampledImage %type_sampled_image_f32_cube_0101 %img %sampler
3616 %res1 = OpImageDrefGather %f32vec4 %simg %f32vec4_0000 %u32_1
3617 )";
3618 
3619   CompileSuccessfully(GenerateShaderCode(body).c_str());
3620   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3621   EXPECT_THAT(getDiagnosticString(),
3622               HasSubstr("Expected Dref to be of 32-bit float type"));
3623 }
3624 
TEST_F(ValidateImage,DrefGatherWrongDimVulkan)3625 TEST_F(ValidateImage, DrefGatherWrongDimVulkan) {
3626   const std::string body = R"(
3627 %img = OpLoad %type_image_f32_3d_0001 %uniform_image_f32_3d_0001
3628 %sampler = OpLoad %type_sampler %uniform_sampler
3629 %simg = OpSampledImage %type_sampled_image_f32_3d_0001 %img %sampler
3630 %res1 = OpImageDrefGather %f32vec4 %simg %f32vec4_0000 %f32_0_5
3631 )";
3632 
3633   CompileSuccessfully(
3634       GenerateShaderCode(body, "", "Fragment", "", SPV_ENV_VULKAN_1_0).c_str());
3635   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
3636   EXPECT_THAT(getDiagnosticString(),
3637               AnyVUID("VUID-StandaloneSpirv-OpImage-04777"));
3638   EXPECT_THAT(getDiagnosticString(),
3639               HasSubstr("Expected Image 'Dim' to be 2D, Cube, or Rect"));
3640 }
3641 
TEST_F(ValidateImage,ReadSuccess1)3642 TEST_F(ValidateImage, ReadSuccess1) {
3643   const std::string body = R"(
3644 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
3645 %res1 = OpImageRead %u32vec4 %img %u32vec2_01
3646 )";
3647 
3648   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
3649   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3650   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3651 }
3652 
TEST_F(ValidateImage,ReadSuccess2)3653 TEST_F(ValidateImage, ReadSuccess2) {
3654   const std::string body = R"(
3655 %img = OpLoad %type_image_f32_1d_0002_rgba32f %uniform_image_f32_1d_0002_rgba32f
3656 %res1 = OpImageRead %f32vec4 %img %u32vec2_01
3657 )";
3658 
3659   const std::string extra = "\nOpCapability Image1D\n";
3660   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3661   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3662 }
3663 
TEST_F(ValidateImage,ReadSuccess3)3664 TEST_F(ValidateImage, ReadSuccess3) {
3665   const std::string body = R"(
3666 %img = OpLoad %type_image_f32_cube_0102_rgba32f %uniform_image_f32_cube_0102_rgba32f
3667 %res1 = OpImageRead %f32vec4 %img %u32vec3_012
3668 )";
3669 
3670   const std::string extra = "\nOpCapability ImageCubeArray\n";
3671   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3672   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3673 }
3674 
TEST_F(ValidateImage,ReadSuccess4)3675 TEST_F(ValidateImage, ReadSuccess4) {
3676   const std::string body = R"(
3677 %img = OpLoad %type_image_f32_spd_0002 %uniform_image_f32_spd_0002
3678 %res1 = OpImageRead %f32vec4 %img %u32vec2_01
3679 )";
3680 
3681   CompileSuccessfully(GenerateShaderCode(body).c_str());
3682   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3683 }
3684 
TEST_F(ValidateImage,ReadNeedCapabilityStorageImageReadWithoutFormat)3685 TEST_F(ValidateImage, ReadNeedCapabilityStorageImageReadWithoutFormat) {
3686   const std::string body = R"(
3687 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
3688 %res1 = OpImageRead %u32vec4 %img %u32vec2_01
3689 )";
3690 
3691   CompileSuccessfully(GenerateShaderCode(body).c_str());
3692   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3693 }
3694 
TEST_F(ValidateImage,ReadNeedCapabilityStorageImageReadWithoutFormatVulkan)3695 TEST_F(ValidateImage, ReadNeedCapabilityStorageImageReadWithoutFormatVulkan) {
3696   const std::string body = R"(
3697 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
3698 %res1 = OpImageRead %u32vec4 %img %u32vec2_01
3699 )";
3700 
3701   spv_target_env env = SPV_ENV_VULKAN_1_0;
3702   CompileSuccessfully(GenerateShaderCode(body, "", "Fragment", "", env).c_str(),
3703                       env);
3704   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
3705   EXPECT_THAT(getDiagnosticString(),
3706               HasSubstr("Capability StorageImageReadWithoutFormat is required "
3707                         "to read storage image"));
3708 }
3709 
TEST_F(ValidateImage,ReadNeedCapabilityImage1D)3710 TEST_F(ValidateImage, ReadNeedCapabilityImage1D) {
3711   const std::string body = R"(
3712 %img = OpLoad %type_image_f32_1d_0002_rgba32f %uniform_image_f32_1d_0002_rgba32f
3713 %res1 = OpImageRead %f32vec4 %img %u32vec2_01
3714 )";
3715 
3716   CompileSuccessfully(GenerateShaderCode(body).c_str());
3717   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3718   EXPECT_THAT(
3719       getDiagnosticString(),
3720       HasSubstr("Capability Image1D is required to access storage image"));
3721 }
3722 
TEST_F(ValidateImage,ReadNeedCapabilityImageCubeArray)3723 TEST_F(ValidateImage, ReadNeedCapabilityImageCubeArray) {
3724   const std::string body = R"(
3725 %img = OpLoad %type_image_f32_cube_0102_rgba32f %uniform_image_f32_cube_0102_rgba32f
3726 %res1 = OpImageRead %f32vec4 %img %u32vec3_012
3727 )";
3728 
3729   CompileSuccessfully(GenerateShaderCode(body).c_str());
3730   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3731   EXPECT_THAT(
3732       getDiagnosticString(),
3733       HasSubstr(
3734           "Capability ImageCubeArray is required to access storage image"));
3735 }
3736 
3737 // TODO(atgoo@github.com) Disabled until the spec is clarified.
TEST_F(ValidateImage,DISABLED_ReadWrongResultType)3738 TEST_F(ValidateImage, DISABLED_ReadWrongResultType) {
3739   const std::string body = R"(
3740 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
3741 %res1 = OpImageRead %f32 %img %u32vec2_01
3742 )";
3743 
3744   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
3745   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3746   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3747   EXPECT_THAT(getDiagnosticString(),
3748               HasSubstr("Expected Result Type to be int or float vector type"));
3749 }
3750 
TEST_F(ValidateImage,ReadScalarResultType_Universal)3751 TEST_F(ValidateImage, ReadScalarResultType_Universal) {
3752   const std::string body = R"(
3753 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
3754 %res1 = OpImageRead %u32 %img %u32vec2_01
3755 )";
3756 
3757   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
3758   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3759   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_0));
3760   EXPECT_THAT(getDiagnosticString(), Eq(""));
3761 }
3762 
TEST_F(ValidateImage,ReadUnusualNumComponentsResultType_Universal)3763 TEST_F(ValidateImage, ReadUnusualNumComponentsResultType_Universal) {
3764   const std::string body = R"(
3765 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
3766 %res1 = OpImageRead %u32vec3 %img %u32vec2_01
3767 )";
3768 
3769   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
3770   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3771   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_0));
3772   EXPECT_THAT(getDiagnosticString(), Eq(""));
3773 }
3774 
TEST_F(ValidateImage,ReadWrongNumComponentsResultType_Vulkan)3775 TEST_F(ValidateImage, ReadWrongNumComponentsResultType_Vulkan) {
3776   const std::string body = R"(
3777 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
3778 %res1 = OpImageRead %u32vec3 %img %u32vec2_01
3779 )";
3780 
3781   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
3782   CompileSuccessfully(
3783       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_VULKAN_1_0)
3784           .c_str());
3785   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
3786   EXPECT_THAT(getDiagnosticString(),
3787               AnyVUID("VUID-StandaloneSpirv-Result-04780"));
3788   EXPECT_THAT(getDiagnosticString(),
3789               HasSubstr("Expected Result Type to have 4 components"));
3790 }
3791 
TEST_F(ValidateImage,ReadNotImage)3792 TEST_F(ValidateImage, ReadNotImage) {
3793   const std::string body = R"(
3794 %sampler = OpLoad %type_sampler %uniform_sampler
3795 %res1 = OpImageRead %f32vec4 %sampler %u32vec2_01
3796 )";
3797 
3798   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
3799   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3800   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3801   EXPECT_THAT(getDiagnosticString(),
3802               HasSubstr("Expected Image to be of type OpTypeImage"));
3803 }
3804 
TEST_F(ValidateImage,ReadImageSampled)3805 TEST_F(ValidateImage, ReadImageSampled) {
3806   const std::string body = R"(
3807 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
3808 %res1 = OpImageRead %f32vec4 %img %u32vec2_01
3809 )";
3810 
3811   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
3812   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3813   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3814   EXPECT_THAT(getDiagnosticString(),
3815               HasSubstr("Expected Image 'Sampled' parameter to be 0 or 2"));
3816 }
3817 
TEST_F(ValidateImage,ReadWrongSampledType)3818 TEST_F(ValidateImage, ReadWrongSampledType) {
3819   const std::string body = R"(
3820 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
3821 %res1 = OpImageRead %f32vec4 %img %u32vec2_01
3822 )";
3823 
3824   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
3825   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3826   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3827   EXPECT_THAT(getDiagnosticString(),
3828               HasSubstr("Expected Image 'Sampled Type' to be the same as "
3829                         "Result Type components"));
3830 }
3831 
TEST_F(ValidateImage,ReadVoidSampledType)3832 TEST_F(ValidateImage, ReadVoidSampledType) {
3833   const std::string body = R"(
3834 %img = OpLoad %type_image_void_2d_0002 %uniform_image_void_2d_0002
3835 %res1 = OpImageRead %f32vec4 %img %u32vec2_01
3836 %res2 = OpImageRead %u32vec4 %img %u32vec2_01
3837 %res3 = OpImageRead %s32vec4 %img %u32vec2_01
3838 )";
3839 
3840   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
3841   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3842   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3843 }
3844 
TEST_F(ValidateImage,ReadWrongCoordinateType)3845 TEST_F(ValidateImage, ReadWrongCoordinateType) {
3846   const std::string body = R"(
3847 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
3848 %res1 = OpImageRead %u32vec4 %img %f32vec2_00
3849 )";
3850 
3851   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
3852   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3853   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3854   EXPECT_THAT(getDiagnosticString(),
3855               HasSubstr("Expected Coordinate to be int scalar or vector"));
3856 }
3857 
TEST_F(ValidateImage,ReadCoordinateSizeTooSmall)3858 TEST_F(ValidateImage, ReadCoordinateSizeTooSmall) {
3859   const std::string body = R"(
3860 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
3861 %res1 = OpImageRead %u32vec4 %img %u32_1
3862 )";
3863 
3864   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
3865   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3866   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3867   EXPECT_THAT(getDiagnosticString(),
3868               HasSubstr("Expected Coordinate to have at least 2 components, "
3869                         "but given only 1"));
3870 }
3871 
TEST_F(ValidateImage,WriteSuccess1)3872 TEST_F(ValidateImage, WriteSuccess1) {
3873   const std::string body = R"(
3874 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
3875 OpImageWrite %img %u32vec2_01 %u32vec4_0123
3876 )";
3877 
3878   const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n";
3879   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3880   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3881 }
3882 
TEST_F(ValidateImage,WriteSuccess2)3883 TEST_F(ValidateImage, WriteSuccess2) {
3884   const std::string body = R"(
3885 %img = OpLoad %type_image_f32_1d_0002_rgba32f %uniform_image_f32_1d_0002_rgba32f
3886 OpImageWrite %img %u32_1 %f32vec4_0000
3887 )";
3888 
3889   const std::string extra = "\nOpCapability Image1D\n";
3890   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3891   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3892 }
3893 
TEST_F(ValidateImage,WriteSuccess3)3894 TEST_F(ValidateImage, WriteSuccess3) {
3895   const std::string body = R"(
3896 %img = OpLoad %type_image_f32_cube_0102_rgba32f %uniform_image_f32_cube_0102_rgba32f
3897 OpImageWrite %img %u32vec3_012 %f32vec4_0000
3898 )";
3899 
3900   const std::string extra = "\nOpCapability ImageCubeArray\n";
3901   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
3902   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3903 }
3904 
TEST_F(ValidateImage,WriteSuccess4)3905 TEST_F(ValidateImage, WriteSuccess4) {
3906   const std::string body = R"(
3907 %img = OpLoad %type_image_f32_2d_0012 %uniform_image_f32_2d_0012
3908 OpImageWrite %img %u32vec2_01 %f32vec4_0000 Sample %u32_1
3909 )";
3910 
3911   const std::string extra = R"(
3912     OpCapability StorageImageWriteWithoutFormat
3913     OpCapability StorageImageMultisample
3914     )";
3915 
3916   const std::string declarations = R"(
3917 %type_image_f32_2d_0012 = OpTypeImage %f32 2D 0 0 1 2 Unknown
3918 %ptr_image_f32_2d_0012 = OpTypePointer UniformConstant %type_image_f32_2d_0012
3919 %uniform_image_f32_2d_0012 = OpVariable %ptr_image_f32_2d_0012 UniformConstant
3920     )";
3921   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
3922                                          SPV_ENV_UNIVERSAL_1_0, "GLSL450",
3923                                          declarations)
3924                           .c_str());
3925   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3926 }
3927 
TEST_F(ValidateImage,WriteSubpassData)3928 TEST_F(ValidateImage, WriteSubpassData) {
3929   const std::string body = R"(
3930 %img = OpLoad %type_image_f32_spd_0002 %uniform_image_f32_spd_0002
3931 OpImageWrite %img %u32vec2_01 %f32vec4_0000
3932 )";
3933 
3934   CompileSuccessfully(GenerateShaderCode(body).c_str());
3935   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3936   EXPECT_THAT(getDiagnosticString(),
3937               HasSubstr("Image 'Dim' cannot be SubpassData"));
3938 }
3939 
TEST_F(ValidateImage,WriteNeedCapabilityStorageImageWriteWithoutFormat)3940 TEST_F(ValidateImage, WriteNeedCapabilityStorageImageWriteWithoutFormat) {
3941   const std::string body = R"(
3942 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
3943 OpImageWrite %img %u32vec2_01 %u32vec4_0123
3944 )";
3945 
3946   CompileSuccessfully(GenerateShaderCode(body).c_str());
3947   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3948 }
3949 
TEST_F(ValidateImage,WriteNeedCapabilityStorageImageWriteWithoutFormatVulkan)3950 TEST_F(ValidateImage, WriteNeedCapabilityStorageImageWriteWithoutFormatVulkan) {
3951   const std::string body = R"(
3952 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
3953 OpImageWrite %img %u32vec2_01 %u32vec4_0123
3954 )";
3955 
3956   spv_target_env env = SPV_ENV_VULKAN_1_0;
3957   CompileSuccessfully(GenerateShaderCode(body, "", "Fragment", "", env).c_str(),
3958                       env);
3959   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
3960   EXPECT_THAT(
3961       getDiagnosticString(),
3962       HasSubstr(
3963           "Capability StorageImageWriteWithoutFormat is required to write to "
3964           "storage image"));
3965 }
3966 
TEST_F(ValidateImage,WriteNeedCapabilityImage1D)3967 TEST_F(ValidateImage, WriteNeedCapabilityImage1D) {
3968   const std::string body = R"(
3969 %img = OpLoad %type_image_f32_1d_0002_rgba32f %uniform_image_f32_1d_0002_rgba32f
3970 OpImageWrite %img %u32vec2_01 %f32vec4_0000
3971 )";
3972 
3973   CompileSuccessfully(GenerateShaderCode(body).c_str());
3974   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3975   EXPECT_THAT(getDiagnosticString(),
3976               HasSubstr("Capability Image1D is required to access storage "
3977                         "image"));
3978 }
3979 
TEST_F(ValidateImage,WriteNeedCapabilityImageCubeArray)3980 TEST_F(ValidateImage, WriteNeedCapabilityImageCubeArray) {
3981   const std::string body = R"(
3982 %img = OpLoad %type_image_f32_cube_0102_rgba32f %uniform_image_f32_cube_0102_rgba32f
3983 OpImageWrite %img %u32vec3_012 %f32vec4_0000
3984 )";
3985 
3986   CompileSuccessfully(GenerateShaderCode(body).c_str());
3987   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3988   EXPECT_THAT(
3989       getDiagnosticString(),
3990       HasSubstr(
3991           "Capability ImageCubeArray is required to access storage image"));
3992 }
3993 
TEST_F(ValidateImage,WriteNotImage)3994 TEST_F(ValidateImage, WriteNotImage) {
3995   const std::string body = R"(
3996 %sampler = OpLoad %type_sampler %uniform_sampler
3997 OpImageWrite %sampler %u32vec2_01 %f32vec4_0000
3998 )";
3999 
4000   CompileSuccessfully(GenerateShaderCode(body).c_str());
4001   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4002   EXPECT_THAT(getDiagnosticString(),
4003               HasSubstr("Expected Image to be of type OpTypeImage"));
4004 }
4005 
TEST_F(ValidateImage,WriteImageSampled)4006 TEST_F(ValidateImage, WriteImageSampled) {
4007   const std::string body = R"(
4008 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4009 OpImageWrite %img %u32vec2_01 %f32vec4_0000
4010 )";
4011 
4012   const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n";
4013   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
4014   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4015   EXPECT_THAT(getDiagnosticString(),
4016               HasSubstr("Expected Image 'Sampled' parameter to be 0 or 2"));
4017 }
4018 
TEST_F(ValidateImage,WriteWrongCoordinateType)4019 TEST_F(ValidateImage, WriteWrongCoordinateType) {
4020   const std::string body = R"(
4021 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
4022 OpImageWrite %img %f32vec2_00 %u32vec4_0123
4023 )";
4024 
4025   const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n";
4026   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
4027   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4028   EXPECT_THAT(getDiagnosticString(),
4029               HasSubstr("Expected Coordinate to be int scalar or vector"));
4030 }
4031 
TEST_F(ValidateImage,WriteCoordinateSizeTooSmall)4032 TEST_F(ValidateImage, WriteCoordinateSizeTooSmall) {
4033   const std::string body = R"(
4034 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
4035 OpImageWrite %img %u32_1 %u32vec4_0123
4036 )";
4037 
4038   const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n";
4039   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
4040   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4041   EXPECT_THAT(getDiagnosticString(),
4042               HasSubstr("Expected Coordinate to have at least 2 components, "
4043                         "but given only 1"));
4044 }
4045 
TEST_F(ValidateImage,WriteTexelScalarSuccess)4046 TEST_F(ValidateImage, WriteTexelScalarSuccess) {
4047   const std::string body = R"(
4048 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
4049 OpImageWrite %img %u32vec2_01 %u32_2
4050 )";
4051 
4052   const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n";
4053   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
4054   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
4055 }
4056 
TEST_F(ValidateImage,WriteTexelWrongType)4057 TEST_F(ValidateImage, WriteTexelWrongType) {
4058   const std::string body = R"(
4059 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
4060 OpImageWrite %img %u32vec2_01 %img
4061 )";
4062 
4063   const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n";
4064   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
4065   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4066   EXPECT_THAT(getDiagnosticString(),
4067               HasSubstr("Expected Texel to be int or float vector or scalar"));
4068 }
4069 
TEST_F(ValidateImage,WriteTexelNonNumericalType)4070 TEST_F(ValidateImage, WriteTexelNonNumericalType) {
4071   const std::string body = R"(
4072 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
4073 OpImageWrite %img %u32vec2_01 %boolvec4_tttt
4074 )";
4075 
4076   const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n";
4077   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
4078   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4079   EXPECT_THAT(getDiagnosticString(),
4080               HasSubstr("Expected Texel to be int or float vector or scalar"));
4081 }
4082 
TEST_F(ValidateImage,WriteTexelWrongComponentType)4083 TEST_F(ValidateImage, WriteTexelWrongComponentType) {
4084   const std::string body = R"(
4085 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
4086 OpImageWrite %img %u32vec2_01 %f32vec4_0000
4087 )";
4088 
4089   const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n";
4090   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
4091   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4092   EXPECT_THAT(
4093       getDiagnosticString(),
4094       HasSubstr(
4095           "Expected Image 'Sampled Type' to be the same as Texel components"));
4096 }
4097 
TEST_F(ValidateImage,WriteSampleNotInteger)4098 TEST_F(ValidateImage, WriteSampleNotInteger) {
4099   const std::string body = R"(
4100 %img = OpLoad %type_image_f32_2d_0012 %uniform_image_f32_2d_0012
4101 OpImageWrite %img %u32vec2_01 %f32vec4_0000 Sample %f32_1
4102 )";
4103 
4104   const std::string extra = R"(
4105     OpCapability StorageImageWriteWithoutFormat
4106     OpCapability StorageImageMultisample
4107     )";
4108   const std::string declarations = R"(
4109 %type_image_f32_2d_0012 = OpTypeImage %f32 2D 0 0 1 2 Unknown
4110 %ptr_image_f32_2d_0012 = OpTypePointer UniformConstant %type_image_f32_2d_0012
4111 %uniform_image_f32_2d_0012 = OpVariable %ptr_image_f32_2d_0012 UniformConstant
4112     )";
4113   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
4114                                          SPV_ENV_UNIVERSAL_1_0, "GLSL450",
4115                                          declarations)
4116                           .c_str());
4117   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4118   EXPECT_THAT(getDiagnosticString(),
4119               HasSubstr("Expected Image Operand Sample to be int scalar"));
4120 }
4121 
TEST_F(ValidateImage,WriteSampleNotMultisampled)4122 TEST_F(ValidateImage, WriteSampleNotMultisampled) {
4123   const std::string body = R"(
4124 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
4125 OpImageWrite %img %u32vec2_01 %f32vec4_0000 Sample %u32_1
4126 )";
4127 
4128   const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n";
4129   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
4130   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4131   EXPECT_THAT(
4132       getDiagnosticString(),
4133       HasSubstr("Image Operand Sample requires non-zero 'MS' parameter"));
4134 }
4135 
TEST_F(ValidateImage,SampleWrongOpcode)4136 TEST_F(ValidateImage, SampleWrongOpcode) {
4137   const std::string body = R"(
4138 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
4139 %sampler = OpLoad %type_sampler %uniform_sampler
4140 %simg = OpSampledImage %type_sampled_image_f32_2d_0011 %img %sampler
4141 %res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_00 Sample %u32_1
4142 )";
4143 
4144   CompileSuccessfully(GenerateShaderCode(body).c_str());
4145   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4146   EXPECT_THAT(getDiagnosticString(),
4147               HasSubstr("Sampling operation is invalid for multisample image"));
4148 }
4149 
TEST_F(ValidateImage,SampleImageToImageSuccess)4150 TEST_F(ValidateImage, SampleImageToImageSuccess) {
4151   const std::string body = R"(
4152 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4153 %sampler = OpLoad %type_sampler %uniform_sampler
4154 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4155 %img2 = OpImage %type_image_f32_2d_0001 %simg
4156 )";
4157 
4158   CompileSuccessfully(GenerateShaderCode(body).c_str());
4159   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
4160 }
4161 
TEST_F(ValidateImage,SampleImageToImageWrongResultType)4162 TEST_F(ValidateImage, SampleImageToImageWrongResultType) {
4163   const std::string body = R"(
4164 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4165 %sampler = OpLoad %type_sampler %uniform_sampler
4166 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4167 %img2 = OpImage %type_sampled_image_f32_2d_0001 %simg
4168 )";
4169 
4170   CompileSuccessfully(GenerateShaderCode(body).c_str());
4171   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4172   EXPECT_THAT(getDiagnosticString(),
4173               HasSubstr("Expected Result Type to be OpTypeImage"));
4174 }
4175 
TEST_F(ValidateImage,SampleImageToImageNotSampledImage)4176 TEST_F(ValidateImage, SampleImageToImageNotSampledImage) {
4177   const std::string body = R"(
4178 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4179 %img2 = OpImage %type_image_f32_2d_0001 %img
4180 )";
4181 
4182   CompileSuccessfully(GenerateShaderCode(body).c_str());
4183   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4184   EXPECT_THAT(
4185       getDiagnosticString(),
4186       HasSubstr("Expected Sample Image to be of type OpTypeSampleImage"));
4187 }
4188 
TEST_F(ValidateImage,SampleImageToImageNotTheSameImageType)4189 TEST_F(ValidateImage, SampleImageToImageNotTheSameImageType) {
4190   const std::string body = R"(
4191 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4192 %sampler = OpLoad %type_sampler %uniform_sampler
4193 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4194 %img2 = OpImage %type_image_f32_2d_0002 %simg
4195 )";
4196 
4197   CompileSuccessfully(GenerateShaderCode(body).c_str());
4198   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4199   EXPECT_THAT(getDiagnosticString(),
4200               HasSubstr("Expected Sample Image image type to be equal to "
4201                         "Result Type"));
4202 }
4203 
TEST_F(ValidateImage,QueryFormatSuccess)4204 TEST_F(ValidateImage, QueryFormatSuccess) {
4205   const std::string body = R"(
4206 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4207 %res1 = OpImageQueryFormat %u32 %img
4208 )";
4209 
4210   CompileSuccessfully(GenerateKernelCode(body).c_str());
4211   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
4212 }
4213 
TEST_F(ValidateImage,QueryFormatWrongResultType)4214 TEST_F(ValidateImage, QueryFormatWrongResultType) {
4215   const std::string body = R"(
4216 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4217 %res1 = OpImageQueryFormat %bool %img
4218 )";
4219 
4220   CompileSuccessfully(GenerateKernelCode(body).c_str());
4221   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4222   EXPECT_THAT(getDiagnosticString(),
4223               HasSubstr("Expected Result Type to be int scalar type"));
4224 }
4225 
TEST_F(ValidateImage,QueryFormatNotImage)4226 TEST_F(ValidateImage, QueryFormatNotImage) {
4227   const std::string body = R"(
4228 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4229 %sampler = OpLoad %type_sampler %uniform_sampler
4230 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4231 %res1 = OpImageQueryFormat %u32 %sampler
4232 )";
4233 
4234   CompileSuccessfully(GenerateKernelCode(body).c_str());
4235   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4236   EXPECT_THAT(getDiagnosticString(),
4237               HasSubstr("Expected operand to be of type OpTypeImage"));
4238 }
4239 
TEST_F(ValidateImage,QueryOrderSuccess)4240 TEST_F(ValidateImage, QueryOrderSuccess) {
4241   const std::string body = R"(
4242 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4243 %res1 = OpImageQueryOrder %u32 %img
4244 )";
4245 
4246   CompileSuccessfully(GenerateKernelCode(body).c_str());
4247   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
4248 }
4249 
TEST_F(ValidateImage,QueryOrderWrongResultType)4250 TEST_F(ValidateImage, QueryOrderWrongResultType) {
4251   const std::string body = R"(
4252 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4253 %res1 = OpImageQueryOrder %bool %img
4254 )";
4255 
4256   CompileSuccessfully(GenerateKernelCode(body).c_str());
4257   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4258   EXPECT_THAT(getDiagnosticString(),
4259               HasSubstr("Expected Result Type to be int scalar type"));
4260 }
4261 
TEST_F(ValidateImage,QueryOrderNotImage)4262 TEST_F(ValidateImage, QueryOrderNotImage) {
4263   const std::string body = R"(
4264 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4265 %sampler = OpLoad %type_sampler %uniform_sampler
4266 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4267 %res1 = OpImageQueryOrder %u32 %sampler
4268 )";
4269 
4270   CompileSuccessfully(GenerateKernelCode(body).c_str());
4271   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4272   EXPECT_THAT(getDiagnosticString(),
4273               HasSubstr("Expected operand to be of type OpTypeImage"));
4274 }
4275 
TEST_F(ValidateImage,QuerySizeLodSuccess)4276 TEST_F(ValidateImage, QuerySizeLodSuccess) {
4277   const std::string body = R"(
4278 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4279 %res1 = OpImageQuerySizeLod %u32vec2 %img %u32_1
4280 )";
4281 
4282   CompileSuccessfully(GenerateKernelCode(body).c_str());
4283   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
4284 }
4285 
TEST_F(ValidateImage,QuerySizeLodWrongResultType)4286 TEST_F(ValidateImage, QuerySizeLodWrongResultType) {
4287   const std::string body = R"(
4288 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4289 %res1 = OpImageQuerySizeLod %f32vec2 %img %u32_1
4290 )";
4291 
4292   CompileSuccessfully(GenerateKernelCode(body).c_str());
4293   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4294   EXPECT_THAT(
4295       getDiagnosticString(),
4296       HasSubstr("Expected Result Type to be int scalar or vector type"));
4297 }
4298 
TEST_F(ValidateImage,QuerySizeLodResultTypeWrongSize)4299 TEST_F(ValidateImage, QuerySizeLodResultTypeWrongSize) {
4300   const std::string body = R"(
4301 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4302 %res1 = OpImageQuerySizeLod %u32 %img %u32_1
4303 )";
4304 
4305   CompileSuccessfully(GenerateKernelCode(body).c_str());
4306   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4307   EXPECT_THAT(getDiagnosticString(),
4308               HasSubstr("Result Type has 1 components, but 2 expected"));
4309 }
4310 
TEST_F(ValidateImage,QuerySizeLodNotImage)4311 TEST_F(ValidateImage, QuerySizeLodNotImage) {
4312   const std::string body = R"(
4313 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4314 %sampler = OpLoad %type_sampler %uniform_sampler
4315 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4316 %res1 = OpImageQuerySizeLod %u32vec2 %sampler %u32_1
4317 )";
4318 
4319   CompileSuccessfully(GenerateKernelCode(body).c_str());
4320   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4321   EXPECT_THAT(getDiagnosticString(),
4322               HasSubstr("Expected Image to be of type OpTypeImage"));
4323 }
4324 
TEST_F(ValidateImage,QuerySizeLodSampledImageDirectly)4325 TEST_F(ValidateImage, QuerySizeLodSampledImageDirectly) {
4326   const std::string body = R"(
4327 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4328 %sampler = OpLoad %type_sampler %uniform_sampler
4329 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4330 %res1 = OpImageQuerySizeLod %u32vec2 %simg %u32_1
4331 )";
4332 
4333   CompileSuccessfully(GenerateShaderCode(body).c_str());
4334   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4335   EXPECT_THAT(getDiagnosticString(),
4336               HasSubstr("OpSampledImage instruction must not appear as operand "
4337                         "for OpImageQuerySizeLod"));
4338 }
4339 
TEST_F(ValidateImage,QuerySizeLodMultisampledError)4340 TEST_F(ValidateImage, QuerySizeLodMultisampledError) {
4341   const std::string body = R"(
4342 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
4343 %res1 = OpImageQuerySizeLod %u32vec2 %img %u32_1
4344 )";
4345 
4346   CompileSuccessfully(GenerateKernelCode(body).c_str());
4347   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4348   EXPECT_THAT(getDiagnosticString(), HasSubstr("Image 'MS' must be 0"));
4349 }
4350 
TEST_F(ValidateImage,QuerySizeLodNonSampledUniversalSuccess)4351 TEST_F(ValidateImage, QuerySizeLodNonSampledUniversalSuccess) {
4352   const std::string body = R"(
4353 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
4354 %res1 = OpImageQuerySizeLod %u32vec2 %img %u32_1
4355 )";
4356 
4357   CompileSuccessfully(GenerateShaderCode(body).c_str());
4358   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
4359   EXPECT_EQ(getDiagnosticString(), "");
4360 }
4361 
TEST_F(ValidateImage,QuerySizeLodVulkanNonSampledError)4362 TEST_F(ValidateImage, QuerySizeLodVulkanNonSampledError) {
4363   // Create a whole shader module.  Avoid Vulkan incompatibility with
4364   // SampledRrect images inserted by helper function GenerateShaderCode.
4365   const std::string body = R"(
4366 OpCapability Shader
4367 OpCapability ImageQuery
4368 OpMemoryModel Logical Simple
4369 OpEntryPoint Fragment %main "main"
4370 OpExecutionMode %main OriginUpperLeft
4371 
4372 %f32 = OpTypeFloat 32
4373 %u32 = OpTypeInt 32 0
4374 %u32_0 = OpConstant %u32 0
4375 %u32vec2 = OpTypeVector %u32 2
4376 %void = OpTypeVoid
4377 %voidfn = OpTypeFunction %void
4378 
4379 ; Test with a storage image.
4380 %type_image_f32_2d_0002 = OpTypeImage %f32 2D 0 0 0 2 Rgba32f
4381 %ptr_image_f32_2d_0002 = OpTypePointer UniformConstant %type_image_f32_2d_0002
4382 %uniform_image_f32_2d_0002 = OpVariable %ptr_image_f32_2d_0002 UniformConstant
4383 
4384 %main = OpFunction %void None %voidfn
4385 %entry = OpLabel
4386 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
4387 %res1 = OpImageQuerySizeLod %u32vec2 %img %u32_0
4388 OpReturn
4389 OpFunctionEnd
4390 )";
4391 
4392   CompileSuccessfully(body.c_str());
4393   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
4394   EXPECT_THAT(getDiagnosticString(),
4395               AnyVUID("VUID-StandaloneSpirv-OpImageQuerySizeLod-04659"));
4396   EXPECT_THAT(
4397       getDiagnosticString(),
4398       HasSubstr(
4399           "OpImageQuerySizeLod must only consume an \"Image\" operand whose "
4400           "type has its \"Sampled\" operand set to 1"));
4401 }
4402 
TEST_F(ValidateImage,QuerySizeLodWrongImageDim)4403 TEST_F(ValidateImage, QuerySizeLodWrongImageDim) {
4404   const std::string body = R"(
4405 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
4406 %res1 = OpImageQuerySizeLod %u32vec2 %img %u32_1
4407 )";
4408 
4409   CompileSuccessfully(GenerateKernelCode(body).c_str());
4410   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4411   EXPECT_THAT(getDiagnosticString(),
4412               HasSubstr("Image 'Dim' must be 1D, 2D, 3D or Cube"));
4413 }
4414 
TEST_F(ValidateImage,QuerySizeLodWrongLodType)4415 TEST_F(ValidateImage, QuerySizeLodWrongLodType) {
4416   const std::string body = R"(
4417 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4418 %res1 = OpImageQuerySizeLod %u32vec2 %img %f32_0
4419 )";
4420 
4421   CompileSuccessfully(GenerateKernelCode(body).c_str());
4422   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4423   EXPECT_THAT(getDiagnosticString(),
4424               HasSubstr("Expected Level of Detail to be int scalar"));
4425 }
4426 
TEST_F(ValidateImage,QuerySizeSuccess)4427 TEST_F(ValidateImage, QuerySizeSuccess) {
4428   const std::string body = R"(
4429 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
4430 %res1 = OpImageQuerySize %u32vec2 %img
4431 )";
4432 
4433   CompileSuccessfully(GenerateKernelCode(body).c_str());
4434   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
4435 }
4436 
TEST_F(ValidateImage,QuerySizeWrongResultType)4437 TEST_F(ValidateImage, QuerySizeWrongResultType) {
4438   const std::string body = R"(
4439 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
4440 %res1 = OpImageQuerySize %f32vec2 %img
4441 )";
4442 
4443   CompileSuccessfully(GenerateKernelCode(body).c_str());
4444   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4445   EXPECT_THAT(
4446       getDiagnosticString(),
4447       HasSubstr("Expected Result Type to be int scalar or vector type"));
4448 }
4449 
TEST_F(ValidateImage,QuerySizeNotImage)4450 TEST_F(ValidateImage, QuerySizeNotImage) {
4451   const std::string body = R"(
4452 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
4453 %sampler = OpLoad %type_sampler %uniform_sampler
4454 %simg = OpSampledImage %type_sampled_image_f32_2d_0011 %img %sampler
4455 %res1 = OpImageQuerySize %u32vec2 %sampler
4456 )";
4457 
4458   CompileSuccessfully(GenerateKernelCode(body).c_str());
4459   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4460   EXPECT_THAT(getDiagnosticString(),
4461               HasSubstr("Expected Image to be of type OpTypeImage"));
4462 }
4463 
TEST_F(ValidateImage,QuerySizeSampledImageDirectly)4464 TEST_F(ValidateImage, QuerySizeSampledImageDirectly) {
4465   const std::string body = R"(
4466 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
4467 %sampler = OpLoad %type_sampler %uniform_sampler
4468 %simg = OpSampledImage %type_sampled_image_f32_2d_0011 %img %sampler
4469 %res1 = OpImageQuerySize %u32vec2 %simg
4470 )";
4471 
4472   CompileSuccessfully(GenerateShaderCode(body).c_str());
4473   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4474   EXPECT_THAT(getDiagnosticString(),
4475               HasSubstr("OpSampledImage instruction must not appear as operand "
4476                         "for OpImageQuerySize"));
4477 }
4478 
TEST_F(ValidateImage,QuerySizeDimSubpassDataBad)4479 TEST_F(ValidateImage, QuerySizeDimSubpassDataBad) {
4480   const std::string body = R"(
4481 %img = OpLoad %type_image_f32_spd_0002 %uniform_image_f32_spd_0002
4482 %res1 = OpImageQuerySize %u32vec2 %img
4483 )";
4484 
4485   CompileSuccessfully(GenerateShaderCode(body).c_str());
4486   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4487   EXPECT_THAT(
4488       getDiagnosticString(),
4489       HasSubstr("Image 'Dim' must be 1D, Buffer, 2D, Cube, 3D or Rect"));
4490 }
4491 
TEST_F(ValidateImage,QuerySizeWrongSampling)4492 TEST_F(ValidateImage, QuerySizeWrongSampling) {
4493   const std::string body = R"(
4494 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4495 %res1 = OpImageQuerySize %u32vec2 %img
4496 )";
4497 
4498   CompileSuccessfully(GenerateKernelCode(body).c_str());
4499   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4500   EXPECT_THAT(
4501       getDiagnosticString(),
4502       HasSubstr("Image must have either 'MS'=1 or 'Sampled'=0 or 'Sampled'=2"));
4503 }
4504 
TEST_F(ValidateImage,QuerySizeWrongNumberOfComponents)4505 TEST_F(ValidateImage, QuerySizeWrongNumberOfComponents) {
4506   const std::string body = R"(
4507 %img = OpLoad %type_image_f32_3d_0111 %uniform_image_f32_3d_0111
4508 %res1 = OpImageQuerySize %u32vec2 %img
4509 )";
4510 
4511   CompileSuccessfully(GenerateShaderCode(body).c_str());
4512   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4513   EXPECT_THAT(getDiagnosticString(),
4514               HasSubstr("Result Type has 2 components, but 4 expected"));
4515 }
4516 
TEST_F(ValidateImage,QueryLodSuccessKernel)4517 TEST_F(ValidateImage, QueryLodSuccessKernel) {
4518   const std::string body = R"(
4519 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4520 %sampler = OpLoad %type_sampler %uniform_sampler
4521 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4522 %res1 = OpImageQueryLod %f32vec2 %simg %f32vec2_hh
4523 %res2 = OpImageQueryLod %f32vec2 %simg %u32vec2_01
4524 )";
4525 
4526   CompileSuccessfully(GenerateKernelCode(body).c_str());
4527   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
4528 }
4529 
TEST_F(ValidateImage,QueryLodSuccessShader)4530 TEST_F(ValidateImage, QueryLodSuccessShader) {
4531   const std::string body = R"(
4532 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4533 %sampler = OpLoad %type_sampler %uniform_sampler
4534 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4535 %res1 = OpImageQueryLod %f32vec2 %simg %f32vec2_hh
4536 )";
4537 
4538   CompileSuccessfully(GenerateShaderCode(body).c_str());
4539   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
4540 }
4541 
TEST_F(ValidateImage,QueryLodWrongResultType)4542 TEST_F(ValidateImage, QueryLodWrongResultType) {
4543   const std::string body = R"(
4544 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4545 %sampler = OpLoad %type_sampler %uniform_sampler
4546 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4547 %res1 = OpImageQueryLod %u32vec2 %simg %f32vec2_hh
4548 )";
4549 
4550   CompileSuccessfully(GenerateKernelCode(body).c_str());
4551   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4552   EXPECT_THAT(getDiagnosticString(),
4553               HasSubstr("Expected Result Type to be float vector type"));
4554 }
4555 
TEST_F(ValidateImage,QueryLodResultTypeWrongSize)4556 TEST_F(ValidateImage, QueryLodResultTypeWrongSize) {
4557   const std::string body = R"(
4558 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4559 %sampler = OpLoad %type_sampler %uniform_sampler
4560 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4561 %res1 = OpImageQueryLod %f32vec3 %simg %f32vec2_hh
4562 )";
4563 
4564   CompileSuccessfully(GenerateKernelCode(body).c_str());
4565   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4566   EXPECT_THAT(getDiagnosticString(),
4567               HasSubstr("Expected Result Type to have 2 components"));
4568 }
4569 
TEST_F(ValidateImage,QueryLodNotSampledImage)4570 TEST_F(ValidateImage, QueryLodNotSampledImage) {
4571   const std::string body = R"(
4572 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4573 %res1 = OpImageQueryLod %f32vec2 %img %f32vec2_hh
4574 )";
4575 
4576   CompileSuccessfully(GenerateKernelCode(body).c_str());
4577   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4578   EXPECT_THAT(
4579       getDiagnosticString(),
4580       HasSubstr("Expected Image operand to be of type OpTypeSampledImage"));
4581 }
4582 
TEST_F(ValidateImage,QueryLodWrongDim)4583 TEST_F(ValidateImage, QueryLodWrongDim) {
4584   const std::string body = R"(
4585 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
4586 %sampler = OpLoad %type_sampler %uniform_sampler
4587 %simg = OpSampledImage %type_sampled_image_f32_rect_0001 %img %sampler
4588 %res1 = OpImageQueryLod %f32vec2 %simg %f32vec2_hh
4589 )";
4590 
4591   CompileSuccessfully(GenerateKernelCode(body).c_str());
4592   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4593   EXPECT_THAT(getDiagnosticString(),
4594               HasSubstr("Image 'Dim' must be 1D, 2D, 3D or Cube"));
4595 }
4596 
TEST_F(ValidateImage,QueryLodWrongCoordinateType)4597 TEST_F(ValidateImage, QueryLodWrongCoordinateType) {
4598   const std::string body = R"(
4599 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4600 %sampler = OpLoad %type_sampler %uniform_sampler
4601 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4602 %res1 = OpImageQueryLod %f32vec2 %simg %u32vec2_01
4603 )";
4604 
4605   CompileSuccessfully(GenerateShaderCode(body).c_str());
4606   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4607   EXPECT_THAT(getDiagnosticString(),
4608               HasSubstr("Expected Coordinate to be float scalar or vector"));
4609 }
4610 
TEST_F(ValidateImage,QueryLodCoordinateSizeTooSmall)4611 TEST_F(ValidateImage, QueryLodCoordinateSizeTooSmall) {
4612   const std::string body = R"(
4613 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4614 %sampler = OpLoad %type_sampler %uniform_sampler
4615 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4616 %res1 = OpImageQueryLod %f32vec2 %simg %f32_0
4617 )";
4618 
4619   CompileSuccessfully(GenerateShaderCode(body).c_str());
4620   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4621   EXPECT_THAT(getDiagnosticString(),
4622               HasSubstr("Expected Coordinate to have at least 2 components, "
4623                         "but given only 1"));
4624 }
4625 
TEST_F(ValidateImage,QueryLevelsSuccess)4626 TEST_F(ValidateImage, QueryLevelsSuccess) {
4627   const std::string body = R"(
4628 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4629 %res1 = OpImageQueryLevels %u32 %img
4630 )";
4631 
4632   CompileSuccessfully(GenerateKernelCode(body).c_str());
4633   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
4634 }
4635 
TEST_F(ValidateImage,QueryLevelsWrongResultType)4636 TEST_F(ValidateImage, QueryLevelsWrongResultType) {
4637   const std::string body = R"(
4638 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4639 %res1 = OpImageQueryLevels %f32 %img
4640 )";
4641 
4642   CompileSuccessfully(GenerateKernelCode(body).c_str());
4643   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4644   EXPECT_THAT(getDiagnosticString(),
4645               HasSubstr("Expected Result Type to be int scalar type"));
4646 }
4647 
TEST_F(ValidateImage,QueryLevelsNotImage)4648 TEST_F(ValidateImage, QueryLevelsNotImage) {
4649   const std::string body = R"(
4650 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4651 %sampler = OpLoad %type_sampler %uniform_sampler
4652 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4653 %res1 = OpImageQueryLevels %u32 %sampler
4654 )";
4655 
4656   CompileSuccessfully(GenerateKernelCode(body).c_str());
4657   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4658   EXPECT_THAT(getDiagnosticString(),
4659               HasSubstr("Expected Image to be of type OpTypeImage"));
4660 }
4661 
TEST_F(ValidateImage,QueryLevelsSampledImageDirectly)4662 TEST_F(ValidateImage, QueryLevelsSampledImageDirectly) {
4663   const std::string body = R"(
4664 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4665 %sampler = OpLoad %type_sampler %uniform_sampler
4666 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4667 %res1 = OpImageQueryLevels %u32 %simg
4668 )";
4669 
4670   CompileSuccessfully(GenerateShaderCode(body).c_str());
4671   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4672   EXPECT_THAT(getDiagnosticString(),
4673               HasSubstr("OpSampledImage instruction must not appear as operand "
4674                         "for OpImageQueryLevels"));
4675 }
4676 
TEST_F(ValidateImage,QueryLevelsWrongDim)4677 TEST_F(ValidateImage, QueryLevelsWrongDim) {
4678   const std::string body = R"(
4679 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
4680 %res1 = OpImageQueryLevels %u32 %img
4681 )";
4682 
4683   CompileSuccessfully(GenerateKernelCode(body).c_str());
4684   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4685   EXPECT_THAT(getDiagnosticString(),
4686               HasSubstr("Image 'Dim' must be 1D, 2D, 3D or Cube"));
4687 }
4688 
TEST_F(ValidateImage,QuerySizeLevelsNonSampledUniversalSuccess)4689 TEST_F(ValidateImage, QuerySizeLevelsNonSampledUniversalSuccess) {
4690   const std::string body = R"(
4691 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
4692 %res1 = OpImageQueryLevels %u32 %img
4693 )";
4694 
4695   CompileSuccessfully(GenerateShaderCode(body).c_str());
4696   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
4697   EXPECT_EQ(getDiagnosticString(), "");
4698 }
4699 
TEST_F(ValidateImage,QuerySizeLevelsVulkanNonSampledError)4700 TEST_F(ValidateImage, QuerySizeLevelsVulkanNonSampledError) {
4701   // Create a whole shader module.  Avoid Vulkan incompatibility with
4702   // SampledRrect images inserted by helper function GenerateShaderCode.
4703   const std::string body = R"(
4704 OpCapability Shader
4705 OpCapability ImageQuery
4706 OpMemoryModel Logical Simple
4707 OpEntryPoint Fragment %main "main"
4708 OpExecutionMode %main OriginUpperLeft
4709 
4710 %f32 = OpTypeFloat 32
4711 %u32 = OpTypeInt 32 0
4712 %void = OpTypeVoid
4713 %voidfn = OpTypeFunction %void
4714 
4715 ; Test with a storage image.
4716 %type_image_f32_2d_0002 = OpTypeImage %f32 2D 0 0 0 2 Rgba32f
4717 %ptr_image_f32_2d_0002 = OpTypePointer UniformConstant %type_image_f32_2d_0002
4718 %uniform_image_f32_2d_0002 = OpVariable %ptr_image_f32_2d_0002 UniformConstant
4719 
4720 %main = OpFunction %void None %voidfn
4721 %entry = OpLabel
4722 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
4723 %res1 = OpImageQueryLevels %u32 %img
4724 OpReturn
4725 OpFunctionEnd
4726 )";
4727 
4728   CompileSuccessfully(body.c_str());
4729   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
4730   EXPECT_THAT(getDiagnosticString(),
4731               AnyVUID("VUID-StandaloneSpirv-OpImageQuerySizeLod-04659"));
4732   EXPECT_THAT(
4733       getDiagnosticString(),
4734       HasSubstr("OpImageQueryLevels must only consume an \"Image\" operand "
4735                 "whose type has its \"Sampled\" operand set to 1"));
4736 }
4737 
TEST_F(ValidateImage,QuerySamplesSuccess)4738 TEST_F(ValidateImage, QuerySamplesSuccess) {
4739   const std::string body = R"(
4740 %img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
4741 %res1 = OpImageQuerySamples %u32 %img
4742 )";
4743 
4744   CompileSuccessfully(GenerateKernelCode(body).c_str());
4745   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
4746 }
4747 
TEST_F(ValidateImage,QuerySamplesNot2D)4748 TEST_F(ValidateImage, QuerySamplesNot2D) {
4749   const std::string body = R"(
4750 %img = OpLoad %type_image_f32_3d_0011 %uniform_image_f32_3d_0011
4751 %res1 = OpImageQuerySamples %u32 %img
4752 )";
4753 
4754   CompileSuccessfully(GenerateKernelCode(body).c_str());
4755   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4756   EXPECT_THAT(getDiagnosticString(), HasSubstr("Image 'Dim' must be 2D"));
4757 }
4758 
TEST_F(ValidateImage,QuerySamplesNotMultisampled)4759 TEST_F(ValidateImage, QuerySamplesNotMultisampled) {
4760   const std::string body = R"(
4761 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4762 %res1 = OpImageQuerySamples %u32 %img
4763 )";
4764 
4765   CompileSuccessfully(GenerateKernelCode(body).c_str());
4766   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
4767   EXPECT_THAT(getDiagnosticString(), HasSubstr("Image 'MS' must be 1"));
4768 }
4769 
TEST_F(ValidateImage,QueryLodWrongExecutionModel)4770 TEST_F(ValidateImage, QueryLodWrongExecutionModel) {
4771   const std::string body = R"(
4772 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4773 %sampler = OpLoad %type_sampler %uniform_sampler
4774 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4775 %res1 = OpImageQueryLod %f32vec2 %simg %f32vec2_hh
4776 )";
4777 
4778   CompileSuccessfully(GenerateShaderCode(body, "", "Vertex").c_str());
4779   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4780   EXPECT_THAT(
4781       getDiagnosticString(),
4782       HasSubstr(
4783           "OpImageQueryLod requires Fragment or GLCompute execution model"));
4784 }
4785 
TEST_F(ValidateImage,QueryLodWrongExecutionModelWithFunc)4786 TEST_F(ValidateImage, QueryLodWrongExecutionModelWithFunc) {
4787   const std::string body = R"(
4788 %call_ret = OpFunctionCall %void %my_func
4789 OpReturn
4790 OpFunctionEnd
4791 %my_func = OpFunction %void None %func
4792 %my_func_entry = OpLabel
4793 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4794 %sampler = OpLoad %type_sampler %uniform_sampler
4795 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4796 %res1 = OpImageQueryLod %f32vec2 %simg %f32vec2_hh
4797 )";
4798 
4799   CompileSuccessfully(GenerateShaderCode(body, "", "Vertex").c_str());
4800   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4801   EXPECT_THAT(
4802       getDiagnosticString(),
4803       HasSubstr(
4804           "OpImageQueryLod requires Fragment or GLCompute execution model"));
4805 }
4806 
TEST_F(ValidateImage,QueryLodComputeShaderDerivatives)4807 TEST_F(ValidateImage, QueryLodComputeShaderDerivatives) {
4808   const std::string body = R"(
4809 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4810 %sampler = OpLoad %type_sampler %uniform_sampler
4811 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4812 %res1 = OpImageQueryLod %f32vec2 %simg %f32vec2_hh
4813 )";
4814 
4815   const std::string extra = R"(
4816 OpCapability ComputeDerivativeGroupLinearNV
4817 OpExtension "SPV_NV_compute_shader_derivatives"
4818 )";
4819   const std::string mode = R"(
4820 OpExecutionMode %main LocalSize 8 8 1
4821 OpExecutionMode %main DerivativeGroupLinearNV
4822 )";
4823   CompileSuccessfully(
4824       GenerateShaderCode(body, extra, "GLCompute", mode).c_str());
4825   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
4826 }
4827 
TEST_F(ValidateImage,QueryLodUniversalSuccess)4828 TEST_F(ValidateImage, QueryLodUniversalSuccess) {
4829   // Create a whole shader module.  Avoid Vulkan incompatibility with
4830   // SampledRrect images inserted by helper function GenerateShaderCode.
4831   const std::string body = R"(
4832 OpCapability Shader
4833 OpCapability ImageQuery
4834 OpMemoryModel Logical Simple
4835 OpEntryPoint Fragment %main "main"
4836 OpExecutionMode %main OriginUpperLeft
4837 
4838 OpDecorate %uniform_image_f32_2d_0000 DescriptorSet 0
4839 OpDecorate %uniform_image_f32_2d_0000 Binding 0
4840 OpDecorate %sampler DescriptorSet 0
4841 OpDecorate %sampler Binding 1
4842 
4843 %f32 = OpTypeFloat 32
4844 %f32vec2 = OpTypeVector %f32 2
4845 %f32vec2_null = OpConstantNull %f32vec2
4846 %u32 = OpTypeInt 32 0
4847 %u32vec2 = OpTypeVector %u32 2
4848 %void = OpTypeVoid
4849 %voidfn = OpTypeFunction %void
4850 
4851 ; Test with an image with sampled = 0
4852 %type_image_f32_2d_0000 = OpTypeImage %f32 2D 0 0 0 0 Rgba32f
4853 %ptr_image_f32_2d_0000 = OpTypePointer UniformConstant %type_image_f32_2d_0000
4854 %uniform_image_f32_2d_0000 = OpVariable %ptr_image_f32_2d_0000 UniformConstant
4855 %sampled_image_ty = OpTypeSampledImage %type_image_f32_2d_0000
4856 
4857 %sampler_ty = OpTypeSampler
4858 %ptr_sampler_ty = OpTypePointer UniformConstant %sampler_ty
4859 %sampler = OpVariable %ptr_sampler_ty UniformConstant
4860 
4861 
4862 %main = OpFunction %void None %voidfn
4863 %entry = OpLabel
4864 %img = OpLoad %type_image_f32_2d_0000 %uniform_image_f32_2d_0000
4865 %s = OpLoad %sampler_ty %sampler
4866 %simg = OpSampledImage %sampled_image_ty %img %s
4867 %res1 = OpImageQueryLod %f32vec2 %simg %f32vec2_null
4868 OpReturn
4869 OpFunctionEnd
4870 )";
4871 
4872   CompileSuccessfully(body.c_str());
4873   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
4874 }
4875 
TEST_F(ValidateImage,QueryLodVulkanNonSampledError)4876 TEST_F(ValidateImage, QueryLodVulkanNonSampledError) {
4877   // Create a whole shader module.  Avoid Vulkan incompatibility with
4878   // SampledRrect images inserted by helper function GenerateShaderCode.
4879   const std::string body = R"(
4880 OpCapability Shader
4881 OpCapability ImageQuery
4882 OpMemoryModel Logical Simple
4883 OpEntryPoint Fragment %main "main"
4884 OpExecutionMode %main OriginUpperLeft
4885 
4886 OpDecorate %sampled_image DescriptorSet 0
4887 OpDecorate %sampled_image Binding 0
4888 
4889 %f32 = OpTypeFloat 32
4890 %f32vec2 = OpTypeVector %f32 2
4891 %f32vec2_null = OpConstantNull %f32vec2
4892 %u32 = OpTypeInt 32 0
4893 %u32vec2 = OpTypeVector %u32 2
4894 %void = OpTypeVoid
4895 %voidfn = OpTypeFunction %void
4896 
4897 ; Test with an image with Sampled = 2
4898 ; In Vulkan it Sampled must be 1 or 2, checked in another part of the
4899 ; validation flow.
4900 %type_image_f32_2d_0002 = OpTypeImage %f32 2D 0 0 0 2 Rgba32f
4901 
4902 ; Expect to fail here.
4903 %sampled_image_ty = OpTypeSampledImage %type_image_f32_2d_0002
4904 %ptr_sampled_image_ty = OpTypePointer UniformConstant %sampled_image_ty
4905 %sampled_image = OpVariable %ptr_sampled_image_ty UniformConstant
4906 
4907 %main = OpFunction %void None %voidfn
4908 %entry = OpLabel
4909 %simg = OpLoad %sampled_image_ty %sampled_image
4910 %res1 = OpImageQueryLod %f32vec2 %simg %f32vec2_null
4911 OpReturn
4912 OpFunctionEnd
4913 )";
4914 
4915   CompileSuccessfully(body.c_str());
4916   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
4917   EXPECT_THAT(getDiagnosticString(),
4918               AnyVUID("VUID-StandaloneSpirv-OpTypeImage-04657"));
4919   EXPECT_THAT(getDiagnosticString(),
4920               HasSubstr("Sampled image type requires an image type with "
4921                         "\"Sampled\" operand set to 0 or 1"));
4922 }
4923 
TEST_F(ValidateImage,QueryLodComputeShaderDerivativesMissingMode)4924 TEST_F(ValidateImage, QueryLodComputeShaderDerivativesMissingMode) {
4925   const std::string body = R"(
4926 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4927 %sampler = OpLoad %type_sampler %uniform_sampler
4928 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4929 %res1 = OpImageQueryLod %f32vec2 %simg %f32vec2_hh
4930 )";
4931 
4932   const std::string extra = R"(
4933 OpCapability ComputeDerivativeGroupLinearNV
4934 OpExtension "SPV_NV_compute_shader_derivatives"
4935 )";
4936   const std::string mode = R"(
4937 OpExecutionMode %main LocalSize 8 8 1
4938 )";
4939   CompileSuccessfully(
4940       GenerateShaderCode(body, extra, "GLCompute", mode).c_str());
4941   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4942   EXPECT_THAT(getDiagnosticString(),
4943               HasSubstr("OpImageQueryLod requires DerivativeGroupQuadsNV or "
4944                         "DerivativeGroupLinearNV execution mode for GLCompute "
4945                         "execution model"));
4946 }
4947 
TEST_F(ValidateImage,ImplicitLodWrongExecutionModel)4948 TEST_F(ValidateImage, ImplicitLodWrongExecutionModel) {
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   CompileSuccessfully(GenerateShaderCode(body, "", "Vertex").c_str());
4957   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4958   EXPECT_THAT(getDiagnosticString(),
4959               HasSubstr("ImplicitLod instructions require Fragment or "
4960                         "GLCompute execution model"));
4961 }
4962 
TEST_F(ValidateImage,ImplicitLodComputeShaderDerivatives)4963 TEST_F(ValidateImage, ImplicitLodComputeShaderDerivatives) {
4964   const std::string body = R"(
4965 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4966 %sampler = OpLoad %type_sampler %uniform_sampler
4967 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4968 %res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh
4969 )";
4970 
4971   const std::string extra = R"(
4972 OpCapability ComputeDerivativeGroupLinearNV
4973 OpExtension "SPV_NV_compute_shader_derivatives"
4974 )";
4975   const std::string mode = R"(
4976 OpExecutionMode %main LocalSize 8 8 1
4977 OpExecutionMode %main DerivativeGroupLinearNV
4978 )";
4979   CompileSuccessfully(
4980       GenerateShaderCode(body, extra, "GLCompute", mode).c_str());
4981   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
4982 }
4983 
TEST_F(ValidateImage,ImplicitLodComputeShaderDerivativesMissingMode)4984 TEST_F(ValidateImage, ImplicitLodComputeShaderDerivativesMissingMode) {
4985   const std::string body = R"(
4986 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
4987 %sampler = OpLoad %type_sampler %uniform_sampler
4988 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
4989 %res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh
4990 )";
4991 
4992   const std::string extra = R"(
4993 OpCapability ComputeDerivativeGroupLinearNV
4994 OpExtension "SPV_NV_compute_shader_derivatives"
4995 )";
4996   const std::string mode = R"(
4997 OpExecutionMode %main LocalSize 8 8 1
4998 )";
4999   CompileSuccessfully(
5000       GenerateShaderCode(body, extra, "GLCompute", mode).c_str());
5001   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5002   EXPECT_THAT(
5003       getDiagnosticString(),
5004       HasSubstr("ImplicitLod instructions require DerivativeGroupQuadsNV or "
5005                 "DerivativeGroupLinearNV execution mode for GLCompute "
5006                 "execution model"));
5007 }
5008 
TEST_F(ValidateImage,ReadSubpassDataWrongExecutionModel)5009 TEST_F(ValidateImage, ReadSubpassDataWrongExecutionModel) {
5010   const std::string body = R"(
5011 %img = OpLoad %type_image_f32_spd_0002 %uniform_image_f32_spd_0002
5012 %res1 = OpImageRead %f32vec4 %img %u32vec2_01
5013 )";
5014 
5015   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
5016   CompileSuccessfully(GenerateShaderCode(body, extra, "Vertex").c_str());
5017   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5018   EXPECT_THAT(getDiagnosticString(),
5019               HasSubstr("Dim SubpassData requires Fragment execution model"));
5020 }
5021 
TEST_F(ValidateImage,SparseSampleImplicitLodSuccess)5022 TEST_F(ValidateImage, SparseSampleImplicitLodSuccess) {
5023   const std::string body = R"(
5024 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5025 %sampler = OpLoad %type_sampler %uniform_sampler
5026 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5027 %res1 = OpImageSparseSampleImplicitLod %struct_u32_f32vec4 %simg %f32vec2_hh
5028 %res2 = OpImageSparseSampleImplicitLod %struct_u32_f32vec4 %simg %f32vec2_hh Bias %f32_0_25
5029 %res4 = OpImageSparseSampleImplicitLod %struct_u32_f32vec4 %simg %f32vec2_hh ConstOffset %s32vec2_01
5030 %res5 = OpImageSparseSampleImplicitLod %struct_u32_f32vec4 %simg %f32vec2_hh Offset %s32vec2_01
5031 %res6 = OpImageSparseSampleImplicitLod %struct_u32_f32vec4 %simg %f32vec2_hh MinLod %f32_0_5
5032 %res7 = OpImageSparseSampleImplicitLod %struct_u64_f32vec4 %simg %f32vec2_hh Bias|Offset|MinLod %f32_0_25 %s32vec2_01 %f32_0_5
5033 %res8 = OpImageSparseSampleImplicitLod %struct_u32_f32vec4 %simg %f32vec2_hh NonPrivateTexelKHR
5034 )";
5035 
5036   const std::string extra = R"(
5037 OpCapability VulkanMemoryModelKHR
5038 OpExtension "SPV_KHR_vulkan_memory_model"
5039 )";
5040   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
5041                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
5042                           .c_str());
5043   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5044 }
5045 
TEST_F(ValidateImage,SparseSampleImplicitLodResultTypeNotStruct)5046 TEST_F(ValidateImage, SparseSampleImplicitLodResultTypeNotStruct) {
5047   const std::string body = R"(
5048 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5049 %sampler = OpLoad %type_sampler %uniform_sampler
5050 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5051 %res1 = OpImageSparseSampleImplicitLod %f32 %simg %f32vec2_hh
5052 )";
5053 
5054   CompileSuccessfully(GenerateShaderCode(body).c_str());
5055   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5056   EXPECT_THAT(getDiagnosticString(),
5057               HasSubstr("Expected Result Type to be OpTypeStruct"));
5058 }
5059 
TEST_F(ValidateImage,SparseSampleImplicitLodResultTypeNotTwoMembers1)5060 TEST_F(ValidateImage, SparseSampleImplicitLodResultTypeNotTwoMembers1) {
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 %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 int "
5072                         "scalar and a texel"));
5073 }
5074 
TEST_F(ValidateImage,SparseSampleImplicitLodResultTypeNotTwoMembers2)5075 TEST_F(ValidateImage, SparseSampleImplicitLodResultTypeNotTwoMembers2) {
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_u32_f32vec4_u32 %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,SparseSampleImplicitLodResultTypeFirstMemberNotInt)5090 TEST_F(ValidateImage, SparseSampleImplicitLodResultTypeFirstMemberNotInt) {
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_f32_f32vec4 %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 to be a struct containing an "
5102                         "int scalar and a texel"));
5103 }
5104 
TEST_F(ValidateImage,SparseSampleImplicitLodResultTypeTexelNotVector)5105 TEST_F(ValidateImage, SparseSampleImplicitLodResultTypeTexelNotVector) {
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_u32 %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 be int or "
5117                         "float vector type"));
5118 }
5119 
TEST_F(ValidateImage,SparseSampleImplicitLodWrongNumComponentsTexel)5120 TEST_F(ValidateImage, SparseSampleImplicitLodWrongNumComponentsTexel) {
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_f32vec3 %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 Result Type's second member to have 4 "
5132                         "components"));
5133 }
5134 
TEST_F(ValidateImage,SparseSampleImplicitLodWrongComponentTypeTexel)5135 TEST_F(ValidateImage, SparseSampleImplicitLodWrongComponentTypeTexel) {
5136   const std::string body = R"(
5137 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5138 %sampler = OpLoad %type_sampler %uniform_sampler
5139 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5140 %res1 = OpImageSparseSampleImplicitLod %struct_u32_u32vec4 %simg %f32vec2_hh
5141 )";
5142 
5143   CompileSuccessfully(GenerateShaderCode(body).c_str());
5144   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5145   EXPECT_THAT(getDiagnosticString(),
5146               HasSubstr("Expected Image 'Sampled Type' to be the same as "
5147                         "Result Type's second member components"));
5148 }
5149 
TEST_F(ValidateImage,SparseSampleDrefImplicitLodSuccess)5150 TEST_F(ValidateImage, SparseSampleDrefImplicitLodSuccess) {
5151   const std::string body = R"(
5152 %img = OpLoad %type_image_u32_2d_0001 %uniform_image_u32_2d_0001
5153 %sampler = OpLoad %type_sampler %uniform_sampler
5154 %simg = OpSampledImage %type_sampled_image_u32_2d_0001 %img %sampler
5155 %res1 = OpImageSparseSampleDrefImplicitLod %struct_u32_u32 %simg %f32vec2_hh %f32_1
5156 %res2 = OpImageSparseSampleDrefImplicitLod %struct_u32_u32 %simg %f32vec2_hh %f32_1 Bias %f32_0_25
5157 %res4 = OpImageSparseSampleDrefImplicitLod %struct_u32_u32 %simg %f32vec2_hh %f32_1 ConstOffset %s32vec2_01
5158 %res5 = OpImageSparseSampleDrefImplicitLod %struct_u32_u32 %simg %f32vec2_hh %f32_1 Offset %s32vec2_01
5159 %res6 = OpImageSparseSampleDrefImplicitLod %struct_u32_u32 %simg %f32vec2_hh %f32_1 MinLod %f32_0_5
5160 %res7 = OpImageSparseSampleDrefImplicitLod %struct_u32_u32 %simg %f32vec2_hh %f32_1 Bias|Offset|MinLod %f32_0_25 %s32vec2_01 %f32_0_5
5161 %res8 = OpImageSparseSampleDrefImplicitLod %struct_u32_u32 %simg %f32vec2_hh %f32_1 NonPrivateTexelKHR
5162 )";
5163 
5164   const std::string extra = R"(
5165 OpCapability VulkanMemoryModelKHR
5166 OpExtension "SPV_KHR_vulkan_memory_model"
5167 )";
5168   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
5169                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
5170                           .c_str());
5171   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5172 }
5173 
TEST_F(ValidateImage,SparseSampleDrefImplicitLodResultTypeNotStruct)5174 TEST_F(ValidateImage, SparseSampleDrefImplicitLodResultTypeNotStruct) {
5175   const std::string body = R"(
5176 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5177 %sampler = OpLoad %type_sampler %uniform_sampler
5178 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5179 %res1 = OpImageSparseSampleDrefImplicitLod %f32 %simg %f32vec2_hh %f32_1
5180 )";
5181 
5182   CompileSuccessfully(GenerateShaderCode(body).c_str());
5183   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5184   EXPECT_THAT(getDiagnosticString(),
5185               HasSubstr("Expected Result Type to be OpTypeStruct"));
5186 }
5187 
TEST_F(ValidateImage,SparseSampleDrefImplicitLodResultTypeNotTwoMembers1)5188 TEST_F(ValidateImage, SparseSampleDrefImplicitLodResultTypeNotTwoMembers1) {
5189   const std::string body = R"(
5190 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5191 %sampler = OpLoad %type_sampler %uniform_sampler
5192 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5193 %res1 = OpImageSparseSampleDrefImplicitLod %struct_u32 %simg %f32vec2_hh %f32_1
5194 )";
5195 
5196   CompileSuccessfully(GenerateShaderCode(body).c_str());
5197   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5198   EXPECT_THAT(
5199       getDiagnosticString(),
5200       HasSubstr("Expected Result Type to be a struct containing an int scalar "
5201                 "and a texel"));
5202 }
5203 
TEST_F(ValidateImage,SparseSampleDrefImplicitLodResultTypeNotTwoMembers2)5204 TEST_F(ValidateImage, SparseSampleDrefImplicitLodResultTypeNotTwoMembers2) {
5205   const std::string body = R"(
5206 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5207 %sampler = OpLoad %type_sampler %uniform_sampler
5208 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5209 %res1 = OpImageSparseSampleDrefImplicitLod %struct_u32_f32_u32 %simg %f32vec2_hh %f32_1
5210 )";
5211 
5212   CompileSuccessfully(GenerateShaderCode(body).c_str());
5213   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5214   EXPECT_THAT(
5215       getDiagnosticString(),
5216       HasSubstr("Expected Result Type to be a struct containing an int scalar "
5217                 "and a texel"));
5218 }
5219 
TEST_F(ValidateImage,SparseSampleDrefImplicitLodResultTypeFirstMemberNotInt)5220 TEST_F(ValidateImage, SparseSampleDrefImplicitLodResultTypeFirstMemberNotInt) {
5221   const std::string body = R"(
5222 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5223 %sampler = OpLoad %type_sampler %uniform_sampler
5224 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5225 %res1 = OpImageSparseSampleDrefImplicitLod %struct_f32_f32 %simg %f32vec2_hh %f32_1
5226 )";
5227 
5228   CompileSuccessfully(GenerateShaderCode(body).c_str());
5229   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5230   EXPECT_THAT(
5231       getDiagnosticString(),
5232       HasSubstr("Expected Result Type to be a struct containing an int scalar "
5233                 "and a texel"));
5234 }
5235 
TEST_F(ValidateImage,SparseSampleDrefImplicitLodDifferentSampledType)5236 TEST_F(ValidateImage, SparseSampleDrefImplicitLodDifferentSampledType) {
5237   const std::string body = R"(
5238 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5239 %sampler = OpLoad %type_sampler %uniform_sampler
5240 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5241 %res1 = OpImageSparseSampleDrefImplicitLod %struct_u32_u32 %simg %f32vec2_hh %f32_1
5242 )";
5243 
5244   CompileSuccessfully(GenerateShaderCode(body).c_str());
5245   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5246   EXPECT_THAT(getDiagnosticString(),
5247               HasSubstr("Expected Image 'Sampled Type' to be the same as "
5248                         "Result Type's second member"));
5249 }
5250 
TEST_F(ValidateImage,SparseFetchSuccess)5251 TEST_F(ValidateImage, SparseFetchSuccess) {
5252   const std::string body = R"(
5253 %img = OpLoad %type_image_f32_1d_0001 %uniform_image_f32_1d_0001
5254 %res1 = OpImageSparseFetch %struct_u32_f32vec4 %img %u32vec2_01
5255 %res2 = OpImageSparseFetch %struct_u32_f32vec4 %img %u32vec2_01 NonPrivateTexelKHR
5256 )";
5257 
5258   const std::string extra = R"(
5259 OpCapability VulkanMemoryModelKHR
5260 OpExtension "SPV_KHR_vulkan_memory_model"
5261 )";
5262   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
5263                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
5264                           .c_str());
5265   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5266 }
5267 
TEST_F(ValidateImage,SparseFetchResultTypeNotStruct)5268 TEST_F(ValidateImage, SparseFetchResultTypeNotStruct) {
5269   const std::string body = R"(
5270 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
5271 %res1 = OpImageSparseFetch %f32 %img %u32vec2_01
5272 )";
5273 
5274   CompileSuccessfully(GenerateShaderCode(body).c_str());
5275   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5276   EXPECT_THAT(getDiagnosticString(),
5277               HasSubstr("Expected Result Type to be OpTypeStruct"));
5278 }
5279 
TEST_F(ValidateImage,SparseFetchResultTypeNotTwoMembers1)5280 TEST_F(ValidateImage, SparseFetchResultTypeNotTwoMembers1) {
5281   const std::string body = R"(
5282 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
5283 %res1 = OpImageSparseFetch %struct_u32 %img %u32vec2_01
5284 )";
5285 
5286   CompileSuccessfully(GenerateShaderCode(body).c_str());
5287   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5288   EXPECT_THAT(getDiagnosticString(),
5289               HasSubstr("Expected Result Type to be a struct containing an "
5290                         "int scalar and a texel"));
5291 }
5292 
TEST_F(ValidateImage,SparseFetchResultTypeNotTwoMembers2)5293 TEST_F(ValidateImage, SparseFetchResultTypeNotTwoMembers2) {
5294   const std::string body = R"(
5295 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
5296 %res1 = OpImageSparseFetch %struct_u32_f32vec4_u32 %img %u32vec2_01
5297 )";
5298 
5299   CompileSuccessfully(GenerateShaderCode(body).c_str());
5300   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5301   EXPECT_THAT(getDiagnosticString(),
5302               HasSubstr("Expected Result Type to be a struct containing an "
5303                         "int scalar and a texel"));
5304 }
5305 
TEST_F(ValidateImage,SparseFetchResultTypeFirstMemberNotInt)5306 TEST_F(ValidateImage, SparseFetchResultTypeFirstMemberNotInt) {
5307   const std::string body = R"(
5308 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
5309 %res1 = OpImageSparseFetch %struct_f32_f32vec4 %img %u32vec2_01
5310 )";
5311 
5312   CompileSuccessfully(GenerateShaderCode(body).c_str());
5313   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5314   EXPECT_THAT(getDiagnosticString(),
5315               HasSubstr("Expected Result Type to be a struct containing an "
5316                         "int scalar and a texel"));
5317 }
5318 
TEST_F(ValidateImage,SparseFetchResultTypeTexelNotVector)5319 TEST_F(ValidateImage, SparseFetchResultTypeTexelNotVector) {
5320   const std::string body = R"(
5321 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
5322 %res1 = OpImageSparseFetch %struct_u32_u32 %img %u32vec2_01
5323 )";
5324 
5325   CompileSuccessfully(GenerateShaderCode(body).c_str());
5326   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5327   EXPECT_THAT(getDiagnosticString(),
5328               HasSubstr("Expected Result Type's second member to be int or "
5329                         "float vector type"));
5330 }
5331 
TEST_F(ValidateImage,SparseFetchWrongNumComponentsTexel)5332 TEST_F(ValidateImage, SparseFetchWrongNumComponentsTexel) {
5333   const std::string body = R"(
5334 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
5335 %res1 = OpImageSparseFetch %struct_u32_f32vec3 %img %u32vec2_01
5336 )";
5337 
5338   CompileSuccessfully(GenerateShaderCode(body).c_str());
5339   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5340   EXPECT_THAT(getDiagnosticString(),
5341               HasSubstr("Expected Result Type's second member to have 4 "
5342                         "components"));
5343 }
5344 
TEST_F(ValidateImage,SparseFetchWrongComponentTypeTexel)5345 TEST_F(ValidateImage, SparseFetchWrongComponentTypeTexel) {
5346   const std::string body = R"(
5347 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
5348 %res1 = OpImageSparseFetch %struct_u32_u32vec4 %img %u32vec2_01
5349 )";
5350 
5351   CompileSuccessfully(GenerateShaderCode(body).c_str());
5352   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5353   EXPECT_THAT(getDiagnosticString(),
5354               HasSubstr("Expected Image 'Sampled Type' to be the same as "
5355                         "Result Type's second member components"));
5356 }
5357 
TEST_F(ValidateImage,SparseReadSuccess)5358 TEST_F(ValidateImage, SparseReadSuccess) {
5359   const std::string body = R"(
5360 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
5361 %res1 = OpImageSparseRead %struct_u32_f32vec4 %img %u32vec2_01
5362 )";
5363 
5364   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
5365   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
5366   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
5367 }
5368 
TEST_F(ValidateImage,SparseReadResultTypeNotStruct)5369 TEST_F(ValidateImage, SparseReadResultTypeNotStruct) {
5370   const std::string body = R"(
5371 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
5372 %res1 = OpImageSparseRead %f32 %img %u32vec2_01
5373 )";
5374 
5375   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
5376   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
5377   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5378   EXPECT_THAT(getDiagnosticString(),
5379               HasSubstr("Expected Result Type to be OpTypeStruct"));
5380 }
5381 
TEST_F(ValidateImage,SparseReadResultTypeNotTwoMembers1)5382 TEST_F(ValidateImage, SparseReadResultTypeNotTwoMembers1) {
5383   const std::string body = R"(
5384 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
5385 %res1 = OpImageSparseRead %struct_u32 %img %u32vec2_01
5386 )";
5387 
5388   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
5389   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
5390   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5391   EXPECT_THAT(getDiagnosticString(),
5392               HasSubstr("Expected Result Type to be a struct containing an "
5393                         "int scalar and a texel"));
5394 }
5395 
TEST_F(ValidateImage,SparseReadResultTypeNotTwoMembers2)5396 TEST_F(ValidateImage, SparseReadResultTypeNotTwoMembers2) {
5397   const std::string body = R"(
5398 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
5399 %res1 = OpImageSparseRead %struct_u32_f32vec4_u32 %img %u32vec2_01
5400 )";
5401 
5402   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
5403   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
5404   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5405   EXPECT_THAT(getDiagnosticString(),
5406               HasSubstr("Expected Result Type to be a struct containing an "
5407                         "int scalar and a texel"));
5408 }
5409 
TEST_F(ValidateImage,SparseReadResultTypeFirstMemberNotInt)5410 TEST_F(ValidateImage, SparseReadResultTypeFirstMemberNotInt) {
5411   const std::string body = R"(
5412 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
5413 %res1 = OpImageSparseRead %struct_f32_f32vec4 %img %u32vec2_01
5414 )";
5415 
5416   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
5417   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
5418   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5419   EXPECT_THAT(getDiagnosticString(),
5420               HasSubstr("Expected Result Type to be a struct containing an "
5421                         "int scalar and a texel"));
5422 }
5423 
TEST_F(ValidateImage,SparseReadResultTypeTexelWrongType)5424 TEST_F(ValidateImage, SparseReadResultTypeTexelWrongType) {
5425   const std::string body = R"(
5426 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
5427 %res1 = OpImageSparseRead %struct_u32_u32arr4 %img %u32vec2_01
5428 )";
5429 
5430   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
5431   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
5432   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5433   EXPECT_THAT(getDiagnosticString(),
5434               HasSubstr("Expected Result Type's second member to be int or "
5435                         "float scalar or vector type"));
5436 }
5437 
TEST_F(ValidateImage,SparseReadWrongComponentTypeTexel)5438 TEST_F(ValidateImage, SparseReadWrongComponentTypeTexel) {
5439   const std::string body = R"(
5440 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
5441 %res1 = OpImageSparseRead %struct_u32_u32vec4 %img %u32vec2_01
5442 )";
5443 
5444   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
5445   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
5446   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5447   EXPECT_THAT(getDiagnosticString(),
5448               HasSubstr("Expected Image 'Sampled Type' to be the same as "
5449                         "Result Type's second member components"));
5450 }
5451 
TEST_F(ValidateImage,SparseReadSubpassDataNotAllowed)5452 TEST_F(ValidateImage, SparseReadSubpassDataNotAllowed) {
5453   const std::string body = R"(
5454 %img = OpLoad %type_image_f32_spd_0002 %uniform_image_f32_spd_0002
5455 %res1 = OpImageSparseRead %struct_u32_f32vec4 %img %u32vec2_01
5456 )";
5457 
5458   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
5459   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment").c_str());
5460   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5461   EXPECT_THAT(
5462       getDiagnosticString(),
5463       HasSubstr("Image Dim SubpassData cannot be used with ImageSparseRead"));
5464 }
5465 
TEST_F(ValidateImage,SparseGatherSuccess)5466 TEST_F(ValidateImage, SparseGatherSuccess) {
5467   const std::string body = R"(
5468 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5469 %sampler = OpLoad %type_sampler %uniform_sampler
5470 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5471 %res1 = OpImageSparseGather %struct_u32_f32vec4 %simg %f32vec4_0000 %u32_1
5472 %res2 = OpImageSparseGather %struct_u32_f32vec4 %simg %f32vec4_0000 %u32_1 NonPrivateTexelKHR
5473 )";
5474 
5475   const std::string extra = R"(
5476 OpCapability VulkanMemoryModelKHR
5477 OpExtension "SPV_KHR_vulkan_memory_model"
5478 )";
5479   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
5480                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
5481                           .c_str());
5482   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5483 }
5484 
TEST_F(ValidateImage,SparseGatherResultTypeNotStruct)5485 TEST_F(ValidateImage, SparseGatherResultTypeNotStruct) {
5486   const std::string body = R"(
5487 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5488 %sampler = OpLoad %type_sampler %uniform_sampler
5489 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5490 %res1 = OpImageSparseGather %f32 %simg %f32vec2_hh %u32_1
5491 )";
5492 
5493   CompileSuccessfully(GenerateShaderCode(body).c_str());
5494   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5495   EXPECT_THAT(getDiagnosticString(),
5496               HasSubstr("Expected Result Type to be OpTypeStruct"));
5497 }
5498 
TEST_F(ValidateImage,SparseGatherResultTypeNotTwoMembers1)5499 TEST_F(ValidateImage, SparseGatherResultTypeNotTwoMembers1) {
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 %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,SparseGatherResultTypeNotTwoMembers2)5514 TEST_F(ValidateImage, SparseGatherResultTypeNotTwoMembers2) {
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_u32_f32vec4_u32 %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 int "
5526                         "scalar and a texel"));
5527 }
5528 
TEST_F(ValidateImage,SparseGatherResultTypeFirstMemberNotInt)5529 TEST_F(ValidateImage, SparseGatherResultTypeFirstMemberNotInt) {
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_f32_f32vec4 %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 to be a struct containing an "
5541                         "int scalar and a texel"));
5542 }
5543 
TEST_F(ValidateImage,SparseGatherResultTypeTexelNotVector)5544 TEST_F(ValidateImage, SparseGatherResultTypeTexelNotVector) {
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_u32 %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 be int or "
5556                         "float vector type"));
5557 }
5558 
TEST_F(ValidateImage,SparseGatherWrongNumComponentsTexel)5559 TEST_F(ValidateImage, SparseGatherWrongNumComponentsTexel) {
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_f32vec3 %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 Result Type's second member to have 4 "
5571                         "components"));
5572 }
5573 
TEST_F(ValidateImage,SparseGatherWrongComponentTypeTexel)5574 TEST_F(ValidateImage, SparseGatherWrongComponentTypeTexel) {
5575   const std::string body = R"(
5576 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5577 %sampler = OpLoad %type_sampler %uniform_sampler
5578 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5579 %res1 = OpImageSparseGather %struct_u32_u32vec4 %simg %f32vec2_hh %u32_1
5580 )";
5581 
5582   CompileSuccessfully(GenerateShaderCode(body).c_str());
5583   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5584   EXPECT_THAT(getDiagnosticString(),
5585               HasSubstr("Expected Image 'Sampled Type' to be the same as "
5586                         "Result Type's second member components"));
5587 }
5588 
TEST_F(ValidateImage,SparseTexelsResidentSuccess)5589 TEST_F(ValidateImage, SparseTexelsResidentSuccess) {
5590   const std::string body = R"(
5591 %res1 = OpImageSparseTexelsResident %bool %u32_1
5592 )";
5593 
5594   CompileSuccessfully(GenerateShaderCode(body).c_str());
5595   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
5596 }
5597 
TEST_F(ValidateImage,SparseTexelsResidentResultTypeNotBool)5598 TEST_F(ValidateImage, SparseTexelsResidentResultTypeNotBool) {
5599   const std::string body = R"(
5600 %res1 = OpImageSparseTexelsResident %u32 %u32_1
5601 )";
5602 
5603   CompileSuccessfully(GenerateShaderCode(body).c_str());
5604   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
5605   EXPECT_THAT(getDiagnosticString(),
5606               HasSubstr("Expected Result Type to be bool scalar type"));
5607 }
5608 
TEST_F(ValidateImage,MakeTexelVisibleKHRSuccessImageRead)5609 TEST_F(ValidateImage, MakeTexelVisibleKHRSuccessImageRead) {
5610   const std::string body = R"(
5611 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
5612 %res1 = OpImageRead %u32vec4 %img %u32vec2_01 MakeTexelVisibleKHR|NonPrivateTexelKHR %u32_2
5613 )";
5614 
5615   const std::string extra = R"(
5616 OpCapability StorageImageReadWithoutFormat
5617 OpCapability VulkanMemoryModelKHR
5618 OpExtension "SPV_KHR_vulkan_memory_model"
5619 )";
5620   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
5621                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
5622                           .c_str());
5623   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5624 }
5625 
TEST_F(ValidateImage,MakeTexelVisibleKHRSuccessImageSparseRead)5626 TEST_F(ValidateImage, MakeTexelVisibleKHRSuccessImageSparseRead) {
5627   const std::string body = R"(
5628 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
5629 %res1 = OpImageSparseRead %struct_u32_f32vec4 %img %u32vec2_01 MakeTexelVisibleKHR|NonPrivateTexelKHR %u32_2
5630 )";
5631 
5632   const std::string extra = R"(
5633 OpCapability StorageImageReadWithoutFormat
5634 OpCapability VulkanMemoryModelKHR
5635 OpExtension "SPV_KHR_vulkan_memory_model"
5636 )";
5637   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
5638                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
5639                           .c_str());
5640   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5641 }
5642 
TEST_F(ValidateImage,MakeTexelVisibleKHRFailureOpcode)5643 TEST_F(ValidateImage, MakeTexelVisibleKHRFailureOpcode) {
5644   const std::string body = R"(
5645 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5646 %sampler = OpLoad %type_sampler %uniform_sampler
5647 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5648 %res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh MakeTexelVisibleKHR|NonPrivateTexelKHR %u32_1
5649 )";
5650 
5651   const std::string extra = R"(
5652 OpCapability StorageImageReadWithoutFormat
5653 OpCapability VulkanMemoryModelKHR
5654 OpExtension "SPV_KHR_vulkan_memory_model"
5655 )";
5656   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
5657                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
5658                           .c_str());
5659   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
5660             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5661   EXPECT_THAT(
5662       getDiagnosticString(),
5663       HasSubstr("Image Operand MakeTexelVisibleKHR can only be used with "
5664                 "OpImageRead or OpImageSparseRead: OpImageSampleImplicitLod"));
5665 }
5666 
TEST_F(ValidateImage,MakeTexelVisibleKHRFailureMissingNonPrivate)5667 TEST_F(ValidateImage, MakeTexelVisibleKHRFailureMissingNonPrivate) {
5668   const std::string body = R"(
5669 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
5670 %res1 = OpImageRead %u32vec4 %img %u32vec2_01 MakeTexelVisibleKHR %u32_1
5671 )";
5672 
5673   const std::string extra = R"(
5674 OpCapability StorageImageReadWithoutFormat
5675 OpCapability VulkanMemoryModelKHR
5676 OpExtension "SPV_KHR_vulkan_memory_model"
5677 )";
5678   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
5679                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
5680                           .c_str());
5681   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
5682             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5683   EXPECT_THAT(getDiagnosticString(),
5684               HasSubstr("Image Operand MakeTexelVisibleKHR requires "
5685                         "NonPrivateTexelKHR is also specified: OpImageRead"));
5686 }
5687 
TEST_F(ValidateImage,MakeTexelAvailableKHRSuccessImageWrite)5688 TEST_F(ValidateImage, MakeTexelAvailableKHRSuccessImageWrite) {
5689   const std::string body = R"(
5690 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
5691 OpImageWrite %img %u32vec2_01 %u32vec4_0123 MakeTexelAvailableKHR|NonPrivateTexelKHR %u32_2
5692 )";
5693 
5694   const std::string extra = R"(
5695 OpCapability StorageImageWriteWithoutFormat
5696 OpCapability VulkanMemoryModelKHR
5697 OpExtension "SPV_KHR_vulkan_memory_model"
5698 )";
5699   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
5700                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
5701                           .c_str());
5702   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5703 }
5704 
TEST_F(ValidateImage,MakeTexelAvailableKHRFailureOpcode)5705 TEST_F(ValidateImage, MakeTexelAvailableKHRFailureOpcode) {
5706   const std::string body = R"(
5707 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
5708 %sampler = OpLoad %type_sampler %uniform_sampler
5709 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
5710 %res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh MakeTexelAvailableKHR|NonPrivateTexelKHR %u32_1
5711 )";
5712 
5713   const std::string extra = R"(
5714 OpCapability StorageImageReadWithoutFormat
5715 OpCapability VulkanMemoryModelKHR
5716 OpExtension "SPV_KHR_vulkan_memory_model"
5717 )";
5718   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
5719                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
5720                           .c_str());
5721   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
5722             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5723   EXPECT_THAT(getDiagnosticString(),
5724               HasSubstr("Image Operand MakeTexelAvailableKHR can only be used "
5725                         "with OpImageWrite: OpImageSampleImplicitLod"));
5726 }
5727 
TEST_F(ValidateImage,MakeTexelAvailableKHRFailureMissingNonPrivate)5728 TEST_F(ValidateImage, MakeTexelAvailableKHRFailureMissingNonPrivate) {
5729   const std::string body = R"(
5730 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
5731 OpImageWrite %img %u32vec2_01 %u32vec4_0123 MakeTexelAvailableKHR %u32_1
5732 )";
5733 
5734   const std::string extra = R"(
5735 OpCapability StorageImageWriteWithoutFormat
5736 OpCapability VulkanMemoryModelKHR
5737 OpExtension "SPV_KHR_vulkan_memory_model"
5738 )";
5739   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
5740                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
5741                           .c_str());
5742   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
5743             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5744   EXPECT_THAT(getDiagnosticString(),
5745               HasSubstr("Image Operand MakeTexelAvailableKHR requires "
5746                         "NonPrivateTexelKHR is also specified: OpImageWrite"));
5747 }
5748 
TEST_F(ValidateImage,VulkanMemoryModelDeviceScopeImageWriteBad)5749 TEST_F(ValidateImage, VulkanMemoryModelDeviceScopeImageWriteBad) {
5750   const std::string body = R"(
5751 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
5752 OpImageWrite %img %u32vec2_01 %u32vec4_0123 MakeTexelAvailableKHR|NonPrivateTexelKHR %u32_1
5753 )";
5754 
5755   const std::string extra = R"(
5756 OpCapability StorageImageWriteWithoutFormat
5757 OpCapability VulkanMemoryModelKHR
5758 OpExtension "SPV_KHR_vulkan_memory_model"
5759 )";
5760   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
5761                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
5762                           .c_str());
5763   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
5764             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5765   EXPECT_THAT(
5766       getDiagnosticString(),
5767       HasSubstr("Use of device scope with VulkanKHR memory model requires the "
5768                 "VulkanMemoryModelDeviceScopeKHR capability"));
5769 }
5770 
TEST_F(ValidateImage,VulkanMemoryModelDeviceScopeImageWriteGood)5771 TEST_F(ValidateImage, VulkanMemoryModelDeviceScopeImageWriteGood) {
5772   const std::string body = R"(
5773 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
5774 OpImageWrite %img %u32vec2_01 %u32vec4_0123 MakeTexelAvailableKHR|NonPrivateTexelKHR %u32_1
5775 )";
5776 
5777   const std::string extra = R"(
5778 OpCapability StorageImageWriteWithoutFormat
5779 OpCapability VulkanMemoryModelKHR
5780 OpCapability VulkanMemoryModelDeviceScopeKHR
5781 OpExtension "SPV_KHR_vulkan_memory_model"
5782 )";
5783   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
5784                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
5785                           .c_str());
5786   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5787 }
5788 
TEST_F(ValidateImage,VulkanMemoryModelDeviceScopeImageReadBad)5789 TEST_F(ValidateImage, VulkanMemoryModelDeviceScopeImageReadBad) {
5790   const std::string body = R"(
5791 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
5792 %res1 = OpImageRead %u32vec4 %img %u32vec2_01 MakeTexelVisibleKHR|NonPrivateTexelKHR %u32_1
5793 )";
5794 
5795   const std::string extra = R"(
5796 OpCapability StorageImageReadWithoutFormat
5797 OpCapability VulkanMemoryModelKHR
5798 OpExtension "SPV_KHR_vulkan_memory_model"
5799 )";
5800   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
5801                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
5802                           .c_str());
5803   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
5804             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5805   EXPECT_THAT(
5806       getDiagnosticString(),
5807       HasSubstr("Use of device scope with VulkanKHR memory model requires the "
5808                 "VulkanMemoryModelDeviceScopeKHR capability"));
5809 }
5810 
TEST_F(ValidateImage,VulkanMemoryModelDeviceScopeImageReadGood)5811 TEST_F(ValidateImage, VulkanMemoryModelDeviceScopeImageReadGood) {
5812   const std::string body = R"(
5813 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
5814 %res1 = OpImageRead %u32vec4 %img %u32vec2_01 MakeTexelVisibleKHR|NonPrivateTexelKHR %u32_1
5815 )";
5816 
5817   const std::string extra = R"(
5818 OpCapability StorageImageReadWithoutFormat
5819 OpCapability VulkanMemoryModelKHR
5820 OpCapability VulkanMemoryModelDeviceScopeKHR
5821 OpExtension "SPV_KHR_vulkan_memory_model"
5822 )";
5823   CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
5824                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
5825                           .c_str());
5826   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5827 }
5828 
5829 // This example used to cause a seg fault on OpReturnValue, verifying it doesn't
5830 // anymore.
TEST_F(ValidateImage,Issue2463NoSegFault)5831 TEST_F(ValidateImage, Issue2463NoSegFault) {
5832   const std::string spirv = R"(
5833                OpCapability Linkage
5834                OpCapability Shader
5835           %1 = OpExtInstImport "GLSL.std.450"
5836                OpMemoryModel Logical GLSL450
5837        %void = OpTypeVoid
5838           %6 = OpTypeFunction %void
5839       %float = OpTypeFloat 32
5840           %8 = OpTypeImage %float 3D 0 0 0 1 Unknown
5841 %_ptr_UniformConstant_8 = OpTypePointer UniformConstant %8
5842          %10 = OpTypeSampler
5843 %_ptr_UniformConstant_10 = OpTypePointer UniformConstant %10
5844          %12 = OpTypeSampledImage %8
5845          %13 = OpTypeFunction %12 %_ptr_UniformConstant_8 %_ptr_UniformConstant_10
5846          %23 = OpFunction %12 None %13
5847          %24 = OpFunctionParameter %_ptr_UniformConstant_8
5848          %25 = OpFunctionParameter %_ptr_UniformConstant_10
5849          %26 = OpLabel
5850          %27 = OpLoad %8 %24
5851          %28 = OpLoad %10 %25
5852          %29 = OpSampledImage %12 %27 %28
5853                OpReturnValue %29
5854                OpFunctionEnd
5855 )";
5856 
5857   CompileSuccessfully(spirv);
5858   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5859   EXPECT_THAT(getDiagnosticString(),
5860               HasSubstr("OpSampledImage instruction must not appear as operand "
5861                         "for OpReturnValue"));
5862 }
5863 
TEST_F(ValidateImage,SignExtendV13Bad)5864 TEST_F(ValidateImage, SignExtendV13Bad) {
5865   const std::string body = R"(
5866 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
5867 %res1 = OpImageRead %u32vec4 %img %u32vec2_01 SignExtend
5868 )";
5869 
5870   CompileSuccessfully(
5871       GenerateShaderCode(body, "", "Fragment", "", SPV_ENV_UNIVERSAL_1_3));
5872   ASSERT_EQ(SPV_ERROR_WRONG_VERSION, ValidateInstructions());
5873   EXPECT_THAT(
5874       getDiagnosticString(),
5875       HasSubstr("SignExtend(4096) requires SPIR-V version 1.4 or later"));
5876 }
5877 
TEST_F(ValidateImage,ZeroExtendV13Bad)5878 TEST_F(ValidateImage, ZeroExtendV13Bad) {
5879   const std::string body = R"(
5880 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
5881 %res1 = OpImageRead %u32vec4 %img %u32vec2_01 ZeroExtend
5882 )";
5883 
5884   CompileSuccessfully(
5885       GenerateShaderCode(body, "", "Fragment", "", SPV_ENV_UNIVERSAL_1_3));
5886   ASSERT_EQ(SPV_ERROR_WRONG_VERSION, ValidateInstructions());
5887   EXPECT_THAT(
5888       getDiagnosticString(),
5889       HasSubstr("ZeroExtend(8192) requires SPIR-V version 1.4 or later"));
5890 }
5891 
TEST_F(ValidateImage,SignExtendScalarUIntTexelV14Good)5892 TEST_F(ValidateImage, SignExtendScalarUIntTexelV14Good) {
5893   // Unsigned int sampled type
5894   const std::string body = R"(
5895 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
5896 %res1 = OpImageRead %u32 %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,SignExtendScalarSIntTexelV14Good)5907 TEST_F(ValidateImage, SignExtendScalarSIntTexelV14Good) {
5908   // Signed int sampled type
5909   const std::string body = R"(
5910 %img = OpLoad %type_image_s32_2d_0002 %uniform_image_s32_2d_0002
5911 %res1 = OpImageRead %s32 %img %u32vec2_01 SignExtend
5912 )";
5913   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
5914 
5915   CompileSuccessfully(
5916       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4),
5917       SPV_ENV_UNIVERSAL_1_4);
5918   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
5919   EXPECT_THAT(getDiagnosticString(), Eq(""));
5920 }
5921 
TEST_F(ValidateImage,SignExtendScalarVectorUIntTexelV14Good)5922 TEST_F(ValidateImage, SignExtendScalarVectorUIntTexelV14Good) {
5923   const std::string body = R"(
5924 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
5925 %res1 = OpImageRead %u32vec4 %img %u32vec2_01 SignExtend
5926 )";
5927   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
5928 
5929   CompileSuccessfully(
5930       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4),
5931       SPV_ENV_UNIVERSAL_1_4);
5932   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
5933   EXPECT_THAT(getDiagnosticString(), Eq(""));
5934 }
5935 
TEST_F(ValidateImage,SignExtendVectorSIntTexelV14Good)5936 TEST_F(ValidateImage, SignExtendVectorSIntTexelV14Good) {
5937   const std::string body = R"(
5938 %img = OpLoad %type_image_s32_2d_0002 %uniform_image_s32_2d_0002
5939 %res1 = OpImageRead %s32vec4 %img %u32vec2_01 SignExtend
5940 )";
5941   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
5942 
5943   CompileSuccessfully(
5944       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4),
5945       SPV_ENV_UNIVERSAL_1_4);
5946   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
5947   EXPECT_THAT(getDiagnosticString(), Eq(""));
5948 }
5949 
5950 // No negative tests for SignExtend since we don't truly know the
5951 // texel format.
5952 
TEST_F(ValidateImage,ZeroExtendScalarUIntTexelV14Good)5953 TEST_F(ValidateImage, ZeroExtendScalarUIntTexelV14Good) {
5954   // Unsigned int sampled type
5955   const std::string body = R"(
5956 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
5957 %res1 = OpImageRead %u32 %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,ZeroExtendScalarSIntTexelV14Good)5968 TEST_F(ValidateImage, ZeroExtendScalarSIntTexelV14Good) {
5969   // Zeroed int sampled type
5970   const std::string body = R"(
5971 %img = OpLoad %type_image_s32_2d_0002 %uniform_image_s32_2d_0002
5972 %res1 = OpImageRead %s32 %img %u32vec2_01 ZeroExtend
5973 )";
5974   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
5975 
5976   CompileSuccessfully(
5977       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4),
5978       SPV_ENV_UNIVERSAL_1_4);
5979   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
5980   EXPECT_THAT(getDiagnosticString(), Eq(""));
5981 }
5982 
TEST_F(ValidateImage,ZeroExtendScalarVectorUIntTexelV14Good)5983 TEST_F(ValidateImage, ZeroExtendScalarVectorUIntTexelV14Good) {
5984   const std::string body = R"(
5985 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
5986 %res1 = OpImageRead %u32vec4 %img %u32vec2_01 ZeroExtend
5987 )";
5988   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
5989 
5990   CompileSuccessfully(
5991       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4),
5992       SPV_ENV_UNIVERSAL_1_4);
5993   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
5994   EXPECT_THAT(getDiagnosticString(), Eq(""));
5995 }
5996 
TEST_F(ValidateImage,ZeroExtendVectorSIntTexelV14Good)5997 TEST_F(ValidateImage, ZeroExtendVectorSIntTexelV14Good) {
5998   const std::string body = R"(
5999 %img = OpLoad %type_image_s32_2d_0002 %uniform_image_s32_2d_0002
6000 %res1 = OpImageRead %s32vec4 %img %u32vec2_01 ZeroExtend
6001 )";
6002   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
6003 
6004   CompileSuccessfully(
6005       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4),
6006       SPV_ENV_UNIVERSAL_1_4);
6007   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
6008   EXPECT_THAT(getDiagnosticString(), Eq(""));
6009 }
6010 
TEST_F(ValidateImage,ReadLodAMDSuccess1)6011 TEST_F(ValidateImage, ReadLodAMDSuccess1) {
6012   const std::string body = R"(
6013 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
6014 %res1 = OpImageRead %u32vec4 %img %u32vec2_01 Lod %u32_0
6015 )";
6016 
6017   const std::string extra =
6018       "\nOpCapability StorageImageReadWithoutFormat\n"
6019       "OpCapability ImageReadWriteLodAMD\n"
6020       "OpExtension \"SPV_AMD_shader_image_load_store_lod\"\n";
6021   CompileSuccessfully(
6022       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_1),
6023       SPV_ENV_UNIVERSAL_1_1);
6024   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
6025 }
6026 
TEST_F(ValidateImage,ReadLodAMDSuccess2)6027 TEST_F(ValidateImage, ReadLodAMDSuccess2) {
6028   const std::string body = R"(
6029 %img = OpLoad %type_image_f32_1d_0002_rgba32f %uniform_image_f32_1d_0002_rgba32f
6030 %res1 = OpImageRead %f32vec4 %img %u32vec2_01 Lod %u32_0
6031 )";
6032 
6033   const std::string extra =
6034       "\nOpCapability Image1D\n"
6035       "OpCapability ImageReadWriteLodAMD\n"
6036       "OpExtension \"SPV_AMD_shader_image_load_store_lod\"\n";
6037   CompileSuccessfully(
6038       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_1),
6039       SPV_ENV_UNIVERSAL_1_1);
6040   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
6041 }
6042 
TEST_F(ValidateImage,ReadLodAMDSuccess3)6043 TEST_F(ValidateImage, ReadLodAMDSuccess3) {
6044   const std::string body = R"(
6045 %img = OpLoad %type_image_f32_cube_0102_rgba32f %uniform_image_f32_cube_0102_rgba32f
6046 %res1 = OpImageRead %f32vec4 %img %u32vec3_012 Lod %u32_0
6047 )";
6048 
6049   const std::string extra =
6050       "\nOpCapability ImageCubeArray\n"
6051       "OpCapability ImageReadWriteLodAMD\n"
6052       "OpExtension \"SPV_AMD_shader_image_load_store_lod\"\n";
6053   CompileSuccessfully(
6054       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_1),
6055       SPV_ENV_UNIVERSAL_1_1);
6056   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
6057 }
6058 
TEST_F(ValidateImage,ReadLodAMDNeedCapability)6059 TEST_F(ValidateImage, ReadLodAMDNeedCapability) {
6060   const std::string body = R"(
6061 %img = OpLoad %type_image_f32_cube_0102_rgba32f %uniform_image_f32_cube_0102_rgba32f
6062 %res1 = OpImageRead %f32vec4 %img %u32vec3_012 Lod %u32_0
6063 )";
6064 
6065   const std::string extra = "\nOpCapability ImageCubeArray\n";
6066   CompileSuccessfully(
6067       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_1),
6068       SPV_ENV_UNIVERSAL_1_1);
6069   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
6070             ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
6071   EXPECT_THAT(getDiagnosticString(),
6072               HasSubstr("Image Operand Lod can only be used with ExplicitLod "
6073                         "opcodes and OpImageFetch"));
6074 }
6075 
TEST_F(ValidateImage,WriteLodAMDSuccess1)6076 TEST_F(ValidateImage, WriteLodAMDSuccess1) {
6077   const std::string body = R"(
6078 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
6079 OpImageWrite %img %u32vec2_01 %u32vec4_0123 Lod %u32_0
6080 )";
6081 
6082   const std::string extra =
6083       "\nOpCapability StorageImageWriteWithoutFormat\n"
6084       "OpCapability ImageReadWriteLodAMD\n"
6085       "OpExtension \"SPV_AMD_shader_image_load_store_lod\"\n";
6086   CompileSuccessfully(
6087       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_1),
6088       SPV_ENV_UNIVERSAL_1_1);
6089   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
6090 }
6091 
TEST_F(ValidateImage,WriteLodAMDSuccess2)6092 TEST_F(ValidateImage, WriteLodAMDSuccess2) {
6093   const std::string body = R"(
6094 %img = OpLoad %type_image_f32_1d_0002_rgba32f %uniform_image_f32_1d_0002_rgba32f
6095 OpImageWrite %img %u32_1 %f32vec4_0000 Lod %u32_0
6096 )";
6097 
6098   const std::string extra =
6099       "\nOpCapability Image1D\n"
6100       "OpCapability ImageReadWriteLodAMD\n"
6101       "OpExtension \"SPV_AMD_shader_image_load_store_lod\"\n";
6102   CompileSuccessfully(
6103       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_1),
6104       SPV_ENV_UNIVERSAL_1_1);
6105   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
6106 }
6107 
TEST_F(ValidateImage,WriteLodAMDSuccess3)6108 TEST_F(ValidateImage, WriteLodAMDSuccess3) {
6109   const std::string body = R"(
6110 %img = OpLoad %type_image_f32_cube_0102_rgba32f %uniform_image_f32_cube_0102_rgba32f
6111 OpImageWrite %img %u32vec3_012 %f32vec4_0000 Lod %u32_0
6112 )";
6113 
6114   const std::string extra =
6115       "\nOpCapability ImageCubeArray\n"
6116       "OpCapability ImageReadWriteLodAMD\n"
6117       "OpExtension \"SPV_AMD_shader_image_load_store_lod\"\n";
6118   CompileSuccessfully(
6119       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_1),
6120       SPV_ENV_UNIVERSAL_1_1);
6121   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
6122 }
6123 
TEST_F(ValidateImage,WriteLodAMDNeedCapability)6124 TEST_F(ValidateImage, WriteLodAMDNeedCapability) {
6125   const std::string body = R"(
6126 %img = OpLoad %type_image_f32_cube_0102_rgba32f %uniform_image_f32_cube_0102_rgba32f
6127 OpImageWrite %img %u32vec3_012 %f32vec4_0000 Lod %u32_0
6128 )";
6129 
6130   const std::string extra = "\nOpCapability ImageCubeArray\n";
6131   CompileSuccessfully(
6132       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_1),
6133       SPV_ENV_UNIVERSAL_1_1);
6134   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
6135             ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
6136   EXPECT_THAT(getDiagnosticString(),
6137               HasSubstr("Image Operand Lod can only be used with ExplicitLod "
6138                         "opcodes and OpImageFetch"));
6139 }
6140 
TEST_F(ValidateImage,SparseReadLodAMDSuccess)6141 TEST_F(ValidateImage, SparseReadLodAMDSuccess) {
6142   const std::string body = R"(
6143 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
6144 %res1 = OpImageSparseRead %struct_u32_f32vec4 %img %u32vec2_01 Lod %u32_0
6145 )";
6146 
6147   const std::string extra =
6148       "\nOpCapability StorageImageReadWithoutFormat\n"
6149       "OpCapability ImageReadWriteLodAMD\n"
6150       "OpExtension \"SPV_AMD_shader_image_load_store_lod\"\n";
6151   CompileSuccessfully(
6152       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_1),
6153       SPV_ENV_UNIVERSAL_1_1);
6154   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
6155 }
6156 
TEST_F(ValidateImage,SparseReadLodAMDNeedCapability)6157 TEST_F(ValidateImage, SparseReadLodAMDNeedCapability) {
6158   const std::string body = R"(
6159 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
6160 %res1 = OpImageSparseRead %struct_u32_f32vec4 %img %u32vec2_01 Lod %u32_0
6161 )";
6162 
6163   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
6164   CompileSuccessfully(
6165       GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_1),
6166       SPV_ENV_UNIVERSAL_1_1);
6167   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
6168             ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
6169   EXPECT_THAT(getDiagnosticString(),
6170               HasSubstr("Image Operand Lod can only be used with ExplicitLod "
6171                         "opcodes and OpImageFetch"));
6172 }
6173 
TEST_F(ValidateImage,GatherBiasAMDSuccess)6174 TEST_F(ValidateImage, GatherBiasAMDSuccess) {
6175   const std::string body = R"(
6176 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
6177 %sampler = OpLoad %type_sampler %uniform_sampler
6178 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
6179 %res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 Bias %f32_1
6180 )";
6181 
6182   const std::string extra = R"(
6183 OpCapability ImageGatherBiasLodAMD
6184 OpExtension "SPV_AMD_texture_gather_bias_lod"
6185 )";
6186   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
6187   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
6188 }
6189 
TEST_F(ValidateImage,GatherLodAMDSuccess)6190 TEST_F(ValidateImage, GatherLodAMDSuccess) {
6191   const std::string body = R"(
6192 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
6193 %sampler = OpLoad %type_sampler %uniform_sampler
6194 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
6195 %res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 Lod %f32_1
6196 )";
6197 
6198   const std::string extra = R"(
6199 OpCapability ImageGatherBiasLodAMD
6200 OpExtension "SPV_AMD_texture_gather_bias_lod"
6201 )";
6202   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
6203   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
6204 }
6205 
TEST_F(ValidateImage,SparseGatherBiasAMDSuccess)6206 TEST_F(ValidateImage, SparseGatherBiasAMDSuccess) {
6207   const std::string body = R"(
6208 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
6209 %sampler = OpLoad %type_sampler %uniform_sampler
6210 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
6211 %res1 = OpImageSparseGather %struct_u32_f32vec4 %simg %f32vec4_0000 %u32_1 Bias %f32_1
6212 )";
6213 
6214   const std::string extra = R"(
6215 OpCapability ImageGatherBiasLodAMD
6216 OpExtension "SPV_AMD_texture_gather_bias_lod"
6217 )";
6218   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
6219   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
6220 }
6221 
TEST_F(ValidateImage,SparseGatherLodAMDSuccess)6222 TEST_F(ValidateImage, SparseGatherLodAMDSuccess) {
6223   const std::string body = R"(
6224 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
6225 %sampler = OpLoad %type_sampler %uniform_sampler
6226 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
6227 %res1 = OpImageSparseGather %struct_u32_f32vec4 %simg %f32vec4_0000 %u32_1 Lod %f32_1
6228 )";
6229 
6230   const std::string extra = R"(
6231 OpCapability ImageGatherBiasLodAMD
6232 OpExtension "SPV_AMD_texture_gather_bias_lod"
6233 )";
6234   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
6235   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
6236 }
6237 
6238 // No negative tests for ZeroExtend since we don't truly know the
6239 // texel format.
6240 
6241 // Tests for 64-bit images
6242 static const std::string capabilities_and_extensions_image64 = R"(
6243 OpCapability Int64ImageEXT
6244 OpExtension "SPV_EXT_shader_image_int64"
6245 )";
6246 static const std::string capabilities_and_extensions_image64_atomic = R"(
6247 OpCapability Int64Atomics
6248 OpCapability Int64ImageEXT
6249 OpExtension "SPV_EXT_shader_image_int64"
6250 )";
6251 static const std::string declarations_image64 = R"(
6252 %type_image_u64_buffer_0002_r64ui = OpTypeImage %u64 Buffer 0 0 0 2 R64ui
6253 %ptr_Image_u64 = OpTypePointer Image %u64
6254 %ptr_image_u64_buffer_0002_r64ui = OpTypePointer Private %type_image_u64_buffer_0002_r64ui
6255 %private_image_u64_buffer_0002_r64ui = OpVariable %ptr_image_u64_buffer_0002_r64ui Private
6256 )";
6257 static const std::string declarations_image64i = R"(
6258 %type_image_s64_buffer_0002_r64i = OpTypeImage %s64 Buffer 0 0 0 2 R64i
6259 %ptr_Image_s64 = OpTypePointer Image %s64
6260 %ptr_image_s64_buffer_0002_r64i = OpTypePointer Private %type_image_s64_buffer_0002_r64i
6261 %private_image_s64_buffer_0002_r64i = OpVariable %ptr_image_s64_buffer_0002_r64i Private
6262 )";
6263 
TEST_F(ValidateImage,Image64MissingCapability)6264 TEST_F(ValidateImage, Image64MissingCapability) {
6265   CompileSuccessfully(GenerateShaderCode("", "", "Fragment", "",
6266                                          SPV_ENV_UNIVERSAL_1_3, "GLSL450",
6267                                          declarations_image64)
6268                           .c_str());
6269   ASSERT_EQ(SPV_ERROR_INVALID_CAPABILITY, ValidateInstructions());
6270 }
6271 
TEST_F(ValidateImage,Image64MissingExtension)6272 TEST_F(ValidateImage, Image64MissingExtension) {
6273   const std::string extra = R"(
6274 OpCapability Int64ImageEXT
6275 )";
6276 
6277   CompileSuccessfully(GenerateShaderCode("", extra, "Fragment", "",
6278                                          SPV_ENV_UNIVERSAL_1_3, "GLSL450",
6279                                          declarations_image64)
6280                           .c_str());
6281   ASSERT_EQ(SPV_ERROR_MISSING_EXTENSION, ValidateInstructions());
6282 }
6283 
TEST_F(ValidateImage,ImageTexelPointer64Success)6284 TEST_F(ValidateImage, ImageTexelPointer64Success) {
6285   const std::string body = R"(
6286 %texel_ptr = OpImageTexelPointer %ptr_Image_u64 %private_image_u64_buffer_0002_r64ui %u32_0 %u32_0
6287 %sum = OpAtomicIAdd %u64 %texel_ptr %u32_1 %u32_0 %u64_1
6288 )";
6289 
6290   CompileSuccessfully(
6291       GenerateShaderCode(body, capabilities_and_extensions_image64_atomic,
6292                          "Fragment", "", SPV_ENV_UNIVERSAL_1_3, "GLSL450",
6293                          declarations_image64)
6294           .c_str());
6295   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
6296 }
6297 
TEST_F(ValidateImage,ImageTexelPointer64ResultTypeNotPointer)6298 TEST_F(ValidateImage, ImageTexelPointer64ResultTypeNotPointer) {
6299   const std::string body = R"(
6300 %texel_ptr = OpImageTexelPointer %type_image_u64_buffer_0002_r64ui %private_image_u64_buffer_0002_r64ui %u32_0 %u32_0
6301 %sum = OpAtomicIAdd %u64 %texel_ptr %u32_1 %u32_0 %u64_1
6302 )";
6303 
6304   CompileSuccessfully(
6305       GenerateShaderCode(body, capabilities_and_extensions_image64_atomic,
6306                          "Fragment", "", SPV_ENV_UNIVERSAL_1_3, "GLSL450",
6307                          declarations_image64)
6308           .c_str());
6309   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
6310   EXPECT_THAT(getDiagnosticString(),
6311               HasSubstr("Expected Result Type to be OpTypePointer"));
6312 }
6313 
TEST_F(ValidateImage,ImageTexelPointer64ResultTypeNotImageClass)6314 TEST_F(ValidateImage, ImageTexelPointer64ResultTypeNotImageClass) {
6315   const std::string body = R"(
6316 %texel_ptr = OpImageTexelPointer %ptr_image_f32_cube_0101 %private_image_u64_buffer_0002_r64ui %u32_0 %u32_0
6317 %sum = OpAtomicIAdd %u64 %texel_ptr %u32_1 %u32_0 %u64_1
6318 )";
6319 
6320   CompileSuccessfully(
6321       GenerateShaderCode(body, capabilities_and_extensions_image64_atomic,
6322                          "Fragment", "", SPV_ENV_UNIVERSAL_1_3, "GLSL450",
6323                          declarations_image64)
6324           .c_str());
6325   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
6326   EXPECT_THAT(getDiagnosticString(),
6327               HasSubstr("Expected Result Type to be OpTypePointer whose "
6328                         "Storage Class operand is Image"));
6329 }
6330 
TEST_F(ValidateImage,ImageTexelPointer64SampleNotZeroForImageWithMSZero)6331 TEST_F(ValidateImage, ImageTexelPointer64SampleNotZeroForImageWithMSZero) {
6332   const std::string body = R"(
6333 %texel_ptr = OpImageTexelPointer %ptr_Image_u64 %private_image_u64_buffer_0002_r64ui %u32_0 %u32_1
6334 %sum = OpAtomicIAdd %u64 %texel_ptr %u32_1 %u32_0 %u64_1
6335 )";
6336 
6337   CompileSuccessfully(
6338       GenerateShaderCode(body, capabilities_and_extensions_image64_atomic,
6339                          "Fragment", "", SPV_ENV_UNIVERSAL_1_3, "GLSL450",
6340                          declarations_image64)
6341           .c_str());
6342   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
6343   EXPECT_THAT(getDiagnosticString(),
6344               HasSubstr("Expected Sample for Image with MS 0 to be a valid "
6345                         "<id> for the value 0"));
6346 }
6347 
TEST_F(ValidateImage,ImageTexelPointerR32uiSuccessVulkan)6348 TEST_F(ValidateImage, ImageTexelPointerR32uiSuccessVulkan) {
6349   const std::string body = R"(
6350 %texel_ptr = OpImageTexelPointer %ptr_Image_u32 %private_image_u32_buffer_0002_r32ui %u32_0 %u32_0
6351 )";
6352 
6353   spv_target_env env = SPV_ENV_VULKAN_1_0;
6354   CompileSuccessfully(GenerateShaderCode(body, "", "Fragment", "", env).c_str(),
6355                       env);
6356   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(env));
6357 }
6358 
TEST_F(ValidateImage,ImageTexelPointerR32iSuccessVulkan)6359 TEST_F(ValidateImage, ImageTexelPointerR32iSuccessVulkan) {
6360   const std::string& declarations = R"(
6361 %type_image_s32_buffer_0002_r32i = OpTypeImage %s32 Buffer 0 0 0 2 R32i
6362 %ptr_Image_s32 = OpTypePointer Image %s32
6363 %ptr_image_s32_buffer_0002_r32i = OpTypePointer Private %type_image_s32_buffer_0002_r32i
6364 %private_image_s32_buffer_0002_r32i = OpVariable %ptr_image_s32_buffer_0002_r32i Private
6365 )";
6366 
6367   const std::string body = R"(
6368 %texel_ptr = OpImageTexelPointer %ptr_Image_s32 %private_image_s32_buffer_0002_r32i %u32_0 %u32_0
6369 )";
6370 
6371   spv_target_env env = SPV_ENV_VULKAN_1_0;
6372   CompileSuccessfully(
6373       GenerateShaderCode(body, "", "Fragment", "", env, "GLSL450", declarations)
6374           .c_str(),
6375       env);
6376   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(env));
6377 }
6378 
TEST_F(ValidateImage,ImageTexelPointerR64uiSuccessVulkan)6379 TEST_F(ValidateImage, ImageTexelPointerR64uiSuccessVulkan) {
6380   const std::string body = R"(
6381 %texel_ptr = OpImageTexelPointer %ptr_Image_u64 %private_image_u64_buffer_0002_r64ui %u32_0 %u32_0
6382 )";
6383 
6384   spv_target_env env = SPV_ENV_VULKAN_1_0;
6385   CompileSuccessfully(
6386       GenerateShaderCode(body, capabilities_and_extensions_image64, "Fragment",
6387                          "", env, "GLSL450", declarations_image64)
6388           .c_str(),
6389       env);
6390   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(env));
6391 }
6392 
TEST_F(ValidateImage,ImageTexelPointerR64iSuccessVulkan)6393 TEST_F(ValidateImage, ImageTexelPointerR64iSuccessVulkan) {
6394   const std::string body = R"(
6395 %texel_ptr = OpImageTexelPointer %ptr_Image_s64 %private_image_s64_buffer_0002_r64i %u32_0 %u32_0
6396 )";
6397 
6398   spv_target_env env = SPV_ENV_VULKAN_1_0;
6399   CompileSuccessfully(
6400       GenerateShaderCode(body, capabilities_and_extensions_image64, "Fragment",
6401                          "", env, "GLSL450", declarations_image64i)
6402           .c_str(),
6403       env);
6404   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(env));
6405 }
6406 
TEST_F(ValidateImage,ImageTexelPointerR32fSuccessVulkan)6407 TEST_F(ValidateImage, ImageTexelPointerR32fSuccessVulkan) {
6408   const std::string& declarations = R"(
6409 %type_image_f32_buffer_0002_r32f = OpTypeImage %f32 Buffer 0 0 0 2 R32f
6410 %ptr_image_f32_buffer_0002_r32f = OpTypePointer Private %type_image_f32_buffer_0002_r32f
6411 %private_image_f32_buffer_0002_r32f = OpVariable %ptr_image_f32_buffer_0002_r32f Private
6412 )";
6413 
6414   const std::string body = R"(
6415 %texel_ptr = OpImageTexelPointer %ptr_Image_f32 %private_image_f32_buffer_0002_r32f %u32_0 %u32_0
6416 )";
6417 
6418   spv_target_env env = SPV_ENV_VULKAN_1_0;
6419   CompileSuccessfully(
6420       GenerateShaderCode(body, "", "Fragment", "", env, "GLSL450", declarations)
6421           .c_str(),
6422       env);
6423   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(env));
6424 }
6425 
TEST_F(ValidateImage,ImageTexelPointerRgba32iVulkan)6426 TEST_F(ValidateImage, ImageTexelPointerRgba32iVulkan) {
6427   const std::string& declarations = R"(
6428 %type_image_s32_buffer_0002_rgba32i = OpTypeImage %s32 Buffer 0 0 0 2 Rgba32i
6429 %ptr_Image_s32 = OpTypePointer Image %s32
6430 %ptr_image_s32_buffer_0002_rgba32i = OpTypePointer Private %type_image_s32_buffer_0002_rgba32i
6431 %private_image_s32_buffer_0002_rgba32i = OpVariable %ptr_image_s32_buffer_0002_rgba32i Private
6432 )";
6433 
6434   const std::string body = R"(
6435 %texel_ptr = OpImageTexelPointer %ptr_Image_s32 %private_image_s32_buffer_0002_rgba32i %u32_0 %u32_0
6436 )";
6437 
6438   spv_target_env env = SPV_ENV_VULKAN_1_0;
6439   CompileSuccessfully(
6440       GenerateShaderCode(body, "", "Fragment", "", env, "GLSL450", declarations)
6441           .c_str(),
6442       env);
6443   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
6444   EXPECT_THAT(getDiagnosticString(),
6445               AnyVUID("VUID-StandaloneSpirv-OpImageTexelPointer-04658"));
6446   EXPECT_THAT(getDiagnosticString(),
6447               HasSubstr("Expected the Image Format in Image to be R64i, R64ui, "
6448                         "R32f, R32i, or R32ui for Vulkan environment"));
6449 }
6450 
TEST_F(ValidateImage,ImageTexelPointerRgba16fVulkan)6451 TEST_F(ValidateImage, ImageTexelPointerRgba16fVulkan) {
6452   const std::string& declarations = R"(
6453 %type_image_s32_buffer_0002_rgba16f = OpTypeImage %s32 Buffer 0 0 0 2 Rgba16f
6454 %ptr_Image_s32 = OpTypePointer Image %s32
6455 %ptr_image_s32_buffer_0002_rgba16f = OpTypePointer Private %type_image_s32_buffer_0002_rgba16f
6456 %private_image_s32_buffer_0002_rgba16f = OpVariable %ptr_image_s32_buffer_0002_rgba16f Private
6457 )";
6458 
6459   const std::string body = R"(
6460 %texel_ptr = OpImageTexelPointer %ptr_Image_s32 %private_image_s32_buffer_0002_rgba16f %u32_0 %u32_0
6461 )";
6462 
6463   spv_target_env env = SPV_ENV_VULKAN_1_0;
6464   CompileSuccessfully(
6465       GenerateShaderCode(body, "", "Fragment", "", env, "GLSL450", declarations)
6466           .c_str(),
6467       env);
6468   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
6469   EXPECT_THAT(getDiagnosticString(),
6470               AnyVUID("VUID-StandaloneSpirv-OpImageTexelPointer-04658"));
6471   EXPECT_THAT(getDiagnosticString(),
6472               HasSubstr("Expected the Image Format in Image to be R64i, R64ui, "
6473                         "R32f, R32i, or R32ui for Vulkan environment"));
6474 }
6475 
TEST_F(ValidateImage,ImageExecutionModeLimitationNoMode)6476 TEST_F(ValidateImage, ImageExecutionModeLimitationNoMode) {
6477   const std::string text = R"(
6478 OpCapability Shader
6479 OpMemoryModel Logical GLSL450
6480 OpEntryPoint GLCompute %2 " " %4
6481 %void = OpTypeVoid
6482 %8 = OpTypeFunction %void
6483 %float = OpTypeFloat 32
6484 %v4float = OpTypeVector %float 4
6485 %12 = OpTypeImage %float 2D 0 0 0 1 Rgba8ui
6486 %13 = OpTypeSampledImage %12
6487 %_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
6488 %5 = OpVariable %_ptr_UniformConstant_13 UniformConstant
6489 %_ptr_Input_v4float = OpTypePointer Input %v4float
6490 %4 = OpVariable %_ptr_Input_v4float Input
6491 %v2float = OpTypeVector %float 2
6492 %float_1_35631564en19 = OpConstant %float 1.35631564e-19
6493 %2 = OpFunction %void None %8
6494 %8224 = OpLabel
6495 %6 = OpLoad %13 %5
6496 %19 = OpLoad %v4float %4
6497 %20 = OpVectorShuffle %v2float %19 %19 0 1
6498 %21 = OpVectorTimesScalar %v2float %20 %float_1_35631564en19
6499 %65312 = OpImageSampleImplicitLod %v4float %6 %21
6500 OpUnreachable
6501 OpFunctionEnd
6502 )";
6503 
6504   CompileSuccessfully(text);
6505   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6506   EXPECT_THAT(getDiagnosticString(),
6507               HasSubstr("ImplicitLod instructions require "
6508                         "DerivativeGroupQuadsNV or DerivativeGroupLinearNV "
6509                         "execution mode for GLCompute execution model"));
6510 }
6511 
TEST_F(ValidateImage,TypeSampledImageNotBufferPost1p6)6512 TEST_F(ValidateImage, TypeSampledImageNotBufferPost1p6) {
6513   const std::string text = R"(
6514 OpCapability Shader
6515 OpCapability Linkage
6516 OpCapability SampledBuffer
6517 OpMemoryModel Logical GLSL450
6518 %float = OpTypeFloat 32
6519 %image = OpTypeImage %float Buffer 0 0 0 1 Unknown
6520 %sampled = OpTypeSampledImage %image
6521 )";
6522 
6523   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_6);
6524   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_6));
6525   EXPECT_THAT(getDiagnosticString(),
6526               HasSubstr("In SPIR-V 1.6 or later, sampled image dimension must "
6527                         "not be Buffer"));
6528 }
6529 
TEST_F(ValidateImage,NonTemporalImage)6530 TEST_F(ValidateImage, NonTemporalImage) {
6531   const std::string text = R"(
6532 OpCapability Shader
6533 OpMemoryModel Logical GLSL450
6534 OpEntryPoint Fragment %2 " " %4 %5
6535 OpExecutionMode %2 OriginUpperLeft
6536 %void = OpTypeVoid
6537 %8 = OpTypeFunction %void
6538 %float = OpTypeFloat 32
6539 %v4float = OpTypeVector %float 4
6540 %12 = OpTypeImage %float 2D 0 0 0 1 Rgba8ui
6541 %13 = OpTypeSampledImage %12
6542 %_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
6543 %5 = OpVariable %_ptr_UniformConstant_13 UniformConstant
6544 %_ptr_Input_v4float = OpTypePointer Input %v4float
6545 %4 = OpVariable %_ptr_Input_v4float Input
6546 %v2float = OpTypeVector %float 2
6547 %float_1_35631564en19 = OpConstant %float 1.35631564e-19
6548 %2 = OpFunction %void None %8
6549 %8224 = OpLabel
6550 %6 = OpLoad %13 %5
6551 %19 = OpLoad %v4float %4
6552 %20 = OpVectorShuffle %v2float %19 %19 0 1
6553 %21 = OpVectorTimesScalar %v2float %20 %float_1_35631564en19
6554 %65312 = OpImageSampleImplicitLod %v4float %6 %21 Nontemporal
6555 OpReturn
6556 OpFunctionEnd
6557 )";
6558 
6559   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_6);
6560   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_6));
6561 }
6562 
TEST_F(ValidateImage,NVBindlessSamplerBuiltins)6563 TEST_F(ValidateImage, NVBindlessSamplerBuiltins) {
6564   const std::string text = R"(
6565               OpCapability Shader
6566               OpCapability Int64
6567               OpCapability Image1D
6568               OpCapability BindlessTextureNV
6569               OpExtension "SPV_NV_bindless_texture"
6570          %1 = OpExtInstImport "GLSL.std.450"
6571               OpMemoryModel Logical GLSL450
6572               OpSamplerImageAddressingModeNV 64
6573               OpEntryPoint Fragment %main "main"
6574               OpExecutionMode %main OriginUpperLeft
6575               OpSource GLSL 450
6576               OpName %main "main"
6577               OpName %s2D "s2D"
6578               OpName %textureHandle "textureHandle"
6579               OpName %i1D "i1D"
6580               OpName %s "s"
6581               OpName %temp "temp"
6582       %void = OpTypeVoid
6583          %3 = OpTypeFunction %void
6584      %float = OpTypeFloat 32
6585          %7 = OpTypeImage %float 2D 0 0 0 1 Unknown
6586          %8 = OpTypeSampledImage %7
6587 %_ptr_Function_8 = OpTypePointer Function %8
6588      %ulong = OpTypeInt 64 0
6589 %_ptr_Private_ulong = OpTypePointer Private %ulong
6590 %textureHandle = OpVariable %_ptr_Private_ulong Private
6591         %16 = OpTypeImage %float 1D 0 0 0 2 Rgba32f
6592 %_ptr_Function_16 = OpTypePointer Function %16
6593         %21 = OpTypeSampler
6594 %_ptr_Function_21 = OpTypePointer Function %21
6595 %_ptr_Function_ulong = OpTypePointer Function %ulong
6596       %main = OpFunction %void None %3
6597          %5 = OpLabel
6598        %s2D = OpVariable %_ptr_Function_8 Function
6599        %i1D = OpVariable %_ptr_Function_16 Function
6600          %s = OpVariable %_ptr_Function_21 Function
6601       %temp = OpVariable %_ptr_Function_ulong Function
6602         %14 = OpLoad %ulong %textureHandle
6603         %15 = OpConvertUToSampledImageNV %8 %14
6604               OpStore %s2D %15
6605         %19 = OpLoad %ulong %textureHandle
6606         %20 = OpConvertUToImageNV %16 %19
6607               OpStore %i1D %20
6608         %24 = OpLoad %ulong %textureHandle
6609         %25 = OpConvertUToSamplerNV %21 %24
6610               OpStore %s %25
6611         %28 = OpLoad %8 %s2D
6612         %29 = OpConvertSampledImageToUNV %ulong %28
6613               OpStore %temp %29
6614         %30 = OpLoad %16 %i1D
6615         %31 = OpConvertImageToUNV %ulong %30
6616               OpStore %temp %31
6617         %32 = OpLoad %21 %s
6618         %33 = OpConvertSamplerToUNV %ulong %32
6619               OpStore %temp %33
6620               OpReturn
6621               OpFunctionEnd
6622 )";
6623 
6624   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
6625   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6626 }
6627 
TEST_F(ValidateImage,NVBindlessAddressingMode64)6628 TEST_F(ValidateImage, NVBindlessAddressingMode64) {
6629   std::string text = R"(
6630          OpCapability Shader
6631          OpCapability BindlessTextureNV
6632          OpExtension "SPV_NV_bindless_texture"
6633          OpMemoryModel Logical GLSL450
6634          OpSamplerImageAddressingModeNV 64
6635          OpEntryPoint GLCompute %func "main"
6636 %voidt = OpTypeVoid
6637 %uintt = OpTypeInt 32 0
6638 %funct = OpTypeFunction %voidt
6639 %func  = OpFunction %voidt None %funct
6640 %entry = OpLabel
6641 %udef  = OpUndef %uintt
6642          OpReturn
6643          OpFunctionEnd
6644 )";
6645   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
6646   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6647 }
6648 
TEST_F(ValidateImage,NVBindlessAddressingMode32)6649 TEST_F(ValidateImage, NVBindlessAddressingMode32) {
6650   std::string text = R"(
6651          OpCapability Shader
6652          OpCapability BindlessTextureNV
6653          OpExtension "SPV_NV_bindless_texture"
6654          OpMemoryModel Logical GLSL450
6655          OpSamplerImageAddressingModeNV 32
6656          OpEntryPoint GLCompute %func "main"
6657 %voidt = OpTypeVoid
6658 %uintt = OpTypeInt 32 0
6659 %funct = OpTypeFunction %voidt
6660 %func  = OpFunction %voidt None %funct
6661 %entry = OpLabel
6662 %udef  = OpUndef %uintt
6663          OpReturn
6664          OpFunctionEnd
6665 )";
6666   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
6667   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6668 }
6669 
TEST_F(ValidateImage,NVBindlessInvalidAddressingMode)6670 TEST_F(ValidateImage, NVBindlessInvalidAddressingMode) {
6671   std::string text = R"(
6672          OpCapability Shader
6673          OpCapability BindlessTextureNV
6674          OpExtension "SPV_NV_bindless_texture"
6675          OpMemoryModel Logical GLSL450
6676          OpSamplerImageAddressingModeNV 0
6677          OpEntryPoint GLCompute %func "main"
6678 %voidt = OpTypeVoid
6679 %uintt = OpTypeInt 32 0
6680 %funct = OpTypeFunction %voidt
6681 %func  = OpFunction %voidt None %funct
6682 %entry = OpLabel
6683 %udef  = OpUndef %uintt
6684          OpReturn
6685          OpFunctionEnd
6686 )";
6687   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
6688   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
6689             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6690   EXPECT_THAT(
6691       getDiagnosticString(),
6692       HasSubstr("OpSamplerImageAddressingModeNV bitwidth should be 64 or 32"));
6693 }
6694 
TEST_F(ValidateImage,QCOMImageProcessingBlockMatchSADNoDecorationA)6695 TEST_F(ValidateImage, QCOMImageProcessingBlockMatchSADNoDecorationA) {
6696   std::string text = R"(
6697            OpCapability Shader
6698            OpCapability TextureBlockMatchQCOM
6699            OpExtension "SPV_QCOM_image_processing"
6700       %1 = OpExtInstImport "GLSL.std.450"
6701            OpMemoryModel Logical GLSL450
6702            OpEntryPoint Fragment %2 "main" %3 %4 %5 %6
6703            OpExecutionMode %2 OriginUpperLeft
6704            OpDecorate %3 Location 0
6705            OpDecorate %4 DescriptorSet 0
6706            OpDecorate %4 Binding 1
6707            OpDecorate %5 DescriptorSet 0
6708            OpDecorate %5 Binding 3
6709            OpDecorate %6 DescriptorSet 0
6710            OpDecorate %6 Binding 2
6711            OpDecorate %6 BlockMatchTextureQCOM
6712    %void = OpTypeVoid
6713       %8 = OpTypeFunction %void
6714    %uint = OpTypeInt 32 0
6715  %v2uint = OpTypeVector %uint 2
6716 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
6717   %float = OpTypeFloat 32
6718 %v4float = OpTypeVector %float 4
6719 %_ptr_Input_float = OpTypePointer Input %float
6720 %_ptr_Function_uint = OpTypePointer Function %uint
6721 %uint_4 = OpConstant %uint 4
6722     %17 = OpConstantComposite %v2uint %uint_4 %uint_4
6723 %_ptr_Output_v4float = OpTypePointer Output %v4float
6724      %3 = OpVariable %_ptr_Output_v4float Output
6725     %19 = OpTypeImage %float 2D 0 0 0 1 Unknown
6726 %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19
6727      %4 = OpVariable %_ptr_UniformConstant_19 UniformConstant
6728     %21 = OpTypeSampler
6729 %_ptr_UniformConstant_21 = OpTypePointer UniformConstant %21
6730     %5 = OpVariable %_ptr_UniformConstant_21 UniformConstant
6731    %23 = OpTypeSampledImage %19
6732     %6 = OpVariable %_ptr_UniformConstant_19 UniformConstant
6733     %2 = OpFunction %void None %8
6734    %24 = OpLabel
6735    %25 = OpVariable %_ptr_Function_v2uint Function
6736    %26 = OpLoad %19 %4
6737    %27 = OpLoad %21 %5
6738    %28 = OpSampledImage %23 %26 %27
6739    %29 = OpLoad %v2uint %25
6740    %30 = OpLoad %19 %6
6741    %31 = OpLoad %21 %5
6742    %32 = OpSampledImage %23 %30 %31
6743    %33 = OpImageBlockMatchSADQCOM %v4float %28 %29 %32 %29 %29
6744          OpStore %3 %33
6745          OpReturn
6746          OpFunctionEnd
6747 )";
6748   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
6749   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
6750             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
6751   EXPECT_THAT(getDiagnosticString(),
6752               HasSubstr("Missing decoration BlockMatchTextureQCOM"));
6753 }
6754 
TEST_F(ValidateImage,QCOMImageProcessingBlockMatchSADNoDecorationB)6755 TEST_F(ValidateImage, QCOMImageProcessingBlockMatchSADNoDecorationB) {
6756   std::string text = R"(
6757            OpCapability Shader
6758            OpCapability TextureBlockMatchQCOM
6759            OpExtension "SPV_QCOM_image_processing"
6760       %1 = OpExtInstImport "GLSL.std.450"
6761            OpMemoryModel Logical GLSL450
6762            OpEntryPoint Fragment %2 "main" %3 %4 %5 %6
6763            OpExecutionMode %2 OriginUpperLeft
6764            OpDecorate %3 Location 0
6765            OpDecorate %4 DescriptorSet 0
6766            OpDecorate %4 Binding 1
6767            OpDecorate %5 DescriptorSet 0
6768            OpDecorate %5 Binding 3
6769            OpDecorate %5 BlockMatchTextureQCOM
6770            OpDecorate %6 DescriptorSet 0
6771            OpDecorate %6 Binding 2
6772    %void = OpTypeVoid
6773       %8 = OpTypeFunction %void
6774    %uint = OpTypeInt 32 0
6775  %v2uint = OpTypeVector %uint 2
6776 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
6777   %float = OpTypeFloat 32
6778 %v4float = OpTypeVector %float 4
6779 %_ptr_Input_float = OpTypePointer Input %float
6780 %_ptr_Function_uint = OpTypePointer Function %uint
6781 %uint_4 = OpConstant %uint 4
6782     %17 = OpConstantComposite %v2uint %uint_4 %uint_4
6783 %_ptr_Output_v4float = OpTypePointer Output %v4float
6784      %3 = OpVariable %_ptr_Output_v4float Output
6785     %19 = OpTypeImage %float 2D 0 0 0 1 Unknown
6786 %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19
6787      %4 = OpVariable %_ptr_UniformConstant_19 UniformConstant
6788     %21 = OpTypeSampler
6789 %_ptr_UniformConstant_21 = OpTypePointer UniformConstant %21
6790     %5 = OpVariable %_ptr_UniformConstant_21 UniformConstant
6791    %23 = OpTypeSampledImage %19
6792     %6 = OpVariable %_ptr_UniformConstant_19 UniformConstant
6793     %2 = OpFunction %void None %8
6794    %24 = OpLabel
6795    %25 = OpVariable %_ptr_Function_v2uint Function
6796    %26 = OpLoad %19 %4
6797    %27 = OpLoad %21 %5
6798    %28 = OpSampledImage %23 %26 %27
6799    %29 = OpLoad %v2uint %25
6800    %30 = OpLoad %19 %6
6801    %31 = OpLoad %21 %5
6802    %32 = OpSampledImage %23 %30 %31
6803    %33 = OpImageBlockMatchSADQCOM %v4float %28 %29 %32 %29 %29
6804          OpStore %3 %33
6805          OpReturn
6806          OpFunctionEnd
6807 )";
6808   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
6809   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
6810             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
6811   EXPECT_THAT(getDiagnosticString(),
6812               HasSubstr("Missing decoration BlockMatchTextureQCOM"));
6813 }
6814 
TEST_F(ValidateImage,QCOMImageProcessingBlockMatchSADNoDecorationC)6815 TEST_F(ValidateImage, QCOMImageProcessingBlockMatchSADNoDecorationC) {
6816   std::string text = R"(
6817                OpCapability Shader
6818                OpCapability TextureBlockMatchQCOM
6819                OpExtension "SPV_QCOM_image_processing"
6820           %1 = OpExtInstImport "GLSL.std.450"
6821                OpMemoryModel Logical GLSL450
6822                OpEntryPoint Fragment %2 "main" %3 %4 %5
6823                OpExecutionMode %2 OriginUpperLeft
6824                OpDecorate %3 Location 0
6825                OpDecorate %4 DescriptorSet 0
6826                OpDecorate %4 Binding 4
6827                OpDecorate %5 DescriptorSet 0
6828                OpDecorate %5 Binding 5
6829                OpDecorate %5 BlockMatchTextureQCOM
6830        %void = OpTypeVoid
6831           %7 = OpTypeFunction %void
6832        %uint = OpTypeInt 32 0
6833      %v2uint = OpTypeVector %uint 2
6834 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
6835       %float = OpTypeFloat 32
6836     %v4float = OpTypeVector %float 4
6837 %_ptr_Input_v4float = OpTypePointer Input %v4float
6838 %_ptr_Input_float = OpTypePointer Input %float
6839 %_ptr_Function_uint = OpTypePointer Function %uint
6840 %_ptr_Output_v4float = OpTypePointer Output %v4float
6841           %3 = OpVariable %_ptr_Output_v4float Output
6842          %18 = OpTypeImage %float 2D 0 0 0 1 Unknown
6843          %19 = OpTypeSampledImage %18
6844 %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19
6845           %4 = OpVariable %_ptr_UniformConstant_19 UniformConstant
6846           %5 = OpVariable %_ptr_UniformConstant_19 UniformConstant
6847          %21 = OpTypeImage %float 2D 0 1 0 1 Unknown
6848           %2 = OpFunction %void None %7
6849          %22 = OpLabel
6850          %23 = OpVariable %_ptr_Function_v2uint Function
6851          %24 = OpLoad %19 %4
6852          %25 = OpLoad %v2uint %23
6853          %26 = OpLoad %19 %5
6854          %27 = OpLoad %v2uint %23
6855          %28 = OpLoad %v2uint %23
6856          %29 = OpImageBlockMatchSADQCOM %v4float %24 %25 %26 %27 %28
6857                OpStore %3 %29
6858                OpReturn
6859                OpFunctionEnd
6860 )";
6861   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
6862   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
6863             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
6864   EXPECT_THAT(getDiagnosticString(),
6865               HasSubstr("Missing decoration BlockMatchTextureQCOM"));
6866 }
6867 
TEST_F(ValidateImage,QCOMImageProcessingBlockMatchSADNoDecorationD)6868 TEST_F(ValidateImage, QCOMImageProcessingBlockMatchSADNoDecorationD) {
6869   std::string text = R"(
6870                OpCapability Shader
6871                OpCapability TextureBlockMatchQCOM
6872                OpExtension "SPV_QCOM_image_processing"
6873           %1 = OpExtInstImport "GLSL.std.450"
6874                OpMemoryModel Logical GLSL450
6875                OpEntryPoint Fragment %2 "main" %3 %4 %5
6876                OpExecutionMode %2 OriginUpperLeft
6877                OpDecorate %3 Location 0
6878                OpDecorate %4 DescriptorSet 0
6879                OpDecorate %4 Binding 4
6880                OpDecorate %4 BlockMatchTextureQCOM
6881                OpDecorate %5 DescriptorSet 0
6882                OpDecorate %5 Binding 5
6883        %void = OpTypeVoid
6884           %7 = OpTypeFunction %void
6885        %uint = OpTypeInt 32 0
6886      %v2uint = OpTypeVector %uint 2
6887 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
6888       %float = OpTypeFloat 32
6889     %v4float = OpTypeVector %float 4
6890 %_ptr_Input_v4float = OpTypePointer Input %v4float
6891 %_ptr_Input_float = OpTypePointer Input %float
6892 %_ptr_Function_uint = OpTypePointer Function %uint
6893 %_ptr_Output_v4float = OpTypePointer Output %v4float
6894           %3 = OpVariable %_ptr_Output_v4float Output
6895          %18 = OpTypeImage %float 2D 0 0 0 1 Unknown
6896          %19 = OpTypeSampledImage %18
6897 %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19
6898           %4 = OpVariable %_ptr_UniformConstant_19 UniformConstant
6899           %5 = OpVariable %_ptr_UniformConstant_19 UniformConstant
6900          %21 = OpTypeImage %float 2D 0 1 0 1 Unknown
6901           %2 = OpFunction %void None %7
6902          %22 = OpLabel
6903          %23 = OpVariable %_ptr_Function_v2uint Function
6904          %24 = OpLoad %19 %4
6905          %25 = OpLoad %v2uint %23
6906          %26 = OpLoad %19 %5
6907          %27 = OpLoad %v2uint %23
6908          %28 = OpLoad %v2uint %23
6909          %29 = OpImageBlockMatchSADQCOM %v4float %24 %25 %26 %27 %28
6910                OpStore %3 %29
6911                OpReturn
6912                OpFunctionEnd
6913 )";
6914   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
6915   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
6916             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
6917   EXPECT_THAT(getDiagnosticString(),
6918               HasSubstr("Missing decoration BlockMatchTextureQCOM"));
6919 }
6920 
TEST_F(ValidateImage,QCOMImageProcessingBlockMatchSSDNoDecorationA)6921 TEST_F(ValidateImage, QCOMImageProcessingBlockMatchSSDNoDecorationA) {
6922   std::string text = R"(
6923            OpCapability Shader
6924            OpCapability TextureBlockMatchQCOM
6925            OpExtension "SPV_QCOM_image_processing"
6926       %1 = OpExtInstImport "GLSL.std.450"
6927            OpMemoryModel Logical GLSL450
6928            OpEntryPoint Fragment %2 "main" %3 %4 %5 %6
6929            OpExecutionMode %2 OriginUpperLeft
6930            OpDecorate %3 Location 0
6931            OpDecorate %4 DescriptorSet 0
6932            OpDecorate %4 Binding 1
6933            OpDecorate %5 DescriptorSet 0
6934            OpDecorate %5 Binding 3
6935            OpDecorate %6 DescriptorSet 0
6936            OpDecorate %6 Binding 2
6937            OpDecorate %6 BlockMatchTextureQCOM
6938    %void = OpTypeVoid
6939       %8 = OpTypeFunction %void
6940    %uint = OpTypeInt 32 0
6941  %v2uint = OpTypeVector %uint 2
6942 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
6943   %float = OpTypeFloat 32
6944 %v4float = OpTypeVector %float 4
6945 %_ptr_Input_float = OpTypePointer Input %float
6946 %_ptr_Function_uint = OpTypePointer Function %uint
6947 %uint_4 = OpConstant %uint 4
6948     %17 = OpConstantComposite %v2uint %uint_4 %uint_4
6949 %_ptr_Output_v4float = OpTypePointer Output %v4float
6950      %3 = OpVariable %_ptr_Output_v4float Output
6951     %19 = OpTypeImage %float 2D 0 0 0 1 Unknown
6952 %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19
6953      %4 = OpVariable %_ptr_UniformConstant_19 UniformConstant
6954     %21 = OpTypeSampler
6955 %_ptr_UniformConstant_21 = OpTypePointer UniformConstant %21
6956     %5 = OpVariable %_ptr_UniformConstant_21 UniformConstant
6957    %23 = OpTypeSampledImage %19
6958     %6 = OpVariable %_ptr_UniformConstant_19 UniformConstant
6959     %2 = OpFunction %void None %8
6960    %24 = OpLabel
6961    %25 = OpVariable %_ptr_Function_v2uint Function
6962    %26 = OpLoad %19 %4
6963    %27 = OpLoad %21 %5
6964    %28 = OpSampledImage %23 %26 %27
6965    %29 = OpLoad %v2uint %25
6966    %30 = OpLoad %19 %6
6967    %31 = OpLoad %21 %5
6968    %32 = OpSampledImage %23 %30 %31
6969    %33 = OpImageBlockMatchSSDQCOM %v4float %28 %29 %32 %29 %29
6970          OpStore %3 %33
6971          OpReturn
6972          OpFunctionEnd
6973 )";
6974   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
6975   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
6976             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
6977   EXPECT_THAT(getDiagnosticString(),
6978               HasSubstr("Missing decoration BlockMatchTextureQCOM"));
6979 }
6980 
TEST_F(ValidateImage,QCOMImageProcessingBlockMatchSSDNoDecorationB)6981 TEST_F(ValidateImage, QCOMImageProcessingBlockMatchSSDNoDecorationB) {
6982   std::string text = R"(
6983            OpCapability Shader
6984            OpCapability TextureBlockMatchQCOM
6985            OpExtension "SPV_QCOM_image_processing"
6986       %1 = OpExtInstImport "GLSL.std.450"
6987            OpMemoryModel Logical GLSL450
6988            OpEntryPoint Fragment %2 "main" %3 %4 %5 %6
6989            OpExecutionMode %2 OriginUpperLeft
6990            OpDecorate %3 Location 0
6991            OpDecorate %4 DescriptorSet 0
6992            OpDecorate %4 Binding 1
6993            OpDecorate %5 DescriptorSet 0
6994            OpDecorate %5 Binding 3
6995            OpDecorate %5 BlockMatchTextureQCOM
6996            OpDecorate %6 DescriptorSet 0
6997            OpDecorate %6 Binding 2
6998    %void = OpTypeVoid
6999       %8 = OpTypeFunction %void
7000    %uint = OpTypeInt 32 0
7001  %v2uint = OpTypeVector %uint 2
7002 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
7003   %float = OpTypeFloat 32
7004 %v4float = OpTypeVector %float 4
7005 %_ptr_Input_float = OpTypePointer Input %float
7006 %_ptr_Function_uint = OpTypePointer Function %uint
7007 %uint_4 = OpConstant %uint 4
7008     %17 = OpConstantComposite %v2uint %uint_4 %uint_4
7009 %_ptr_Output_v4float = OpTypePointer Output %v4float
7010      %3 = OpVariable %_ptr_Output_v4float Output
7011     %19 = OpTypeImage %float 2D 0 0 0 1 Unknown
7012 %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19
7013      %4 = OpVariable %_ptr_UniformConstant_19 UniformConstant
7014     %21 = OpTypeSampler
7015 %_ptr_UniformConstant_21 = OpTypePointer UniformConstant %21
7016     %5 = OpVariable %_ptr_UniformConstant_21 UniformConstant
7017    %23 = OpTypeSampledImage %19
7018     %6 = OpVariable %_ptr_UniformConstant_19 UniformConstant
7019     %2 = OpFunction %void None %8
7020    %24 = OpLabel
7021    %25 = OpVariable %_ptr_Function_v2uint Function
7022    %26 = OpLoad %19 %4
7023    %27 = OpLoad %21 %5
7024    %28 = OpSampledImage %23 %26 %27
7025    %29 = OpLoad %v2uint %25
7026    %30 = OpLoad %19 %6
7027    %31 = OpLoad %21 %5
7028    %32 = OpSampledImage %23 %30 %31
7029    %33 = OpImageBlockMatchSSDQCOM %v4float %28 %29 %32 %29 %29
7030          OpStore %3 %33
7031          OpReturn
7032          OpFunctionEnd
7033 )";
7034   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
7035   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
7036             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
7037   EXPECT_THAT(getDiagnosticString(),
7038               HasSubstr("Missing decoration BlockMatchTextureQCOM"));
7039 }
7040 
TEST_F(ValidateImage,QCOMImageProcessingBlockMatchSSDNoDecorationC)7041 TEST_F(ValidateImage, QCOMImageProcessingBlockMatchSSDNoDecorationC) {
7042   std::string text = R"(
7043                OpCapability Shader
7044                OpCapability TextureBlockMatchQCOM
7045                OpExtension "SPV_QCOM_image_processing"
7046           %1 = OpExtInstImport "GLSL.std.450"
7047                OpMemoryModel Logical GLSL450
7048                OpEntryPoint Fragment %2 "main" %3 %4 %5
7049                OpExecutionMode %2 OriginUpperLeft
7050                OpDecorate %3 Location 0
7051                OpDecorate %4 DescriptorSet 0
7052                OpDecorate %4 Binding 4
7053                OpDecorate %5 DescriptorSet 0
7054                OpDecorate %5 Binding 5
7055                OpDecorate %5 BlockMatchTextureQCOM
7056        %void = OpTypeVoid
7057           %7 = OpTypeFunction %void
7058        %uint = OpTypeInt 32 0
7059      %v2uint = OpTypeVector %uint 2
7060 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
7061       %float = OpTypeFloat 32
7062     %v4float = OpTypeVector %float 4
7063 %_ptr_Input_v4float = OpTypePointer Input %v4float
7064 %_ptr_Input_float = OpTypePointer Input %float
7065 %_ptr_Function_uint = OpTypePointer Function %uint
7066 %_ptr_Output_v4float = OpTypePointer Output %v4float
7067           %3 = OpVariable %_ptr_Output_v4float Output
7068          %18 = OpTypeImage %float 2D 0 0 0 1 Unknown
7069          %19 = OpTypeSampledImage %18
7070 %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19
7071           %4 = OpVariable %_ptr_UniformConstant_19 UniformConstant
7072           %5 = OpVariable %_ptr_UniformConstant_19 UniformConstant
7073          %21 = OpTypeImage %float 2D 0 1 0 1 Unknown
7074           %2 = OpFunction %void None %7
7075          %22 = OpLabel
7076          %23 = OpVariable %_ptr_Function_v2uint Function
7077          %24 = OpLoad %19 %4
7078          %25 = OpLoad %v2uint %23
7079          %26 = OpLoad %19 %5
7080          %27 = OpLoad %v2uint %23
7081          %28 = OpLoad %v2uint %23
7082          %29 = OpImageBlockMatchSSDQCOM %v4float %24 %25 %26 %27 %28
7083                OpStore %3 %29
7084                OpReturn
7085                OpFunctionEnd
7086 )";
7087   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
7088   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
7089             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
7090   EXPECT_THAT(getDiagnosticString(),
7091               HasSubstr("Missing decoration BlockMatchTextureQCOM"));
7092 }
7093 
TEST_F(ValidateImage,QCOMImageProcessingBlockMatchSSDNoDecorationD)7094 TEST_F(ValidateImage, QCOMImageProcessingBlockMatchSSDNoDecorationD) {
7095   std::string text = R"(
7096                OpCapability Shader
7097                OpCapability TextureBlockMatchQCOM
7098                OpExtension "SPV_QCOM_image_processing"
7099           %1 = OpExtInstImport "GLSL.std.450"
7100                OpMemoryModel Logical GLSL450
7101                OpEntryPoint Fragment %2 "main" %3 %4 %5
7102                OpExecutionMode %2 OriginUpperLeft
7103                OpDecorate %3 Location 0
7104                OpDecorate %4 DescriptorSet 0
7105                OpDecorate %4 Binding 4
7106                OpDecorate %4 BlockMatchTextureQCOM
7107                OpDecorate %5 DescriptorSet 0
7108                OpDecorate %5 Binding 5
7109        %void = OpTypeVoid
7110           %7 = OpTypeFunction %void
7111        %uint = OpTypeInt 32 0
7112      %v2uint = OpTypeVector %uint 2
7113 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
7114       %float = OpTypeFloat 32
7115     %v4float = OpTypeVector %float 4
7116 %_ptr_Input_v4float = OpTypePointer Input %v4float
7117 %_ptr_Input_float = OpTypePointer Input %float
7118 %_ptr_Function_uint = OpTypePointer Function %uint
7119 %_ptr_Output_v4float = OpTypePointer Output %v4float
7120           %3 = OpVariable %_ptr_Output_v4float Output
7121          %18 = OpTypeImage %float 2D 0 0 0 1 Unknown
7122          %19 = OpTypeSampledImage %18
7123 %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19
7124           %4 = OpVariable %_ptr_UniformConstant_19 UniformConstant
7125           %5 = OpVariable %_ptr_UniformConstant_19 UniformConstant
7126          %21 = OpTypeImage %float 2D 0 1 0 1 Unknown
7127           %2 = OpFunction %void None %7
7128          %22 = OpLabel
7129          %23 = OpVariable %_ptr_Function_v2uint Function
7130          %24 = OpLoad %19 %4
7131          %25 = OpLoad %v2uint %23
7132          %26 = OpLoad %19 %5
7133          %27 = OpLoad %v2uint %23
7134          %28 = OpLoad %v2uint %23
7135          %29 = OpImageBlockMatchSSDQCOM %v4float %24 %25 %26 %27 %28
7136                OpStore %3 %29
7137                OpReturn
7138                OpFunctionEnd
7139 )";
7140   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
7141   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
7142             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
7143   EXPECT_THAT(getDiagnosticString(),
7144               HasSubstr("Missing decoration BlockMatchTextureQCOM"));
7145 }
7146 
TEST_F(ValidateImage,QCOMImageProcessingSampleWeightedNoDecorationA)7147 TEST_F(ValidateImage, QCOMImageProcessingSampleWeightedNoDecorationA) {
7148   std::string text = R"(
7149                OpCapability Shader
7150                OpCapability TextureSampleWeightedQCOM
7151                OpExtension "SPV_QCOM_image_processing"
7152           %1 = OpExtInstImport "GLSL.std.450"
7153                OpMemoryModel Logical GLSL450
7154                OpEntryPoint Fragment %2 "main" %3 %4 %5 %6 %7
7155                OpExecutionMode %2 OriginUpperLeft
7156                OpDecorate %3 Location 0
7157                OpDecorate %4 DescriptorSet 0
7158                OpDecorate %4 Binding 1
7159                OpDecorate %5 DescriptorSet 0
7160                OpDecorate %5 Binding 3
7161                OpDecorate %6 Location 0
7162                OpDecorate %7 DescriptorSet 0
7163                OpDecorate %7 Binding 0
7164        %void = OpTypeVoid
7165           %9 = OpTypeFunction %void
7166       %float = OpTypeFloat 32
7167     %v4float = OpTypeVector %float 4
7168 %_ptr_Output_v4float = OpTypePointer Output %v4float
7169           %3 = OpVariable %_ptr_Output_v4float Output
7170          %13 = OpTypeImage %float 2D 0 0 0 1 Unknown
7171 %_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
7172           %4 = OpVariable %_ptr_UniformConstant_13 UniformConstant
7173          %15 = OpTypeSampler
7174 %_ptr_UniformConstant_15 = OpTypePointer UniformConstant %15
7175           %5 = OpVariable %_ptr_UniformConstant_15 UniformConstant
7176          %17 = OpTypeSampledImage %13
7177 %_ptr_Input_v4float = OpTypePointer Input %v4float
7178           %6 = OpVariable %_ptr_Input_v4float Input
7179     %v2float = OpTypeVector %float 2
7180          %20 = OpTypeImage %float 2D 0 1 0 1 Unknown
7181 %_ptr_UniformConstant_20 = OpTypePointer UniformConstant %20
7182           %7 = OpVariable %_ptr_UniformConstant_20 UniformConstant
7183          %22 = OpTypeSampledImage %20
7184 %_ptr_UniformConstant_17 = OpTypePointer UniformConstant %17
7185           %2 = OpFunction %void None %9
7186          %24 = OpLabel
7187          %25 = OpLoad %13 %4
7188          %26 = OpLoad %15 %5
7189          %27 = OpSampledImage %17 %25 %26
7190          %28 = OpLoad %v4float %6
7191          %29 = OpVectorShuffle %v2float %28 %28 0 1
7192          %30 = OpLoad %20 %7
7193          %31 = OpLoad %15 %5
7194          %32 = OpSampledImage %22 %30 %31
7195          %33 = OpImageSampleWeightedQCOM %v4float %27 %29 %32
7196                OpStore %3 %33
7197                OpReturn
7198                OpFunctionEnd
7199 )";
7200   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
7201   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
7202             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
7203   EXPECT_THAT(getDiagnosticString(),
7204               HasSubstr("Missing decoration WeightTextureQCOM"));
7205 }
7206 
TEST_F(ValidateImage,QCOMImageProcessingSampleWeightedNoDecorationB)7207 TEST_F(ValidateImage, QCOMImageProcessingSampleWeightedNoDecorationB) {
7208   std::string text = R"(
7209                OpCapability Shader
7210                OpCapability TextureSampleWeightedQCOM
7211                OpExtension "SPV_QCOM_image_processing"
7212           %1 = OpExtInstImport "GLSL.std.450"
7213                OpMemoryModel Logical GLSL450
7214                OpEntryPoint Fragment %2 "main" %3 %4 %5 %6
7215                OpExecutionMode %2 OriginUpperLeft
7216                OpDecorate %3 Location 0
7217                OpDecorate %4 Location 0
7218                OpDecorate %5 DescriptorSet 0
7219                OpDecorate %5 Binding 4
7220                OpDecorate %6 DescriptorSet 0
7221                OpDecorate %6 Binding 5
7222        %void = OpTypeVoid
7223           %8 = OpTypeFunction %void
7224       %float = OpTypeFloat 32
7225     %v4float = OpTypeVector %float 4
7226 %_ptr_Output_v4float = OpTypePointer Output %v4float
7227           %3 = OpVariable %_ptr_Output_v4float Output
7228          %12 = OpTypeImage %float 2D 0 0 0 1 Unknown
7229 %_ptr_UniformConstant_12 = OpTypePointer UniformConstant %12
7230          %14 = OpTypeSampler
7231 %_ptr_UniformConstant_14 = OpTypePointer UniformConstant %14
7232          %16 = OpTypeSampledImage %12
7233 %_ptr_Input_v4float = OpTypePointer Input %v4float
7234           %4 = OpVariable %_ptr_Input_v4float Input
7235     %v2float = OpTypeVector %float 2
7236          %19 = OpTypeImage %float 2D 0 1 0 1 Unknown
7237 %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19
7238          %21 = OpTypeSampledImage %19
7239 %_ptr_UniformConstant_16 = OpTypePointer UniformConstant %16
7240           %5 = OpVariable %_ptr_UniformConstant_16 UniformConstant
7241 %_ptr_UniformConstant_21 = OpTypePointer UniformConstant %21
7242           %6 = OpVariable %_ptr_UniformConstant_21 UniformConstant
7243           %2 = OpFunction %void None %8
7244          %24 = OpLabel
7245          %25 = OpLoad %16 %5
7246          %26 = OpLoad %v4float %4
7247          %27 = OpVectorShuffle %v2float %26 %26 0 1
7248          %28 = OpLoad %21 %6
7249          %29 = OpImageSampleWeightedQCOM %v4float %25 %27 %28
7250                OpStore %3 %29
7251                OpReturn
7252                OpFunctionEnd
7253 )";
7254   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
7255   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
7256             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
7257   EXPECT_THAT(getDiagnosticString(),
7258               HasSubstr("Missing decoration WeightTextureQCOM"));
7259 }
7260 
TEST_F(ValidateImage,QCOMImageProcessingBlockMatchWindowSADInvalidUseA)7261 TEST_F(ValidateImage, QCOMImageProcessingBlockMatchWindowSADInvalidUseA) {
7262   std::string text = R"(
7263 ; SPIR-V
7264 ; Version: 1.0
7265 ; Generator: Khronos Glslang Reference Front End; 11
7266 ; Bound: 79
7267 ; Schema: 0
7268                OpCapability Shader
7269                OpCapability TextureBlockMatchQCOM
7270                OpExtension "SPV_QCOM_image_processing"
7271           %1 = OpExtInstImport "GLSL.std.450"
7272                OpMemoryModel Logical GLSL450
7273                OpEntryPoint Fragment %main "main" %100 %101 %102 %103 %104
7274                OpExecutionMode %main OriginUpperLeft
7275                OpDecorate %100 Location 0
7276                OpDecorate %101 Location 0
7277                OpDecorate %102 DescriptorSet 0
7278                OpDecorate %102 Binding 1
7279                OpDecorate %103 DescriptorSet 0
7280                OpDecorate %103 Binding 3
7281                OpDecorate %104 DescriptorSet 0
7282                OpDecorate %104 Binding 2
7283                OpDecorate %102 BlockMatchTextureQCOM
7284                OpDecorate %104 BlockMatchTextureQCOM
7285        %void = OpTypeVoid
7286           %3 = OpTypeFunction %void
7287        %uint = OpTypeInt 32 0
7288      %v2uint = OpTypeVector %uint 2
7289 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
7290       %float = OpTypeFloat 32
7291     %v4float = OpTypeVector %float 4
7292 %_ptr_Input_v4float = OpTypePointer Input %v4float
7293  %100 = OpVariable %_ptr_Input_v4float Input
7294 %_ptr_Output_v4float = OpTypePointer Output %v4float
7295   %101 = OpVariable %_ptr_Output_v4float Output
7296          %42 = OpTypeImage %float 2D 0 0 0 1 Unknown
7297 %_ptr_UniformConstant_42 = OpTypePointer UniformConstant %42
7298  %102 = OpVariable %_ptr_UniformConstant_42 UniformConstant
7299          %46 = OpTypeSampler
7300 %_ptr_UniformConstant_46 = OpTypePointer UniformConstant %46
7301        %103 = OpVariable %_ptr_UniformConstant_46 UniformConstant
7302          %50 = OpTypeSampledImage %42
7303  %104 = OpVariable %_ptr_UniformConstant_42 UniformConstant
7304     %v2float = OpTypeVector %float 2
7305        %main = OpFunction %void None %3
7306           %5 = OpLabel
7307          %15 = OpVariable %_ptr_Function_v2uint Function
7308          %45 = OpLoad %42 %102
7309          %49 = OpLoad %46 %103
7310          %51 = OpSampledImage %50 %45 %49
7311          %52 = OpLoad %v2uint %15
7312          %54 = OpLoad %42 %104
7313          %55 = OpLoad %46 %103
7314          %56 = OpSampledImage %50 %54 %55
7315          %57 = OpLoad %v2uint %15
7316          %58 = OpLoad %v2uint %15
7317          %59 = OpImageBlockMatchSADQCOM %v4float %51 %52 %56 %57 %58
7318                OpStore %101 %59
7319          %69 = OpLoad %42 %102
7320          %70 = OpLoad %46 %103
7321          %71 = OpSampledImage %50 %69 %70
7322          %73 = OpLoad %v4float %100
7323          %74 = OpVectorShuffle %v2float %73 %73 0 0
7324          %75 = OpImageSampleImplicitLod %v4float %71 %74
7325                OpStore %101 %75
7326                OpReturn
7327                OpFunctionEnd
7328 )";
7329   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
7330   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
7331             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
7332   EXPECT_THAT(
7333       getDiagnosticString(),
7334       HasSubstr("Illegal use of QCOM image processing decorated texture"));
7335 }
7336 
TEST_F(ValidateImage,QCOMImageProcessingBlockMatchSADInvalidUseB)7337 TEST_F(ValidateImage, QCOMImageProcessingBlockMatchSADInvalidUseB) {
7338   std::string text = R"(
7339 ; SPIR-V
7340 ; Version: 1.0
7341 ; Generator: Khronos Glslang Reference Front End; 11
7342 ; Bound: 79
7343 ; Schema: 0
7344                OpCapability Shader
7345                OpCapability TextureBlockMatchQCOM
7346                OpExtension "SPV_QCOM_image_processing"
7347           %1 = OpExtInstImport "GLSL.std.450"
7348                OpMemoryModel Logical GLSL450
7349                OpEntryPoint Fragment %main "main" %100 %101 %102 %103 %104
7350                OpExecutionMode %main OriginUpperLeft
7351                OpDecorate %100 Location 0
7352                OpDecorate %101 Location 0
7353                OpDecorate %102 DescriptorSet 0
7354                OpDecorate %102 Binding 1
7355                OpDecorate %103 DescriptorSet 0
7356                OpDecorate %103 Binding 3
7357                OpDecorate %104 DescriptorSet 0
7358                OpDecorate %104 Binding 2
7359                OpDecorate %102 BlockMatchTextureQCOM
7360                OpDecorate %104 BlockMatchTextureQCOM
7361        %void = OpTypeVoid
7362           %3 = OpTypeFunction %void
7363        %uint = OpTypeInt 32 0
7364      %v2uint = OpTypeVector %uint 2
7365 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
7366       %float = OpTypeFloat 32
7367     %v4float = OpTypeVector %float 4
7368 %_ptr_Input_v4float = OpTypePointer Input %v4float
7369  %100 = OpVariable %_ptr_Input_v4float Input
7370 %_ptr_Output_v4float = OpTypePointer Output %v4float
7371   %101 = OpVariable %_ptr_Output_v4float Output
7372          %42 = OpTypeImage %float 2D 0 0 0 1 Unknown
7373 %_ptr_UniformConstant_42 = OpTypePointer UniformConstant %42
7374  %102 = OpVariable %_ptr_UniformConstant_42 UniformConstant
7375          %46 = OpTypeSampler
7376 %_ptr_UniformConstant_46 = OpTypePointer UniformConstant %46
7377        %103 = OpVariable %_ptr_UniformConstant_46 UniformConstant
7378          %50 = OpTypeSampledImage %42
7379  %104 = OpVariable %_ptr_UniformConstant_42 UniformConstant
7380     %v2float = OpTypeVector %float 2
7381        %main = OpFunction %void None %3
7382           %5 = OpLabel
7383          %15 = OpVariable %_ptr_Function_v2uint Function
7384          %45 = OpLoad %42 %102
7385          %49 = OpLoad %46 %103
7386          %51 = OpSampledImage %50 %45 %49
7387          %52 = OpLoad %v2uint %15
7388          %54 = OpLoad %42 %104
7389          %55 = OpLoad %46 %103
7390          %56 = OpSampledImage %50 %54 %55
7391          %57 = OpLoad %v2uint %15
7392          %58 = OpLoad %v2uint %15
7393          %59 = OpImageBlockMatchSADQCOM %v4float %51 %52 %56 %57 %58
7394                OpStore %101 %59
7395          %69 = OpLoad %42 %104
7396          %70 = OpLoad %46 %103
7397          %71 = OpSampledImage %50 %69 %70
7398          %73 = OpLoad %v4float %100
7399          %74 = OpVectorShuffle %v2float %73 %73 0 0
7400          %75 = OpImageSampleImplicitLod %v4float %71 %74
7401                OpStore %101 %75
7402                OpReturn
7403                OpFunctionEnd
7404 )";
7405   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
7406   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
7407             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
7408   EXPECT_THAT(
7409       getDiagnosticString(),
7410       HasSubstr("Illegal use of QCOM image processing decorated texture"));
7411 }
7412 
TEST_F(ValidateImage,QCOMImageProcessingBlockMatchSADInvalidUseC)7413 TEST_F(ValidateImage, QCOMImageProcessingBlockMatchSADInvalidUseC) {
7414   std::string text = R"(
7415                OpCapability Shader
7416                OpCapability TextureBlockMatchQCOM
7417                OpExtension "SPV_QCOM_image_processing"
7418           %1 = OpExtInstImport "GLSL.std.450"
7419                OpMemoryModel Logical GLSL450
7420                OpEntryPoint Fragment %2 "main" %3 %4 %5 %6
7421                OpExecutionMode %2 OriginUpperLeft
7422                OpDecorate %3 Location 0
7423                OpDecorate %4 Location 0
7424                OpDecorate %5 DescriptorSet 0
7425                OpDecorate %5 Binding 4
7426                OpDecorate %6 DescriptorSet 0
7427                OpDecorate %6 Binding 5
7428                OpDecorate %5 BlockMatchTextureQCOM
7429                OpDecorate %6 BlockMatchTextureQCOM
7430        %void = OpTypeVoid
7431           %8 = OpTypeFunction %void
7432        %uint = OpTypeInt 32 0
7433      %v2uint = OpTypeVector %uint 2
7434 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
7435       %float = OpTypeFloat 32
7436     %v4float = OpTypeVector %float 4
7437 %_ptr_Input_v4float = OpTypePointer Input %v4float
7438           %3 = OpVariable %_ptr_Input_v4float Input
7439      %uint_4 = OpConstant %uint 4
7440          %16 = OpConstantComposite %v2uint %uint_4 %uint_4
7441 %_ptr_Output_v4float = OpTypePointer Output %v4float
7442           %4 = OpVariable %_ptr_Output_v4float Output
7443          %18 = OpTypeImage %float 2D 0 0 0 1 Unknown
7444 %_ptr_UniformConstant_18 = OpTypePointer UniformConstant %18
7445          %20 = OpTypeSampledImage %18
7446 %_ptr_UniformConstant_20 = OpTypePointer UniformConstant %20
7447           %5 = OpVariable %_ptr_UniformConstant_20 UniformConstant
7448           %6 = OpVariable %_ptr_UniformConstant_20 UniformConstant
7449     %v2float = OpTypeVector %float 2
7450          %23 = OpTypeImage %float 2D 0 1 0 1 Unknown
7451           %2 = OpFunction %void None %8
7452          %24 = OpLabel
7453          %25 = OpVariable %_ptr_Function_v2uint Function
7454                OpStore %25 %16
7455          %26 = OpLoad %20 %5
7456          %27 = OpLoad %v2uint %25
7457          %28 = OpLoad %20 %6
7458          %29 = OpLoad %v2uint %25
7459          %30 = OpLoad %v2uint %25
7460          %31 = OpImageBlockMatchSADQCOM %v4float %26 %27 %28 %29 %30
7461                OpStore %4 %31
7462          %32 = OpLoad %20 %5
7463          %33 = OpLoad %v4float %3
7464          %34 = OpVectorShuffle %v2float %33 %33 0 2
7465          %35 = OpImageSampleImplicitLod %v4float %32 %34
7466                OpStore %4 %35
7467                OpReturn
7468                OpFunctionEnd
7469 )";
7470   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
7471   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
7472             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
7473   EXPECT_THAT(
7474       getDiagnosticString(),
7475       HasSubstr("Illegal use of QCOM image processing decorated texture"));
7476 }
7477 
TEST_F(ValidateImage,QCOMImageProcessingBlockMatchSADInvalidUseD)7478 TEST_F(ValidateImage, QCOMImageProcessingBlockMatchSADInvalidUseD) {
7479   std::string text = R"(
7480                OpCapability Shader
7481                OpCapability TextureBlockMatchQCOM
7482                OpExtension "SPV_QCOM_image_processing"
7483           %1 = OpExtInstImport "GLSL.std.450"
7484                OpMemoryModel Logical GLSL450
7485                OpEntryPoint Fragment %2 "main" %3 %4 %5 %6
7486                OpExecutionMode %2 OriginUpperLeft
7487                OpDecorate %3 Location 0
7488                OpDecorate %4 Location 0
7489                OpDecorate %5 DescriptorSet 0
7490                OpDecorate %5 Binding 4
7491                OpDecorate %6 DescriptorSet 0
7492                OpDecorate %6 Binding 5
7493                OpDecorate %5 BlockMatchTextureQCOM
7494                OpDecorate %6 BlockMatchTextureQCOM
7495        %void = OpTypeVoid
7496           %8 = OpTypeFunction %void
7497        %uint = OpTypeInt 32 0
7498      %v2uint = OpTypeVector %uint 2
7499 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
7500       %float = OpTypeFloat 32
7501     %v4float = OpTypeVector %float 4
7502 %_ptr_Input_v4float = OpTypePointer Input %v4float
7503           %3 = OpVariable %_ptr_Input_v4float Input
7504      %uint_4 = OpConstant %uint 4
7505          %16 = OpConstantComposite %v2uint %uint_4 %uint_4
7506 %_ptr_Output_v4float = OpTypePointer Output %v4float
7507           %4 = OpVariable %_ptr_Output_v4float Output
7508          %18 = OpTypeImage %float 2D 0 0 0 1 Unknown
7509 %_ptr_UniformConstant_18 = OpTypePointer UniformConstant %18
7510          %20 = OpTypeSampledImage %18
7511 %_ptr_UniformConstant_20 = OpTypePointer UniformConstant %20
7512           %5 = OpVariable %_ptr_UniformConstant_20 UniformConstant
7513           %6 = OpVariable %_ptr_UniformConstant_20 UniformConstant
7514     %v2float = OpTypeVector %float 2
7515          %23 = OpTypeImage %float 2D 0 1 0 1 Unknown
7516           %2 = OpFunction %void None %8
7517          %24 = OpLabel
7518          %25 = OpVariable %_ptr_Function_v2uint Function
7519                OpStore %25 %16
7520          %26 = OpLoad %20 %5
7521          %27 = OpLoad %v2uint %25
7522          %28 = OpLoad %20 %6
7523          %29 = OpLoad %v2uint %25
7524          %30 = OpLoad %v2uint %25
7525          %31 = OpImageBlockMatchSADQCOM %v4float %26 %27 %28 %29 %30
7526                OpStore %4 %31
7527          %32 = OpLoad %20 %6
7528          %33 = OpLoad %v4float %3
7529          %34 = OpVectorShuffle %v2float %33 %33 0 2
7530          %35 = OpImageSampleImplicitLod %v4float %32 %34
7531                OpStore %4 %35
7532                OpReturn
7533                OpFunctionEnd
7534 )";
7535   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
7536   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
7537             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
7538   EXPECT_THAT(
7539       getDiagnosticString(),
7540       HasSubstr("Illegal use of QCOM image processing decorated texture"));
7541 }
7542 
TEST_F(ValidateImage,QCOMImageProcessingBlockMatchSSDInvalidUseA)7543 TEST_F(ValidateImage, QCOMImageProcessingBlockMatchSSDInvalidUseA) {
7544   std::string text = R"(
7545 ; SPIR-V
7546 ; Version: 1.0
7547 ; Generator: Khronos Glslang Reference Front End; 11
7548 ; Bound: 79
7549 ; Schema: 0
7550                OpCapability Shader
7551                OpCapability TextureBlockMatchQCOM
7552                OpExtension "SPV_QCOM_image_processing"
7553           %1 = OpExtInstImport "GLSL.std.450"
7554                OpMemoryModel Logical GLSL450
7555                OpEntryPoint Fragment %main "main" %100 %101 %102 %103 %104
7556                OpExecutionMode %main OriginUpperLeft
7557                OpDecorate %100 Location 0
7558                OpDecorate %101 Location 0
7559                OpDecorate %102 DescriptorSet 0
7560                OpDecorate %102 Binding 1
7561                OpDecorate %103 DescriptorSet 0
7562                OpDecorate %103 Binding 3
7563                OpDecorate %104 DescriptorSet 0
7564                OpDecorate %104 Binding 2
7565                OpDecorate %102 BlockMatchTextureQCOM
7566                OpDecorate %104 BlockMatchTextureQCOM
7567        %void = OpTypeVoid
7568           %3 = OpTypeFunction %void
7569        %uint = OpTypeInt 32 0
7570      %v2uint = OpTypeVector %uint 2
7571 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
7572       %float = OpTypeFloat 32
7573     %v4float = OpTypeVector %float 4
7574 %_ptr_Input_v4float = OpTypePointer Input %v4float
7575  %100 = OpVariable %_ptr_Input_v4float Input
7576 %_ptr_Output_v4float = OpTypePointer Output %v4float
7577   %101 = OpVariable %_ptr_Output_v4float Output
7578          %42 = OpTypeImage %float 2D 0 0 0 1 Unknown
7579 %_ptr_UniformConstant_42 = OpTypePointer UniformConstant %42
7580  %102 = OpVariable %_ptr_UniformConstant_42 UniformConstant
7581          %46 = OpTypeSampler
7582 %_ptr_UniformConstant_46 = OpTypePointer UniformConstant %46
7583        %103 = OpVariable %_ptr_UniformConstant_46 UniformConstant
7584          %50 = OpTypeSampledImage %42
7585  %104 = OpVariable %_ptr_UniformConstant_42 UniformConstant
7586     %v2float = OpTypeVector %float 2
7587        %main = OpFunction %void None %3
7588           %5 = OpLabel
7589          %15 = OpVariable %_ptr_Function_v2uint Function
7590          %45 = OpLoad %42 %102
7591          %49 = OpLoad %46 %103
7592          %51 = OpSampledImage %50 %45 %49
7593          %52 = OpLoad %v2uint %15
7594          %54 = OpLoad %42 %104
7595          %55 = OpLoad %46 %103
7596          %56 = OpSampledImage %50 %54 %55
7597          %57 = OpLoad %v2uint %15
7598          %58 = OpLoad %v2uint %15
7599          %59 = OpImageBlockMatchSSDQCOM %v4float %51 %52 %56 %57 %58
7600                OpStore %101 %59
7601          %69 = OpLoad %42 %102
7602          %70 = OpLoad %46 %103
7603          %71 = OpSampledImage %50 %69 %70
7604          %73 = OpLoad %v4float %100
7605          %74 = OpVectorShuffle %v2float %73 %73 0 0
7606          %75 = OpImageSampleImplicitLod %v4float %71 %74
7607                OpStore %101 %75
7608                OpReturn
7609                OpFunctionEnd
7610 )";
7611   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
7612   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
7613             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
7614   EXPECT_THAT(
7615       getDiagnosticString(),
7616       HasSubstr("Illegal use of QCOM image processing decorated texture"));
7617 }
7618 
TEST_F(ValidateImage,QCOMImageProcessingBlockMatchSSDInvalidUseB)7619 TEST_F(ValidateImage, QCOMImageProcessingBlockMatchSSDInvalidUseB) {
7620   std::string text = R"(
7621 ; SPIR-V
7622 ; Version: 1.0
7623 ; Generator: Khronos Glslang Reference Front End; 11
7624 ; Bound: 79
7625 ; Schema: 0
7626                OpCapability Shader
7627                OpCapability TextureBlockMatchQCOM
7628                OpExtension "SPV_QCOM_image_processing"
7629           %1 = OpExtInstImport "GLSL.std.450"
7630                OpMemoryModel Logical GLSL450
7631                OpEntryPoint Fragment %main "main" %100 %101 %102 %103 %104
7632                OpExecutionMode %main OriginUpperLeft
7633                OpDecorate %100 Location 0
7634                OpDecorate %101 Location 0
7635                OpDecorate %102 DescriptorSet 0
7636                OpDecorate %102 Binding 1
7637                OpDecorate %103 DescriptorSet 0
7638                OpDecorate %103 Binding 3
7639                OpDecorate %104 DescriptorSet 0
7640                OpDecorate %104 Binding 2
7641                OpDecorate %102 BlockMatchTextureQCOM
7642                OpDecorate %104 BlockMatchTextureQCOM
7643        %void = OpTypeVoid
7644           %3 = OpTypeFunction %void
7645        %uint = OpTypeInt 32 0
7646      %v2uint = OpTypeVector %uint 2
7647 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
7648       %float = OpTypeFloat 32
7649     %v4float = OpTypeVector %float 4
7650 %_ptr_Input_v4float = OpTypePointer Input %v4float
7651  %100 = OpVariable %_ptr_Input_v4float Input
7652 %_ptr_Output_v4float = OpTypePointer Output %v4float
7653   %101 = OpVariable %_ptr_Output_v4float Output
7654          %42 = OpTypeImage %float 2D 0 0 0 1 Unknown
7655 %_ptr_UniformConstant_42 = OpTypePointer UniformConstant %42
7656  %102 = OpVariable %_ptr_UniformConstant_42 UniformConstant
7657          %46 = OpTypeSampler
7658 %_ptr_UniformConstant_46 = OpTypePointer UniformConstant %46
7659        %103 = OpVariable %_ptr_UniformConstant_46 UniformConstant
7660          %50 = OpTypeSampledImage %42
7661  %104 = OpVariable %_ptr_UniformConstant_42 UniformConstant
7662     %v2float = OpTypeVector %float 2
7663        %main = OpFunction %void None %3
7664           %5 = OpLabel
7665          %15 = OpVariable %_ptr_Function_v2uint Function
7666          %45 = OpLoad %42 %102
7667          %49 = OpLoad %46 %103
7668          %51 = OpSampledImage %50 %45 %49
7669          %52 = OpLoad %v2uint %15
7670          %54 = OpLoad %42 %104
7671          %55 = OpLoad %46 %103
7672          %56 = OpSampledImage %50 %54 %55
7673          %57 = OpLoad %v2uint %15
7674          %58 = OpLoad %v2uint %15
7675          %59 = OpImageBlockMatchSSDQCOM %v4float %51 %52 %56 %57 %58
7676                OpStore %101 %59
7677          %69 = OpLoad %42 %104
7678          %70 = OpLoad %46 %103
7679          %71 = OpSampledImage %50 %69 %70
7680          %73 = OpLoad %v4float %100
7681          %74 = OpVectorShuffle %v2float %73 %73 0 0
7682          %75 = OpImageSampleImplicitLod %v4float %71 %74
7683                OpStore %101 %75
7684                OpReturn
7685                OpFunctionEnd
7686 )";
7687   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
7688   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
7689             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
7690   EXPECT_THAT(
7691       getDiagnosticString(),
7692       HasSubstr("Illegal use of QCOM image processing decorated texture"));
7693 }
7694 
TEST_F(ValidateImage,QCOMImageProcessingBlockMatchSSDInvalidUseC)7695 TEST_F(ValidateImage, QCOMImageProcessingBlockMatchSSDInvalidUseC) {
7696   std::string text = R"(
7697                OpCapability Shader
7698                OpCapability TextureBlockMatchQCOM
7699                OpExtension "SPV_QCOM_image_processing"
7700           %1 = OpExtInstImport "GLSL.std.450"
7701                OpMemoryModel Logical GLSL450
7702                OpEntryPoint Fragment %2 "main" %3 %4 %5 %6
7703                OpExecutionMode %2 OriginUpperLeft
7704                OpDecorate %3 Location 0
7705                OpDecorate %4 Location 0
7706                OpDecorate %5 DescriptorSet 0
7707                OpDecorate %5 Binding 4
7708                OpDecorate %6 DescriptorSet 0
7709                OpDecorate %6 Binding 5
7710                OpDecorate %5 BlockMatchTextureQCOM
7711                OpDecorate %6 BlockMatchTextureQCOM
7712        %void = OpTypeVoid
7713           %8 = OpTypeFunction %void
7714        %uint = OpTypeInt 32 0
7715      %v2uint = OpTypeVector %uint 2
7716 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
7717       %float = OpTypeFloat 32
7718     %v4float = OpTypeVector %float 4
7719 %_ptr_Input_v4float = OpTypePointer Input %v4float
7720           %3 = OpVariable %_ptr_Input_v4float Input
7721      %uint_4 = OpConstant %uint 4
7722          %16 = OpConstantComposite %v2uint %uint_4 %uint_4
7723 %_ptr_Output_v4float = OpTypePointer Output %v4float
7724           %4 = OpVariable %_ptr_Output_v4float Output
7725          %18 = OpTypeImage %float 2D 0 0 0 1 Unknown
7726 %_ptr_UniformConstant_18 = OpTypePointer UniformConstant %18
7727          %20 = OpTypeSampledImage %18
7728 %_ptr_UniformConstant_20 = OpTypePointer UniformConstant %20
7729           %5 = OpVariable %_ptr_UniformConstant_20 UniformConstant
7730           %6 = OpVariable %_ptr_UniformConstant_20 UniformConstant
7731     %v2float = OpTypeVector %float 2
7732          %23 = OpTypeImage %float 2D 0 1 0 1 Unknown
7733           %2 = OpFunction %void None %8
7734          %24 = OpLabel
7735          %25 = OpVariable %_ptr_Function_v2uint Function
7736                OpStore %25 %16
7737          %26 = OpLoad %20 %5
7738          %27 = OpLoad %v2uint %25
7739          %28 = OpLoad %20 %6
7740          %29 = OpLoad %v2uint %25
7741          %30 = OpLoad %v2uint %25
7742          %31 = OpImageBlockMatchSSDQCOM %v4float %26 %27 %28 %29 %30
7743                OpStore %4 %31
7744          %32 = OpLoad %20 %5
7745          %33 = OpLoad %v4float %3
7746          %34 = OpVectorShuffle %v2float %33 %33 0 2
7747          %35 = OpImageSampleImplicitLod %v4float %32 %34
7748                OpStore %4 %35
7749                OpReturn
7750                OpFunctionEnd
7751 )";
7752   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
7753   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
7754             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
7755   EXPECT_THAT(
7756       getDiagnosticString(),
7757       HasSubstr("Illegal use of QCOM image processing decorated texture"));
7758 }
7759 
TEST_F(ValidateImage,QCOMImageProcessingBlockMatchSSDInvalidUseD)7760 TEST_F(ValidateImage, QCOMImageProcessingBlockMatchSSDInvalidUseD) {
7761   std::string text = R"(
7762                OpCapability Shader
7763                OpCapability TextureBlockMatchQCOM
7764                OpExtension "SPV_QCOM_image_processing"
7765           %1 = OpExtInstImport "GLSL.std.450"
7766                OpMemoryModel Logical GLSL450
7767                OpEntryPoint Fragment %2 "main" %3 %4 %5 %6
7768                OpExecutionMode %2 OriginUpperLeft
7769                OpDecorate %3 Location 0
7770                OpDecorate %4 Location 0
7771                OpDecorate %5 DescriptorSet 0
7772                OpDecorate %5 Binding 4
7773                OpDecorate %6 DescriptorSet 0
7774                OpDecorate %6 Binding 5
7775                OpDecorate %5 BlockMatchTextureQCOM
7776                OpDecorate %6 BlockMatchTextureQCOM
7777        %void = OpTypeVoid
7778           %8 = OpTypeFunction %void
7779        %uint = OpTypeInt 32 0
7780      %v2uint = OpTypeVector %uint 2
7781 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
7782       %float = OpTypeFloat 32
7783     %v4float = OpTypeVector %float 4
7784 %_ptr_Input_v4float = OpTypePointer Input %v4float
7785           %3 = OpVariable %_ptr_Input_v4float Input
7786      %uint_4 = OpConstant %uint 4
7787          %16 = OpConstantComposite %v2uint %uint_4 %uint_4
7788 %_ptr_Output_v4float = OpTypePointer Output %v4float
7789           %4 = OpVariable %_ptr_Output_v4float Output
7790          %18 = OpTypeImage %float 2D 0 0 0 1 Unknown
7791 %_ptr_UniformConstant_18 = OpTypePointer UniformConstant %18
7792          %20 = OpTypeSampledImage %18
7793 %_ptr_UniformConstant_20 = OpTypePointer UniformConstant %20
7794           %5 = OpVariable %_ptr_UniformConstant_20 UniformConstant
7795           %6 = OpVariable %_ptr_UniformConstant_20 UniformConstant
7796     %v2float = OpTypeVector %float 2
7797          %23 = OpTypeImage %float 2D 0 1 0 1 Unknown
7798           %2 = OpFunction %void None %8
7799          %24 = OpLabel
7800          %25 = OpVariable %_ptr_Function_v2uint Function
7801                OpStore %25 %16
7802          %26 = OpLoad %20 %5
7803          %27 = OpLoad %v2uint %25
7804          %28 = OpLoad %20 %6
7805          %29 = OpLoad %v2uint %25
7806          %30 = OpLoad %v2uint %25
7807          %31 = OpImageBlockMatchSSDQCOM %v4float %26 %27 %28 %29 %30
7808                OpStore %4 %31
7809          %32 = OpLoad %20 %6
7810          %33 = OpLoad %v4float %3
7811          %34 = OpVectorShuffle %v2float %33 %33 0 2
7812          %35 = OpImageSampleImplicitLod %v4float %32 %34
7813                OpStore %4 %35
7814                OpReturn
7815                OpFunctionEnd
7816 )";
7817   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
7818   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
7819             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
7820   EXPECT_THAT(
7821       getDiagnosticString(),
7822       HasSubstr("Illegal use of QCOM image processing decorated texture"));
7823 }
7824 
TEST_F(ValidateImage,QCOMImageProcessingSampleWeightedInvalidUseA)7825 TEST_F(ValidateImage, QCOMImageProcessingSampleWeightedInvalidUseA) {
7826   std::string text = R"(
7827                OpCapability Shader
7828                OpCapability TextureSampleWeightedQCOM
7829                OpExtension "SPV_QCOM_image_processing"
7830           %1 = OpExtInstImport "GLSL.std.450"
7831                OpMemoryModel Logical GLSL450
7832                OpEntryPoint Fragment %2 "main" %3 %4 %5 %6
7833                OpExecutionMode %2 OriginUpperLeft
7834                OpDecorate %3 Location 0
7835                OpDecorate %4 Location 0
7836                OpDecorate %5 DescriptorSet 0
7837                OpDecorate %5 Binding 4
7838                OpDecorate %6 DescriptorSet 0
7839                OpDecorate %6 Binding 5
7840                OpDecorate %6 WeightTextureQCOM
7841        %void = OpTypeVoid
7842           %8 = OpTypeFunction %void
7843       %float = OpTypeFloat 32
7844     %v4float = OpTypeVector %float 4
7845 %_ptr_Output_v4float = OpTypePointer Output %v4float
7846           %3 = OpVariable %_ptr_Output_v4float Output
7847          %12 = OpTypeImage %float 2D 0 0 0 1 Unknown
7848 %_ptr_UniformConstant_12 = OpTypePointer UniformConstant %12
7849          %14 = OpTypeSampledImage %12
7850 %_ptr_Input_v4float = OpTypePointer Input %v4float
7851           %4 = OpVariable %_ptr_Input_v4float Input
7852     %v2float = OpTypeVector %float 2
7853          %17 = OpTypeImage %float 2D 0 1 0 1 Unknown
7854 %_ptr_UniformConstant_17 = OpTypePointer UniformConstant %17
7855          %19 = OpTypeSampledImage %17
7856 %_ptr_UniformConstant_14 = OpTypePointer UniformConstant %14
7857           %5 = OpVariable %_ptr_UniformConstant_14 UniformConstant
7858 %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19
7859           %6 = OpVariable %_ptr_UniformConstant_19 UniformConstant
7860     %v3float = OpTypeVector %float 3
7861           %2 = OpFunction %void None %8
7862          %23 = OpLabel
7863          %24 = OpLoad %v4float %4
7864          %25 = OpVectorShuffle %v2float %24 %24 0 1
7865          %26 = OpLoad %14 %5
7866          %27 = OpLoad %v4float %4
7867          %28 = OpVectorShuffle %v2float %27 %27 0 1
7868          %29 = OpLoad %19 %6
7869          %30 = OpImageSampleWeightedQCOM %v4float %26 %28 %29
7870                OpStore %3 %30
7871          %31 = OpLoad %19 %6
7872          %32 = OpLoad %v4float %4
7873          %33 = OpVectorShuffle %v3float %32 %32 0 1 0
7874          %34 = OpCompositeExtract %float %33 0
7875          %35 = OpCompositeExtract %float %33 1
7876          %36 = OpCompositeExtract %float %33 2
7877          %37 = OpCompositeConstruct %v3float %34 %35 %36
7878          %38 = OpImageSampleImplicitLod %v4float %31 %37
7879                OpStore %3 %38
7880                OpReturn
7881                OpFunctionEnd
7882 )";
7883   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
7884   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
7885             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
7886   EXPECT_THAT(
7887       getDiagnosticString(),
7888       HasSubstr("Illegal use of QCOM image processing decorated texture"));
7889 }
7890 
TEST_F(ValidateImage,QCOMImageProcessingSampleWeightedInvalidUseB)7891 TEST_F(ValidateImage, QCOMImageProcessingSampleWeightedInvalidUseB) {
7892   std::string text = R"(
7893                OpCapability Shader
7894                OpCapability TextureSampleWeightedQCOM
7895                OpExtension "SPV_QCOM_image_processing"
7896           %1 = OpExtInstImport "GLSL.std.450"
7897                OpMemoryModel Logical GLSL450
7898                OpEntryPoint Fragment %2 "main" %3 %4 %5 %6 %7
7899                OpExecutionMode %2 OriginUpperLeft
7900                OpDecorate %3 Location 0
7901                OpDecorate %5 DescriptorSet 0
7902                OpDecorate %5 Binding 1
7903                OpDecorate %6 DescriptorSet 0
7904                OpDecorate %6 Binding 3
7905                OpDecorate %4 Location 0
7906                OpDecorate %7 DescriptorSet 0
7907                OpDecorate %7 Binding 0
7908                OpDecorate %7 WeightTextureQCOM
7909        %void = OpTypeVoid
7910           %9 = OpTypeFunction %void
7911       %float = OpTypeFloat 32
7912     %v4float = OpTypeVector %float 4
7913 %_ptr_Output_v4float = OpTypePointer Output %v4float
7914           %3 = OpVariable %_ptr_Output_v4float Output
7915          %13 = OpTypeImage %float 2D 0 0 0 1 Unknown
7916 %_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
7917           %5 = OpVariable %_ptr_UniformConstant_13 UniformConstant
7918          %15 = OpTypeSampler
7919 %_ptr_UniformConstant_15 = OpTypePointer UniformConstant %15
7920           %6 = OpVariable %_ptr_UniformConstant_15 UniformConstant
7921          %17 = OpTypeSampledImage %13
7922 %_ptr_Input_v4float = OpTypePointer Input %v4float
7923           %4 = OpVariable %_ptr_Input_v4float Input
7924     %v2float = OpTypeVector %float 2
7925          %20 = OpTypeImage %float 2D 0 1 0 1 Unknown
7926 %_ptr_UniformConstant_20 = OpTypePointer UniformConstant %20
7927           %7 = OpVariable %_ptr_UniformConstant_20 UniformConstant
7928          %22 = OpTypeSampledImage %20
7929     %v3float = OpTypeVector %float 3
7930           %2 = OpFunction %void None %9
7931          %24 = OpLabel
7932          %25 = OpLoad %13 %5
7933          %26 = OpLoad %15 %6
7934          %27 = OpSampledImage %17 %25 %26
7935          %28 = OpLoad %v4float %4
7936          %29 = OpVectorShuffle %v2float %28 %28 0 1
7937          %30 = OpLoad %20 %7
7938          %31 = OpLoad %15 %6
7939          %32 = OpSampledImage %22 %30 %31
7940          %33 = OpImageSampleWeightedQCOM %v4float %27 %29 %32
7941                OpStore %3 %33
7942          %34 = OpLoad %20 %7
7943          %35 = OpLoad %15 %6
7944          %36 = OpSampledImage %22 %34 %35
7945          %37 = OpLoad %v4float %4
7946          %38 = OpVectorShuffle %v3float %37 %37 0 1 0
7947          %39 = OpCompositeExtract %float %38 0
7948          %40 = OpCompositeExtract %float %38 1
7949          %41 = OpCompositeExtract %float %38 2
7950          %42 = OpCompositeConstruct %v3float %39 %40 %41
7951          %43 = OpImageSampleImplicitLod %v4float %36 %42
7952                OpStore %3 %43
7953                OpReturn
7954                OpFunctionEnd
7955 )";
7956   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
7957   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
7958             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
7959   EXPECT_THAT(
7960       getDiagnosticString(),
7961       HasSubstr("Illegal use of QCOM image processing decorated texture"));
7962 }
7963 
TEST_F(ValidateImage,QCOMImageProcessing2BlockMatchWindowSADNoDecorTargetIT)7964 TEST_F(ValidateImage, QCOMImageProcessing2BlockMatchWindowSADNoDecorTargetIT) {
7965   const std::string text = R"(
7966                OpCapability Shader
7967                OpCapability TextureBlockMatchQCOM
7968                OpCapability TextureBlockMatch2QCOM
7969                OpExtension "SPV_QCOM_image_processing"
7970                OpExtension "SPV_QCOM_image_processing2"
7971           %1 = OpExtInstImport "GLSL.std.450"
7972                OpMemoryModel Logical GLSL450
7973                OpEntryPoint Fragment %2 "main" %3 %4 %5
7974                OpExecutionMode %2 OriginUpperLeft
7975                OpDecorate %3 Location 0
7976                OpDecorate %4 DescriptorSet 0
7977                OpDecorate %4 Binding 4
7978                OpDecorate %4 BlockMatchSamplerQCOM
7979                OpDecorate %5 DescriptorSet 0
7980                OpDecorate %5 Binding 5
7981                OpDecorate %5 BlockMatchTextureQCOM
7982                OpDecorate %5 BlockMatchSamplerQCOM
7983        %void = OpTypeVoid
7984           %7 = OpTypeFunction %void
7985        %uint = OpTypeInt 32 0
7986      %v2uint = OpTypeVector %uint 2
7987 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
7988       %float = OpTypeFloat 32
7989     %v4float = OpTypeVector %float 4
7990 %_ptr_Input_v4float = OpTypePointer Input %v4float
7991 %_ptr_Input_float = OpTypePointer Input %float
7992 %_ptr_Function_uint = OpTypePointer Function %uint
7993 %_ptr_Output_v4float = OpTypePointer Output %v4float
7994           %3 = OpVariable %_ptr_Output_v4float Output
7995          %18 = OpTypeImage %float 2D 0 0 0 1 Unknown
7996          %19 = OpTypeSampledImage %18
7997 %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19
7998           %4 = OpVariable %_ptr_UniformConstant_19 UniformConstant
7999           %5 = OpVariable %_ptr_UniformConstant_19 UniformConstant
8000          %21 = OpTypeImage %float 2D 0 1 0 1 Unknown
8001           %2 = OpFunction %void None %7
8002          %22 = OpLabel
8003          %23 = OpVariable %_ptr_Function_v2uint Function
8004          %24 = OpLoad %19 %4
8005          %25 = OpLoad %v2uint %23
8006          %26 = OpLoad %19 %5
8007          %27 = OpLoad %v2uint %23
8008          %28 = OpLoad %v2uint %23
8009          %29 = OpImageBlockMatchWindowSADQCOM %v4float %24 %25 %26 %27 %28
8010                OpStore %3 %29
8011                OpReturn
8012                OpFunctionEnd
8013 )";
8014   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
8015   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
8016             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
8017   EXPECT_THAT(getDiagnosticString(),
8018               HasSubstr("Missing decoration BlockMatchTextureQCOM"));
8019 }
8020 
TEST_F(ValidateImage,QCOMImageProcessing2BlockMatchWindowSADNoDecorTargetIS)8021 TEST_F(ValidateImage, QCOMImageProcessing2BlockMatchWindowSADNoDecorTargetIS) {
8022   const std::string text = R"(
8023                OpCapability Shader
8024                OpCapability TextureBlockMatchQCOM
8025                OpCapability TextureBlockMatch2QCOM
8026                OpExtension "SPV_QCOM_image_processing"
8027                OpExtension "SPV_QCOM_image_processing2"
8028           %1 = OpExtInstImport "GLSL.std.450"
8029                OpMemoryModel Logical GLSL450
8030                OpEntryPoint Fragment %2 "main" %3 %4 %5
8031                OpExecutionMode %2 OriginUpperLeft
8032                OpDecorate %3 Location 0
8033                OpDecorate %4 DescriptorSet 0
8034                OpDecorate %4 Binding 4
8035                OpDecorate %4 BlockMatchTextureQCOM
8036                OpDecorate %5 DescriptorSet 0
8037                OpDecorate %5 Binding 5
8038                OpDecorate %5 BlockMatchTextureQCOM
8039                OpDecorate %5 BlockMatchSamplerQCOM
8040        %void = OpTypeVoid
8041           %7 = OpTypeFunction %void
8042        %uint = OpTypeInt 32 0
8043      %v2uint = OpTypeVector %uint 2
8044 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
8045       %float = OpTypeFloat 32
8046     %v4float = OpTypeVector %float 4
8047 %_ptr_Input_v4float = OpTypePointer Input %v4float
8048 %_ptr_Input_float = OpTypePointer Input %float
8049 %_ptr_Function_uint = OpTypePointer Function %uint
8050 %_ptr_Output_v4float = OpTypePointer Output %v4float
8051           %3 = OpVariable %_ptr_Output_v4float Output
8052          %18 = OpTypeImage %float 2D 0 0 0 1 Unknown
8053          %19 = OpTypeSampledImage %18
8054 %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19
8055           %4 = OpVariable %_ptr_UniformConstant_19 UniformConstant
8056           %5 = OpVariable %_ptr_UniformConstant_19 UniformConstant
8057          %21 = OpTypeImage %float 2D 0 1 0 1 Unknown
8058           %2 = OpFunction %void None %7
8059          %22 = OpLabel
8060          %23 = OpVariable %_ptr_Function_v2uint Function
8061          %24 = OpLoad %19 %4
8062          %25 = OpLoad %v2uint %23
8063          %26 = OpLoad %19 %5
8064          %27 = OpLoad %v2uint %23
8065          %28 = OpLoad %v2uint %23
8066          %29 = OpImageBlockMatchWindowSADQCOM %v4float %24 %25 %26 %27 %28
8067                OpStore %3 %29
8068                OpReturn
8069                OpFunctionEnd
8070 )";
8071   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
8072   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
8073             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
8074   EXPECT_THAT(getDiagnosticString(),
8075               HasSubstr("Missing decoration BlockMatchSamplerQCOM"));
8076 }
8077 
TEST_F(ValidateImage,QCOMImageProcessing2BlockMatchWindowSADNoDecorRefIT)8078 TEST_F(ValidateImage, QCOMImageProcessing2BlockMatchWindowSADNoDecorRefIT) {
8079   const std::string text = R"(
8080                OpCapability Shader
8081                OpCapability TextureBlockMatchQCOM
8082                OpCapability TextureBlockMatch2QCOM
8083                OpExtension "SPV_QCOM_image_processing"
8084                OpExtension "SPV_QCOM_image_processing2"
8085           %1 = OpExtInstImport "GLSL.std.450"
8086                OpMemoryModel Logical GLSL450
8087                OpEntryPoint Fragment %2 "main" %3 %4 %5
8088                OpExecutionMode %2 OriginUpperLeft
8089                OpDecorate %3 Location 0
8090                OpDecorate %4 DescriptorSet 0
8091                OpDecorate %4 Binding 4
8092                OpDecorate %4 BlockMatchTextureQCOM
8093                OpDecorate %4 BlockMatchSamplerQCOM
8094                OpDecorate %5 DescriptorSet 0
8095                OpDecorate %5 Binding 5
8096                OpDecorate %5 BlockMatchSamplerQCOM
8097        %void = OpTypeVoid
8098           %7 = OpTypeFunction %void
8099        %uint = OpTypeInt 32 0
8100      %v2uint = OpTypeVector %uint 2
8101 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
8102       %float = OpTypeFloat 32
8103     %v4float = OpTypeVector %float 4
8104 %_ptr_Input_v4float = OpTypePointer Input %v4float
8105 %_ptr_Input_float = OpTypePointer Input %float
8106 %_ptr_Function_uint = OpTypePointer Function %uint
8107 %_ptr_Output_v4float = OpTypePointer Output %v4float
8108           %3 = OpVariable %_ptr_Output_v4float Output
8109          %18 = OpTypeImage %float 2D 0 0 0 1 Unknown
8110          %19 = OpTypeSampledImage %18
8111 %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19
8112           %4 = OpVariable %_ptr_UniformConstant_19 UniformConstant
8113           %5 = OpVariable %_ptr_UniformConstant_19 UniformConstant
8114          %21 = OpTypeImage %float 2D 0 1 0 1 Unknown
8115           %2 = OpFunction %void None %7
8116          %22 = OpLabel
8117          %23 = OpVariable %_ptr_Function_v2uint Function
8118          %24 = OpLoad %19 %4
8119          %25 = OpLoad %v2uint %23
8120          %26 = OpLoad %19 %5
8121          %27 = OpLoad %v2uint %23
8122          %28 = OpLoad %v2uint %23
8123          %29 = OpImageBlockMatchWindowSADQCOM %v4float %24 %25 %26 %27 %28
8124                OpStore %3 %29
8125                OpReturn
8126                OpFunctionEnd
8127 )";
8128   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
8129   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
8130             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
8131   EXPECT_THAT(getDiagnosticString(),
8132               HasSubstr("Missing decoration BlockMatchTextureQCOM"));
8133 }
8134 
TEST_F(ValidateImage,QCOMImageProcessing2BlockMatchWindowSADNoDecorRefIS)8135 TEST_F(ValidateImage, QCOMImageProcessing2BlockMatchWindowSADNoDecorRefIS) {
8136   const std::string text = R"(
8137                OpCapability Shader
8138                OpCapability TextureBlockMatchQCOM
8139                OpCapability TextureBlockMatch2QCOM
8140                OpExtension "SPV_QCOM_image_processing"
8141                OpExtension "SPV_QCOM_image_processing2"
8142           %1 = OpExtInstImport "GLSL.std.450"
8143                OpMemoryModel Logical GLSL450
8144                OpEntryPoint Fragment %2 "main" %3 %4 %5
8145                OpExecutionMode %2 OriginUpperLeft
8146                OpDecorate %3 Location 0
8147                OpDecorate %4 DescriptorSet 0
8148                OpDecorate %4 Binding 4
8149                OpDecorate %4 BlockMatchTextureQCOM
8150                OpDecorate %4 BlockMatchSamplerQCOM
8151                OpDecorate %5 DescriptorSet 0
8152                OpDecorate %5 Binding 5
8153                OpDecorate %5 BlockMatchTextureQCOM
8154        %void = OpTypeVoid
8155           %7 = OpTypeFunction %void
8156        %uint = OpTypeInt 32 0
8157      %v2uint = OpTypeVector %uint 2
8158 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
8159       %float = OpTypeFloat 32
8160     %v4float = OpTypeVector %float 4
8161 %_ptr_Input_v4float = OpTypePointer Input %v4float
8162 %_ptr_Input_float = OpTypePointer Input %float
8163 %_ptr_Function_uint = OpTypePointer Function %uint
8164 %_ptr_Output_v4float = OpTypePointer Output %v4float
8165           %3 = OpVariable %_ptr_Output_v4float Output
8166          %18 = OpTypeImage %float 2D 0 0 0 1 Unknown
8167          %19 = OpTypeSampledImage %18
8168 %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19
8169           %4 = OpVariable %_ptr_UniformConstant_19 UniformConstant
8170           %5 = OpVariable %_ptr_UniformConstant_19 UniformConstant
8171          %21 = OpTypeImage %float 2D 0 1 0 1 Unknown
8172           %2 = OpFunction %void None %7
8173          %22 = OpLabel
8174          %23 = OpVariable %_ptr_Function_v2uint Function
8175          %24 = OpLoad %19 %4
8176          %25 = OpLoad %v2uint %23
8177          %26 = OpLoad %19 %5
8178          %27 = OpLoad %v2uint %23
8179          %28 = OpLoad %v2uint %23
8180          %29 = OpImageBlockMatchWindowSADQCOM %v4float %24 %25 %26 %27 %28
8181                OpStore %3 %29
8182                OpReturn
8183                OpFunctionEnd
8184 )";
8185   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
8186   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
8187             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
8188   EXPECT_THAT(getDiagnosticString(),
8189               HasSubstr("Missing decoration BlockMatchSamplerQCOM"));
8190 }
8191 
TEST_F(ValidateImage,QCOMImageProcessing2BlockMatchWindowSADNoDecorTargetNIT)8192 TEST_F(ValidateImage, QCOMImageProcessing2BlockMatchWindowSADNoDecorTargetNIT) {
8193   const std::string text = R"(
8194            OpCapability Shader
8195            OpCapability TextureBlockMatchQCOM
8196            OpCapability TextureBlockMatch2QCOM
8197            OpExtension "SPV_QCOM_image_processing"
8198            OpExtension "SPV_QCOM_image_processing2"
8199       %1 = OpExtInstImport "GLSL.std.450"
8200            OpMemoryModel Logical GLSL450
8201            OpEntryPoint Fragment %2 "main" %3 %4 %5 %6
8202            OpExecutionMode %2 OriginUpperLeft
8203            OpDecorate %3 Location 0
8204            OpDecorate %4 DescriptorSet 0
8205            OpDecorate %4 Binding 1
8206            OpDecorate %4 BlockMatchSamplerQCOM
8207            OpDecorate %5 DescriptorSet 0
8208            OpDecorate %5 Binding 3
8209            OpDecorate %6 DescriptorSet 0
8210            OpDecorate %6 Binding 2
8211            OpDecorate %6 BlockMatchTextureQCOM
8212            OpDecorate %6 BlockMatchSamplerQCOM
8213    %void = OpTypeVoid
8214       %8 = OpTypeFunction %void
8215    %uint = OpTypeInt 32 0
8216  %v2uint = OpTypeVector %uint 2
8217 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
8218   %float = OpTypeFloat 32
8219 %v4float = OpTypeVector %float 4
8220 %_ptr_Input_float = OpTypePointer Input %float
8221 %_ptr_Function_uint = OpTypePointer Function %uint
8222 %uint_4 = OpConstant %uint 4
8223     %17 = OpConstantComposite %v2uint %uint_4 %uint_4
8224 %_ptr_Output_v4float = OpTypePointer Output %v4float
8225      %3 = OpVariable %_ptr_Output_v4float Output
8226     %19 = OpTypeImage %float 2D 0 0 0 1 Unknown
8227 %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19
8228      %4 = OpVariable %_ptr_UniformConstant_19 UniformConstant
8229     %21 = OpTypeSampler
8230 %_ptr_UniformConstant_21 = OpTypePointer UniformConstant %21
8231     %5 = OpVariable %_ptr_UniformConstant_21 UniformConstant
8232    %23 = OpTypeSampledImage %19
8233     %6 = OpVariable %_ptr_UniformConstant_19 UniformConstant
8234     %2 = OpFunction %void None %8
8235    %24 = OpLabel
8236    %25 = OpVariable %_ptr_Function_v2uint Function
8237    %26 = OpLoad %19 %4
8238    %27 = OpLoad %21 %5
8239    %28 = OpSampledImage %23 %26 %27
8240    %29 = OpLoad %v2uint %25
8241    %30 = OpLoad %19 %6
8242    %31 = OpLoad %21 %5
8243    %32 = OpSampledImage %23 %30 %31
8244    %33 = OpImageBlockMatchWindowSADQCOM %v4float %28 %29 %32 %29 %29
8245          OpStore %3 %33
8246          OpReturn
8247          OpFunctionEnd
8248 )";
8249   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
8250   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
8251             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
8252   EXPECT_THAT(getDiagnosticString(),
8253               HasSubstr("Missing decoration BlockMatchTextureQCOM"));
8254 }
8255 
TEST_F(ValidateImage,QCOMImageProcessing2BlockMatchWindowSADNoDecorTargetNIS)8256 TEST_F(ValidateImage, QCOMImageProcessing2BlockMatchWindowSADNoDecorTargetNIS) {
8257   const std::string text = R"(
8258            OpCapability Shader
8259            OpCapability TextureBlockMatchQCOM
8260            OpCapability TextureBlockMatch2QCOM
8261            OpExtension "SPV_QCOM_image_processing"
8262            OpExtension "SPV_QCOM_image_processing2"
8263       %1 = OpExtInstImport "GLSL.std.450"
8264            OpMemoryModel Logical GLSL450
8265            OpEntryPoint Fragment %2 "main" %3 %4 %5 %6
8266            OpExecutionMode %2 OriginUpperLeft
8267            OpDecorate %3 Location 0
8268            OpDecorate %4 DescriptorSet 0
8269            OpDecorate %4 Binding 1
8270            OpDecorate %4 BlockMatchTextureQCOM
8271            OpDecorate %5 DescriptorSet 0
8272            OpDecorate %5 Binding 3
8273            OpDecorate %6 DescriptorSet 0
8274            OpDecorate %6 Binding 2
8275            OpDecorate %6 BlockMatchTextureQCOM
8276            OpDecorate %6 BlockMatchSamplerQCOM
8277    %void = OpTypeVoid
8278       %8 = OpTypeFunction %void
8279    %uint = OpTypeInt 32 0
8280  %v2uint = OpTypeVector %uint 2
8281 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
8282   %float = OpTypeFloat 32
8283 %v4float = OpTypeVector %float 4
8284 %_ptr_Input_float = OpTypePointer Input %float
8285 %_ptr_Function_uint = OpTypePointer Function %uint
8286 %uint_4 = OpConstant %uint 4
8287     %17 = OpConstantComposite %v2uint %uint_4 %uint_4
8288 %_ptr_Output_v4float = OpTypePointer Output %v4float
8289      %3 = OpVariable %_ptr_Output_v4float Output
8290     %19 = OpTypeImage %float 2D 0 0 0 1 Unknown
8291 %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19
8292      %4 = OpVariable %_ptr_UniformConstant_19 UniformConstant
8293     %21 = OpTypeSampler
8294 %_ptr_UniformConstant_21 = OpTypePointer UniformConstant %21
8295     %5 = OpVariable %_ptr_UniformConstant_21 UniformConstant
8296    %23 = OpTypeSampledImage %19
8297     %6 = OpVariable %_ptr_UniformConstant_19 UniformConstant
8298     %2 = OpFunction %void None %8
8299    %24 = OpLabel
8300    %25 = OpVariable %_ptr_Function_v2uint Function
8301    %26 = OpLoad %19 %4
8302    %27 = OpLoad %21 %5
8303    %28 = OpSampledImage %23 %26 %27
8304    %29 = OpLoad %v2uint %25
8305    %30 = OpLoad %19 %6
8306    %31 = OpLoad %21 %5
8307    %32 = OpSampledImage %23 %30 %31
8308    %33 = OpImageBlockMatchWindowSADQCOM %v4float %28 %29 %32 %29 %29
8309          OpStore %3 %33
8310          OpReturn
8311          OpFunctionEnd
8312 )";
8313   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
8314   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
8315             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
8316   EXPECT_THAT(getDiagnosticString(),
8317               HasSubstr("Missing decoration BlockMatchSamplerQCOM"));
8318 }
8319 
TEST_F(ValidateImage,QCOMImageProcessing2BlockMatchWindowSADNoDecorRefNIT)8320 TEST_F(ValidateImage, QCOMImageProcessing2BlockMatchWindowSADNoDecorRefNIT) {
8321   const std::string text = R"(
8322            OpCapability Shader
8323            OpCapability TextureBlockMatchQCOM
8324            OpCapability TextureBlockMatch2QCOM
8325            OpExtension "SPV_QCOM_image_processing"
8326            OpExtension "SPV_QCOM_image_processing2"
8327       %1 = OpExtInstImport "GLSL.std.450"
8328            OpMemoryModel Logical GLSL450
8329            OpEntryPoint Fragment %2 "main" %3 %4 %5 %6
8330            OpExecutionMode %2 OriginUpperLeft
8331            OpDecorate %3 Location 0
8332            OpDecorate %4 DescriptorSet 0
8333            OpDecorate %4 Binding 1
8334            OpDecorate %4 BlockMatchTextureQCOM
8335            OpDecorate %5 DescriptorSet 0
8336            OpDecorate %5 Binding 3
8337            OpDecorate %5 BlockMatchSamplerQCOM
8338            OpDecorate %6 DescriptorSet 0
8339            OpDecorate %6 Binding 2
8340            OpDecorate %6 BlockMatchSamplerQCOM
8341    %void = OpTypeVoid
8342       %8 = OpTypeFunction %void
8343    %uint = OpTypeInt 32 0
8344  %v2uint = OpTypeVector %uint 2
8345 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
8346   %float = OpTypeFloat 32
8347 %v4float = OpTypeVector %float 4
8348 %_ptr_Input_float = OpTypePointer Input %float
8349 %_ptr_Function_uint = OpTypePointer Function %uint
8350 %uint_4 = OpConstant %uint 4
8351     %17 = OpConstantComposite %v2uint %uint_4 %uint_4
8352 %_ptr_Output_v4float = OpTypePointer Output %v4float
8353      %3 = OpVariable %_ptr_Output_v4float Output
8354     %19 = OpTypeImage %float 2D 0 0 0 1 Unknown
8355 %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19
8356      %4 = OpVariable %_ptr_UniformConstant_19 UniformConstant
8357     %21 = OpTypeSampler
8358 %_ptr_UniformConstant_21 = OpTypePointer UniformConstant %21
8359     %5 = OpVariable %_ptr_UniformConstant_21 UniformConstant
8360    %23 = OpTypeSampledImage %19
8361     %6 = OpVariable %_ptr_UniformConstant_19 UniformConstant
8362     %2 = OpFunction %void None %8
8363    %24 = OpLabel
8364    %25 = OpVariable %_ptr_Function_v2uint Function
8365    %26 = OpLoad %19 %4
8366    %27 = OpLoad %21 %5
8367    %28 = OpSampledImage %23 %26 %27
8368    %29 = OpLoad %v2uint %25
8369    %30 = OpLoad %19 %6
8370    %31 = OpLoad %21 %5
8371    %32 = OpSampledImage %23 %30 %31
8372    %33 = OpImageBlockMatchWindowSADQCOM %v4float %28 %29 %32 %29 %29
8373          OpStore %3 %33
8374          OpReturn
8375          OpFunctionEnd
8376 )";
8377   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
8378   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
8379             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
8380   EXPECT_THAT(getDiagnosticString(),
8381               HasSubstr("Missing decoration BlockMatchTextureQCOM"));
8382 }
8383 
TEST_F(ValidateImage,QCOMImageProcessing2BlockMatchWindowSADNoDecorRefNIS)8384 TEST_F(ValidateImage, QCOMImageProcessing2BlockMatchWindowSADNoDecorRefNIS) {
8385   const std::string text = R"(
8386            OpCapability Shader
8387            OpCapability TextureBlockMatchQCOM
8388            OpCapability TextureBlockMatch2QCOM
8389            OpExtension "SPV_QCOM_image_processing"
8390            OpExtension "SPV_QCOM_image_processing2"
8391       %1 = OpExtInstImport "GLSL.std.450"
8392            OpMemoryModel Logical GLSL450
8393            OpEntryPoint Fragment %2 "main" %3 %4 %5 %6
8394            OpExecutionMode %2 OriginUpperLeft
8395            OpDecorate %3 Location 0
8396            OpDecorate %4 DescriptorSet 0
8397            OpDecorate %4 Binding 1
8398            OpDecorate %4 BlockMatchTextureQCOM
8399            OpDecorate %4 BlockMatchSamplerQCOM
8400            OpDecorate %5 DescriptorSet 0
8401            OpDecorate %5 Binding 3
8402            OpDecorate %6 DescriptorSet 0
8403            OpDecorate %6 Binding 2
8404            OpDecorate %6 BlockMatchTextureQCOM
8405    %void = OpTypeVoid
8406       %8 = OpTypeFunction %void
8407    %uint = OpTypeInt 32 0
8408  %v2uint = OpTypeVector %uint 2
8409 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
8410   %float = OpTypeFloat 32
8411 %v4float = OpTypeVector %float 4
8412 %_ptr_Input_float = OpTypePointer Input %float
8413 %_ptr_Function_uint = OpTypePointer Function %uint
8414 %uint_4 = OpConstant %uint 4
8415     %17 = OpConstantComposite %v2uint %uint_4 %uint_4
8416 %_ptr_Output_v4float = OpTypePointer Output %v4float
8417      %3 = OpVariable %_ptr_Output_v4float Output
8418     %19 = OpTypeImage %float 2D 0 0 0 1 Unknown
8419 %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19
8420      %4 = OpVariable %_ptr_UniformConstant_19 UniformConstant
8421     %21 = OpTypeSampler
8422 %_ptr_UniformConstant_21 = OpTypePointer UniformConstant %21
8423     %5 = OpVariable %_ptr_UniformConstant_21 UniformConstant
8424    %23 = OpTypeSampledImage %19
8425     %6 = OpVariable %_ptr_UniformConstant_19 UniformConstant
8426     %2 = OpFunction %void None %8
8427    %24 = OpLabel
8428    %25 = OpVariable %_ptr_Function_v2uint Function
8429    %26 = OpLoad %19 %4
8430    %27 = OpLoad %21 %5
8431    %28 = OpSampledImage %23 %26 %27
8432    %29 = OpLoad %v2uint %25
8433    %30 = OpLoad %19 %6
8434    %31 = OpLoad %21 %5
8435    %32 = OpSampledImage %23 %30 %31
8436    %33 = OpImageBlockMatchWindowSADQCOM %v4float %28 %29 %32 %29 %29
8437          OpStore %3 %33
8438          OpReturn
8439          OpFunctionEnd
8440 )";
8441   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
8442   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
8443             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
8444   EXPECT_THAT(getDiagnosticString(),
8445               HasSubstr("Missing decoration BlockMatchSamplerQCOM"));
8446 }
8447 
TEST_F(ValidateImage,QCOMImageProcessing2BlockMatchWindowSSDNoDecorTargetIT)8448 TEST_F(ValidateImage, QCOMImageProcessing2BlockMatchWindowSSDNoDecorTargetIT) {
8449   const std::string text = R"(
8450                OpCapability Shader
8451                OpCapability TextureBlockMatchQCOM
8452                OpCapability TextureBlockMatch2QCOM
8453                OpExtension "SPV_QCOM_image_processing"
8454                OpExtension "SPV_QCOM_image_processing2"
8455           %1 = OpExtInstImport "GLSL.std.450"
8456                OpMemoryModel Logical GLSL450
8457                OpEntryPoint Fragment %2 "main" %3 %4 %5
8458                OpExecutionMode %2 OriginUpperLeft
8459                OpDecorate %3 Location 0
8460                OpDecorate %4 DescriptorSet 0
8461                OpDecorate %4 Binding 4
8462                OpDecorate %4 BlockMatchSamplerQCOM
8463                OpDecorate %5 DescriptorSet 0
8464                OpDecorate %5 Binding 5
8465                OpDecorate %5 BlockMatchTextureQCOM
8466                OpDecorate %5 BlockMatchSamplerQCOM
8467        %void = OpTypeVoid
8468           %7 = OpTypeFunction %void
8469        %uint = OpTypeInt 32 0
8470      %v2uint = OpTypeVector %uint 2
8471 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
8472       %float = OpTypeFloat 32
8473     %v4float = OpTypeVector %float 4
8474 %_ptr_Input_v4float = OpTypePointer Input %v4float
8475 %_ptr_Input_float = OpTypePointer Input %float
8476 %_ptr_Function_uint = OpTypePointer Function %uint
8477 %_ptr_Output_v4float = OpTypePointer Output %v4float
8478           %3 = OpVariable %_ptr_Output_v4float Output
8479          %18 = OpTypeImage %float 2D 0 0 0 1 Unknown
8480          %19 = OpTypeSampledImage %18
8481 %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19
8482           %4 = OpVariable %_ptr_UniformConstant_19 UniformConstant
8483           %5 = OpVariable %_ptr_UniformConstant_19 UniformConstant
8484          %21 = OpTypeImage %float 2D 0 1 0 1 Unknown
8485           %2 = OpFunction %void None %7
8486          %22 = OpLabel
8487          %23 = OpVariable %_ptr_Function_v2uint Function
8488          %24 = OpLoad %19 %4
8489          %25 = OpLoad %v2uint %23
8490          %26 = OpLoad %19 %5
8491          %27 = OpLoad %v2uint %23
8492          %28 = OpLoad %v2uint %23
8493          %29 = OpImageBlockMatchWindowSSDQCOM %v4float %24 %25 %26 %27 %28
8494                OpStore %3 %29
8495                OpReturn
8496                OpFunctionEnd
8497 )";
8498   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
8499   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
8500             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
8501   EXPECT_THAT(getDiagnosticString(),
8502               HasSubstr("Missing decoration BlockMatchTextureQCOM"));
8503 }
8504 
TEST_F(ValidateImage,QCOMImageProcessing2BlockMatchWindowSSDNoDecorTargetIS)8505 TEST_F(ValidateImage, QCOMImageProcessing2BlockMatchWindowSSDNoDecorTargetIS) {
8506   const std::string text = R"(
8507                OpCapability Shader
8508                OpCapability TextureBlockMatchQCOM
8509                OpCapability TextureBlockMatch2QCOM
8510                OpExtension "SPV_QCOM_image_processing"
8511                OpExtension "SPV_QCOM_image_processing2"
8512           %1 = OpExtInstImport "GLSL.std.450"
8513                OpMemoryModel Logical GLSL450
8514                OpEntryPoint Fragment %2 "main" %3 %4 %5
8515                OpExecutionMode %2 OriginUpperLeft
8516                OpDecorate %3 Location 0
8517                OpDecorate %4 DescriptorSet 0
8518                OpDecorate %4 Binding 4
8519                OpDecorate %4 BlockMatchTextureQCOM
8520                OpDecorate %5 DescriptorSet 0
8521                OpDecorate %5 Binding 5
8522                OpDecorate %5 BlockMatchTextureQCOM
8523                OpDecorate %5 BlockMatchSamplerQCOM
8524        %void = OpTypeVoid
8525           %7 = OpTypeFunction %void
8526        %uint = OpTypeInt 32 0
8527      %v2uint = OpTypeVector %uint 2
8528 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
8529       %float = OpTypeFloat 32
8530     %v4float = OpTypeVector %float 4
8531 %_ptr_Input_v4float = OpTypePointer Input %v4float
8532 %_ptr_Input_float = OpTypePointer Input %float
8533 %_ptr_Function_uint = OpTypePointer Function %uint
8534 %_ptr_Output_v4float = OpTypePointer Output %v4float
8535           %3 = OpVariable %_ptr_Output_v4float Output
8536          %18 = OpTypeImage %float 2D 0 0 0 1 Unknown
8537          %19 = OpTypeSampledImage %18
8538 %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19
8539           %4 = OpVariable %_ptr_UniformConstant_19 UniformConstant
8540           %5 = OpVariable %_ptr_UniformConstant_19 UniformConstant
8541          %21 = OpTypeImage %float 2D 0 1 0 1 Unknown
8542           %2 = OpFunction %void None %7
8543          %22 = OpLabel
8544          %23 = OpVariable %_ptr_Function_v2uint Function
8545          %24 = OpLoad %19 %4
8546          %25 = OpLoad %v2uint %23
8547          %26 = OpLoad %19 %5
8548          %27 = OpLoad %v2uint %23
8549          %28 = OpLoad %v2uint %23
8550          %29 = OpImageBlockMatchWindowSSDQCOM %v4float %24 %25 %26 %27 %28
8551                OpStore %3 %29
8552                OpReturn
8553                OpFunctionEnd
8554 )";
8555   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
8556   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
8557             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
8558   EXPECT_THAT(getDiagnosticString(),
8559               HasSubstr("Missing decoration BlockMatchSamplerQCOM"));
8560 }
8561 
TEST_F(ValidateImage,QCOMImageProcessing2BlockMatchWindowSSDNoDecorRefIT)8562 TEST_F(ValidateImage, QCOMImageProcessing2BlockMatchWindowSSDNoDecorRefIT) {
8563   const std::string text = R"(
8564                OpCapability Shader
8565                OpCapability TextureBlockMatchQCOM
8566                OpCapability TextureBlockMatch2QCOM
8567                OpExtension "SPV_QCOM_image_processing"
8568                OpExtension "SPV_QCOM_image_processing2"
8569           %1 = OpExtInstImport "GLSL.std.450"
8570                OpMemoryModel Logical GLSL450
8571                OpEntryPoint Fragment %2 "main" %3 %4 %5
8572                OpExecutionMode %2 OriginUpperLeft
8573                OpDecorate %3 Location 0
8574                OpDecorate %4 DescriptorSet 0
8575                OpDecorate %4 Binding 4
8576                OpDecorate %4 BlockMatchTextureQCOM
8577                OpDecorate %4 BlockMatchSamplerQCOM
8578                OpDecorate %5 DescriptorSet 0
8579                OpDecorate %5 Binding 5
8580                OpDecorate %5 BlockMatchSamplerQCOM
8581        %void = OpTypeVoid
8582           %7 = OpTypeFunction %void
8583        %uint = OpTypeInt 32 0
8584      %v2uint = OpTypeVector %uint 2
8585 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
8586       %float = OpTypeFloat 32
8587     %v4float = OpTypeVector %float 4
8588 %_ptr_Input_v4float = OpTypePointer Input %v4float
8589 %_ptr_Input_float = OpTypePointer Input %float
8590 %_ptr_Function_uint = OpTypePointer Function %uint
8591 %_ptr_Output_v4float = OpTypePointer Output %v4float
8592           %3 = OpVariable %_ptr_Output_v4float Output
8593          %18 = OpTypeImage %float 2D 0 0 0 1 Unknown
8594          %19 = OpTypeSampledImage %18
8595 %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19
8596           %4 = OpVariable %_ptr_UniformConstant_19 UniformConstant
8597           %5 = OpVariable %_ptr_UniformConstant_19 UniformConstant
8598          %21 = OpTypeImage %float 2D 0 1 0 1 Unknown
8599           %2 = OpFunction %void None %7
8600          %22 = OpLabel
8601          %23 = OpVariable %_ptr_Function_v2uint Function
8602          %24 = OpLoad %19 %4
8603          %25 = OpLoad %v2uint %23
8604          %26 = OpLoad %19 %5
8605          %27 = OpLoad %v2uint %23
8606          %28 = OpLoad %v2uint %23
8607          %29 = OpImageBlockMatchWindowSSDQCOM %v4float %24 %25 %26 %27 %28
8608                OpStore %3 %29
8609                OpReturn
8610                OpFunctionEnd
8611 )";
8612   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
8613   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
8614             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
8615   EXPECT_THAT(getDiagnosticString(),
8616               HasSubstr("Missing decoration BlockMatchTextureQCOM"));
8617 }
8618 
TEST_F(ValidateImage,QCOMImageProcessing2BlockMatchWindowSSDNoDecorRefIS)8619 TEST_F(ValidateImage, QCOMImageProcessing2BlockMatchWindowSSDNoDecorRefIS) {
8620   const std::string text = R"(
8621                OpCapability Shader
8622                OpCapability TextureBlockMatchQCOM
8623                OpCapability TextureBlockMatch2QCOM
8624                OpExtension "SPV_QCOM_image_processing"
8625                OpExtension "SPV_QCOM_image_processing2"
8626           %1 = OpExtInstImport "GLSL.std.450"
8627                OpMemoryModel Logical GLSL450
8628                OpEntryPoint Fragment %2 "main" %3 %4 %5
8629                OpExecutionMode %2 OriginUpperLeft
8630                OpDecorate %3 Location 0
8631                OpDecorate %4 DescriptorSet 0
8632                OpDecorate %4 Binding 4
8633                OpDecorate %4 BlockMatchTextureQCOM
8634                OpDecorate %4 BlockMatchSamplerQCOM
8635                OpDecorate %5 DescriptorSet 0
8636                OpDecorate %5 Binding 5
8637                OpDecorate %5 BlockMatchTextureQCOM
8638        %void = OpTypeVoid
8639           %7 = OpTypeFunction %void
8640        %uint = OpTypeInt 32 0
8641      %v2uint = OpTypeVector %uint 2
8642 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
8643       %float = OpTypeFloat 32
8644     %v4float = OpTypeVector %float 4
8645 %_ptr_Input_v4float = OpTypePointer Input %v4float
8646 %_ptr_Input_float = OpTypePointer Input %float
8647 %_ptr_Function_uint = OpTypePointer Function %uint
8648 %_ptr_Output_v4float = OpTypePointer Output %v4float
8649           %3 = OpVariable %_ptr_Output_v4float Output
8650          %18 = OpTypeImage %float 2D 0 0 0 1 Unknown
8651          %19 = OpTypeSampledImage %18
8652 %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19
8653           %4 = OpVariable %_ptr_UniformConstant_19 UniformConstant
8654           %5 = OpVariable %_ptr_UniformConstant_19 UniformConstant
8655          %21 = OpTypeImage %float 2D 0 1 0 1 Unknown
8656           %2 = OpFunction %void None %7
8657          %22 = OpLabel
8658          %23 = OpVariable %_ptr_Function_v2uint Function
8659          %24 = OpLoad %19 %4
8660          %25 = OpLoad %v2uint %23
8661          %26 = OpLoad %19 %5
8662          %27 = OpLoad %v2uint %23
8663          %28 = OpLoad %v2uint %23
8664          %29 = OpImageBlockMatchWindowSSDQCOM %v4float %24 %25 %26 %27 %28
8665                OpStore %3 %29
8666                OpReturn
8667                OpFunctionEnd
8668 )";
8669   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
8670   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
8671             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
8672   EXPECT_THAT(getDiagnosticString(),
8673               HasSubstr("Missing decoration BlockMatchSamplerQCOM"));
8674 }
8675 
TEST_F(ValidateImage,QCOMImageProcessing2BlockMatchWindowSSDNoDecorTargetNIT)8676 TEST_F(ValidateImage, QCOMImageProcessing2BlockMatchWindowSSDNoDecorTargetNIT) {
8677   const std::string text = R"(
8678            OpCapability Shader
8679            OpCapability TextureBlockMatchQCOM
8680            OpCapability TextureBlockMatch2QCOM
8681            OpExtension "SPV_QCOM_image_processing"
8682            OpExtension "SPV_QCOM_image_processing2"
8683       %1 = OpExtInstImport "GLSL.std.450"
8684            OpMemoryModel Logical GLSL450
8685            OpEntryPoint Fragment %2 "main" %3 %4 %5 %6
8686            OpExecutionMode %2 OriginUpperLeft
8687            OpDecorate %3 Location 0
8688            OpDecorate %4 DescriptorSet 0
8689            OpDecorate %4 Binding 1
8690            OpDecorate %4 BlockMatchSamplerQCOM
8691            OpDecorate %5 DescriptorSet 0
8692            OpDecorate %5 Binding 3
8693            OpDecorate %6 DescriptorSet 0
8694            OpDecorate %6 Binding 2
8695            OpDecorate %6 BlockMatchTextureQCOM
8696            OpDecorate %6 BlockMatchSamplerQCOM
8697    %void = OpTypeVoid
8698       %8 = OpTypeFunction %void
8699    %uint = OpTypeInt 32 0
8700  %v2uint = OpTypeVector %uint 2
8701 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
8702   %float = OpTypeFloat 32
8703 %v4float = OpTypeVector %float 4
8704 %_ptr_Input_float = OpTypePointer Input %float
8705 %_ptr_Function_uint = OpTypePointer Function %uint
8706 %uint_4 = OpConstant %uint 4
8707     %17 = OpConstantComposite %v2uint %uint_4 %uint_4
8708 %_ptr_Output_v4float = OpTypePointer Output %v4float
8709      %3 = OpVariable %_ptr_Output_v4float Output
8710     %19 = OpTypeImage %float 2D 0 0 0 1 Unknown
8711 %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19
8712      %4 = OpVariable %_ptr_UniformConstant_19 UniformConstant
8713     %21 = OpTypeSampler
8714 %_ptr_UniformConstant_21 = OpTypePointer UniformConstant %21
8715     %5 = OpVariable %_ptr_UniformConstant_21 UniformConstant
8716    %23 = OpTypeSampledImage %19
8717     %6 = OpVariable %_ptr_UniformConstant_19 UniformConstant
8718     %2 = OpFunction %void None %8
8719    %24 = OpLabel
8720    %25 = OpVariable %_ptr_Function_v2uint Function
8721    %26 = OpLoad %19 %4
8722    %27 = OpLoad %21 %5
8723    %28 = OpSampledImage %23 %26 %27
8724    %29 = OpLoad %v2uint %25
8725    %30 = OpLoad %19 %6
8726    %31 = OpLoad %21 %5
8727    %32 = OpSampledImage %23 %30 %31
8728    %33 = OpImageBlockMatchWindowSSDQCOM %v4float %28 %29 %32 %29 %29
8729          OpStore %3 %33
8730          OpReturn
8731          OpFunctionEnd
8732 )";
8733   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
8734   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
8735             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
8736   EXPECT_THAT(getDiagnosticString(),
8737               HasSubstr("Missing decoration BlockMatchTextureQCOM"));
8738 }
8739 
TEST_F(ValidateImage,QCOMImageProcessing2BlockMatchWindowSSDNoDecorTargetNIS)8740 TEST_F(ValidateImage, QCOMImageProcessing2BlockMatchWindowSSDNoDecorTargetNIS) {
8741   const std::string text = R"(
8742            OpCapability Shader
8743            OpCapability TextureBlockMatchQCOM
8744            OpCapability TextureBlockMatch2QCOM
8745            OpExtension "SPV_QCOM_image_processing"
8746            OpExtension "SPV_QCOM_image_processing2"
8747       %1 = OpExtInstImport "GLSL.std.450"
8748            OpMemoryModel Logical GLSL450
8749            OpEntryPoint Fragment %2 "main" %3 %4 %5 %6
8750            OpExecutionMode %2 OriginUpperLeft
8751            OpDecorate %3 Location 0
8752            OpDecorate %4 DescriptorSet 0
8753            OpDecorate %4 Binding 1
8754            OpDecorate %4 BlockMatchTextureQCOM
8755            OpDecorate %5 DescriptorSet 0
8756            OpDecorate %5 Binding 3
8757            OpDecorate %6 DescriptorSet 0
8758            OpDecorate %6 Binding 2
8759            OpDecorate %6 BlockMatchTextureQCOM
8760            OpDecorate %6 BlockMatchSamplerQCOM
8761    %void = OpTypeVoid
8762       %8 = OpTypeFunction %void
8763    %uint = OpTypeInt 32 0
8764  %v2uint = OpTypeVector %uint 2
8765 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
8766   %float = OpTypeFloat 32
8767 %v4float = OpTypeVector %float 4
8768 %_ptr_Input_float = OpTypePointer Input %float
8769 %_ptr_Function_uint = OpTypePointer Function %uint
8770 %uint_4 = OpConstant %uint 4
8771     %17 = OpConstantComposite %v2uint %uint_4 %uint_4
8772 %_ptr_Output_v4float = OpTypePointer Output %v4float
8773      %3 = OpVariable %_ptr_Output_v4float Output
8774     %19 = OpTypeImage %float 2D 0 0 0 1 Unknown
8775 %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19
8776      %4 = OpVariable %_ptr_UniformConstant_19 UniformConstant
8777     %21 = OpTypeSampler
8778 %_ptr_UniformConstant_21 = OpTypePointer UniformConstant %21
8779     %5 = OpVariable %_ptr_UniformConstant_21 UniformConstant
8780    %23 = OpTypeSampledImage %19
8781     %6 = OpVariable %_ptr_UniformConstant_19 UniformConstant
8782     %2 = OpFunction %void None %8
8783    %24 = OpLabel
8784    %25 = OpVariable %_ptr_Function_v2uint Function
8785    %26 = OpLoad %19 %4
8786    %27 = OpLoad %21 %5
8787    %28 = OpSampledImage %23 %26 %27
8788    %29 = OpLoad %v2uint %25
8789    %30 = OpLoad %19 %6
8790    %31 = OpLoad %21 %5
8791    %32 = OpSampledImage %23 %30 %31
8792    %33 = OpImageBlockMatchWindowSSDQCOM %v4float %28 %29 %32 %29 %29
8793          OpStore %3 %33
8794          OpReturn
8795          OpFunctionEnd
8796 )";
8797   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
8798   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
8799             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
8800   EXPECT_THAT(getDiagnosticString(),
8801               HasSubstr("Missing decoration BlockMatchSamplerQCOM"));
8802 }
8803 
TEST_F(ValidateImage,QCOMImageProcessing2BlockMatchWindowSSDNoDecorRefNIT)8804 TEST_F(ValidateImage, QCOMImageProcessing2BlockMatchWindowSSDNoDecorRefNIT) {
8805   const std::string text = R"(
8806            OpCapability Shader
8807            OpCapability TextureBlockMatchQCOM
8808            OpCapability TextureBlockMatch2QCOM
8809            OpExtension "SPV_QCOM_image_processing"
8810            OpExtension "SPV_QCOM_image_processing2"
8811       %1 = OpExtInstImport "GLSL.std.450"
8812            OpMemoryModel Logical GLSL450
8813            OpEntryPoint Fragment %2 "main" %3 %4 %5 %6
8814            OpExecutionMode %2 OriginUpperLeft
8815            OpDecorate %3 Location 0
8816            OpDecorate %4 DescriptorSet 0
8817            OpDecorate %4 Binding 1
8818            OpDecorate %4 BlockMatchTextureQCOM
8819            OpDecorate %5 DescriptorSet 0
8820            OpDecorate %5 Binding 3
8821            OpDecorate %5 BlockMatchSamplerQCOM
8822            OpDecorate %6 DescriptorSet 0
8823            OpDecorate %6 Binding 2
8824            OpDecorate %6 BlockMatchSamplerQCOM
8825    %void = OpTypeVoid
8826       %8 = OpTypeFunction %void
8827    %uint = OpTypeInt 32 0
8828  %v2uint = OpTypeVector %uint 2
8829 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
8830   %float = OpTypeFloat 32
8831 %v4float = OpTypeVector %float 4
8832 %_ptr_Input_float = OpTypePointer Input %float
8833 %_ptr_Function_uint = OpTypePointer Function %uint
8834 %uint_4 = OpConstant %uint 4
8835     %17 = OpConstantComposite %v2uint %uint_4 %uint_4
8836 %_ptr_Output_v4float = OpTypePointer Output %v4float
8837      %3 = OpVariable %_ptr_Output_v4float Output
8838     %19 = OpTypeImage %float 2D 0 0 0 1 Unknown
8839 %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19
8840      %4 = OpVariable %_ptr_UniformConstant_19 UniformConstant
8841     %21 = OpTypeSampler
8842 %_ptr_UniformConstant_21 = OpTypePointer UniformConstant %21
8843     %5 = OpVariable %_ptr_UniformConstant_21 UniformConstant
8844    %23 = OpTypeSampledImage %19
8845     %6 = OpVariable %_ptr_UniformConstant_19 UniformConstant
8846     %2 = OpFunction %void None %8
8847    %24 = OpLabel
8848    %25 = OpVariable %_ptr_Function_v2uint Function
8849    %26 = OpLoad %19 %4
8850    %27 = OpLoad %21 %5
8851    %28 = OpSampledImage %23 %26 %27
8852    %29 = OpLoad %v2uint %25
8853    %30 = OpLoad %19 %6
8854    %31 = OpLoad %21 %5
8855    %32 = OpSampledImage %23 %30 %31
8856    %33 = OpImageBlockMatchWindowSSDQCOM %v4float %28 %29 %32 %29 %29
8857          OpStore %3 %33
8858          OpReturn
8859          OpFunctionEnd
8860 )";
8861   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
8862   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
8863             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
8864   EXPECT_THAT(getDiagnosticString(),
8865               HasSubstr("Missing decoration BlockMatchTextureQCOM"));
8866 }
8867 
TEST_F(ValidateImage,QCOMImageProcessing2BlockMatchWindowSSDNoDecorRefNIS)8868 TEST_F(ValidateImage, QCOMImageProcessing2BlockMatchWindowSSDNoDecorRefNIS) {
8869   const std::string text = R"(
8870            OpCapability Shader
8871            OpCapability TextureBlockMatchQCOM
8872            OpCapability TextureBlockMatch2QCOM
8873            OpExtension "SPV_QCOM_image_processing"
8874            OpExtension "SPV_QCOM_image_processing2"
8875       %1 = OpExtInstImport "GLSL.std.450"
8876            OpMemoryModel Logical GLSL450
8877            OpEntryPoint Fragment %2 "main" %3 %4 %5 %6
8878            OpExecutionMode %2 OriginUpperLeft
8879            OpDecorate %3 Location 0
8880            OpDecorate %4 DescriptorSet 0
8881            OpDecorate %4 Binding 1
8882            OpDecorate %4 BlockMatchTextureQCOM
8883            OpDecorate %4 BlockMatchSamplerQCOM
8884            OpDecorate %5 DescriptorSet 0
8885            OpDecorate %5 Binding 3
8886            OpDecorate %6 DescriptorSet 0
8887            OpDecorate %6 Binding 2
8888            OpDecorate %6 BlockMatchTextureQCOM
8889    %void = OpTypeVoid
8890       %8 = OpTypeFunction %void
8891    %uint = OpTypeInt 32 0
8892  %v2uint = OpTypeVector %uint 2
8893 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
8894   %float = OpTypeFloat 32
8895 %v4float = OpTypeVector %float 4
8896 %_ptr_Input_float = OpTypePointer Input %float
8897 %_ptr_Function_uint = OpTypePointer Function %uint
8898 %uint_4 = OpConstant %uint 4
8899     %17 = OpConstantComposite %v2uint %uint_4 %uint_4
8900 %_ptr_Output_v4float = OpTypePointer Output %v4float
8901      %3 = OpVariable %_ptr_Output_v4float Output
8902     %19 = OpTypeImage %float 2D 0 0 0 1 Unknown
8903 %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19
8904      %4 = OpVariable %_ptr_UniformConstant_19 UniformConstant
8905     %21 = OpTypeSampler
8906 %_ptr_UniformConstant_21 = OpTypePointer UniformConstant %21
8907     %5 = OpVariable %_ptr_UniformConstant_21 UniformConstant
8908    %23 = OpTypeSampledImage %19
8909     %6 = OpVariable %_ptr_UniformConstant_19 UniformConstant
8910     %2 = OpFunction %void None %8
8911    %24 = OpLabel
8912    %25 = OpVariable %_ptr_Function_v2uint Function
8913    %26 = OpLoad %19 %4
8914    %27 = OpLoad %21 %5
8915    %28 = OpSampledImage %23 %26 %27
8916    %29 = OpLoad %v2uint %25
8917    %30 = OpLoad %19 %6
8918    %31 = OpLoad %21 %5
8919    %32 = OpSampledImage %23 %30 %31
8920    %33 = OpImageBlockMatchWindowSSDQCOM %v4float %28 %29 %32 %29 %29
8921          OpStore %3 %33
8922          OpReturn
8923          OpFunctionEnd
8924 )";
8925   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
8926   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
8927             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
8928   EXPECT_THAT(getDiagnosticString(),
8929               HasSubstr("Missing decoration BlockMatchSamplerQCOM"));
8930 }
8931 
TEST_F(ValidateImage,QCOMImageProcessing2BlockMatchGatherSADNoDecorTargetIT)8932 TEST_F(ValidateImage, QCOMImageProcessing2BlockMatchGatherSADNoDecorTargetIT) {
8933   const std::string text = R"(
8934                OpCapability Shader
8935                OpCapability TextureBlockMatchQCOM
8936                OpCapability TextureBlockMatch2QCOM
8937                OpExtension "SPV_QCOM_image_processing"
8938                OpExtension "SPV_QCOM_image_processing2"
8939           %1 = OpExtInstImport "GLSL.std.450"
8940                OpMemoryModel Logical GLSL450
8941                OpEntryPoint Fragment %2 "main" %3 %4 %5
8942                OpExecutionMode %2 OriginUpperLeft
8943                OpDecorate %3 Location 0
8944                OpDecorate %4 DescriptorSet 0
8945                OpDecorate %4 Binding 4
8946                OpDecorate %5 DescriptorSet 0
8947                OpDecorate %5 Binding 5
8948                OpDecorate %5 BlockMatchTextureQCOM
8949        %void = OpTypeVoid
8950           %7 = OpTypeFunction %void
8951        %uint = OpTypeInt 32 0
8952      %v2uint = OpTypeVector %uint 2
8953 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
8954       %float = OpTypeFloat 32
8955     %v4float = OpTypeVector %float 4
8956 %_ptr_Input_v4float = OpTypePointer Input %v4float
8957 %_ptr_Input_float = OpTypePointer Input %float
8958 %_ptr_Function_uint = OpTypePointer Function %uint
8959 %_ptr_Output_v4float = OpTypePointer Output %v4float
8960           %3 = OpVariable %_ptr_Output_v4float Output
8961          %18 = OpTypeImage %float 2D 0 0 0 1 Unknown
8962          %19 = OpTypeSampledImage %18
8963 %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19
8964           %4 = OpVariable %_ptr_UniformConstant_19 UniformConstant
8965           %5 = OpVariable %_ptr_UniformConstant_19 UniformConstant
8966          %21 = OpTypeImage %float 2D 0 1 0 1 Unknown
8967           %2 = OpFunction %void None %7
8968          %22 = OpLabel
8969          %23 = OpVariable %_ptr_Function_v2uint Function
8970          %24 = OpLoad %19 %4
8971          %25 = OpLoad %v2uint %23
8972          %26 = OpLoad %19 %5
8973          %27 = OpLoad %v2uint %23
8974          %28 = OpLoad %v2uint %23
8975          %29 = OpImageBlockMatchGatherSADQCOM %v4float %24 %25 %26 %27 %28
8976                OpStore %3 %29
8977                OpReturn
8978                OpFunctionEnd
8979 )";
8980   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
8981   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
8982             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
8983   EXPECT_THAT(getDiagnosticString(),
8984               HasSubstr("Missing decoration BlockMatchTextureQCOM"));
8985 }
8986 
TEST_F(ValidateImage,QCOMImageProcessing2BlockMatchGatherSADNoDecorRefIT)8987 TEST_F(ValidateImage, QCOMImageProcessing2BlockMatchGatherSADNoDecorRefIT) {
8988   const std::string text = R"(
8989                OpCapability Shader
8990                OpCapability TextureBlockMatchQCOM
8991                OpCapability TextureBlockMatch2QCOM
8992                OpExtension "SPV_QCOM_image_processing"
8993                OpExtension "SPV_QCOM_image_processing2"
8994           %1 = OpExtInstImport "GLSL.std.450"
8995                OpMemoryModel Logical GLSL450
8996                OpEntryPoint Fragment %2 "main" %3 %4 %5
8997                OpExecutionMode %2 OriginUpperLeft
8998                OpDecorate %3 Location 0
8999                OpDecorate %4 DescriptorSet 0
9000                OpDecorate %4 Binding 4
9001                OpDecorate %4 BlockMatchTextureQCOM
9002                OpDecorate %5 DescriptorSet 0
9003                OpDecorate %5 Binding 5
9004        %void = OpTypeVoid
9005           %7 = OpTypeFunction %void
9006        %uint = OpTypeInt 32 0
9007      %v2uint = OpTypeVector %uint 2
9008 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
9009       %float = OpTypeFloat 32
9010     %v4float = OpTypeVector %float 4
9011 %_ptr_Input_v4float = OpTypePointer Input %v4float
9012 %_ptr_Input_float = OpTypePointer Input %float
9013 %_ptr_Function_uint = OpTypePointer Function %uint
9014 %_ptr_Output_v4float = OpTypePointer Output %v4float
9015           %3 = OpVariable %_ptr_Output_v4float Output
9016          %18 = OpTypeImage %float 2D 0 0 0 1 Unknown
9017          %19 = OpTypeSampledImage %18
9018 %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19
9019           %4 = OpVariable %_ptr_UniformConstant_19 UniformConstant
9020           %5 = OpVariable %_ptr_UniformConstant_19 UniformConstant
9021          %21 = OpTypeImage %float 2D 0 1 0 1 Unknown
9022           %2 = OpFunction %void None %7
9023          %22 = OpLabel
9024          %23 = OpVariable %_ptr_Function_v2uint Function
9025          %24 = OpLoad %19 %4
9026          %25 = OpLoad %v2uint %23
9027          %26 = OpLoad %19 %5
9028          %27 = OpLoad %v2uint %23
9029          %28 = OpLoad %v2uint %23
9030          %29 = OpImageBlockMatchGatherSADQCOM %v4float %24 %25 %26 %27 %28
9031                OpStore %3 %29
9032                OpReturn
9033                OpFunctionEnd
9034 )";
9035   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
9036   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
9037             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
9038   EXPECT_THAT(getDiagnosticString(),
9039               HasSubstr("Missing decoration BlockMatchTextureQCOM"));
9040 }
9041 
TEST_F(ValidateImage,QCOMImageProcessing2BlockMatchGatherSADNoDecorTargetNIT)9042 TEST_F(ValidateImage, QCOMImageProcessing2BlockMatchGatherSADNoDecorTargetNIT) {
9043   const std::string text = R"(
9044            OpCapability Shader
9045            OpCapability TextureBlockMatchQCOM
9046            OpCapability TextureBlockMatch2QCOM
9047            OpExtension "SPV_QCOM_image_processing"
9048            OpExtension "SPV_QCOM_image_processing2"
9049       %1 = OpExtInstImport "GLSL.std.450"
9050            OpMemoryModel Logical GLSL450
9051            OpEntryPoint Fragment %2 "main" %3 %4 %5 %6
9052            OpExecutionMode %2 OriginUpperLeft
9053            OpDecorate %3 Location 0
9054            OpDecorate %4 DescriptorSet 0
9055            OpDecorate %4 Binding 1
9056            OpDecorate %5 DescriptorSet 0
9057            OpDecorate %5 Binding 3
9058            OpDecorate %6 DescriptorSet 0
9059            OpDecorate %6 Binding 2
9060            OpDecorate %6 BlockMatchTextureQCOM
9061    %void = OpTypeVoid
9062       %8 = OpTypeFunction %void
9063    %uint = OpTypeInt 32 0
9064  %v2uint = OpTypeVector %uint 2
9065 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
9066   %float = OpTypeFloat 32
9067 %v4float = OpTypeVector %float 4
9068 %_ptr_Input_float = OpTypePointer Input %float
9069 %_ptr_Function_uint = OpTypePointer Function %uint
9070 %uint_4 = OpConstant %uint 4
9071     %17 = OpConstantComposite %v2uint %uint_4 %uint_4
9072 %_ptr_Output_v4float = OpTypePointer Output %v4float
9073      %3 = OpVariable %_ptr_Output_v4float Output
9074     %19 = OpTypeImage %float 2D 0 0 0 1 Unknown
9075 %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19
9076      %4 = OpVariable %_ptr_UniformConstant_19 UniformConstant
9077     %21 = OpTypeSampler
9078 %_ptr_UniformConstant_21 = OpTypePointer UniformConstant %21
9079     %5 = OpVariable %_ptr_UniformConstant_21 UniformConstant
9080    %23 = OpTypeSampledImage %19
9081     %6 = OpVariable %_ptr_UniformConstant_19 UniformConstant
9082     %2 = OpFunction %void None %8
9083    %24 = OpLabel
9084    %25 = OpVariable %_ptr_Function_v2uint Function
9085    %26 = OpLoad %19 %4
9086    %27 = OpLoad %21 %5
9087    %28 = OpSampledImage %23 %26 %27
9088    %29 = OpLoad %v2uint %25
9089    %30 = OpLoad %19 %6
9090    %31 = OpLoad %21 %5
9091    %32 = OpSampledImage %23 %30 %31
9092    %33 = OpImageBlockMatchGatherSADQCOM %v4float %28 %29 %32 %29 %29
9093          OpStore %3 %33
9094          OpReturn
9095          OpFunctionEnd
9096 )";
9097   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
9098   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
9099             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
9100   EXPECT_THAT(getDiagnosticString(),
9101               HasSubstr("Missing decoration BlockMatchTextureQCOM"));
9102 }
9103 
TEST_F(ValidateImage,QCOMImageProcessing2BlockMatchGatherSADNoDecorRefNIT)9104 TEST_F(ValidateImage, QCOMImageProcessing2BlockMatchGatherSADNoDecorRefNIT) {
9105   const std::string text = R"(
9106            OpCapability Shader
9107            OpCapability TextureBlockMatchQCOM
9108            OpCapability TextureBlockMatch2QCOM
9109            OpExtension "SPV_QCOM_image_processing"
9110            OpExtension "SPV_QCOM_image_processing2"
9111       %1 = OpExtInstImport "GLSL.std.450"
9112            OpMemoryModel Logical GLSL450
9113            OpEntryPoint Fragment %2 "main" %3 %4 %5 %6
9114            OpExecutionMode %2 OriginUpperLeft
9115            OpDecorate %3 Location 0
9116            OpDecorate %4 DescriptorSet 0
9117            OpDecorate %4 Binding 1
9118            OpDecorate %4 BlockMatchTextureQCOM
9119            OpDecorate %5 DescriptorSet 0
9120            OpDecorate %5 Binding 3
9121            OpDecorate %6 DescriptorSet 0
9122            OpDecorate %6 Binding 2
9123    %void = OpTypeVoid
9124       %8 = OpTypeFunction %void
9125    %uint = OpTypeInt 32 0
9126  %v2uint = OpTypeVector %uint 2
9127 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
9128   %float = OpTypeFloat 32
9129 %v4float = OpTypeVector %float 4
9130 %_ptr_Input_float = OpTypePointer Input %float
9131 %_ptr_Function_uint = OpTypePointer Function %uint
9132 %uint_4 = OpConstant %uint 4
9133     %17 = OpConstantComposite %v2uint %uint_4 %uint_4
9134 %_ptr_Output_v4float = OpTypePointer Output %v4float
9135      %3 = OpVariable %_ptr_Output_v4float Output
9136     %19 = OpTypeImage %float 2D 0 0 0 1 Unknown
9137 %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19
9138      %4 = OpVariable %_ptr_UniformConstant_19 UniformConstant
9139     %21 = OpTypeSampler
9140 %_ptr_UniformConstant_21 = OpTypePointer UniformConstant %21
9141     %5 = OpVariable %_ptr_UniformConstant_21 UniformConstant
9142    %23 = OpTypeSampledImage %19
9143     %6 = OpVariable %_ptr_UniformConstant_19 UniformConstant
9144     %2 = OpFunction %void None %8
9145    %24 = OpLabel
9146    %25 = OpVariable %_ptr_Function_v2uint Function
9147    %26 = OpLoad %19 %4
9148    %27 = OpLoad %21 %5
9149    %28 = OpSampledImage %23 %26 %27
9150    %29 = OpLoad %v2uint %25
9151    %30 = OpLoad %19 %6
9152    %31 = OpLoad %21 %5
9153    %32 = OpSampledImage %23 %30 %31
9154    %33 = OpImageBlockMatchGatherSADQCOM %v4float %28 %29 %32 %29 %29
9155          OpStore %3 %33
9156          OpReturn
9157          OpFunctionEnd
9158 )";
9159   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
9160   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
9161             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
9162   EXPECT_THAT(getDiagnosticString(),
9163               HasSubstr("Missing decoration BlockMatchTextureQCOM"));
9164 }
9165 
TEST_F(ValidateImage,QCOMImageProcessing2BlockMatchGatherSSDNoDecorTargetIT)9166 TEST_F(ValidateImage, QCOMImageProcessing2BlockMatchGatherSSDNoDecorTargetIT) {
9167   const std::string text = R"(
9168                OpCapability Shader
9169                OpCapability TextureBlockMatchQCOM
9170                OpCapability TextureBlockMatch2QCOM
9171                OpExtension "SPV_QCOM_image_processing"
9172                OpExtension "SPV_QCOM_image_processing2"
9173           %1 = OpExtInstImport "GLSL.std.450"
9174                OpMemoryModel Logical GLSL450
9175                OpEntryPoint Fragment %2 "main" %3 %4 %5
9176                OpExecutionMode %2 OriginUpperLeft
9177                OpDecorate %3 Location 0
9178                OpDecorate %4 DescriptorSet 0
9179                OpDecorate %4 Binding 4
9180                OpDecorate %5 DescriptorSet 0
9181                OpDecorate %5 Binding 5
9182                OpDecorate %5 BlockMatchTextureQCOM
9183        %void = OpTypeVoid
9184           %7 = OpTypeFunction %void
9185        %uint = OpTypeInt 32 0
9186      %v2uint = OpTypeVector %uint 2
9187 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
9188       %float = OpTypeFloat 32
9189     %v4float = OpTypeVector %float 4
9190 %_ptr_Input_v4float = OpTypePointer Input %v4float
9191 %_ptr_Input_float = OpTypePointer Input %float
9192 %_ptr_Function_uint = OpTypePointer Function %uint
9193 %_ptr_Output_v4float = OpTypePointer Output %v4float
9194           %3 = OpVariable %_ptr_Output_v4float Output
9195          %18 = OpTypeImage %float 2D 0 0 0 1 Unknown
9196          %19 = OpTypeSampledImage %18
9197 %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19
9198           %4 = OpVariable %_ptr_UniformConstant_19 UniformConstant
9199           %5 = OpVariable %_ptr_UniformConstant_19 UniformConstant
9200          %21 = OpTypeImage %float 2D 0 1 0 1 Unknown
9201           %2 = OpFunction %void None %7
9202          %22 = OpLabel
9203          %23 = OpVariable %_ptr_Function_v2uint Function
9204          %24 = OpLoad %19 %4
9205          %25 = OpLoad %v2uint %23
9206          %26 = OpLoad %19 %5
9207          %27 = OpLoad %v2uint %23
9208          %28 = OpLoad %v2uint %23
9209          %29 = OpImageBlockMatchGatherSSDQCOM %v4float %24 %25 %26 %27 %28
9210                OpStore %3 %29
9211                OpReturn
9212                OpFunctionEnd
9213 )";
9214   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
9215   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
9216             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
9217   EXPECT_THAT(getDiagnosticString(),
9218               HasSubstr("Missing decoration BlockMatchTextureQCOM"));
9219 }
9220 
TEST_F(ValidateImage,QCOMImageProcessing2BlockMatchGatherSSDNoDecorRefIT)9221 TEST_F(ValidateImage, QCOMImageProcessing2BlockMatchGatherSSDNoDecorRefIT) {
9222   const std::string text = R"(
9223                OpCapability Shader
9224                OpCapability TextureBlockMatchQCOM
9225                OpCapability TextureBlockMatch2QCOM
9226                OpExtension "SPV_QCOM_image_processing"
9227                OpExtension "SPV_QCOM_image_processing2"
9228           %1 = OpExtInstImport "GLSL.std.450"
9229                OpMemoryModel Logical GLSL450
9230                OpEntryPoint Fragment %2 "main" %3 %4 %5
9231                OpExecutionMode %2 OriginUpperLeft
9232                OpDecorate %3 Location 0
9233                OpDecorate %4 DescriptorSet 0
9234                OpDecorate %4 Binding 4
9235                OpDecorate %4 BlockMatchTextureQCOM
9236                OpDecorate %5 DescriptorSet 0
9237                OpDecorate %5 Binding 5
9238        %void = OpTypeVoid
9239           %7 = OpTypeFunction %void
9240        %uint = OpTypeInt 32 0
9241      %v2uint = OpTypeVector %uint 2
9242 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
9243       %float = OpTypeFloat 32
9244     %v4float = OpTypeVector %float 4
9245 %_ptr_Input_v4float = OpTypePointer Input %v4float
9246 %_ptr_Input_float = OpTypePointer Input %float
9247 %_ptr_Function_uint = OpTypePointer Function %uint
9248 %_ptr_Output_v4float = OpTypePointer Output %v4float
9249           %3 = OpVariable %_ptr_Output_v4float Output
9250          %18 = OpTypeImage %float 2D 0 0 0 1 Unknown
9251          %19 = OpTypeSampledImage %18
9252 %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19
9253           %4 = OpVariable %_ptr_UniformConstant_19 UniformConstant
9254           %5 = OpVariable %_ptr_UniformConstant_19 UniformConstant
9255          %21 = OpTypeImage %float 2D 0 1 0 1 Unknown
9256           %2 = OpFunction %void None %7
9257          %22 = OpLabel
9258          %23 = OpVariable %_ptr_Function_v2uint Function
9259          %24 = OpLoad %19 %4
9260          %25 = OpLoad %v2uint %23
9261          %26 = OpLoad %19 %5
9262          %27 = OpLoad %v2uint %23
9263          %28 = OpLoad %v2uint %23
9264          %29 = OpImageBlockMatchGatherSSDQCOM %v4float %24 %25 %26 %27 %28
9265                OpStore %3 %29
9266                OpReturn
9267                OpFunctionEnd
9268 )";
9269   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
9270   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
9271             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
9272   EXPECT_THAT(getDiagnosticString(),
9273               HasSubstr("Missing decoration BlockMatchTextureQCOM"));
9274 }
9275 
TEST_F(ValidateImage,QCOMImageProcessing2BlockMatchGatherSSDNoDecorTargetNIT)9276 TEST_F(ValidateImage, QCOMImageProcessing2BlockMatchGatherSSDNoDecorTargetNIT) {
9277   const std::string text = R"(
9278            OpCapability Shader
9279            OpCapability TextureBlockMatchQCOM
9280            OpCapability TextureBlockMatch2QCOM
9281            OpExtension "SPV_QCOM_image_processing"
9282            OpExtension "SPV_QCOM_image_processing2"
9283       %1 = OpExtInstImport "GLSL.std.450"
9284            OpMemoryModel Logical GLSL450
9285            OpEntryPoint Fragment %2 "main" %3 %4 %5 %6
9286            OpExecutionMode %2 OriginUpperLeft
9287            OpDecorate %3 Location 0
9288            OpDecorate %4 DescriptorSet 0
9289            OpDecorate %4 Binding 1
9290            OpDecorate %5 DescriptorSet 0
9291            OpDecorate %5 Binding 3
9292            OpDecorate %6 DescriptorSet 0
9293            OpDecorate %6 Binding 2
9294            OpDecorate %6 BlockMatchTextureQCOM
9295    %void = OpTypeVoid
9296       %8 = OpTypeFunction %void
9297    %uint = OpTypeInt 32 0
9298  %v2uint = OpTypeVector %uint 2
9299 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
9300   %float = OpTypeFloat 32
9301 %v4float = OpTypeVector %float 4
9302 %_ptr_Input_float = OpTypePointer Input %float
9303 %_ptr_Function_uint = OpTypePointer Function %uint
9304 %uint_4 = OpConstant %uint 4
9305     %17 = OpConstantComposite %v2uint %uint_4 %uint_4
9306 %_ptr_Output_v4float = OpTypePointer Output %v4float
9307      %3 = OpVariable %_ptr_Output_v4float Output
9308     %19 = OpTypeImage %float 2D 0 0 0 1 Unknown
9309 %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19
9310      %4 = OpVariable %_ptr_UniformConstant_19 UniformConstant
9311     %21 = OpTypeSampler
9312 %_ptr_UniformConstant_21 = OpTypePointer UniformConstant %21
9313     %5 = OpVariable %_ptr_UniformConstant_21 UniformConstant
9314    %23 = OpTypeSampledImage %19
9315     %6 = OpVariable %_ptr_UniformConstant_19 UniformConstant
9316     %2 = OpFunction %void None %8
9317    %24 = OpLabel
9318    %25 = OpVariable %_ptr_Function_v2uint Function
9319    %26 = OpLoad %19 %4
9320    %27 = OpLoad %21 %5
9321    %28 = OpSampledImage %23 %26 %27
9322    %29 = OpLoad %v2uint %25
9323    %30 = OpLoad %19 %6
9324    %31 = OpLoad %21 %5
9325    %32 = OpSampledImage %23 %30 %31
9326    %33 = OpImageBlockMatchGatherSSDQCOM %v4float %28 %29 %32 %29 %29
9327          OpStore %3 %33
9328          OpReturn
9329          OpFunctionEnd
9330 )";
9331   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
9332   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
9333             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
9334   EXPECT_THAT(getDiagnosticString(),
9335               HasSubstr("Missing decoration BlockMatchTextureQCOM"));
9336 }
9337 
TEST_F(ValidateImage,QCOMImageProcessing2BlockMatchGatherSSDNoDecorRefNIT)9338 TEST_F(ValidateImage, QCOMImageProcessing2BlockMatchGatherSSDNoDecorRefNIT) {
9339   const std::string text = R"(
9340            OpCapability Shader
9341            OpCapability TextureBlockMatchQCOM
9342            OpCapability TextureBlockMatch2QCOM
9343            OpExtension "SPV_QCOM_image_processing"
9344            OpExtension "SPV_QCOM_image_processing2"
9345       %1 = OpExtInstImport "GLSL.std.450"
9346            OpMemoryModel Logical GLSL450
9347            OpEntryPoint Fragment %2 "main" %3 %4 %5 %6
9348            OpExecutionMode %2 OriginUpperLeft
9349            OpDecorate %3 Location 0
9350            OpDecorate %4 DescriptorSet 0
9351            OpDecorate %4 Binding 1
9352            OpDecorate %4 BlockMatchTextureQCOM
9353            OpDecorate %5 DescriptorSet 0
9354            OpDecorate %5 Binding 3
9355            OpDecorate %6 DescriptorSet 0
9356            OpDecorate %6 Binding 2
9357    %void = OpTypeVoid
9358       %8 = OpTypeFunction %void
9359    %uint = OpTypeInt 32 0
9360  %v2uint = OpTypeVector %uint 2
9361 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
9362   %float = OpTypeFloat 32
9363 %v4float = OpTypeVector %float 4
9364 %_ptr_Input_float = OpTypePointer Input %float
9365 %_ptr_Function_uint = OpTypePointer Function %uint
9366 %uint_4 = OpConstant %uint 4
9367     %17 = OpConstantComposite %v2uint %uint_4 %uint_4
9368 %_ptr_Output_v4float = OpTypePointer Output %v4float
9369      %3 = OpVariable %_ptr_Output_v4float Output
9370     %19 = OpTypeImage %float 2D 0 0 0 1 Unknown
9371 %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19
9372      %4 = OpVariable %_ptr_UniformConstant_19 UniformConstant
9373     %21 = OpTypeSampler
9374 %_ptr_UniformConstant_21 = OpTypePointer UniformConstant %21
9375     %5 = OpVariable %_ptr_UniformConstant_21 UniformConstant
9376    %23 = OpTypeSampledImage %19
9377     %6 = OpVariable %_ptr_UniformConstant_19 UniformConstant
9378     %2 = OpFunction %void None %8
9379    %24 = OpLabel
9380    %25 = OpVariable %_ptr_Function_v2uint Function
9381    %26 = OpLoad %19 %4
9382    %27 = OpLoad %21 %5
9383    %28 = OpSampledImage %23 %26 %27
9384    %29 = OpLoad %v2uint %25
9385    %30 = OpLoad %19 %6
9386    %31 = OpLoad %21 %5
9387    %32 = OpSampledImage %23 %30 %31
9388    %33 = OpImageBlockMatchGatherSSDQCOM %v4float %28 %29 %32 %29 %29
9389          OpStore %3 %33
9390          OpReturn
9391          OpFunctionEnd
9392 )";
9393   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
9394   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
9395             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
9396   EXPECT_THAT(getDiagnosticString(),
9397               HasSubstr("Missing decoration BlockMatchTextureQCOM"));
9398 }
9399 
TEST_F(ValidateImage,QCOMImageProcessing2BlockMatchWindowSADInvalidUseTargetI)9400 TEST_F(ValidateImage,
9401        QCOMImageProcessing2BlockMatchWindowSADInvalidUseTargetI) {
9402   const std::string text = R"(
9403                OpCapability Shader
9404                OpCapability TextureBlockMatchQCOM
9405                OpCapability TextureBlockMatch2QCOM
9406                OpExtension "SPV_QCOM_image_processing"
9407                OpExtension "SPV_QCOM_image_processing2"
9408           %1 = OpExtInstImport "GLSL.std.450"
9409                OpMemoryModel Logical GLSL450
9410                OpEntryPoint Fragment %2 "main" %3 %4 %5 %6
9411                OpExecutionMode %2 OriginUpperLeft
9412                OpDecorate %3 Location 0
9413                OpDecorate %4 Location 0
9414                OpDecorate %5 DescriptorSet 0
9415                OpDecorate %5 Binding 4
9416                OpDecorate %6 DescriptorSet 0
9417                OpDecorate %6 Binding 5
9418                OpDecorate %5 BlockMatchTextureQCOM
9419                OpDecorate %5 BlockMatchSamplerQCOM
9420                OpDecorate %6 BlockMatchTextureQCOM
9421                OpDecorate %6 BlockMatchSamplerQCOM
9422        %void = OpTypeVoid
9423           %8 = OpTypeFunction %void
9424        %uint = OpTypeInt 32 0
9425      %v2uint = OpTypeVector %uint 2
9426 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
9427       %float = OpTypeFloat 32
9428     %v4float = OpTypeVector %float 4
9429 %_ptr_Input_v4float = OpTypePointer Input %v4float
9430           %3 = OpVariable %_ptr_Input_v4float Input
9431      %uint_4 = OpConstant %uint 4
9432          %16 = OpConstantComposite %v2uint %uint_4 %uint_4
9433 %_ptr_Output_v4float = OpTypePointer Output %v4float
9434           %4 = OpVariable %_ptr_Output_v4float Output
9435          %18 = OpTypeImage %float 2D 0 0 0 1 Unknown
9436 %_ptr_UniformConstant_18 = OpTypePointer UniformConstant %18
9437          %20 = OpTypeSampledImage %18
9438 %_ptr_UniformConstant_20 = OpTypePointer UniformConstant %20
9439           %5 = OpVariable %_ptr_UniformConstant_20 UniformConstant
9440           %6 = OpVariable %_ptr_UniformConstant_20 UniformConstant
9441     %v2float = OpTypeVector %float 2
9442          %23 = OpTypeImage %float 2D 0 1 0 1 Unknown
9443           %2 = OpFunction %void None %8
9444          %24 = OpLabel
9445          %25 = OpVariable %_ptr_Function_v2uint Function
9446                OpStore %25 %16
9447          %26 = OpLoad %20 %5
9448          %27 = OpLoad %v2uint %25
9449          %28 = OpLoad %20 %6
9450          %29 = OpLoad %v2uint %25
9451          %30 = OpLoad %v2uint %25
9452          %31 = OpImageBlockMatchWindowSADQCOM %v4float %26 %27 %28 %29 %30
9453                OpStore %4 %31
9454          %32 = OpLoad %20 %5
9455          %33 = OpLoad %v4float %3
9456          %34 = OpVectorShuffle %v2float %33 %33 0 2
9457          %35 = OpImageSampleImplicitLod %v4float %32 %34
9458                OpStore %4 %35
9459                OpReturn
9460                OpFunctionEnd
9461 )";
9462   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
9463   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
9464             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
9465   EXPECT_THAT(
9466       getDiagnosticString(),
9467       HasSubstr("Illegal use of QCOM image processing decorated texture"));
9468 }
9469 
TEST_F(ValidateImage,QCOMImageProcessing2BlockMatchWindowSADInvalidUseRefI)9470 TEST_F(ValidateImage, QCOMImageProcessing2BlockMatchWindowSADInvalidUseRefI) {
9471   const std::string text = R"(
9472                OpCapability Shader
9473                OpCapability TextureBlockMatchQCOM
9474                OpCapability TextureBlockMatch2QCOM
9475                OpExtension "SPV_QCOM_image_processing"
9476                OpExtension "SPV_QCOM_image_processing2"
9477           %1 = OpExtInstImport "GLSL.std.450"
9478                OpMemoryModel Logical GLSL450
9479                OpEntryPoint Fragment %2 "main" %3 %4 %5 %6
9480                OpExecutionMode %2 OriginUpperLeft
9481                OpDecorate %3 Location 0
9482                OpDecorate %4 Location 0
9483                OpDecorate %5 DescriptorSet 0
9484                OpDecorate %5 Binding 4
9485                OpDecorate %6 DescriptorSet 0
9486                OpDecorate %6 Binding 5
9487                OpDecorate %5 BlockMatchTextureQCOM
9488                OpDecorate %5 BlockMatchSamplerQCOM
9489                OpDecorate %6 BlockMatchTextureQCOM
9490                OpDecorate %6 BlockMatchSamplerQCOM
9491        %void = OpTypeVoid
9492           %8 = OpTypeFunction %void
9493        %uint = OpTypeInt 32 0
9494      %v2uint = OpTypeVector %uint 2
9495 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
9496       %float = OpTypeFloat 32
9497     %v4float = OpTypeVector %float 4
9498 %_ptr_Input_v4float = OpTypePointer Input %v4float
9499           %3 = OpVariable %_ptr_Input_v4float Input
9500      %uint_4 = OpConstant %uint 4
9501          %16 = OpConstantComposite %v2uint %uint_4 %uint_4
9502 %_ptr_Output_v4float = OpTypePointer Output %v4float
9503           %4 = OpVariable %_ptr_Output_v4float Output
9504          %18 = OpTypeImage %float 2D 0 0 0 1 Unknown
9505 %_ptr_UniformConstant_18 = OpTypePointer UniformConstant %18
9506          %20 = OpTypeSampledImage %18
9507 %_ptr_UniformConstant_20 = OpTypePointer UniformConstant %20
9508           %5 = OpVariable %_ptr_UniformConstant_20 UniformConstant
9509           %6 = OpVariable %_ptr_UniformConstant_20 UniformConstant
9510     %v2float = OpTypeVector %float 2
9511          %23 = OpTypeImage %float 2D 0 1 0 1 Unknown
9512           %2 = OpFunction %void None %8
9513          %24 = OpLabel
9514          %25 = OpVariable %_ptr_Function_v2uint Function
9515                OpStore %25 %16
9516          %26 = OpLoad %20 %5
9517          %27 = OpLoad %v2uint %25
9518          %28 = OpLoad %20 %6
9519          %29 = OpLoad %v2uint %25
9520          %30 = OpLoad %v2uint %25
9521          %31 = OpImageBlockMatchWindowSADQCOM %v4float %26 %27 %28 %29 %30
9522                OpStore %4 %31
9523          %32 = OpLoad %20 %6
9524          %33 = OpLoad %v4float %3
9525          %34 = OpVectorShuffle %v2float %33 %33 0 2
9526          %35 = OpImageSampleImplicitLod %v4float %32 %34
9527                OpStore %4 %35
9528                OpReturn
9529                OpFunctionEnd
9530 )";
9531   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
9532   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
9533             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
9534   EXPECT_THAT(
9535       getDiagnosticString(),
9536       HasSubstr("Illegal use of QCOM image processing decorated texture"));
9537 }
9538 
TEST_F(ValidateImage,QCOMImageProcessing2BlockMatchWindowSADInvalidUseTargetNI)9539 TEST_F(ValidateImage,
9540        QCOMImageProcessing2BlockMatchWindowSADInvalidUseTargetNI) {
9541   const std::string text = R"(
9542                OpCapability Shader
9543                OpCapability TextureBlockMatchQCOM
9544                OpCapability TextureBlockMatch2QCOM
9545                OpExtension "SPV_QCOM_image_processing"
9546                OpExtension "SPV_QCOM_image_processing2"
9547           %1 = OpExtInstImport "GLSL.std.450"
9548                OpMemoryModel Logical GLSL450
9549                OpEntryPoint Fragment %main "main" %100 %101 %102 %103 %104
9550                OpExecutionMode %main OriginUpperLeft
9551                OpDecorate %100 Location 0
9552                OpDecorate %101 Location 0
9553                OpDecorate %102 DescriptorSet 0
9554                OpDecorate %102 Binding 1
9555                OpDecorate %103 DescriptorSet 0
9556                OpDecorate %103 Binding 3
9557                OpDecorate %104 DescriptorSet 0
9558                OpDecorate %104 Binding 2
9559                OpDecorate %102 BlockMatchTextureQCOM
9560                OpDecorate %103 BlockMatchSamplerQCOM
9561                OpDecorate %104 BlockMatchTextureQCOM
9562        %void = OpTypeVoid
9563           %3 = OpTypeFunction %void
9564        %uint = OpTypeInt 32 0
9565      %v2uint = OpTypeVector %uint 2
9566 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
9567       %float = OpTypeFloat 32
9568     %v4float = OpTypeVector %float 4
9569 %_ptr_Input_v4float = OpTypePointer Input %v4float
9570  %100 = OpVariable %_ptr_Input_v4float Input
9571 %_ptr_Output_v4float = OpTypePointer Output %v4float
9572   %101 = OpVariable %_ptr_Output_v4float Output
9573          %42 = OpTypeImage %float 2D 0 0 0 1 Unknown
9574 %_ptr_UniformConstant_42 = OpTypePointer UniformConstant %42
9575  %102 = OpVariable %_ptr_UniformConstant_42 UniformConstant
9576          %46 = OpTypeSampler
9577 %_ptr_UniformConstant_46 = OpTypePointer UniformConstant %46
9578        %103 = OpVariable %_ptr_UniformConstant_46 UniformConstant
9579          %50 = OpTypeSampledImage %42
9580  %104 = OpVariable %_ptr_UniformConstant_42 UniformConstant
9581     %v2float = OpTypeVector %float 2
9582        %main = OpFunction %void None %3
9583           %5 = OpLabel
9584          %15 = OpVariable %_ptr_Function_v2uint Function
9585          %45 = OpLoad %42 %102
9586          %49 = OpLoad %46 %103
9587          %51 = OpSampledImage %50 %45 %49
9588          %52 = OpLoad %v2uint %15
9589          %54 = OpLoad %42 %104
9590          %55 = OpLoad %46 %103
9591          %56 = OpSampledImage %50 %54 %55
9592          %57 = OpLoad %v2uint %15
9593          %58 = OpLoad %v2uint %15
9594          %59 = OpImageBlockMatchWindowSADQCOM %v4float %51 %52 %56 %57 %58
9595                OpStore %101 %59
9596          %69 = OpLoad %42 %102
9597          %70 = OpLoad %46 %103
9598          %71 = OpSampledImage %50 %69 %70
9599          %73 = OpLoad %v4float %100
9600          %74 = OpVectorShuffle %v2float %73 %73 0 0
9601          %75 = OpImageSampleImplicitLod %v4float %71 %74
9602                OpStore %101 %75
9603                OpReturn
9604                OpFunctionEnd
9605 )";
9606   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
9607   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
9608             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
9609   EXPECT_THAT(
9610       getDiagnosticString(),
9611       HasSubstr("Illegal use of QCOM image processing decorated texture"));
9612 }
9613 
TEST_F(ValidateImage,QCOMImageProcessing2BlockMatchWindowSADInvalidUseRefNI)9614 TEST_F(ValidateImage, QCOMImageProcessing2BlockMatchWindowSADInvalidUseRefNI) {
9615   const std::string text = R"(
9616                OpCapability Shader
9617                OpCapability TextureBlockMatchQCOM
9618                OpCapability TextureBlockMatch2QCOM
9619                OpExtension "SPV_QCOM_image_processing"
9620                OpExtension "SPV_QCOM_image_processing2"
9621           %1 = OpExtInstImport "GLSL.std.450"
9622                OpMemoryModel Logical GLSL450
9623                OpEntryPoint Fragment %main "main" %100 %101 %102 %103 %104
9624                OpExecutionMode %main OriginUpperLeft
9625                OpDecorate %100 Location 0
9626                OpDecorate %101 Location 0
9627                OpDecorate %102 DescriptorSet 0
9628                OpDecorate %102 Binding 1
9629                OpDecorate %103 DescriptorSet 0
9630                OpDecorate %103 Binding 3
9631                OpDecorate %104 DescriptorSet 0
9632                OpDecorate %104 Binding 2
9633                OpDecorate %102 BlockMatchTextureQCOM
9634                OpDecorate %103 BlockMatchSamplerQCOM
9635                OpDecorate %104 BlockMatchTextureQCOM
9636        %void = OpTypeVoid
9637           %3 = OpTypeFunction %void
9638        %uint = OpTypeInt 32 0
9639      %v2uint = OpTypeVector %uint 2
9640 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
9641       %float = OpTypeFloat 32
9642     %v4float = OpTypeVector %float 4
9643 %_ptr_Input_v4float = OpTypePointer Input %v4float
9644  %100 = OpVariable %_ptr_Input_v4float Input
9645 %_ptr_Output_v4float = OpTypePointer Output %v4float
9646   %101 = OpVariable %_ptr_Output_v4float Output
9647          %42 = OpTypeImage %float 2D 0 0 0 1 Unknown
9648 %_ptr_UniformConstant_42 = OpTypePointer UniformConstant %42
9649  %102 = OpVariable %_ptr_UniformConstant_42 UniformConstant
9650          %46 = OpTypeSampler
9651 %_ptr_UniformConstant_46 = OpTypePointer UniformConstant %46
9652        %103 = OpVariable %_ptr_UniformConstant_46 UniformConstant
9653          %50 = OpTypeSampledImage %42
9654  %104 = OpVariable %_ptr_UniformConstant_42 UniformConstant
9655     %v2float = OpTypeVector %float 2
9656        %main = OpFunction %void None %3
9657           %5 = OpLabel
9658          %15 = OpVariable %_ptr_Function_v2uint Function
9659          %45 = OpLoad %42 %102
9660          %49 = OpLoad %46 %103
9661          %51 = OpSampledImage %50 %45 %49
9662          %52 = OpLoad %v2uint %15
9663          %54 = OpLoad %42 %104
9664          %55 = OpLoad %46 %103
9665          %56 = OpSampledImage %50 %54 %55
9666          %57 = OpLoad %v2uint %15
9667          %58 = OpLoad %v2uint %15
9668          %59 = OpImageBlockMatchWindowSADQCOM %v4float %51 %52 %56 %57 %58
9669                OpStore %101 %59
9670          %69 = OpLoad %42 %104
9671          %70 = OpLoad %46 %103
9672          %71 = OpSampledImage %50 %69 %70
9673          %73 = OpLoad %v4float %100
9674          %74 = OpVectorShuffle %v2float %73 %73 0 0
9675          %75 = OpImageSampleImplicitLod %v4float %71 %74
9676                OpStore %101 %75
9677                OpReturn
9678                OpFunctionEnd
9679 )";
9680   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
9681   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
9682             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
9683   EXPECT_THAT(
9684       getDiagnosticString(),
9685       HasSubstr("Illegal use of QCOM image processing decorated texture"));
9686 }
9687 
TEST_F(ValidateImage,QCOMImageProcessing2BlockMatchWindowSSDInvalidUseTargetI)9688 TEST_F(ValidateImage,
9689        QCOMImageProcessing2BlockMatchWindowSSDInvalidUseTargetI) {
9690   const std::string text = R"(
9691                OpCapability Shader
9692                OpCapability TextureBlockMatchQCOM
9693                OpCapability TextureBlockMatch2QCOM
9694                OpExtension "SPV_QCOM_image_processing"
9695                OpExtension "SPV_QCOM_image_processing2"
9696           %1 = OpExtInstImport "GLSL.std.450"
9697                OpMemoryModel Logical GLSL450
9698                OpEntryPoint Fragment %2 "main" %3 %4 %5 %6
9699                OpExecutionMode %2 OriginUpperLeft
9700                OpDecorate %3 Location 0
9701                OpDecorate %4 Location 0
9702                OpDecorate %5 DescriptorSet 0
9703                OpDecorate %5 Binding 4
9704                OpDecorate %6 DescriptorSet 0
9705                OpDecorate %6 Binding 5
9706                OpDecorate %5 BlockMatchTextureQCOM
9707                OpDecorate %5 BlockMatchSamplerQCOM
9708                OpDecorate %6 BlockMatchTextureQCOM
9709                OpDecorate %6 BlockMatchSamplerQCOM
9710        %void = OpTypeVoid
9711           %8 = OpTypeFunction %void
9712        %uint = OpTypeInt 32 0
9713      %v2uint = OpTypeVector %uint 2
9714 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
9715       %float = OpTypeFloat 32
9716     %v4float = OpTypeVector %float 4
9717 %_ptr_Input_v4float = OpTypePointer Input %v4float
9718           %3 = OpVariable %_ptr_Input_v4float Input
9719      %uint_4 = OpConstant %uint 4
9720          %16 = OpConstantComposite %v2uint %uint_4 %uint_4
9721 %_ptr_Output_v4float = OpTypePointer Output %v4float
9722           %4 = OpVariable %_ptr_Output_v4float Output
9723          %18 = OpTypeImage %float 2D 0 0 0 1 Unknown
9724 %_ptr_UniformConstant_18 = OpTypePointer UniformConstant %18
9725          %20 = OpTypeSampledImage %18
9726 %_ptr_UniformConstant_20 = OpTypePointer UniformConstant %20
9727           %5 = OpVariable %_ptr_UniformConstant_20 UniformConstant
9728           %6 = OpVariable %_ptr_UniformConstant_20 UniformConstant
9729     %v2float = OpTypeVector %float 2
9730          %23 = OpTypeImage %float 2D 0 1 0 1 Unknown
9731           %2 = OpFunction %void None %8
9732          %24 = OpLabel
9733          %25 = OpVariable %_ptr_Function_v2uint Function
9734                OpStore %25 %16
9735          %26 = OpLoad %20 %5
9736          %27 = OpLoad %v2uint %25
9737          %28 = OpLoad %20 %6
9738          %29 = OpLoad %v2uint %25
9739          %30 = OpLoad %v2uint %25
9740          %31 = OpImageBlockMatchWindowSSDQCOM %v4float %26 %27 %28 %29 %30
9741                OpStore %4 %31
9742          %32 = OpLoad %20 %5
9743          %33 = OpLoad %v4float %3
9744          %34 = OpVectorShuffle %v2float %33 %33 0 2
9745          %35 = OpImageSampleImplicitLod %v4float %32 %34
9746                OpStore %4 %35
9747                OpReturn
9748                OpFunctionEnd
9749 )";
9750   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
9751   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
9752             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
9753   EXPECT_THAT(
9754       getDiagnosticString(),
9755       HasSubstr("Illegal use of QCOM image processing decorated texture"));
9756 }
9757 
TEST_F(ValidateImage,QCOMImageProcessing2BlockMatchWindowSSDInvalidUseRefI)9758 TEST_F(ValidateImage, QCOMImageProcessing2BlockMatchWindowSSDInvalidUseRefI) {
9759   const std::string text = R"(
9760                OpCapability Shader
9761                OpCapability TextureBlockMatchQCOM
9762                OpCapability TextureBlockMatch2QCOM
9763                OpExtension "SPV_QCOM_image_processing"
9764                OpExtension "SPV_QCOM_image_processing2"
9765           %1 = OpExtInstImport "GLSL.std.450"
9766                OpMemoryModel Logical GLSL450
9767                OpEntryPoint Fragment %2 "main" %3 %4 %5 %6
9768                OpExecutionMode %2 OriginUpperLeft
9769                OpDecorate %3 Location 0
9770                OpDecorate %4 Location 0
9771                OpDecorate %5 DescriptorSet 0
9772                OpDecorate %5 Binding 4
9773                OpDecorate %6 DescriptorSet 0
9774                OpDecorate %6 Binding 5
9775                OpDecorate %5 BlockMatchTextureQCOM
9776                OpDecorate %5 BlockMatchSamplerQCOM
9777                OpDecorate %6 BlockMatchTextureQCOM
9778                OpDecorate %6 BlockMatchSamplerQCOM
9779        %void = OpTypeVoid
9780           %8 = OpTypeFunction %void
9781        %uint = OpTypeInt 32 0
9782      %v2uint = OpTypeVector %uint 2
9783 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
9784       %float = OpTypeFloat 32
9785     %v4float = OpTypeVector %float 4
9786 %_ptr_Input_v4float = OpTypePointer Input %v4float
9787           %3 = OpVariable %_ptr_Input_v4float Input
9788      %uint_4 = OpConstant %uint 4
9789          %16 = OpConstantComposite %v2uint %uint_4 %uint_4
9790 %_ptr_Output_v4float = OpTypePointer Output %v4float
9791           %4 = OpVariable %_ptr_Output_v4float Output
9792          %18 = OpTypeImage %float 2D 0 0 0 1 Unknown
9793 %_ptr_UniformConstant_18 = OpTypePointer UniformConstant %18
9794          %20 = OpTypeSampledImage %18
9795 %_ptr_UniformConstant_20 = OpTypePointer UniformConstant %20
9796           %5 = OpVariable %_ptr_UniformConstant_20 UniformConstant
9797           %6 = OpVariable %_ptr_UniformConstant_20 UniformConstant
9798     %v2float = OpTypeVector %float 2
9799          %23 = OpTypeImage %float 2D 0 1 0 1 Unknown
9800           %2 = OpFunction %void None %8
9801          %24 = OpLabel
9802          %25 = OpVariable %_ptr_Function_v2uint Function
9803                OpStore %25 %16
9804          %26 = OpLoad %20 %5
9805          %27 = OpLoad %v2uint %25
9806          %28 = OpLoad %20 %6
9807          %29 = OpLoad %v2uint %25
9808          %30 = OpLoad %v2uint %25
9809          %31 = OpImageBlockMatchWindowSSDQCOM %v4float %26 %27 %28 %29 %30
9810                OpStore %4 %31
9811          %32 = OpLoad %20 %6
9812          %33 = OpLoad %v4float %3
9813          %34 = OpVectorShuffle %v2float %33 %33 0 2
9814          %35 = OpImageSampleImplicitLod %v4float %32 %34
9815                OpStore %4 %35
9816                OpReturn
9817                OpFunctionEnd
9818 )";
9819   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
9820   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
9821             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
9822   EXPECT_THAT(
9823       getDiagnosticString(),
9824       HasSubstr("Illegal use of QCOM image processing decorated texture"));
9825 }
9826 
TEST_F(ValidateImage,QCOMImageProcessing2BlockMatchWindowSSDInvalidUseTargetNI)9827 TEST_F(ValidateImage,
9828        QCOMImageProcessing2BlockMatchWindowSSDInvalidUseTargetNI) {
9829   const std::string text = R"(
9830                OpCapability Shader
9831                OpCapability TextureBlockMatchQCOM
9832                OpCapability TextureBlockMatch2QCOM
9833                OpExtension "SPV_QCOM_image_processing"
9834                OpExtension "SPV_QCOM_image_processing2"
9835           %1 = OpExtInstImport "GLSL.std.450"
9836                OpMemoryModel Logical GLSL450
9837                OpEntryPoint Fragment %main "main" %100 %101 %102 %103 %104
9838                OpExecutionMode %main OriginUpperLeft
9839                OpDecorate %100 Location 0
9840                OpDecorate %101 Location 0
9841                OpDecorate %102 DescriptorSet 0
9842                OpDecorate %102 Binding 1
9843                OpDecorate %103 DescriptorSet 0
9844                OpDecorate %103 Binding 3
9845                OpDecorate %104 DescriptorSet 0
9846                OpDecorate %104 Binding 2
9847                OpDecorate %102 BlockMatchTextureQCOM
9848                OpDecorate %103 BlockMatchSamplerQCOM
9849                OpDecorate %104 BlockMatchTextureQCOM
9850        %void = OpTypeVoid
9851           %3 = OpTypeFunction %void
9852        %uint = OpTypeInt 32 0
9853      %v2uint = OpTypeVector %uint 2
9854 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
9855       %float = OpTypeFloat 32
9856     %v4float = OpTypeVector %float 4
9857 %_ptr_Input_v4float = OpTypePointer Input %v4float
9858  %100 = OpVariable %_ptr_Input_v4float Input
9859 %_ptr_Output_v4float = OpTypePointer Output %v4float
9860   %101 = OpVariable %_ptr_Output_v4float Output
9861          %42 = OpTypeImage %float 2D 0 0 0 1 Unknown
9862 %_ptr_UniformConstant_42 = OpTypePointer UniformConstant %42
9863  %102 = OpVariable %_ptr_UniformConstant_42 UniformConstant
9864          %46 = OpTypeSampler
9865 %_ptr_UniformConstant_46 = OpTypePointer UniformConstant %46
9866        %103 = OpVariable %_ptr_UniformConstant_46 UniformConstant
9867          %50 = OpTypeSampledImage %42
9868  %104 = OpVariable %_ptr_UniformConstant_42 UniformConstant
9869     %v2float = OpTypeVector %float 2
9870        %main = OpFunction %void None %3
9871           %5 = OpLabel
9872          %15 = OpVariable %_ptr_Function_v2uint Function
9873          %45 = OpLoad %42 %102
9874          %49 = OpLoad %46 %103
9875          %51 = OpSampledImage %50 %45 %49
9876          %52 = OpLoad %v2uint %15
9877          %54 = OpLoad %42 %104
9878          %55 = OpLoad %46 %103
9879          %56 = OpSampledImage %50 %54 %55
9880          %57 = OpLoad %v2uint %15
9881          %58 = OpLoad %v2uint %15
9882          %59 = OpImageBlockMatchWindowSSDQCOM %v4float %51 %52 %56 %57 %58
9883                OpStore %101 %59
9884          %69 = OpLoad %42 %102
9885          %70 = OpLoad %46 %103
9886          %71 = OpSampledImage %50 %69 %70
9887          %73 = OpLoad %v4float %100
9888          %74 = OpVectorShuffle %v2float %73 %73 0 0
9889          %75 = OpImageSampleImplicitLod %v4float %71 %74
9890                OpStore %101 %75
9891                OpReturn
9892                OpFunctionEnd
9893 )";
9894   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
9895   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
9896             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
9897   EXPECT_THAT(
9898       getDiagnosticString(),
9899       HasSubstr("Illegal use of QCOM image processing decorated texture"));
9900 }
9901 
TEST_F(ValidateImage,QCOMImageProcessing2BlockMatchWindowSSDInvalidUseRefNI)9902 TEST_F(ValidateImage, QCOMImageProcessing2BlockMatchWindowSSDInvalidUseRefNI) {
9903   const std::string text = R"(
9904                OpCapability Shader
9905                OpCapability TextureBlockMatchQCOM
9906                OpCapability TextureBlockMatch2QCOM
9907                OpExtension "SPV_QCOM_image_processing"
9908                OpExtension "SPV_QCOM_image_processing2"
9909           %1 = OpExtInstImport "GLSL.std.450"
9910                OpMemoryModel Logical GLSL450
9911                OpEntryPoint Fragment %main "main" %100 %101 %102 %103 %104
9912                OpExecutionMode %main OriginUpperLeft
9913                OpDecorate %100 Location 0
9914                OpDecorate %101 Location 0
9915                OpDecorate %102 DescriptorSet 0
9916                OpDecorate %102 Binding 1
9917                OpDecorate %103 DescriptorSet 0
9918                OpDecorate %103 Binding 3
9919                OpDecorate %104 DescriptorSet 0
9920                OpDecorate %104 Binding 2
9921                OpDecorate %102 BlockMatchTextureQCOM
9922                OpDecorate %103 BlockMatchSamplerQCOM
9923                OpDecorate %104 BlockMatchTextureQCOM
9924        %void = OpTypeVoid
9925           %3 = OpTypeFunction %void
9926        %uint = OpTypeInt 32 0
9927      %v2uint = OpTypeVector %uint 2
9928 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
9929       %float = OpTypeFloat 32
9930     %v4float = OpTypeVector %float 4
9931 %_ptr_Input_v4float = OpTypePointer Input %v4float
9932  %100 = OpVariable %_ptr_Input_v4float Input
9933 %_ptr_Output_v4float = OpTypePointer Output %v4float
9934   %101 = OpVariable %_ptr_Output_v4float Output
9935          %42 = OpTypeImage %float 2D 0 0 0 1 Unknown
9936 %_ptr_UniformConstant_42 = OpTypePointer UniformConstant %42
9937  %102 = OpVariable %_ptr_UniformConstant_42 UniformConstant
9938          %46 = OpTypeSampler
9939 %_ptr_UniformConstant_46 = OpTypePointer UniformConstant %46
9940        %103 = OpVariable %_ptr_UniformConstant_46 UniformConstant
9941          %50 = OpTypeSampledImage %42
9942  %104 = OpVariable %_ptr_UniformConstant_42 UniformConstant
9943     %v2float = OpTypeVector %float 2
9944        %main = OpFunction %void None %3
9945           %5 = OpLabel
9946          %15 = OpVariable %_ptr_Function_v2uint Function
9947          %45 = OpLoad %42 %102
9948          %49 = OpLoad %46 %103
9949          %51 = OpSampledImage %50 %45 %49
9950          %52 = OpLoad %v2uint %15
9951          %54 = OpLoad %42 %104
9952          %55 = OpLoad %46 %103
9953          %56 = OpSampledImage %50 %54 %55
9954          %57 = OpLoad %v2uint %15
9955          %58 = OpLoad %v2uint %15
9956          %59 = OpImageBlockMatchWindowSSDQCOM %v4float %51 %52 %56 %57 %58
9957                OpStore %101 %59
9958          %69 = OpLoad %42 %104
9959          %70 = OpLoad %46 %103
9960          %71 = OpSampledImage %50 %69 %70
9961          %73 = OpLoad %v4float %100
9962          %74 = OpVectorShuffle %v2float %73 %73 0 0
9963          %75 = OpImageSampleImplicitLod %v4float %71 %74
9964                OpStore %101 %75
9965                OpReturn
9966                OpFunctionEnd
9967 )";
9968   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
9969   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
9970             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
9971   EXPECT_THAT(
9972       getDiagnosticString(),
9973       HasSubstr("Illegal use of QCOM image processing decorated texture"));
9974 }
9975 
TEST_F(ValidateImage,QCOMImageProcessing2BlockMatchGatherSADInvalidUseTargetI)9976 TEST_F(ValidateImage,
9977        QCOMImageProcessing2BlockMatchGatherSADInvalidUseTargetI) {
9978   const std::string text = R"(
9979                OpCapability Shader
9980                OpCapability TextureBlockMatchQCOM
9981                OpCapability TextureBlockMatch2QCOM
9982                OpExtension "SPV_QCOM_image_processing"
9983                OpExtension "SPV_QCOM_image_processing2"
9984           %1 = OpExtInstImport "GLSL.std.450"
9985                OpMemoryModel Logical GLSL450
9986                OpEntryPoint Fragment %2 "main" %3 %4 %5 %6
9987                OpExecutionMode %2 OriginUpperLeft
9988                OpDecorate %3 Location 0
9989                OpDecorate %4 Location 0
9990                OpDecorate %5 DescriptorSet 0
9991                OpDecorate %5 Binding 4
9992                OpDecorate %6 DescriptorSet 0
9993                OpDecorate %6 Binding 5
9994                OpDecorate %5 BlockMatchTextureQCOM
9995                OpDecorate %6 BlockMatchTextureQCOM
9996        %void = OpTypeVoid
9997           %8 = OpTypeFunction %void
9998        %uint = OpTypeInt 32 0
9999      %v2uint = OpTypeVector %uint 2
10000 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
10001       %float = OpTypeFloat 32
10002     %v4float = OpTypeVector %float 4
10003 %_ptr_Input_v4float = OpTypePointer Input %v4float
10004           %3 = OpVariable %_ptr_Input_v4float Input
10005      %uint_4 = OpConstant %uint 4
10006          %16 = OpConstantComposite %v2uint %uint_4 %uint_4
10007 %_ptr_Output_v4float = OpTypePointer Output %v4float
10008           %4 = OpVariable %_ptr_Output_v4float Output
10009          %18 = OpTypeImage %float 2D 0 0 0 1 Unknown
10010 %_ptr_UniformConstant_18 = OpTypePointer UniformConstant %18
10011          %20 = OpTypeSampledImage %18
10012 %_ptr_UniformConstant_20 = OpTypePointer UniformConstant %20
10013           %5 = OpVariable %_ptr_UniformConstant_20 UniformConstant
10014           %6 = OpVariable %_ptr_UniformConstant_20 UniformConstant
10015     %v2float = OpTypeVector %float 2
10016          %23 = OpTypeImage %float 2D 0 1 0 1 Unknown
10017           %2 = OpFunction %void None %8
10018          %24 = OpLabel
10019          %25 = OpVariable %_ptr_Function_v2uint Function
10020                OpStore %25 %16
10021          %26 = OpLoad %20 %5
10022          %27 = OpLoad %v2uint %25
10023          %28 = OpLoad %20 %6
10024          %29 = OpLoad %v2uint %25
10025          %30 = OpLoad %v2uint %25
10026          %31 = OpImageBlockMatchGatherSADQCOM %v4float %26 %27 %28 %29 %30
10027                OpStore %4 %31
10028          %32 = OpLoad %20 %5
10029          %33 = OpLoad %v4float %3
10030          %34 = OpVectorShuffle %v2float %33 %33 0 2
10031          %35 = OpImageSampleImplicitLod %v4float %32 %34
10032                OpStore %4 %35
10033                OpReturn
10034                OpFunctionEnd
10035 )";
10036   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
10037   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
10038             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
10039   EXPECT_THAT(
10040       getDiagnosticString(),
10041       HasSubstr("Illegal use of QCOM image processing decorated texture"));
10042 }
10043 
TEST_F(ValidateImage,QCOMImageProcessing2BlockMatchGatherSADInvalidUseRefI)10044 TEST_F(ValidateImage, QCOMImageProcessing2BlockMatchGatherSADInvalidUseRefI) {
10045   const std::string text = R"(
10046                OpCapability Shader
10047                OpCapability TextureBlockMatchQCOM
10048                OpCapability TextureBlockMatch2QCOM
10049                OpExtension "SPV_QCOM_image_processing"
10050                OpExtension "SPV_QCOM_image_processing2"
10051           %1 = OpExtInstImport "GLSL.std.450"
10052                OpMemoryModel Logical GLSL450
10053                OpEntryPoint Fragment %2 "main" %3 %4 %5 %6
10054                OpExecutionMode %2 OriginUpperLeft
10055                OpDecorate %3 Location 0
10056                OpDecorate %4 Location 0
10057                OpDecorate %5 DescriptorSet 0
10058                OpDecorate %5 Binding 4
10059                OpDecorate %6 DescriptorSet 0
10060                OpDecorate %6 Binding 5
10061                OpDecorate %5 BlockMatchTextureQCOM
10062                OpDecorate %6 BlockMatchTextureQCOM
10063        %void = OpTypeVoid
10064           %8 = OpTypeFunction %void
10065        %uint = OpTypeInt 32 0
10066      %v2uint = OpTypeVector %uint 2
10067 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
10068       %float = OpTypeFloat 32
10069     %v4float = OpTypeVector %float 4
10070 %_ptr_Input_v4float = OpTypePointer Input %v4float
10071           %3 = OpVariable %_ptr_Input_v4float Input
10072      %uint_4 = OpConstant %uint 4
10073          %16 = OpConstantComposite %v2uint %uint_4 %uint_4
10074 %_ptr_Output_v4float = OpTypePointer Output %v4float
10075           %4 = OpVariable %_ptr_Output_v4float Output
10076          %18 = OpTypeImage %float 2D 0 0 0 1 Unknown
10077 %_ptr_UniformConstant_18 = OpTypePointer UniformConstant %18
10078          %20 = OpTypeSampledImage %18
10079 %_ptr_UniformConstant_20 = OpTypePointer UniformConstant %20
10080           %5 = OpVariable %_ptr_UniformConstant_20 UniformConstant
10081           %6 = OpVariable %_ptr_UniformConstant_20 UniformConstant
10082     %v2float = OpTypeVector %float 2
10083          %23 = OpTypeImage %float 2D 0 1 0 1 Unknown
10084           %2 = OpFunction %void None %8
10085          %24 = OpLabel
10086          %25 = OpVariable %_ptr_Function_v2uint Function
10087                OpStore %25 %16
10088          %26 = OpLoad %20 %5
10089          %27 = OpLoad %v2uint %25
10090          %28 = OpLoad %20 %6
10091          %29 = OpLoad %v2uint %25
10092          %30 = OpLoad %v2uint %25
10093          %31 = OpImageBlockMatchGatherSADQCOM %v4float %26 %27 %28 %29 %30
10094                OpStore %4 %31
10095          %32 = OpLoad %20 %6
10096          %33 = OpLoad %v4float %3
10097          %34 = OpVectorShuffle %v2float %33 %33 0 2
10098          %35 = OpImageSampleImplicitLod %v4float %32 %34
10099                OpStore %4 %35
10100                OpReturn
10101                OpFunctionEnd
10102 )";
10103   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
10104   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
10105             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
10106   EXPECT_THAT(
10107       getDiagnosticString(),
10108       HasSubstr("Illegal use of QCOM image processing decorated texture"));
10109 }
10110 
TEST_F(ValidateImage,QCOMImageProcessing2BlockMatchGatherSADInvalidUseTargetNI)10111 TEST_F(ValidateImage,
10112        QCOMImageProcessing2BlockMatchGatherSADInvalidUseTargetNI) {
10113   const std::string text = R"(
10114                OpCapability Shader
10115                OpCapability TextureBlockMatchQCOM
10116                OpCapability TextureBlockMatch2QCOM
10117                OpExtension "SPV_QCOM_image_processing"
10118                OpExtension "SPV_QCOM_image_processing2"
10119           %1 = OpExtInstImport "GLSL.std.450"
10120                OpMemoryModel Logical GLSL450
10121                OpEntryPoint Fragment %main "main" %100 %101 %102 %103 %104
10122                OpExecutionMode %main OriginUpperLeft
10123                OpDecorate %100 Location 0
10124                OpDecorate %101 Location 0
10125                OpDecorate %102 DescriptorSet 0
10126                OpDecorate %102 Binding 1
10127                OpDecorate %103 DescriptorSet 0
10128                OpDecorate %103 Binding 3
10129                OpDecorate %104 DescriptorSet 0
10130                OpDecorate %104 Binding 2
10131                OpDecorate %102 BlockMatchTextureQCOM
10132                OpDecorate %104 BlockMatchTextureQCOM
10133        %void = OpTypeVoid
10134           %3 = OpTypeFunction %void
10135        %uint = OpTypeInt 32 0
10136      %v2uint = OpTypeVector %uint 2
10137 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
10138       %float = OpTypeFloat 32
10139     %v4float = OpTypeVector %float 4
10140 %_ptr_Input_v4float = OpTypePointer Input %v4float
10141  %100 = OpVariable %_ptr_Input_v4float Input
10142 %_ptr_Output_v4float = OpTypePointer Output %v4float
10143   %101 = OpVariable %_ptr_Output_v4float Output
10144          %42 = OpTypeImage %float 2D 0 0 0 1 Unknown
10145 %_ptr_UniformConstant_42 = OpTypePointer UniformConstant %42
10146  %102 = OpVariable %_ptr_UniformConstant_42 UniformConstant
10147          %46 = OpTypeSampler
10148 %_ptr_UniformConstant_46 = OpTypePointer UniformConstant %46
10149        %103 = OpVariable %_ptr_UniformConstant_46 UniformConstant
10150          %50 = OpTypeSampledImage %42
10151  %104 = OpVariable %_ptr_UniformConstant_42 UniformConstant
10152     %v2float = OpTypeVector %float 2
10153        %main = OpFunction %void None %3
10154           %5 = OpLabel
10155          %15 = OpVariable %_ptr_Function_v2uint Function
10156          %45 = OpLoad %42 %102
10157          %49 = OpLoad %46 %103
10158          %51 = OpSampledImage %50 %45 %49
10159          %52 = OpLoad %v2uint %15
10160          %54 = OpLoad %42 %104
10161          %55 = OpLoad %46 %103
10162          %56 = OpSampledImage %50 %54 %55
10163          %57 = OpLoad %v2uint %15
10164          %58 = OpLoad %v2uint %15
10165          %59 = OpImageBlockMatchGatherSADQCOM %v4float %51 %52 %56 %57 %58
10166                OpStore %101 %59
10167          %69 = OpLoad %42 %102
10168          %70 = OpLoad %46 %103
10169          %71 = OpSampledImage %50 %69 %70
10170          %73 = OpLoad %v4float %100
10171          %74 = OpVectorShuffle %v2float %73 %73 0 0
10172          %75 = OpImageSampleImplicitLod %v4float %71 %74
10173                OpStore %101 %75
10174                OpReturn
10175                OpFunctionEnd
10176 )";
10177   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
10178   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
10179             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
10180   EXPECT_THAT(
10181       getDiagnosticString(),
10182       HasSubstr("Illegal use of QCOM image processing decorated texture"));
10183 }
10184 
TEST_F(ValidateImage,QCOMImageProcessing2BlockMatchGatherSADInvalidUseRefNI)10185 TEST_F(ValidateImage, QCOMImageProcessing2BlockMatchGatherSADInvalidUseRefNI) {
10186   const std::string text = R"(
10187                OpCapability Shader
10188                OpCapability TextureBlockMatchQCOM
10189                OpCapability TextureBlockMatch2QCOM
10190                OpExtension "SPV_QCOM_image_processing"
10191                OpExtension "SPV_QCOM_image_processing2"
10192           %1 = OpExtInstImport "GLSL.std.450"
10193                OpMemoryModel Logical GLSL450
10194                OpEntryPoint Fragment %main "main" %100 %101 %102 %103 %104
10195                OpExecutionMode %main OriginUpperLeft
10196                OpDecorate %100 Location 0
10197                OpDecorate %101 Location 0
10198                OpDecorate %102 DescriptorSet 0
10199                OpDecorate %102 Binding 1
10200                OpDecorate %103 DescriptorSet 0
10201                OpDecorate %103 Binding 3
10202                OpDecorate %104 DescriptorSet 0
10203                OpDecorate %104 Binding 2
10204                OpDecorate %102 BlockMatchTextureQCOM
10205                OpDecorate %104 BlockMatchTextureQCOM
10206        %void = OpTypeVoid
10207           %3 = OpTypeFunction %void
10208        %uint = OpTypeInt 32 0
10209      %v2uint = OpTypeVector %uint 2
10210 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
10211       %float = OpTypeFloat 32
10212     %v4float = OpTypeVector %float 4
10213 %_ptr_Input_v4float = OpTypePointer Input %v4float
10214  %100 = OpVariable %_ptr_Input_v4float Input
10215 %_ptr_Output_v4float = OpTypePointer Output %v4float
10216   %101 = OpVariable %_ptr_Output_v4float Output
10217          %42 = OpTypeImage %float 2D 0 0 0 1 Unknown
10218 %_ptr_UniformConstant_42 = OpTypePointer UniformConstant %42
10219  %102 = OpVariable %_ptr_UniformConstant_42 UniformConstant
10220          %46 = OpTypeSampler
10221 %_ptr_UniformConstant_46 = OpTypePointer UniformConstant %46
10222        %103 = OpVariable %_ptr_UniformConstant_46 UniformConstant
10223          %50 = OpTypeSampledImage %42
10224  %104 = OpVariable %_ptr_UniformConstant_42 UniformConstant
10225     %v2float = OpTypeVector %float 2
10226        %main = OpFunction %void None %3
10227           %5 = OpLabel
10228          %15 = OpVariable %_ptr_Function_v2uint Function
10229          %45 = OpLoad %42 %102
10230          %49 = OpLoad %46 %103
10231          %51 = OpSampledImage %50 %45 %49
10232          %52 = OpLoad %v2uint %15
10233          %54 = OpLoad %42 %104
10234          %55 = OpLoad %46 %103
10235          %56 = OpSampledImage %50 %54 %55
10236          %57 = OpLoad %v2uint %15
10237          %58 = OpLoad %v2uint %15
10238          %59 = OpImageBlockMatchGatherSADQCOM %v4float %51 %52 %56 %57 %58
10239                OpStore %101 %59
10240          %69 = OpLoad %42 %104
10241          %70 = OpLoad %46 %103
10242          %71 = OpSampledImage %50 %69 %70
10243          %73 = OpLoad %v4float %100
10244          %74 = OpVectorShuffle %v2float %73 %73 0 0
10245          %75 = OpImageSampleImplicitLod %v4float %71 %74
10246                OpStore %101 %75
10247                OpReturn
10248                OpFunctionEnd
10249 )";
10250   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
10251   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
10252             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
10253   EXPECT_THAT(
10254       getDiagnosticString(),
10255       HasSubstr("Illegal use of QCOM image processing decorated texture"));
10256 }
10257 
TEST_F(ValidateImage,QCOMImageProcessing2BlockMatchGatherSSDInvalidUseTargetI)10258 TEST_F(ValidateImage,
10259        QCOMImageProcessing2BlockMatchGatherSSDInvalidUseTargetI) {
10260   const std::string text = R"(
10261                OpCapability Shader
10262                OpCapability TextureBlockMatchQCOM
10263                OpCapability TextureBlockMatch2QCOM
10264                OpExtension "SPV_QCOM_image_processing"
10265                OpExtension "SPV_QCOM_image_processing2"
10266           %1 = OpExtInstImport "GLSL.std.450"
10267                OpMemoryModel Logical GLSL450
10268                OpEntryPoint Fragment %2 "main" %3 %4 %5 %6
10269                OpExecutionMode %2 OriginUpperLeft
10270                OpDecorate %3 Location 0
10271                OpDecorate %4 Location 0
10272                OpDecorate %5 DescriptorSet 0
10273                OpDecorate %5 Binding 4
10274                OpDecorate %6 DescriptorSet 0
10275                OpDecorate %6 Binding 5
10276                OpDecorate %5 BlockMatchTextureQCOM
10277                OpDecorate %6 BlockMatchTextureQCOM
10278        %void = OpTypeVoid
10279           %8 = OpTypeFunction %void
10280        %uint = OpTypeInt 32 0
10281      %v2uint = OpTypeVector %uint 2
10282 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
10283       %float = OpTypeFloat 32
10284     %v4float = OpTypeVector %float 4
10285 %_ptr_Input_v4float = OpTypePointer Input %v4float
10286           %3 = OpVariable %_ptr_Input_v4float Input
10287      %uint_4 = OpConstant %uint 4
10288          %16 = OpConstantComposite %v2uint %uint_4 %uint_4
10289 %_ptr_Output_v4float = OpTypePointer Output %v4float
10290           %4 = OpVariable %_ptr_Output_v4float Output
10291          %18 = OpTypeImage %float 2D 0 0 0 1 Unknown
10292 %_ptr_UniformConstant_18 = OpTypePointer UniformConstant %18
10293          %20 = OpTypeSampledImage %18
10294 %_ptr_UniformConstant_20 = OpTypePointer UniformConstant %20
10295           %5 = OpVariable %_ptr_UniformConstant_20 UniformConstant
10296           %6 = OpVariable %_ptr_UniformConstant_20 UniformConstant
10297     %v2float = OpTypeVector %float 2
10298          %23 = OpTypeImage %float 2D 0 1 0 1 Unknown
10299           %2 = OpFunction %void None %8
10300          %24 = OpLabel
10301          %25 = OpVariable %_ptr_Function_v2uint Function
10302                OpStore %25 %16
10303          %26 = OpLoad %20 %5
10304          %27 = OpLoad %v2uint %25
10305          %28 = OpLoad %20 %6
10306          %29 = OpLoad %v2uint %25
10307          %30 = OpLoad %v2uint %25
10308          %31 = OpImageBlockMatchGatherSSDQCOM %v4float %26 %27 %28 %29 %30
10309                OpStore %4 %31
10310          %32 = OpLoad %20 %5
10311          %33 = OpLoad %v4float %3
10312          %34 = OpVectorShuffle %v2float %33 %33 0 2
10313          %35 = OpImageSampleImplicitLod %v4float %32 %34
10314                OpStore %4 %35
10315                OpReturn
10316                OpFunctionEnd
10317 )";
10318   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
10319   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
10320             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
10321   EXPECT_THAT(
10322       getDiagnosticString(),
10323       HasSubstr("Illegal use of QCOM image processing decorated texture"));
10324 }
10325 
TEST_F(ValidateImage,QCOMImageProcessing2BlockMatchGatherSSDInvalidUseRefI)10326 TEST_F(ValidateImage, QCOMImageProcessing2BlockMatchGatherSSDInvalidUseRefI) {
10327   const std::string text = R"(
10328                OpCapability Shader
10329                OpCapability TextureBlockMatchQCOM
10330                OpCapability TextureBlockMatch2QCOM
10331                OpExtension "SPV_QCOM_image_processing"
10332                OpExtension "SPV_QCOM_image_processing2"
10333           %1 = OpExtInstImport "GLSL.std.450"
10334                OpMemoryModel Logical GLSL450
10335                OpEntryPoint Fragment %2 "main" %3 %4 %5 %6
10336                OpExecutionMode %2 OriginUpperLeft
10337                OpDecorate %3 Location 0
10338                OpDecorate %4 Location 0
10339                OpDecorate %5 DescriptorSet 0
10340                OpDecorate %5 Binding 4
10341                OpDecorate %6 DescriptorSet 0
10342                OpDecorate %6 Binding 5
10343                OpDecorate %5 BlockMatchTextureQCOM
10344                OpDecorate %6 BlockMatchTextureQCOM
10345        %void = OpTypeVoid
10346           %8 = OpTypeFunction %void
10347        %uint = OpTypeInt 32 0
10348      %v2uint = OpTypeVector %uint 2
10349 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
10350       %float = OpTypeFloat 32
10351     %v4float = OpTypeVector %float 4
10352 %_ptr_Input_v4float = OpTypePointer Input %v4float
10353           %3 = OpVariable %_ptr_Input_v4float Input
10354      %uint_4 = OpConstant %uint 4
10355          %16 = OpConstantComposite %v2uint %uint_4 %uint_4
10356 %_ptr_Output_v4float = OpTypePointer Output %v4float
10357           %4 = OpVariable %_ptr_Output_v4float Output
10358          %18 = OpTypeImage %float 2D 0 0 0 1 Unknown
10359 %_ptr_UniformConstant_18 = OpTypePointer UniformConstant %18
10360          %20 = OpTypeSampledImage %18
10361 %_ptr_UniformConstant_20 = OpTypePointer UniformConstant %20
10362           %5 = OpVariable %_ptr_UniformConstant_20 UniformConstant
10363           %6 = OpVariable %_ptr_UniformConstant_20 UniformConstant
10364     %v2float = OpTypeVector %float 2
10365          %23 = OpTypeImage %float 2D 0 1 0 1 Unknown
10366           %2 = OpFunction %void None %8
10367          %24 = OpLabel
10368          %25 = OpVariable %_ptr_Function_v2uint Function
10369                OpStore %25 %16
10370          %26 = OpLoad %20 %5
10371          %27 = OpLoad %v2uint %25
10372          %28 = OpLoad %20 %6
10373          %29 = OpLoad %v2uint %25
10374          %30 = OpLoad %v2uint %25
10375          %31 = OpImageBlockMatchGatherSSDQCOM %v4float %26 %27 %28 %29 %30
10376                OpStore %4 %31
10377          %32 = OpLoad %20 %6
10378          %33 = OpLoad %v4float %3
10379          %34 = OpVectorShuffle %v2float %33 %33 0 2
10380          %35 = OpImageSampleImplicitLod %v4float %32 %34
10381                OpStore %4 %35
10382                OpReturn
10383                OpFunctionEnd
10384 )";
10385   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
10386   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
10387             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
10388   EXPECT_THAT(
10389       getDiagnosticString(),
10390       HasSubstr("Illegal use of QCOM image processing decorated texture"));
10391 }
10392 
TEST_F(ValidateImage,QCOMImageProcessing2BlockMatchGatherSSDInvalidUseTargetNI)10393 TEST_F(ValidateImage,
10394        QCOMImageProcessing2BlockMatchGatherSSDInvalidUseTargetNI) {
10395   const std::string text = R"(
10396                OpCapability Shader
10397                OpCapability TextureBlockMatchQCOM
10398                OpCapability TextureBlockMatch2QCOM
10399                OpExtension "SPV_QCOM_image_processing"
10400                OpExtension "SPV_QCOM_image_processing2"
10401           %1 = OpExtInstImport "GLSL.std.450"
10402                OpMemoryModel Logical GLSL450
10403                OpEntryPoint Fragment %main "main" %100 %101 %102 %103 %104
10404                OpExecutionMode %main OriginUpperLeft
10405                OpDecorate %100 Location 0
10406                OpDecorate %101 Location 0
10407                OpDecorate %102 DescriptorSet 0
10408                OpDecorate %102 Binding 1
10409                OpDecorate %103 DescriptorSet 0
10410                OpDecorate %103 Binding 3
10411                OpDecorate %104 DescriptorSet 0
10412                OpDecorate %104 Binding 2
10413                OpDecorate %102 BlockMatchTextureQCOM
10414                OpDecorate %104 BlockMatchTextureQCOM
10415        %void = OpTypeVoid
10416           %3 = OpTypeFunction %void
10417        %uint = OpTypeInt 32 0
10418      %v2uint = OpTypeVector %uint 2
10419 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
10420       %float = OpTypeFloat 32
10421     %v4float = OpTypeVector %float 4
10422 %_ptr_Input_v4float = OpTypePointer Input %v4float
10423  %100 = OpVariable %_ptr_Input_v4float Input
10424 %_ptr_Output_v4float = OpTypePointer Output %v4float
10425   %101 = OpVariable %_ptr_Output_v4float Output
10426          %42 = OpTypeImage %float 2D 0 0 0 1 Unknown
10427 %_ptr_UniformConstant_42 = OpTypePointer UniformConstant %42
10428  %102 = OpVariable %_ptr_UniformConstant_42 UniformConstant
10429          %46 = OpTypeSampler
10430 %_ptr_UniformConstant_46 = OpTypePointer UniformConstant %46
10431        %103 = OpVariable %_ptr_UniformConstant_46 UniformConstant
10432          %50 = OpTypeSampledImage %42
10433  %104 = OpVariable %_ptr_UniformConstant_42 UniformConstant
10434     %v2float = OpTypeVector %float 2
10435        %main = OpFunction %void None %3
10436           %5 = OpLabel
10437          %15 = OpVariable %_ptr_Function_v2uint Function
10438          %45 = OpLoad %42 %102
10439          %49 = OpLoad %46 %103
10440          %51 = OpSampledImage %50 %45 %49
10441          %52 = OpLoad %v2uint %15
10442          %54 = OpLoad %42 %104
10443          %55 = OpLoad %46 %103
10444          %56 = OpSampledImage %50 %54 %55
10445          %57 = OpLoad %v2uint %15
10446          %58 = OpLoad %v2uint %15
10447          %59 = OpImageBlockMatchGatherSSDQCOM %v4float %51 %52 %56 %57 %58
10448                OpStore %101 %59
10449          %69 = OpLoad %42 %102
10450          %70 = OpLoad %46 %103
10451          %71 = OpSampledImage %50 %69 %70
10452          %73 = OpLoad %v4float %100
10453          %74 = OpVectorShuffle %v2float %73 %73 0 0
10454          %75 = OpImageSampleImplicitLod %v4float %71 %74
10455                OpStore %101 %75
10456                OpReturn
10457                OpFunctionEnd
10458 )";
10459   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
10460   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
10461             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
10462   EXPECT_THAT(
10463       getDiagnosticString(),
10464       HasSubstr("Illegal use of QCOM image processing decorated texture"));
10465 }
10466 
TEST_F(ValidateImage,QCOMImageProcessing2BlockMatchGatherSSDInvalidUseRefNI)10467 TEST_F(ValidateImage, QCOMImageProcessing2BlockMatchGatherSSDInvalidUseRefNI) {
10468   const std::string text = R"(
10469                OpCapability Shader
10470                OpCapability TextureBlockMatchQCOM
10471                OpCapability TextureBlockMatch2QCOM
10472                OpExtension "SPV_QCOM_image_processing"
10473                OpExtension "SPV_QCOM_image_processing2"
10474           %1 = OpExtInstImport "GLSL.std.450"
10475                OpMemoryModel Logical GLSL450
10476                OpEntryPoint Fragment %main "main" %100 %101 %102 %103 %104
10477                OpExecutionMode %main OriginUpperLeft
10478                OpDecorate %100 Location 0
10479                OpDecorate %101 Location 0
10480                OpDecorate %102 DescriptorSet 0
10481                OpDecorate %102 Binding 1
10482                OpDecorate %103 DescriptorSet 0
10483                OpDecorate %103 Binding 3
10484                OpDecorate %104 DescriptorSet 0
10485                OpDecorate %104 Binding 2
10486                OpDecorate %102 BlockMatchTextureQCOM
10487                OpDecorate %104 BlockMatchTextureQCOM
10488        %void = OpTypeVoid
10489           %3 = OpTypeFunction %void
10490        %uint = OpTypeInt 32 0
10491      %v2uint = OpTypeVector %uint 2
10492 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
10493       %float = OpTypeFloat 32
10494     %v4float = OpTypeVector %float 4
10495 %_ptr_Input_v4float = OpTypePointer Input %v4float
10496  %100 = OpVariable %_ptr_Input_v4float Input
10497 %_ptr_Output_v4float = OpTypePointer Output %v4float
10498   %101 = OpVariable %_ptr_Output_v4float Output
10499          %42 = OpTypeImage %float 2D 0 0 0 1 Unknown
10500 %_ptr_UniformConstant_42 = OpTypePointer UniformConstant %42
10501  %102 = OpVariable %_ptr_UniformConstant_42 UniformConstant
10502          %46 = OpTypeSampler
10503 %_ptr_UniformConstant_46 = OpTypePointer UniformConstant %46
10504        %103 = OpVariable %_ptr_UniformConstant_46 UniformConstant
10505          %50 = OpTypeSampledImage %42
10506  %104 = OpVariable %_ptr_UniformConstant_42 UniformConstant
10507     %v2float = OpTypeVector %float 2
10508        %main = OpFunction %void None %3
10509           %5 = OpLabel
10510          %15 = OpVariable %_ptr_Function_v2uint Function
10511          %45 = OpLoad %42 %102
10512          %49 = OpLoad %46 %103
10513          %51 = OpSampledImage %50 %45 %49
10514          %52 = OpLoad %v2uint %15
10515          %54 = OpLoad %42 %104
10516          %55 = OpLoad %46 %103
10517          %56 = OpSampledImage %50 %54 %55
10518          %57 = OpLoad %v2uint %15
10519          %58 = OpLoad %v2uint %15
10520          %59 = OpImageBlockMatchGatherSSDQCOM %v4float %51 %52 %56 %57 %58
10521                OpStore %101 %59
10522          %69 = OpLoad %42 %104
10523          %70 = OpLoad %46 %103
10524          %71 = OpSampledImage %50 %69 %70
10525          %73 = OpLoad %v4float %100
10526          %74 = OpVectorShuffle %v2float %73 %73 0 0
10527          %75 = OpImageSampleImplicitLod %v4float %71 %74
10528                OpStore %101 %75
10529                OpReturn
10530                OpFunctionEnd
10531 )";
10532   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
10533   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
10534             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
10535   EXPECT_THAT(
10536       getDiagnosticString(),
10537       HasSubstr("Illegal use of QCOM image processing decorated texture"));
10538 }
10539 
TEST_F(ValidateImage,ImageMSArray_ArrayedSampledTypeRequiresCapability)10540 TEST_F(ValidateImage, ImageMSArray_ArrayedSampledTypeRequiresCapability) {
10541   const std::string code = R"(
10542                OpCapability Shader
10543                OpCapability StorageImageMultisample
10544                OpCapability StorageImageReadWithoutFormat
10545                OpMemoryModel Logical GLSL450
10546                OpEntryPoint Fragment %main "main"
10547                OpExecutionMode %main OriginUpperLeft
10548                OpDecorate %var_image DescriptorSet 0
10549                OpDecorate %var_image Binding 1
10550        %void = OpTypeVoid
10551        %func = OpTypeFunction %void
10552         %f32 = OpTypeFloat 32
10553         %u32 = OpTypeInt 32 0
10554      %uint_2 = OpConstant %u32 2
10555      %uint_1 = OpConstant %u32 1
10556      %v2uint = OpTypeVector %u32 2
10557     %v4float = OpTypeVector %f32 4
10558     %image = OpTypeImage %f32 2D 2 1 1 2 Unknown
10559 %ptr_image = OpTypePointer UniformConstant %image
10560        %10 = OpConstantComposite %v2uint %uint_1 %uint_2
10561 %var_image = OpVariable %ptr_image UniformConstant
10562      %main = OpFunction %void None %func
10563  %main_lab = OpLabel
10564        %18 = OpLoad %image %var_image
10565        %19 = OpImageRead %v4float %18 %10 Sample %uint_2
10566              OpReturn
10567              OpFunctionEnd
10568 )";
10569 
10570   const spv_target_env env = SPV_ENV_VULKAN_1_0;
10571   CompileSuccessfully(code, env);
10572   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
10573   EXPECT_THAT(
10574       getDiagnosticString(),
10575       HasSubstr("Capability ImageMSArray is required to access storage image"));
10576 }
10577 
TEST_F(ValidateImage,ImageMSArray_SampledTypeDoesNotRequireCapability)10578 TEST_F(ValidateImage, ImageMSArray_SampledTypeDoesNotRequireCapability) {
10579   const std::string code = R"(
10580                OpCapability Shader
10581                OpCapability StorageImageMultisample
10582                OpCapability StorageImageReadWithoutFormat
10583                OpMemoryModel Logical GLSL450
10584                OpEntryPoint Fragment %main "main"
10585                OpExecutionMode %main OriginUpperLeft
10586                OpDecorate %var_image DescriptorSet 0
10587                OpDecorate %var_image Binding 1
10588        %void = OpTypeVoid
10589        %func = OpTypeFunction %void
10590         %f32 = OpTypeFloat 32
10591         %u32 = OpTypeInt 32 0
10592      %uint_2 = OpConstant %u32 2
10593      %uint_1 = OpConstant %u32 1
10594      %v2uint = OpTypeVector %u32 2
10595     %v4float = OpTypeVector %f32 4
10596     %image = OpTypeImage %f32 2D 2 0 1 2 Unknown
10597 %ptr_image = OpTypePointer UniformConstant %image
10598        %10 = OpConstantComposite %v2uint %uint_1 %uint_2
10599 %var_image = OpVariable %ptr_image UniformConstant
10600      %main = OpFunction %void None %func
10601  %main_lab = OpLabel
10602        %18 = OpLoad %image %var_image
10603        %19 = OpImageRead %v4float %18 %10 Sample %uint_2
10604              OpReturn
10605              OpFunctionEnd
10606 )";
10607 
10608   const spv_target_env env = SPV_ENV_VULKAN_1_0;
10609   CompileSuccessfully(code, env);
10610   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(env));
10611   EXPECT_THAT(getDiagnosticString(), Eq(""));
10612 }
10613 
TEST_F(ValidateImage,ImageMSArray_ArrayedTypeDoesNotRequireCapability)10614 TEST_F(ValidateImage, ImageMSArray_ArrayedTypeDoesNotRequireCapability) {
10615   const std::string code = R"(
10616                OpCapability Shader
10617                OpCapability StorageImageReadWithoutFormat
10618                OpMemoryModel Logical GLSL450
10619                OpEntryPoint Fragment %main "main"
10620                OpExecutionMode %main OriginUpperLeft
10621                OpDecorate %var_image DescriptorSet 0
10622                OpDecorate %var_image Binding 1
10623        %void = OpTypeVoid
10624        %func = OpTypeFunction %void
10625         %f32 = OpTypeFloat 32
10626         %u32 = OpTypeInt 32 0
10627      %uint_3 = OpConstant %u32 3
10628      %uint_2 = OpConstant %u32 2
10629      %uint_1 = OpConstant %u32 1
10630      %v3uint = OpTypeVector %u32 3
10631     %v4float = OpTypeVector %f32 4
10632     %image = OpTypeImage %f32 2D 2 1 0 2 Unknown
10633 %ptr_image = OpTypePointer UniformConstant %image
10634        %10 = OpConstantComposite %v3uint %uint_1 %uint_2 %uint_3
10635 %var_image = OpVariable %ptr_image UniformConstant
10636      %main = OpFunction %void None %func
10637  %main_lab = OpLabel
10638        %18 = OpLoad %image %var_image
10639        %19 = OpImageRead %v4float %18 %10
10640              OpReturn
10641              OpFunctionEnd
10642 )";
10643 
10644   const spv_target_env env = SPV_ENV_VULKAN_1_0;
10645   CompileSuccessfully(code, env);
10646   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(env));
10647   EXPECT_THAT(getDiagnosticString(), Eq(""));
10648 }
10649 
TEST_F(ValidateImage,SampledImageTypeMismatch)10650 TEST_F(ValidateImage, SampledImageTypeMismatch) {
10651   const std::string code = R"(
10652 OpCapability Shader
10653 OpMemoryModel Logical GLSL450
10654 OpEntryPoint GLCompute %main "main"
10655 OpExecutionMode %main LocalSize 1 1 1
10656 OpDecorate %im_var DescriptorSet 0
10657 OpDecorate %im_var Binding 0
10658 OpDecorate %s_var DescriptorSet 1
10659 OpDecorate %s_var Binding 0
10660 %void = OpTypeVoid
10661 %float = OpTypeFloat 32
10662 %im1_ty = OpTypeImage %float 2D 0 0 0 1 Unknown
10663 %im2_ty = OpTypeImage %float 2D 1 0 0 1 Unknown
10664 %s_ty = OpTypeSampler
10665 %s_im_ty = OpTypeSampledImage %im2_ty
10666 %ptr_im = OpTypePointer UniformConstant %im1_ty
10667 %ptr_s = OpTypePointer UniformConstant %s_ty
10668 %im_var = OpVariable %ptr_im UniformConstant
10669 %s_var = OpVariable %ptr_s UniformConstant
10670 %void_fn = OpTypeFunction %void
10671 %main = OpFunction %void None %void_fn
10672 %entry = OpLabel
10673 %im_ld = OpLoad %im1_ty %im_var
10674 %s_ld = OpLoad %s_ty %s_var
10675 %sampled_image = OpSampledImage %s_im_ty %im_ld %s_ld
10676 OpReturn
10677 OpFunctionEnd
10678 )";
10679 
10680   const spv_target_env env = SPV_ENV_VULKAN_1_0;
10681   CompileSuccessfully(code, env);
10682   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
10683   EXPECT_THAT(
10684       getDiagnosticString(),
10685       HasSubstr("Expected Image to have the same type as Result Type Image"));
10686 }
10687 
10688 }  // namespace
10689 }  // namespace val
10690 }  // namespace spvtools
10691