• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2017-2022 Valve Corporation
2 // Copyright (c) 2017-2022 LunarG Inc.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 
16 // Bindless Check Instrumentation Tests.
17 
18 #include <string>
19 #include <vector>
20 
21 #include "test/opt/assembly_builder.h"
22 #include "test/opt/pass_fixture.h"
23 #include "test/opt/pass_utils.h"
24 
25 namespace spvtools {
26 namespace opt {
27 namespace {
28 
29 using InstBindlessTest = PassTest<::testing::Test>;
30 
31 static const std::string kOutputDecorations = R"(
32 ; CHECK: OpDecorate [[output_buffer_type:%inst_bindless_OutputBuffer]] Block
33 ; CHECK: OpMemberDecorate [[output_buffer_type]] 0 Offset 0
34 ; CHECK: OpMemberDecorate [[output_buffer_type]] 1 Offset 4
35 ; CHECK: OpDecorate [[output_buffer_var:%\w+]] DescriptorSet 7
36 ; CHECK: OpDecorate [[output_buffer_var]] Binding 0
37 )";
38 
39 static const std::string kOutputGlobals = R"(
40 ; CHECK: [[output_buffer_type]] = OpTypeStruct %uint %_runtimearr_uint
41 ; CHECK: [[output_ptr_type:%\w+]] = OpTypePointer StorageBuffer [[output_buffer_type]]
42 ; CHECK: [[output_buffer_var]] = OpVariable [[output_ptr_type]] StorageBuffer
43 )";
44 
45 static const std::string kStreamWrite4Begin = R"(
46 ; CHECK: %inst_bindless_stream_write_4 = OpFunction %void None {{%\w+}}
47 ; CHECK: [[param_1:%\w+]] = OpFunctionParameter %uint
48 ; CHECK: [[param_2:%\w+]] = OpFunctionParameter %uint
49 ; CHECK: [[param_3:%\w+]] = OpFunctionParameter %uint
50 ; CHECK: [[param_4:%\w+]] = OpFunctionParameter %uint
51 ; CHECK: {{%\w+}} = OpLabel
52 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_0
53 ; CHECK: {{%\w+}} = OpAtomicIAdd %uint {{%\w+}} %uint_4 %uint_0 %uint_10
54 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_10
55 ; CHECK: {{%\w+}} = OpArrayLength %uint [[output_buffer_var]] 1
56 ; CHECK: {{%\w+}} = OpULessThanEqual %bool {{%\w+}} {{%\w+}}
57 ; CHECK: OpSelectionMerge {{%\w+}} None
58 ; CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}}
59 ; CHECK: {{%\w+}} = OpLabel
60 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_0
61 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_1 {{%\w+}}
62 ; CHECK: OpStore {{%\w+}} %uint_10
63 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_1
64 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_1 {{%\w+}}
65 ; CHECK: OpStore {{%\w+}} %uint_23
66 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_2
67 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_1 {{%\w+}}
68 ; CHECK: OpStore {{%\w+}} [[param_1]]
69 )";
70 
71 static const std::string kStreamWrite4End = R"(
72 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_7
73 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_1 {{%\w+}}
74 ; CHECK: OpStore {{%\w+}} [[param_2]]
75 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_8
76 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_1 {{%\w+}}
77 ; CHECK: OpStore {{%\w+}} [[param_3]]
78 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_9
79 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_1 {{%\w+}}
80 ; CHECK: OpStore {{%\w+}} [[param_4]]
81 ; CHECK: OpBranch {{%\w+}}
82 ; CHECK: {{%\w+}} = OpLabel
83 ; CHECK: OpReturn
84 ; CHECK: OpFunctionEnd
85 )";
86 
87 // clang-format off
88 static const std::string kStreamWrite4Frag = kStreamWrite4Begin + R"(
89 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_3
90 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_1 {{%\w+}}
91 ; CHECK: OpStore {{%\w+}} %uint_4
92 ; CHECK: {{%\w+}} = OpLoad %v4float %gl_FragCoord
93 ; CHECK: {{%\w+}} = OpBitcast %v4uint {{%\w+}}
94 ; CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0
95 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_4
96 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_1 {{%\w+}}
97 ; CHECK: OpStore {{%\w+}} {{%\w+}}
98 ; CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1
99 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_5
100 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_1 {{%\w+}}
101 ; CHECK: OpStore {{%\w+}} {{%\w+}}
102 )" + kStreamWrite4End;
103 
104 static const std::string kStreamWrite4Tese = kStreamWrite4Begin + R"(
105 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_3
106 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_1 {{%\w+}}
107 ; CHECK: OpStore {{%\w+}} %uint_2
108 ; CHECK: {{%\w+}} = OpLoad %uint %gl_PrimitiveID
109 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_4
110 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_1 {{%\w+}}
111 ; CHECK: OpStore {{%\w+}} {{%\w+}}
112 ; CHECK: {{%\w+}} = OpLoad %v3float %gl_TessCoord
113 ; CHECK: {{%\w+}} = OpBitcast %v3uint {{%\w+}}
114 ; CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0
115 ; CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1
116 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_5
117 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_1 {{%\w+}}
118 ; CHECK: OpStore {{%\w+}} {{%\w+}}
119 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_6
120 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_1 {{%\w+}}
121 ; CHECK: OpStore {{%\w+}} {{%\w+}}
122 )" + kStreamWrite4End;
123 
124 static const std::string kStreamWrite4Vert = kStreamWrite4Begin + R"(
125 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_3
126 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_1 {{%\w+}}
127 ; CHECK: OpStore {{%\w+}} %uint_0
128 ; CHECK: {{%\w+}} = OpLoad %uint %gl_VertexIndex
129 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_4
130 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_1 {{%\w+}}
131 ; CHECK: OpStore {{%\w+}} {{%\w+}}
132 ; CHECK: {{%\w+}} = OpLoad %uint %gl_InstanceIndex
133 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_5
134 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_1 {{%\w+}}
135 ; CHECK: OpStore {{%\w+}} {{%\w+}}
136 )" + kStreamWrite4End;
137 
138 static const std::string kStreamWrite4Compute = kStreamWrite4Begin + R"(
139 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_3
140 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_1 {{%\w+}}
141 ; CHECK: OpStore {{%\w+}} %uint_5
142 ; CHECK: {{%\w+}} = OpLoad %v3uint %gl_GlobalInvocationID
143 ; CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0
144 ; CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1
145 ; CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 2
146 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_4
147 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_1 {{%\w+}}
148 ; CHECK: OpStore {{%\w+}} {{%\w+}}
149 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_5
150 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_1 {{%\w+}}
151 ; CHECK: OpStore {{%\w+}} {{%\w+}}
152 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_6
153 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_1 {{%\w+}}
154 ; CHECK: OpStore {{%\w+}} {{%\w+}}
155 )" + kStreamWrite4End;
156 
157 static const std::string kStreamWrite4Ray = kStreamWrite4Begin + R"(
158 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_3
159 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_1 {{%\w+}}
160 ; CHECK: OpStore {{%\w+}} {{%\w+}}
161 ; CHECK: {{%\w+}} = OpLoad %v3uint {{%\w+}}
162 ; CHECK: {{%\w+}} = OpCompositeExtract %uint %90 0
163 ; CHECK: {{%\w+}} = OpCompositeExtract %uint %90 1
164 ; CHECK: {{%\w+}} = OpCompositeExtract %uint %90 2
165 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_4
166 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_1 {{%\w+}}
167 ; CHECK: OpStore {{%\w+}} {{%\w+}}
168 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_5
169 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_1 {{%\w+}}
170 ; CHECK: OpStore {{%\w+}} {{%\w+}}
171 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_6
172 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_1 {{%\w+}}
173 ; CHECK: OpStore {{%\w+}} {{%\w+}}
174 )" + kStreamWrite4End;
175 // clang-format on
176 
177 static const std::string kStreamWrite5Begin = R"(
178 ; CHECK: %inst_bindless_stream_write_5 = OpFunction %void None {{%\w+}}
179 ; CHECK: [[param_1:%\w+]] = OpFunctionParameter %uint
180 ; CHECK: [[param_2:%\w+]] = OpFunctionParameter %uint
181 ; CHECK: [[param_3:%\w+]] = OpFunctionParameter %uint
182 ; CHECK: [[param_4:%\w+]] = OpFunctionParameter %uint
183 ; CHECK: [[param_5:%\w+]] = OpFunctionParameter %uint
184 ; CHECK: {{%\w+}} = OpLabel
185 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_0
186 ; CHECK: {{%\w+}} = OpAtomicIAdd %uint {{%\w+}} %uint_4 %uint_0 %uint_11
187 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_11
188 ; CHECK: {{%\w+}} = OpArrayLength %uint [[output_buffer_var]] 1
189 ; CHECK: {{%\w+}} = OpULessThanEqual %bool {{%\w+}} {{%\w+}}
190 ; CHECK: OpSelectionMerge {{%\w+}} None
191 ; CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}}
192 ; CHECK: {{%\w+}} = OpLabel
193 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_0
194 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_1 {{%\w+}}
195 ; CHECK: OpStore {{%\w+}} %uint_11
196 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_1
197 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_1 {{%\w+}}
198 ; CHECK: OpStore {{%\w+}} %uint_23
199 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_2
200 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_1 {{%\w+}}
201 ; CHECK: OpStore {{%\w+}} [[param_1]]
202 )";
203 
204 static const std::string kStreamWrite5End = R"(
205 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_7
206 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_1 {{%\w+}}
207 ; CHECK: OpStore {{%\w+}} [[param_2]]
208 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_8
209 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_1 {{%\w+}}
210 ; CHECK: OpStore {{%\w+}} [[param_3]]
211 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_9
212 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_1 {{%\w+}}
213 ; CHECK: OpStore {{%\w+}} [[param_4]]
214 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_10
215 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_1 {{%\w+}}
216 ; CHECK: OpStore {{%\w+}} [[param_5]]
217 ; CHECK: OpBranch {{%\w+}}
218 ; CHECK: {{%\w+}} = OpLabel
219 ; CHECK: OpReturn
220 ; CHECK: OpFunctionEnd
221 )";
222 
223 // clang-format off
224 static const std::string kStreamWrite5Frag = kStreamWrite5Begin + R"(
225 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_3
226 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_1 {{%\w+}}
227 ; CHECK: OpStore {{%\w+}} %uint_4
228 ; CHECK: {{%\w+}} = OpLoad %v4float %gl_FragCoord
229 ; CHECK: {{%\w+}} = OpBitcast %v4uint {{%\w+}}
230 ; CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0
231 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_4
232 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_1 {{%\w+}}
233 ; CHECK: OpStore {{%\w+}} {{%\w+}}
234 ; CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1
235 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_5
236 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_1 {{%\w+}}
237 ; CHECK: OpStore {{%\w+}} {{%\w+}}
238 )" + kStreamWrite4End;
239 
240 static const std::string kStreamWrite5Vert = kStreamWrite5Begin + R"(
241 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_3
242 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_1 {{%\w+}}
243 ; CHECK: OpStore {{%\w+}} %uint_0
244 ; CHECK: {{%\w+}} = OpLoad %uint %gl_VertexIndex
245 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_4
246 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_1 {{%\w+}}
247 ; CHECK: OpStore {{%\w+}} {{%\w+}}
248 ; CHECK: {{%\w+}} = OpLoad %uint %gl_InstanceIndex
249 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_5
250 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_1 {{%\w+}}
251 ; CHECK: OpStore {{%\w+}} {{%\w+}}
252 )" + kStreamWrite5End;
253 // clang-format on
254 
255 static const std::string kInputDecorations = R"(
256 ; CHECK: OpDecorate [[input_buffer_type:%inst_bindless_InputBuffer]] Block
257 ; CHECK: OpMemberDecorate [[input_buffer_type]] 0 Offset 0
258 ; CHECK: OpDecorate [[input_buffer_var:%\w+]] DescriptorSet 7
259 ; CHECK: OpDecorate [[input_buffer_var]] Binding 1
260 )";
261 
262 static const std::string kInputGlobals = R"(
263 ; CHECK: [[input_buffer_type]] = OpTypeStruct %_runtimearr_uint
264 ; CHECK: [[input_ptr_type:%\w+]] = OpTypePointer StorageBuffer [[input_buffer_type]]
265 ; CHECK: [[input_buffer_var]] = OpVariable [[input_ptr_type]] StorageBuffer
266 )";
267 
268 static const std::string kDirectRead2 = R"(
269 ; CHECK: %inst_bindless_direct_read_2 = OpFunction %uint None {{%\w+}}
270 ; CHECK: [[param_1:%\w+]] = OpFunctionParameter %uint
271 ; CHECK: [[param_2:%\w+]] = OpFunctionParameter %uint
272 ; CHECK: {{%\w+}} = OpLabel
273 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[input_buffer_var]] %uint_0 [[param_1]]
274 ; CHECK: {{%\w+}} = OpLoad %uint {{%\w+}}
275 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} [[param_2]]
276 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[input_buffer_var]] %uint_0 {{%\w+}}
277 ; CHECK: {{%\w+}} = OpLoad %uint {{%\w+}}
278 ; CHECK: OpReturnValue {{%\w+}}
279 ; CHECK: OpFunctionEnd
280 )";
281 
282 static const std::string kDirectRead3 = R"(
283  ;CHECK: %inst_bindless_direct_read_3 = OpFunction %uint None {{%\w+}}
284 ; CHECK: [[param_1:%\w+]] = OpFunctionParameter %uint
285 ; CHECK: [[param_2:%\w+]] = OpFunctionParameter %uint
286 ; CHECK: [[param_3:%\w+]] = OpFunctionParameter %uint
287  ;CHECK: {{%\w+}} = OpLabel
288  ;CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[input_buffer_var]] %uint_0 [[param_1]]
289  ;CHECK: {{%\w+}} = OpLoad %uint {{%\w+}}
290  ;CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} [[param_2]]
291  ;CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[input_buffer_var]] %uint_0 {{%\w+}}
292  ;CHECK: {{%\w+}} = OpLoad %uint {{%\w+}}
293  ;CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} [[param_3]]
294  ;CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[input_buffer_var]] %uint_0 {{%\w+}}
295  ;CHECK: {{%\w+}} = OpLoad %uint {{%\w+}}
296  ;CHECK: OpReturnValue {{%\w+}}
297  ;CHECK: OpFunctionEnd
298 )";
299 
300 static const std::string kDirectRead4 = R"(
301 ; CHECK: %inst_bindless_direct_read_4 = OpFunction %uint None {{%\w+}}
302 ; CHECK: [[param_1:%\w+]] = OpFunctionParameter %uint
303 ; CHECK: [[param_2:%\w+]] = OpFunctionParameter %uint
304 ; CHECK: [[param_3:%\w+]] = OpFunctionParameter %uint
305 ; CHECK: [[param_4:%\w+]] = OpFunctionParameter %uint
306 ; CHECK: {{%\w+}} = OpLabel
307 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[input_buffer_var]] %uint_0 [[param_1]]
308 ; CHECK: {{%\w+}} = OpLoad %uint {{%\w+}}
309 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} [[param_2]]
310 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[input_buffer_var]] %uint_0 {{%\w+}}
311 ; CHECK: {{%\w+}} = OpLoad %uint {{%\w+}}
312 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} [[param_3]]
313 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[input_buffer_var]] %uint_0 {{%\w+}}
314 ; CHECK: {{%\w+}} = OpLoad %uint {{%\w+}}
315 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} [[param_4]]
316 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[input_buffer_var]] %uint_0 {{%\w+}}
317 ; CHECK: {{%\w+}} = OpLoad %uint {{%\w+}}
318 ; CHECK: OpReturnValue {{%\w+}}
319 ; CHECK: OpFunctionEnd
320 )";
321 
TEST_F(InstBindlessTest,NoInstrumentConstIndexInbounds)322 TEST_F(InstBindlessTest, NoInstrumentConstIndexInbounds) {
323   // Texture2D g_tColor[128];
324   //
325   // SamplerState g_sAniso;
326   //
327   // struct PS_INPUT
328   // {
329   //   float2 vTextureCoords : TEXCOORD2;
330   // };
331   //
332   // struct PS_OUTPUT
333   // {
334   //   float4 vColor : SV_Target0;
335   // };
336   //
337   // PS_OUTPUT MainPs(PS_INPUT i)
338   // {
339   //   PS_OUTPUT ps_output;
340   //
341   //   ps_output.vColor = g_tColor[ 37 ].Sample(g_sAniso, i.vTextureCoords.xy);
342   //   return ps_output;
343   // }
344 
345   const std::string before =
346       R"(OpCapability Shader
347 %1 = OpExtInstImport "GLSL.std.450"
348 OpMemoryModel Logical GLSL450
349 OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor
350 OpExecutionMode %MainPs OriginUpperLeft
351 OpSource HLSL 500
352 OpName %MainPs "MainPs"
353 OpName %g_tColor "g_tColor"
354 OpName %g_sAniso "g_sAniso"
355 OpName %i_vTextureCoords "i.vTextureCoords"
356 OpName %_entryPointOutput_vColor "@entryPointOutput.vColor"
357 OpDecorate %g_tColor DescriptorSet 3
358 OpDecorate %g_tColor Binding 0
359 OpDecorate %g_sAniso DescriptorSet 0
360 OpDecorate %i_vTextureCoords Location 0
361 OpDecorate %_entryPointOutput_vColor Location 0
362 %void = OpTypeVoid
363 %8 = OpTypeFunction %void
364 %float = OpTypeFloat 32
365 %v2float = OpTypeVector %float 2
366 %v4float = OpTypeVector %float 4
367 %int = OpTypeInt 32 1
368 %int_0 = OpConstant %int 0
369 %int_37 = OpConstant %int 37
370 %15 = OpTypeImage %float 2D 0 0 0 1 Unknown
371 %uint = OpTypeInt 32 0
372 %uint_128 = OpConstant %uint 128
373 %_arr_15_uint_128 = OpTypeArray %15 %uint_128
374 %_ptr_UniformConstant__arr_15_uint_128 = OpTypePointer UniformConstant %_arr_15_uint_128
375 %g_tColor = OpVariable %_ptr_UniformConstant__arr_15_uint_128 UniformConstant
376 %_ptr_UniformConstant_15 = OpTypePointer UniformConstant %15
377 %21 = OpTypeSampler
378 %_ptr_UniformConstant_21 = OpTypePointer UniformConstant %21
379 %g_sAniso = OpVariable %_ptr_UniformConstant_21 UniformConstant
380 %23 = OpTypeSampledImage %15
381 %_ptr_Input_v2float = OpTypePointer Input %v2float
382 %i_vTextureCoords = OpVariable %_ptr_Input_v2float Input
383 %_ptr_Output_v4float = OpTypePointer Output %v4float
384 %_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output
385 %MainPs = OpFunction %void None %8
386 %26 = OpLabel
387 %27 = OpLoad %v2float %i_vTextureCoords
388 %28 = OpAccessChain %_ptr_UniformConstant_15 %g_tColor %int_37
389 %29 = OpLoad %15 %28
390 %30 = OpLoad %21 %g_sAniso
391 %31 = OpSampledImage %23 %29 %30
392 %32 = OpImageSampleImplicitLod %v4float %31 %27
393 OpStore %_entryPointOutput_vColor %32
394 OpReturn
395 OpFunctionEnd
396 )";
397 
398   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
399   SinglePassRunAndCheck<InstBindlessCheckPass>(
400       before, before, true, true, 7u, 23u, false, false, false, false, false);
401 }
402 
TEST_F(InstBindlessTest,NoInstrumentNonBindless)403 TEST_F(InstBindlessTest, NoInstrumentNonBindless) {
404   // This test verifies that the pass will correctly not instrument vanilla
405   // texture sample.
406   //
407   // Texture2D g_tColor;
408   //
409   // SamplerState g_sAniso;
410   //
411   // struct PS_INPUT
412   // {
413   //   float2 vTextureCoords : TEXCOORD2;
414   // };
415   //
416   // struct PS_OUTPUT
417   // {
418   //   float4 vColor : SV_Target0;
419   // };
420   //
421   // PS_OUTPUT MainPs(PS_INPUT i)
422   // {
423   //   PS_OUTPUT ps_output;
424   //   ps_output.vColor =
425   //       g_tColor.Sample(g_sAniso, i.vTextureCoords.xy);
426   //   return ps_output;
427   // }
428 
429   const std::string whole_file =
430       R"(OpCapability Shader
431 %1 = OpExtInstImport "GLSL.std.450"
432 OpMemoryModel Logical GLSL450
433 OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor
434 OpExecutionMode %MainPs OriginUpperLeft
435 OpSource HLSL 500
436 OpName %MainPs "MainPs"
437 OpName %g_tColor "g_tColor"
438 OpName %g_sAniso "g_sAniso"
439 OpName %i_vTextureCoords "i.vTextureCoords"
440 OpName %_entryPointOutput_vColor "@entryPointOutput.vColor"
441 OpDecorate %g_tColor DescriptorSet 0
442 OpDecorate %g_tColor Binding 0
443 OpDecorate %g_sAniso DescriptorSet 0
444 OpDecorate %g_sAniso Binding 0
445 OpDecorate %i_vTextureCoords Location 0
446 OpDecorate %_entryPointOutput_vColor Location 0
447 %void = OpTypeVoid
448 %8 = OpTypeFunction %void
449 %float = OpTypeFloat 32
450 %v2float = OpTypeVector %float 2
451 %v4float = OpTypeVector %float 4
452 %12 = OpTypeImage %float 2D 0 0 0 1 Unknown
453 %_ptr_UniformConstant_12 = OpTypePointer UniformConstant %12
454 %g_tColor = OpVariable %_ptr_UniformConstant_12 UniformConstant
455 %14 = OpTypeSampler
456 %_ptr_UniformConstant_14 = OpTypePointer UniformConstant %14
457 %g_sAniso = OpVariable %_ptr_UniformConstant_14 UniformConstant
458 %16 = OpTypeSampledImage %12
459 %_ptr_Input_v2float = OpTypePointer Input %v2float
460 %i_vTextureCoords = OpVariable %_ptr_Input_v2float Input
461 %_ptr_Output_v4float = OpTypePointer Output %v4float
462 %_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output
463 %MainPs = OpFunction %void None %8
464 %19 = OpLabel
465 %20 = OpLoad %v2float %i_vTextureCoords
466 %21 = OpLoad %12 %g_tColor
467 %22 = OpLoad %14 %g_sAniso
468 %23 = OpSampledImage %16 %21 %22
469 %24 = OpImageSampleImplicitLod %v4float %23 %20
470 OpStore %_entryPointOutput_vColor %24
471 OpReturn
472 OpFunctionEnd
473 )";
474 
475   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
476   SinglePassRunAndCheck<InstBindlessCheckPass>(whole_file, whole_file, true,
477                                                true, 7u, 23u, false, false,
478                                                false, false, false);
479 }
480 
TEST_F(InstBindlessTest,Simple)481 TEST_F(InstBindlessTest, Simple) {
482   // Texture2D g_tColor[128];
483   //
484   // layout(push_constant) cbuffer PerViewConstantBuffer_t
485   // {
486   //   uint g_nDataIdx;
487   // };
488   //
489   // SamplerState g_sAniso;
490   //
491   // struct PS_INPUT
492   // {
493   //   float2 vTextureCoords : TEXCOORD2;
494   // };
495   //
496   // struct PS_OUTPUT
497   // {
498   //   float4 vColor : SV_Target0;
499   // };
500   //
501   // PS_OUTPUT MainPs(PS_INPUT i)
502   // {
503   //   PS_OUTPUT ps_output;
504   //   ps_output.vColor =
505   //       g_tColor[ g_nDataIdx ].Sample(g_sAniso, i.vTextureCoords.xy);
506   //   return ps_output;
507   // }
508 
509   const std::string entry = R"(
510 OpCapability Shader
511 ; CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class"
512 %1 = OpExtInstImport "GLSL.std.450"
513 OpMemoryModel Logical GLSL450
514 OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor
515 ; CHECK: OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord
516 OpExecutionMode %MainPs OriginUpperLeft
517 OpSource HLSL 500
518 )";
519 
520   // clang-format off
521   const std::string names_annots = R"(
522 OpName %MainPs "MainPs"
523 OpName %g_tColor "g_tColor"
524 OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t"
525 OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx"
526 OpName %_ ""
527 OpName %g_sAniso "g_sAniso"
528 OpName %i_vTextureCoords "i.vTextureCoords"
529 OpName %_entryPointOutput_vColor "@entryPointOutput.vColor"
530 OpDecorate %g_tColor DescriptorSet 3
531 OpDecorate %g_tColor Binding 0
532 OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0
533 OpDecorate %PerViewConstantBuffer_t Block
534 OpDecorate %g_sAniso DescriptorSet 0
535 OpDecorate %i_vTextureCoords Location 0
536 OpDecorate %_entryPointOutput_vColor Location 0
537 ; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
538 )" + kOutputDecorations + R"(
539 ; CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord
540 )";
541 
542   const std::string consts_types_vars = R"(
543 %void = OpTypeVoid
544 %10 = OpTypeFunction %void
545 %float = OpTypeFloat 32
546 %v2float = OpTypeVector %float 2
547 %v4float = OpTypeVector %float 4
548 %int = OpTypeInt 32 1
549 %int_0 = OpConstant %int 0
550 %16 = OpTypeImage %float 2D 0 0 0 1 Unknown
551 %uint = OpTypeInt 32 0
552 %uint_128 = OpConstant %uint 128
553 %_arr_16_uint_128 = OpTypeArray %16 %uint_128
554 %_ptr_UniformConstant__arr_16_uint_128 = OpTypePointer UniformConstant %_arr_16_uint_128
555 %g_tColor = OpVariable %_ptr_UniformConstant__arr_16_uint_128 UniformConstant
556 %PerViewConstantBuffer_t = OpTypeStruct %uint
557 %_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t
558 %_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant
559 %_ptr_PushConstant_uint = OpTypePointer PushConstant %uint
560 %_ptr_UniformConstant_16 = OpTypePointer UniformConstant %16
561 %24 = OpTypeSampler
562 %_ptr_UniformConstant_24 = OpTypePointer UniformConstant %24
563 %g_sAniso = OpVariable %_ptr_UniformConstant_24 UniformConstant
564 %26 = OpTypeSampledImage %16
565 %_ptr_Input_v2float = OpTypePointer Input %v2float
566 %i_vTextureCoords = OpVariable %_ptr_Input_v2float Input
567 %_ptr_Output_v4float = OpTypePointer Output %v4float
568 %_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output
569 ; CHECK: %uint_0 = OpConstant %uint 0
570 ; CHECK: %bool = OpTypeBool
571 ; CHECK: %48 = OpTypeFunction %void %uint %uint %uint %uint
572 ; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
573 )" + kOutputGlobals + R"(
574 ; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
575 ; CHECK: %uint_10 = OpConstant %uint 10
576 ; CHECK: %uint_4 = OpConstant %uint 4
577 ; CHECK: %uint_1 = OpConstant %uint 1
578 ; CHECK: %uint_23 = OpConstant %uint 23
579 ; CHECK: %uint_2 = OpConstant %uint 2
580 ; CHECK: %uint_3 = OpConstant %uint 3
581 ; CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float
582 ; CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
583 ; CHECK: %v4uint = OpTypeVector %uint 4
584 ; CHECK: %uint_5 = OpConstant %uint 5
585 ; CHECK: %uint_7 = OpConstant %uint 7
586 ; CHECK: %uint_8 = OpConstant %uint 8
587 ; CHECK: %uint_9 = OpConstant %uint 9
588 ; CHECK: %uint_56 = OpConstant %uint 56
589 ; CHECK: %103 = OpConstantNull %v4float
590 )";
591   // clang-format on
592 
593   const std::string main_func = R"(
594 %MainPs = OpFunction %void None %10
595 %29 = OpLabel
596 %30 = OpLoad %v2float %i_vTextureCoords
597 %31 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0
598 %32 = OpLoad %uint %31
599 %33 = OpAccessChain %_ptr_UniformConstant_16 %g_tColor %32
600 %34 = OpLoad %16 %33
601 %35 = OpLoad %24 %g_sAniso
602 %36 = OpSampledImage %26 %34 %35
603 %37 = OpImageSampleImplicitLod %v4float %36 %30
604 OpStore %_entryPointOutput_vColor %37
605 ; CHECK-NOT: %37 = OpImageSampleImplicitLod %v4float %36 %30
606 ; CHECK-NOT: OpStore %_entryPointOutput_vColor %37
607 ; CHECK: %40 = OpULessThan %bool %32 %uint_128
608 ; CHECK: OpSelectionMerge %41 None
609 ; CHECK: OpBranchConditional %40 %42 %43
610 ; CHECK: %42 = OpLabel
611 ; CHECK: %44 = OpLoad %16 %33
612 ; CHECK: %45 = OpSampledImage %26 %44 %35
613 ; CHECK: %46 = OpImageSampleImplicitLod %v4float %45 %30
614 ; CHECK: OpBranch %41
615 ; CHECK: %43 = OpLabel
616 ; CHECK: %102 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_56 %uint_0 %32 %uint_128
617 ; CHECK: OpBranch %41
618 ; CHECK: %41 = OpLabel
619 ; CHECK: %104 = OpPhi %v4float %46 %42 %103 %43
620 ; CHECK: OpStore %_entryPointOutput_vColor %104
621 OpReturn
622 OpFunctionEnd
623 )";
624 
625   const std::string output_func = kStreamWrite4Frag;
626 
627   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
628   SinglePassRunAndMatch<InstBindlessCheckPass, uint32_t, uint32_t, bool, bool>(
629       entry + names_annots + consts_types_vars + main_func + output_func, true,
630       7u, 23u, false, false, false, false, false);
631 }
632 
TEST_F(InstBindlessTest,InstrumentMultipleInstructions)633 TEST_F(InstBindlessTest, InstrumentMultipleInstructions) {
634   // Texture2D g_tColor[128];
635   //
636   // layout(push_constant) cbuffer PerViewConstantBuffer_t
637   // {
638   //   uint g_nDataIdx;
639   //   uint g_nDataIdx2;
640   // };
641   //
642   // SamplerState g_sAniso;
643   //
644   // struct PS_INPUT
645   // {
646   //   float2 vTextureCoords : TEXCOORD2;
647   // };
648   //
649   // struct PS_OUTPUT
650   // {
651   //   float4 vColor : SV_Target0;
652   // };
653   //
654   // PS_OUTPUT MainPs(PS_INPUT i)
655   // {
656   //   PS_OUTPUT ps_output;
657   //
658   //   float t  = g_tColor[g_nDataIdx ].Sample(g_sAniso, i.vTextureCoords.xy);
659   //   float t2 = g_tColor[g_nDataIdx2].Sample(g_sAniso, i.vTextureCoords.xy);
660   //   ps_output.vColor = t + t2;
661   //   return ps_output;
662   // }
663 
664   // clang-format off
665   const std::string defs = R"(
666 OpCapability Shader
667 ; CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class"
668 %1 = OpExtInstImport "GLSL.std.450"
669 OpMemoryModel Logical GLSL450
670 OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor
671 ; CHECK: OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord
672 OpExecutionMode %MainPs OriginUpperLeft
673 OpSource HLSL 500
674 OpName %MainPs "MainPs"
675 OpName %g_tColor "g_tColor"
676 OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t"
677 OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx"
678 OpName %_ ""
679 OpName %g_sAniso "g_sAniso"
680 OpName %i_vTextureCoords "i.vTextureCoords"
681 OpName %_entryPointOutput_vColor "@entryPointOutput.vColor"
682 OpDecorate %g_tColor DescriptorSet 3
683 OpDecorate %g_tColor Binding 0
684 OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0
685 OpMemberDecorate %PerViewConstantBuffer_t 1 Offset 4
686 OpDecorate %PerViewConstantBuffer_t Block
687 OpDecorate %g_sAniso DescriptorSet 0
688 OpDecorate %i_vTextureCoords Location 0
689 OpDecorate %_entryPointOutput_vColor Location 0
690 ; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
691 )" + kOutputDecorations + R"(
692 ; CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord
693 %void = OpTypeVoid
694 %10 = OpTypeFunction %void
695 %float = OpTypeFloat 32
696 %v2float = OpTypeVector %float 2
697 %v4float = OpTypeVector %float 4
698 %int = OpTypeInt 32 1
699 %int_0 = OpConstant %int 0
700 %int_1 = OpConstant %int 1
701 %17 = OpTypeImage %float 2D 0 0 0 1 Unknown
702 %uint = OpTypeInt 32 0
703 %uint_128 = OpConstant %uint 128
704 %_arr_17_uint_128 = OpTypeArray %17 %uint_128
705 %_ptr_UniformConstant__arr_17_uint_128 = OpTypePointer UniformConstant %_arr_17_uint_128
706 %g_tColor = OpVariable %_ptr_UniformConstant__arr_17_uint_128 UniformConstant
707 %PerViewConstantBuffer_t = OpTypeStruct %uint %uint
708 %_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t
709 %_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant
710 %_ptr_PushConstant_uint = OpTypePointer PushConstant %uint
711 %_ptr_UniformConstant_17 = OpTypePointer UniformConstant %17
712 %25 = OpTypeSampler
713 %_ptr_UniformConstant_25 = OpTypePointer UniformConstant %25
714 %g_sAniso = OpVariable %_ptr_UniformConstant_25 UniformConstant
715 %27 = OpTypeSampledImage %17
716 %_ptr_Input_v2float = OpTypePointer Input %v2float
717 %i_vTextureCoords = OpVariable %_ptr_Input_v2float Input
718 %_ptr_Output_v4float = OpTypePointer Output %v4float
719 %_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output
720 ; CHECK: %uint_0 = OpConstant %uint 0
721 ; CHECK: %bool = OpTypeBool
722 ; CHECK: %56 = OpTypeFunction %void %uint %uint %uint %uint
723 ; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
724 )" + kOutputGlobals + R"(
725 ; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
726 ; CHECK: %uint_10 = OpConstant %uint 10
727 ; CHECK: %uint_4 = OpConstant %uint 4
728 ; CHECK: %uint_1 = OpConstant %uint 1
729 ; CHECK: %uint_23 = OpConstant %uint 23
730 ; CHECK: %uint_2 = OpConstant %uint 2
731 ; CHECK: %uint_3 = OpConstant %uint 3
732 ; CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float
733 ; CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
734 ; CHECK: %v4uint = OpTypeVector %uint 4
735 ; CHECK: %uint_5 = OpConstant %uint 5
736 ; CHECK: %uint_7 = OpConstant %uint 7
737 ; CHECK: %uint_8 = OpConstant %uint 8
738 ; CHECK: %uint_9 = OpConstant %uint 9
739 ; CHECK: %uint_58 = OpConstant %uint 58
740 ; CHECK: %111 = OpConstantNull %v4float
741 ; CHECK: %uint_64 = OpConstant %uint 64
742 )";
743   // clang-format on
744 
745   const std::string main_func =
746       R"(%MainPs = OpFunction %void None %10
747 %30 = OpLabel
748 %31 = OpLoad %v2float %i_vTextureCoords
749 %32 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0
750 %33 = OpLoad %uint %32
751 %34 = OpAccessChain %_ptr_UniformConstant_17 %g_tColor %33
752 %35 = OpLoad %17 %34
753 %36 = OpLoad %25 %g_sAniso
754 %37 = OpSampledImage %27 %35 %36
755 %38 = OpImageSampleImplicitLod %v4float %37 %31
756 ; CHECK-NOT: %38 = OpImageSampleImplicitLod %v4float %37 %31
757 ; CHECK: %48 = OpULessThan %bool %33 %uint_128
758 ; CHECK: OpSelectionMerge %49 None
759 ; CHECK: OpBranchConditional %48 %50 %51
760 ; CHECK: %50 = OpLabel
761 ; CHECK: %52 = OpLoad %17 %34
762 ; CHECK: %53 = OpSampledImage %27 %52 %36
763 ; CHECK: %54 = OpImageSampleImplicitLod %v4float %53 %31
764 ; CHECK: OpBranch %49
765 ; CHECK: %51 = OpLabel
766 ; CHECK: %110 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_58 %uint_0 %33 %uint_128
767 ; CHECK: OpBranch %49
768 ; CHECK: %49 = OpLabel
769 ; CHECK: %112 = OpPhi %v4float %54 %50 %111 %51
770 %39 = OpAccessChain %_ptr_PushConstant_uint %_ %int_1
771 %40 = OpLoad %uint %39
772 %41 = OpAccessChain %_ptr_UniformConstant_17 %g_tColor %40
773 %42 = OpLoad %17 %41
774 %43 = OpSampledImage %27 %42 %36
775 %44 = OpImageSampleImplicitLod %v4float %43 %31
776 %45 = OpFAdd %v4float %38 %44
777 ; CHECK-NOT: %44 = OpImageSampleImplicitLod %v4float %43 %31
778 ; CHECK-NOT: %45 = OpFAdd %v4float %38 %44
779 ; CHECK: %113 = OpULessThan %bool %40 %uint_128
780 ; CHECK: OpSelectionMerge %114 None
781 ; CHECK: OpBranchConditional %113 %115 %116
782 ; CHECK: %115 = OpLabel
783 ; CHECK: %117 = OpLoad %17 %41
784 ; CHECK: %118 = OpSampledImage %27 %117 %36
785 ; CHECK: %119 = OpImageSampleImplicitLod %v4float %118 %31
786 ; CHECK: OpBranch %114
787 ; CHECK: %116 = OpLabel
788 ; CHECK: %121 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_64 %uint_0 %40 %uint_128
789 ; CHECK: OpBranch %114
790 ; CHECK: %114 = OpLabel
791 ; CHECK: %122 = OpPhi %v4float %119 %115 %111 %116
792 ; CHECK: %45 = OpFAdd %v4float %112 %122
793 OpStore %_entryPointOutput_vColor %45
794 OpReturn
795 OpFunctionEnd
796 )";
797 
798   const std::string output_func = kStreamWrite4Frag;
799 
800   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
801   SinglePassRunAndMatch<InstBindlessCheckPass>(defs + main_func + output_func,
802                                                true, 7u, 23u, false, false,
803                                                false, false, false);
804 }
805 
TEST_F(InstBindlessTest,InstrumentOpImage)806 TEST_F(InstBindlessTest, InstrumentOpImage) {
807   // This test verifies that the pass will correctly instrument shader
808   // using OpImage. This test was created by editing the SPIR-V
809   // from the Simple test.
810 
811   // clang-format off
812   const std::string defs = R"(
813 OpCapability Shader
814 OpCapability StorageImageReadWithoutFormat
815 ; CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class"
816 %1 = OpExtInstImport "GLSL.std.450"
817 OpMemoryModel Logical GLSL450
818 OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor
819 ; CHECK: OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord
820 OpExecutionMode %MainPs OriginUpperLeft
821 OpSource HLSL 500
822 OpName %MainPs "MainPs"
823 OpName %g_tColor "g_tColor"
824 OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t"
825 OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx"
826 OpName %_ ""
827 OpName %i_vTextureCoords "i.vTextureCoords"
828 OpName %_entryPointOutput_vColor "@entryPointOutput.vColor"
829 OpDecorate %g_tColor DescriptorSet 3
830 OpDecorate %g_tColor Binding 0
831 OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0
832 OpDecorate %PerViewConstantBuffer_t Block
833 OpDecorate %i_vTextureCoords Location 0
834 OpDecorate %_entryPointOutput_vColor Location 0
835 ; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
836 )" + kOutputDecorations + R"(
837 ; CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord
838 %void = OpTypeVoid
839 %3 = OpTypeFunction %void
840 %float = OpTypeFloat 32
841 %v4float = OpTypeVector %float 4
842 %int = OpTypeInt 32 1
843 %v2int = OpTypeVector %int 2
844 %int_0 = OpConstant %int 0
845 %20 = OpTypeImage %float 2D 0 0 0 0 Unknown
846 %uint = OpTypeInt 32 0
847 %uint_128 = OpConstant %uint 128
848 %39 = OpTypeSampledImage %20
849 %_arr_39_uint_128 = OpTypeArray %39 %uint_128
850 %_ptr_UniformConstant__arr_39_uint_128 = OpTypePointer UniformConstant %_arr_39_uint_128
851 %g_tColor = OpVariable %_ptr_UniformConstant__arr_39_uint_128 UniformConstant
852 %PerViewConstantBuffer_t = OpTypeStruct %uint
853 %_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t
854 %_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant
855 %_ptr_PushConstant_uint = OpTypePointer PushConstant %uint
856 %_ptr_UniformConstant_39 = OpTypePointer UniformConstant %39
857 %_ptr_Input_v2int = OpTypePointer Input %v2int
858 %i_vTextureCoords = OpVariable %_ptr_Input_v2int Input
859 %_ptr_Output_v4float = OpTypePointer Output %v4float
860 %_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output
861 ; CHECK: uint_0 = OpConstant %uint 0
862 ; CHECK: bool = OpTypeBool
863 ; CHECK: %86 = OpTypeFunction %void %uint %uint %uint %uint
864 ; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
865 )" + kOutputGlobals + R"(
866 ; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
867 ; CHECK: %uint_10 = OpConstant %uint 10
868 ; CHECK: %uint_4 = OpConstant %uint 4
869 ; CHECK: %uint_1 = OpConstant %uint 1
870 ; CHECK: %uint_23 = OpConstant %uint 23
871 ; CHECK: %uint_2 = OpConstant %uint 2
872 ; CHECK: %uint_3 = OpConstant %uint 3
873 ; CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float
874 ; CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
875 ; CHECK: %v4uint = OpTypeVector %uint 4
876 ; CHECK: %uint_5 = OpConstant %uint 5
877 ; CHECK: %uint_7 = OpConstant %uint 7
878 ; CHECK: %uint_8 = OpConstant %uint 8
879 ; CHECK: %uint_9 = OpConstant %uint 9
880 ; CHECK: %uint_51 = OpConstant %uint 51
881 ; CHECK: %141 = OpConstantNull %v4float
882 )";
883   // clang-format on
884 
885   const std::string main_func = R"(
886 %MainPs = OpFunction %void None %3
887 %5 = OpLabel
888 %53 = OpLoad %v2int %i_vTextureCoords
889 %63 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0
890 %64 = OpLoad %uint %63
891 %65 = OpAccessChain %_ptr_UniformConstant_39 %g_tColor %64
892 %66 = OpLoad %39 %65
893 %75 = OpImage %20 %66
894 %71 = OpImageRead %v4float %75 %53
895 OpStore %_entryPointOutput_vColor %71
896 ; CHECK-NOT: %71 = OpImageRead %v4float %75 %53
897 ; CHECK-NOT: OpStore %_entryPointOutput_vColor %71
898 ; CHECK: %78 = OpULessThan %bool %64 %uint_128
899 ; CHECK: OpSelectionMerge %79 None
900 ; CHECK: OpBranchConditional %78 %80 %81
901 ; CHECK: %80 = OpLabel
902 ; CHECK: %82 = OpLoad %39 %65
903 ; CHECK: %83 = OpImage %20 %82
904 ; CHECK: %84 = OpImageRead %v4float %83 %53
905 ; CHECK: OpBranch %79
906 ; CHECK: %81 = OpLabel
907 ; CHECK: %140 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_51 %uint_0 %64 %uint_128
908 ; CHECK: OpBranch %79
909 ; CHECK: %79 = OpLabel
910 ; CHECK: %142 = OpPhi %v4float %84 %80 %141 %81
911 ; CHECK: OpStore %_entryPointOutput_vColor %142
912 OpReturn
913 OpFunctionEnd
914 )";
915 
916   const std::string output_func = kStreamWrite4Frag;
917 
918   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
919   SinglePassRunAndMatch<InstBindlessCheckPass>(defs + main_func + output_func,
920                                                true, 7u, 23u, false, false,
921                                                false, false, false);
922 }
923 
TEST_F(InstBindlessTest,InstrumentSampledImage)924 TEST_F(InstBindlessTest, InstrumentSampledImage) {
925   // This test verifies that the pass will correctly instrument shader
926   // using sampled image. This test was created by editing the SPIR-V
927   // from the Simple test.
928 
929   // clang-format off
930   const std::string defs = R"(
931 OpCapability Shader
932 ; CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class"
933 %1 = OpExtInstImport "GLSL.std.450"
934 OpMemoryModel Logical GLSL450
935 OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor
936 ; CHECK: OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord
937 OpExecutionMode %MainPs OriginUpperLeft
938 OpSource HLSL 500
939 OpName %MainPs "MainPs"
940 OpName %g_tColor "g_tColor"
941 OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t"
942 OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx"
943 OpName %_ ""
944 OpName %i_vTextureCoords "i.vTextureCoords"
945 OpName %_entryPointOutput_vColor "@entryPointOutput.vColor"
946 OpDecorate %g_tColor DescriptorSet 3
947 OpDecorate %g_tColor Binding 0
948 OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0
949 OpDecorate %PerViewConstantBuffer_t Block
950 OpDecorate %i_vTextureCoords Location 0
951 OpDecorate %_entryPointOutput_vColor Location 0
952 )" + kOutputDecorations + R"(
953 ; CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord
954 %void = OpTypeVoid
955 %3 = OpTypeFunction %void
956 %float = OpTypeFloat 32
957 %v2float = OpTypeVector %float 2
958 %v4float = OpTypeVector %float 4
959 %int = OpTypeInt 32 1
960 %int_0 = OpConstant %int 0
961 %20 = OpTypeImage %float 2D 0 0 0 1 Unknown
962 %uint = OpTypeInt 32 0
963 %uint_128 = OpConstant %uint 128
964 %39 = OpTypeSampledImage %20
965 %_arr_39_uint_128 = OpTypeArray %39 %uint_128
966 %_ptr_UniformConstant__arr_39_uint_128 = OpTypePointer UniformConstant %_arr_39_uint_128
967 %g_tColor = OpVariable %_ptr_UniformConstant__arr_39_uint_128 UniformConstant
968 %PerViewConstantBuffer_t = OpTypeStruct %uint
969 %_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t
970 %_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant
971 %_ptr_PushConstant_uint = OpTypePointer PushConstant %uint
972 %_ptr_UniformConstant_39 = OpTypePointer UniformConstant %39
973 %_ptr_Input_v2float = OpTypePointer Input %v2float
974 %i_vTextureCoords = OpVariable %_ptr_Input_v2float Input
975 %_ptr_Output_v4float = OpTypePointer Output %v4float
976 %_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output
977 ; CHECK: uint_0 = OpConstant %uint 0
978 ; CHECK: bool = OpTypeBool
979 ; CHECK: %81 = OpTypeFunction %void %uint %uint %uint %uint
980 ; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
981 )" + kOutputGlobals + R"(
982 ; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
983 ; CHECK: %uint_10 = OpConstant %uint 10
984 ; CHECK: %uint_4 = OpConstant %uint 4
985 ; CHECK: %uint_1 = OpConstant %uint 1
986 ; CHECK: %uint_23 = OpConstant %uint 23
987 ; CHECK: %uint_2 = OpConstant %uint 2
988 ; CHECK: %uint_3 = OpConstant %uint 3
989 ; CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float
990 ; CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
991 ; CHECK: %v4uint = OpTypeVector %uint 4
992 ; CHECK: %uint_5 = OpConstant %uint 5
993 ; CHECK: %uint_7 = OpConstant %uint 7
994 ; CHECK: %uint_8 = OpConstant %uint 8
995 ; CHECK: %uint_9 = OpConstant %uint 9
996 ; CHECK: %uint_49 = OpConstant %uint 49
997 ; CHECK: %136 = OpConstantNull %v4float
998 )";
999   // clang-format on
1000 
1001   const std::string main_func = R"(
1002 %MainPs = OpFunction %void None %3
1003 %5 = OpLabel
1004 %53 = OpLoad %v2float %i_vTextureCoords
1005 %63 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0
1006 %64 = OpLoad %uint %63
1007 %65 = OpAccessChain %_ptr_UniformConstant_39 %g_tColor %64
1008 %66 = OpLoad %39 %65
1009 %71 = OpImageSampleImplicitLod %v4float %66 %53
1010 OpStore %_entryPointOutput_vColor %71
1011 ; CHECK-NOT: %71 = OpImageSampleImplicitLod %v4float %66 %53
1012 ; CHECK-NOT: OpStore %_entryPointOutput_vColor %71
1013 ; CHECK: %74 = OpULessThan %bool %64 %uint_128
1014 ; CHECK: OpSelectionMerge %75 None
1015 ; CHECK: OpBranchConditional %74 %76 %77
1016 ; CHECK: %76 = OpLabel
1017 ; CHECK: %78 = OpLoad %39 %65
1018 ; CHECK: %79 = OpImageSampleImplicitLod %v4float %78 %53
1019 ; CHECK: OpBranch %75
1020 ; CHECK: %77 = OpLabel
1021 ; CHECK: %135 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_49 %uint_0 %64 %uint_128
1022 ; CHECK: OpBranch %75
1023 ; CHECK: %75 = OpLabel
1024 ; CHECK: %137 = OpPhi %v4float %79 %76 %136 %77
1025 ; CHECK: OpStore %_entryPointOutput_vColor %137
1026 OpReturn
1027 OpFunctionEnd
1028 )";
1029 
1030   const std::string output_func = kStreamWrite4Frag;
1031 
1032   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1033   SinglePassRunAndMatch<InstBindlessCheckPass>(defs + main_func + output_func,
1034                                                true, 7u, 23u, false, false,
1035                                                false, false, false);
1036 }
1037 
TEST_F(InstBindlessTest,InstrumentImageWrite)1038 TEST_F(InstBindlessTest, InstrumentImageWrite) {
1039   // This test verifies that the pass will correctly instrument shader
1040   // doing bindless image write. This test was created by editing the SPIR-V
1041   // from the Simple test.
1042 
1043   // clang-format off
1044   const std::string defs = R"(
1045 OpCapability Shader
1046 OpCapability StorageImageWriteWithoutFormat
1047 ; CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class"
1048 %1 = OpExtInstImport "GLSL.std.450"
1049 OpMemoryModel Logical GLSL450
1050 OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor
1051 ; CHECK: OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord
1052 OpExecutionMode %MainPs OriginUpperLeft
1053 OpSource HLSL 500
1054 OpName %MainPs "MainPs"
1055 OpName %g_tColor "g_tColor"
1056 OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t"
1057 OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx"
1058 OpName %_ ""
1059 OpName %i_vTextureCoords "i.vTextureCoords"
1060 OpName %_entryPointOutput_vColor "@entryPointOutput.vColor"
1061 OpDecorate %g_tColor DescriptorSet 3
1062 OpDecorate %g_tColor Binding 0
1063 OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0
1064 OpDecorate %PerViewConstantBuffer_t Block
1065 OpDecorate %i_vTextureCoords Location 0
1066 OpDecorate %_entryPointOutput_vColor Location 0
1067 ; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
1068 )" + kOutputDecorations + R"(
1069 ; CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord
1070 %void = OpTypeVoid
1071 %3 = OpTypeFunction %void
1072 %float = OpTypeFloat 32
1073 %v2float = OpTypeVector %float 2
1074 %v4float = OpTypeVector %float 4
1075 %int = OpTypeInt 32 1
1076 %v2int = OpTypeVector %int 2
1077 %int_0 = OpConstant %int 0
1078 %20 = OpTypeImage %float 2D 0 0 0 0 Unknown
1079 %uint = OpTypeInt 32 0
1080 %uint_128 = OpConstant %uint 128
1081 %80 = OpConstantNull %v4float
1082 %_arr_20_uint_128 = OpTypeArray %20 %uint_128
1083 %_ptr_UniformConstant__arr_20_uint_128 = OpTypePointer UniformConstant %_arr_20_uint_128
1084 %g_tColor = OpVariable %_ptr_UniformConstant__arr_20_uint_128 UniformConstant
1085 %PerViewConstantBuffer_t = OpTypeStruct %uint
1086 %_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t
1087 %_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant
1088 %_ptr_PushConstant_uint = OpTypePointer PushConstant %uint
1089 %_ptr_UniformConstant_20 = OpTypePointer UniformConstant %20
1090 %_ptr_Input_v2int = OpTypePointer Input %v2int
1091 %i_vTextureCoords = OpVariable %_ptr_Input_v2int Input
1092 %_ptr_Output_v4float = OpTypePointer Output %v4float
1093 %_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output
1094 ; CHECK: uint_0 = OpConstant %uint 0
1095 ; CHECK: bool = OpTypeBool
1096 ; CHECK: %41 = OpTypeFunction %void %uint %uint %uint %uint
1097 ; CHECK: _runtimearr_uint = OpTypeRuntimeArray %uint
1098 )" + kOutputGlobals + R"(
1099 ; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
1100 ; CHECK: %uint_10 = OpConstant %uint 10
1101 ; CHECK: %uint_4 = OpConstant %uint 4
1102 ; CHECK: %uint_1 = OpConstant %uint 1
1103 ; CHECK: %uint_23 = OpConstant %uint 23
1104 ; CHECK: %uint_2 = OpConstant %uint 2
1105 ; CHECK: %uint_3 = OpConstant %uint 3
1106 ; CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float
1107 ; CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
1108 ; CHECK: %v4uint = OpTypeVector %uint 4
1109 ; CHECK: %uint_5 = OpConstant %uint 5
1110 ; CHECK: %uint_7 = OpConstant %uint 7
1111 ; CHECK: %uint_8 = OpConstant %uint 8
1112 ; CHECK: %uint_9 = OpConstant %uint 9
1113 ; CHECK: %uint_51 = OpConstant %uint 51
1114 )";
1115   // clang-format on
1116 
1117   const std::string main_func = R"(
1118 %MainPs = OpFunction %void None %3
1119 %5 = OpLabel
1120 %53 = OpLoad %v2int %i_vTextureCoords
1121 %63 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0
1122 %64 = OpLoad %uint %63
1123 %65 = OpAccessChain %_ptr_UniformConstant_20 %g_tColor %64
1124 %66 = OpLoad %20 %65
1125 OpImageWrite %66 %53 %80
1126 OpStore %_entryPointOutput_vColor %80
1127 ; CHECK-NOT: OpImageWrite %66 %53 %80
1128 ; CHECK-NOT: OpStore %_entryPointOutput_vColor %80
1129 ; CHECK: %35 = OpULessThan %bool %30 %uint_128
1130 ; CHECK: OpSelectionMerge %36 None
1131 ; CHECK: OpBranchConditional %35 %37 %38
1132 ; CHECK: %37 = OpLabel
1133 ; CHECK: %39 = OpLoad %16 %31
1134 ; CHECK: OpImageWrite %39 %28 %19
1135 ; CHECK: OpBranch %36
1136 ; CHECK: %38 = OpLabel
1137 ; CHECK: %95 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_51 %uint_0 %30 %uint_128
1138 ; CHECK: OpBranch %36
1139 ; CHECK: %36 = OpLabel
1140 ; CHECK: OpStore %_entryPointOutput_vColor %19
1141 OpReturn
1142 OpFunctionEnd
1143 )";
1144 
1145   const std::string output_func = kStreamWrite4Frag;
1146 
1147   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1148   SinglePassRunAndMatch<InstBindlessCheckPass>(defs + main_func + output_func,
1149                                                true, 7u, 23u, false, false,
1150                                                false, false, false);
1151 }
1152 
TEST_F(InstBindlessTest,InstrumentVertexSimple)1153 TEST_F(InstBindlessTest, InstrumentVertexSimple) {
1154   // This test verifies that the pass will correctly instrument shader
1155   // doing bindless image write. This test was created by editing the SPIR-V
1156   // from the Simple test.
1157 
1158   // clang-format off
1159   const std::string defs = R"(
1160 OpCapability Shader
1161 OpCapability Sampled1D
1162 ; CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class"
1163 %1 = OpExtInstImport "GLSL.std.450"
1164 OpMemoryModel Logical GLSL450
1165 OpEntryPoint Vertex %main "main" %_ %coords2D
1166 OpSource GLSL 450
1167 OpName %main "main"
1168 OpName %lod "lod"
1169 OpName %coords1D "coords1D"
1170 OpName %gl_PerVertex "gl_PerVertex"
1171 OpMemberName %gl_PerVertex 0 "gl_Position"
1172 OpMemberName %gl_PerVertex 1 "gl_PointSize"
1173 OpMemberName %gl_PerVertex 2 "gl_ClipDistance"
1174 OpMemberName %gl_PerVertex 3 "gl_CullDistance"
1175 OpName %_ ""
1176 OpName %texSampler1D "texSampler1D"
1177 OpName %foo "foo"
1178 OpMemberName %foo 0 "g_idx"
1179 OpName %__0 ""
1180 OpName %coords2D "coords2D"
1181 ; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
1182 )" + kOutputDecorations + R"(
1183 ; CHECK: OpDecorate %gl_VertexIndex BuiltIn VertexIndex
1184 ; CHECK: OpDecorate %gl_InstanceIndex BuiltIn InstanceIndex
1185 OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
1186 OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
1187 OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
1188 OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
1189 OpDecorate %gl_PerVertex Block
1190 OpDecorate %texSampler1D DescriptorSet 0
1191 OpDecorate %texSampler1D Binding 3
1192 OpMemberDecorate %foo 0 Offset 0
1193 OpDecorate %foo Block
1194 OpDecorate %__0 DescriptorSet 0
1195 OpDecorate %__0 Binding 5
1196 OpDecorate %coords2D Location 0
1197 %void = OpTypeVoid
1198 %3 = OpTypeFunction %void
1199 %float = OpTypeFloat 32
1200 %_ptr_Function_float = OpTypePointer Function %float
1201 %float_3 = OpConstant %float 3
1202 %float_1_78900003 = OpConstant %float 1.78900003
1203 %v4float = OpTypeVector %float 4
1204 %uint = OpTypeInt 32 0
1205 %uint_1 = OpConstant %uint 1
1206 %_arr_float_uint_1 = OpTypeArray %float %uint_1
1207 %gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
1208 %_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
1209 %_ = OpVariable %_ptr_Output_gl_PerVertex Output
1210 %int = OpTypeInt 32 1
1211 %int_0 = OpConstant %int 0
1212 %21 = OpTypeImage %float 1D 0 0 0 1 Unknown
1213 %22 = OpTypeSampledImage %21
1214 %uint_128 = OpConstant %uint 128
1215 %_arr_22_uint_128 = OpTypeArray %22 %uint_128
1216 %_ptr_UniformConstant__arr_22_uint_128 = OpTypePointer UniformConstant %_arr_22_uint_128
1217 %texSampler1D = OpVariable %_ptr_UniformConstant__arr_22_uint_128 UniformConstant
1218 %foo = OpTypeStruct %int
1219 %_ptr_Uniform_foo = OpTypePointer Uniform %foo
1220 %__0 = OpVariable %_ptr_Uniform_foo Uniform
1221 %_ptr_Uniform_int = OpTypePointer Uniform %int
1222 %_ptr_UniformConstant_22 = OpTypePointer UniformConstant %22
1223 %_ptr_Output_v4float = OpTypePointer Output %v4float
1224 %v2float = OpTypeVector %float 2
1225 %_ptr_Input_v2float = OpTypePointer Input %v2float
1226 %coords2D = OpVariable %_ptr_Input_v2float Input
1227 ; CHECK: %uint_0 = OpConstant %uint 0
1228 ; CHECK: %bool = OpTypeBool
1229 ; CHECK: %54 = OpTypeFunction %void %uint %uint %uint %uint
1230 ; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
1231 )" + kOutputGlobals + R"(
1232 ; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
1233 ; CHECK: %uint_10 = OpConstant %uint 10
1234 ; CHECK: %uint_4 = OpConstant %uint 4
1235 ; CHECK: %uint_23 = OpConstant %uint 23
1236 ; CHECK: %uint_2 = OpConstant %uint 2
1237 ; CHECK: %uint_3 = OpConstant %uint 3
1238 ; CHECK: %_ptr_Input_uint = OpTypePointer Input %uint
1239 ; CHECK: %gl_VertexIndex = OpVariable %_ptr_Input_uint Input
1240 ; CHECK: %gl_InstanceIndex = OpVariable %_ptr_Input_uint Input
1241 ; CHECK: %uint_5 = OpConstant %uint 5
1242 ; CHECK: %uint_7 = OpConstant %uint 7
1243 ; CHECK: %uint_8 = OpConstant %uint 8
1244 ; CHECK: %uint_9 = OpConstant %uint 9
1245 ; CHECK: %uint_74 = OpConstant %uint 74
1246 ; CHECK: %106 = OpConstantNull %v4float
1247 )";
1248   // clang-format on
1249 
1250   const std::string main_func = R"(
1251 %main = OpFunction %void None %3
1252 %5 = OpLabel
1253 %lod = OpVariable %_ptr_Function_float Function
1254 %coords1D = OpVariable %_ptr_Function_float Function
1255 OpStore %lod %float_3
1256 OpStore %coords1D %float_1_78900003
1257 %31 = OpAccessChain %_ptr_Uniform_int %__0 %int_0
1258 %32 = OpLoad %int %31
1259 %34 = OpAccessChain %_ptr_UniformConstant_22 %texSampler1D %32
1260 %35 = OpLoad %22 %34
1261 %36 = OpLoad %float %coords1D
1262 %37 = OpLoad %float %lod
1263 %38 = OpImageSampleExplicitLod %v4float %35 %36 Lod %37
1264 %40 = OpAccessChain %_ptr_Output_v4float %_ %int_0
1265 OpStore %40 %38
1266 ; CHECK-NOT: %38 = OpImageSampleExplicitLod %v4float %35 %36 Lod %37
1267 ; CHECK-NOT: %40 = OpAccessChain %_ptr_Output_v4float %_ %int_0
1268 ; CHECK-NOT: OpStore %40 %38
1269 ; CHECK: %46 = OpULessThan %bool %37 %uint_128
1270 ; CHECK: OpSelectionMerge %47 None
1271 ; CHECK: OpBranchConditional %46 %48 %49
1272 ; CHECK: %48 = OpLabel
1273 ; CHECK: %50 = OpLoad %25 %38
1274 ; CHECK: %51 = OpImageSampleExplicitLod %v4float %50 %40 Lod %41
1275 ; CHECK: OpBranch %47
1276 ; CHECK: %49 = OpLabel
1277 ; CHECK: %52 = OpBitcast %uint %37
1278 ; CHECK: %105 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_74 %uint_0 %52 %uint_128
1279 ; CHECK: OpBranch %47
1280 ; CHECK: %47 = OpLabel
1281 ; CHECK: %107 = OpPhi %v4float %51 %48 %106 %49
1282 ; CHECK: %43 = OpAccessChain %_ptr_Output_v4float %_ %int_0
1283 ; CHECK: OpStore %43 %107
1284 OpReturn
1285 OpFunctionEnd
1286 )";
1287 
1288   const std::string output_func = kStreamWrite4Vert;
1289 
1290   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1291   SinglePassRunAndMatch<InstBindlessCheckPass>(defs + main_func + output_func,
1292                                                true, 7u, 23u, false, false,
1293                                                false, false, false);
1294 }
1295 
TEST_F(InstBindlessTest,InstrumentTeseSimple)1296 TEST_F(InstBindlessTest, InstrumentTeseSimple) {
1297   // This test verifies that the pass will correctly instrument tessellation
1298   // evaluation shader doing bindless buffer load.
1299   //
1300   // clang-format off
1301   //
1302   // #version 450
1303   // #extension GL_EXT_nonuniform_qualifier : enable
1304   //
1305   // layout(std140, set = 0, binding = 0) uniform ufoo { uint index; } uniform_index_buffer;
1306   //
1307   // layout(set = 0, binding = 1) buffer bfoo { vec4 val; } adds[11];
1308   //
1309   // layout(triangles, equal_spacing, cw) in;
1310   //
1311   // void main() {
1312   //   gl_Position = adds[uniform_index_buffer.index].val;
1313   // }
1314   //
1315 
1316   const std::string defs = R"(
1317 OpCapability Tessellation
1318 %1 = OpExtInstImport "GLSL.std.450"
1319 OpMemoryModel Logical GLSL450
1320 OpEntryPoint TessellationEvaluation %main "main" %_
1321 ; CHECK: OpEntryPoint TessellationEvaluation %main "main" %_ %gl_PrimitiveID %gl_TessCoord
1322 OpExecutionMode %main Triangles
1323 OpExecutionMode %main SpacingEqual
1324 OpExecutionMode %main VertexOrderCw
1325 OpSource GLSL 450
1326 OpSourceExtension "GL_EXT_nonuniform_qualifier"
1327 OpName %main "main"
1328 OpName %gl_PerVertex "gl_PerVertex"
1329 OpMemberName %gl_PerVertex 0 "gl_Position"
1330 OpMemberName %gl_PerVertex 1 "gl_PointSize"
1331 OpMemberName %gl_PerVertex 2 "gl_ClipDistance"
1332 OpMemberName %gl_PerVertex 3 "gl_CullDistance"
1333 OpName %_ ""
1334 OpName %bfoo "bfoo"
1335 OpMemberName %bfoo 0 "val"
1336 OpName %adds "adds"
1337 OpName %ufoo "ufoo"
1338 OpMemberName %ufoo 0 "index"
1339 OpName %uniform_index_buffer "uniform_index_buffer"
1340 OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
1341 OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
1342 OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
1343 OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
1344 OpDecorate %gl_PerVertex Block
1345 OpMemberDecorate %bfoo 0 Offset 0
1346 OpDecorate %bfoo Block
1347 OpDecorate %adds DescriptorSet 0
1348 OpDecorate %adds Binding 1
1349 OpMemberDecorate %ufoo 0 Offset 0
1350 OpDecorate %ufoo Block
1351 OpDecorate %uniform_index_buffer DescriptorSet 0
1352 OpDecorate %uniform_index_buffer Binding 0
1353 ; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
1354 )" + kOutputDecorations + R"(
1355 ; CHECK: OpDecorate %gl_PrimitiveID BuiltIn PrimitiveId
1356 ; CHECK: OpDecorate %gl_TessCoord BuiltIn TessCoord
1357 %void = OpTypeVoid
1358 %3 = OpTypeFunction %void
1359 %float = OpTypeFloat 32
1360 %v4float = OpTypeVector %float 4
1361 %uint = OpTypeInt 32 0
1362 %uint_1 = OpConstant %uint 1
1363 %_arr_float_uint_1 = OpTypeArray %float %uint_1
1364 %gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
1365 %_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
1366 %_ = OpVariable %_ptr_Output_gl_PerVertex Output
1367 %int = OpTypeInt 32 1
1368 %int_0 = OpConstant %int 0
1369 %bfoo = OpTypeStruct %v4float
1370 %uint_11 = OpConstant %uint 11
1371 %_arr_bfoo_uint_11 = OpTypeArray %bfoo %uint_11
1372 %_ptr_StorageBuffer__arr_bfoo_uint_11 = OpTypePointer StorageBuffer %_arr_bfoo_uint_11
1373 %adds = OpVariable %_ptr_StorageBuffer__arr_bfoo_uint_11 StorageBuffer
1374 %ufoo = OpTypeStruct %uint
1375 %_ptr_Uniform_ufoo = OpTypePointer Uniform %ufoo
1376 %uniform_index_buffer = OpVariable %_ptr_Uniform_ufoo Uniform
1377 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
1378 %_ptr_StorageBuffer_v4float = OpTypePointer StorageBuffer %v4float
1379 %_ptr_Output_v4float = OpTypePointer Output %v4float
1380 ; CHECK: %uint_0 = OpConstant %uint 0
1381 ; CHECK: %bool = OpTypeBool
1382 ; CHECK: %40 = OpTypeFunction %void %uint %uint %uint %uint
1383 ; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
1384 )" + kOutputGlobals + R"(
1385 ; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
1386 ; CHECK: %uint_10 = OpConstant %uint 10
1387 ; CHECK: %uint_4 = OpConstant %uint 4
1388 ; CHECK: %uint_23 = OpConstant %uint 23
1389 ; CHECK: %uint_2 = OpConstant %uint 2
1390 ; CHECK: %uint_3 = OpConstant %uint 3
1391 ; CHECK: %_ptr_Input_uint = OpTypePointer Input %uint
1392 ; CHECK: %gl_PrimitiveID = OpVariable %_ptr_Input_uint Input
1393 ; CHECK: %v3float = OpTypeVector %float 3
1394 ; CHECK: %_ptr_Input_v3float = OpTypePointer Input %v3float
1395 ; CHECK: %gl_TessCoord = OpVariable %_ptr_Input_v3float Input
1396 ; CHECK: %v3uint = OpTypeVector %uint 3
1397 ; CHECK: %uint_5 = OpConstant %uint 5
1398 ; CHECK: %uint_6 = OpConstant %uint 6
1399 ; CHECK: %uint_7 = OpConstant %uint 7
1400 ; CHECK: %uint_8 = OpConstant %uint 8
1401 ; CHECK: %uint_9 = OpConstant %uint 9
1402 ; CHECK: %uint_63 = OpConstant %uint 63
1403 ; CHECK: %101 = OpConstantNull %v4float
1404 )";
1405   // clang-format on
1406 
1407   const std::string main_func = R"(
1408 %main = OpFunction %void None %3
1409 %5 = OpLabel
1410 %25 = OpAccessChain %_ptr_Uniform_uint %uniform_index_buffer %int_0
1411 %26 = OpLoad %uint %25
1412 %28 = OpAccessChain %_ptr_StorageBuffer_v4float %adds %26 %int_0
1413 %29 = OpLoad %v4float %28
1414 ; CHECK-NOT: %29 = OpLoad %v4float %28
1415 ; CHECK: %34 = OpULessThan %bool %28 %uint_11
1416 ; CHECK: OpSelectionMerge %35 None
1417 ; CHECK: OpBranchConditional %34 %36 %37
1418 ; CHECK: %36 = OpLabel
1419 ; CHECK: %38 = OpLoad %v4float %29
1420 ; CHECK: OpBranch %35
1421 ; CHECK: %37 = OpLabel
1422 ; CHECK: %100 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_63 %uint_0 %28 %uint_11
1423 ; CHECK: OpBranch %35
1424 ; CHECK: %35 = OpLabel
1425 ; CHECK: %102 = OpPhi %v4float %38 %36 %101 %37
1426 %31 = OpAccessChain %_ptr_Output_v4float %_ %int_0
1427 OpStore %31 %29
1428 ; CHECK-NOT: OpStore %31 %29
1429 ; CHECK: OpStore %31 %102
1430 OpReturn
1431 OpFunctionEnd
1432 )";
1433 
1434   const std::string output_func = kStreamWrite4Tese;
1435 
1436   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1437   SinglePassRunAndMatch<InstBindlessCheckPass>(defs + main_func + output_func,
1438                                                true, 7u, 23u, false, false,
1439                                                false, false, false);
1440 }
1441 
TEST_F(InstBindlessTest,MultipleDebugFunctions)1442 TEST_F(InstBindlessTest, MultipleDebugFunctions) {
1443   // Same source as Simple, but compiled -g and not optimized, especially not
1444   // inlined. The OpSource has had the source extracted for the sake of brevity.
1445 
1446   // clang-format off
1447   const std::string defs = R"(
1448 OpCapability Shader
1449 ; CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class"
1450 %2 = OpExtInstImport "GLSL.std.450"
1451 OpMemoryModel Logical GLSL450
1452 OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor
1453 ; CHECK: OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord
1454 OpExecutionMode %MainPs OriginUpperLeft
1455 %1 = OpString "foo5.frag"
1456 OpSource HLSL 500 %1
1457 OpName %MainPs "MainPs"
1458 OpName %PS_INPUT "PS_INPUT"
1459 OpMemberName %PS_INPUT 0 "vTextureCoords"
1460 OpName %PS_OUTPUT "PS_OUTPUT"
1461 OpMemberName %PS_OUTPUT 0 "vColor"
1462 OpName %_MainPs_struct_PS_INPUT_vf21_ "@MainPs(struct-PS_INPUT-vf21;"
1463 OpName %i "i"
1464 OpName %ps_output "ps_output"
1465 OpName %g_tColor "g_tColor"
1466 OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t"
1467 OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx"
1468 OpName %_ ""
1469 OpName %g_sAniso "g_sAniso"
1470 OpName %i_0 "i"
1471 OpName %i_vTextureCoords "i.vTextureCoords"
1472 OpName %_entryPointOutput_vColor "@entryPointOutput.vColor"
1473 OpName %param "param"
1474 OpDecorate %g_tColor DescriptorSet 0
1475 OpDecorate %g_tColor Binding 0
1476 OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0
1477 OpDecorate %PerViewConstantBuffer_t Block
1478 OpDecorate %g_sAniso DescriptorSet 0
1479 OpDecorate %g_sAniso Binding 1
1480 OpDecorate %i_vTextureCoords Location 0
1481 OpDecorate %_entryPointOutput_vColor Location 0
1482 ; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
1483 )" + kOutputDecorations + R"(
1484 ; CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord
1485 %void = OpTypeVoid
1486 %4 = OpTypeFunction %void
1487 %float = OpTypeFloat 32
1488 %v2float = OpTypeVector %float 2
1489 %PS_INPUT = OpTypeStruct %v2float
1490 %_ptr_Function_PS_INPUT = OpTypePointer Function %PS_INPUT
1491 %v4float = OpTypeVector %float 4
1492 %PS_OUTPUT = OpTypeStruct %v4float
1493 %13 = OpTypeFunction %PS_OUTPUT %_ptr_Function_PS_INPUT
1494 %_ptr_Function_PS_OUTPUT = OpTypePointer Function %PS_OUTPUT
1495 %int = OpTypeInt 32 1
1496 %int_0 = OpConstant %int 0
1497 %21 = OpTypeImage %float 2D 0 0 0 1 Unknown
1498 %uint = OpTypeInt 32 0
1499 %uint_128 = OpConstant %uint 128
1500 %_arr_21_uint_128 = OpTypeArray %21 %uint_128
1501 %_ptr_UniformConstant__arr_21_uint_128 = OpTypePointer UniformConstant %_arr_21_uint_128
1502 %g_tColor = OpVariable %_ptr_UniformConstant__arr_21_uint_128 UniformConstant
1503 %PerViewConstantBuffer_t = OpTypeStruct %uint
1504 %_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t
1505 %_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant
1506 %_ptr_PushConstant_uint = OpTypePointer PushConstant %uint
1507 %_ptr_UniformConstant_21 = OpTypePointer UniformConstant %21
1508 %36 = OpTypeSampler
1509 %_ptr_UniformConstant_36 = OpTypePointer UniformConstant %36
1510 %g_sAniso = OpVariable %_ptr_UniformConstant_36 UniformConstant
1511 %40 = OpTypeSampledImage %21
1512 %_ptr_Function_v2float = OpTypePointer Function %v2float
1513 %_ptr_Function_v4float = OpTypePointer Function %v4float
1514 %_ptr_Input_v2float = OpTypePointer Input %v2float
1515 %i_vTextureCoords = OpVariable %_ptr_Input_v2float Input
1516 %_ptr_Output_v4float = OpTypePointer Output %v4float
1517 %_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output
1518 ; CHECK: %uint_0 = OpConstant %uint 0
1519 ; CHECK: %bool = OpTypeBool
1520 ; CHECK: %70 = OpTypeFunction %void %uint %uint %uint %uint
1521 ; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
1522 )" + kOutputGlobals + R"(
1523 ; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
1524 ; CHECK: %uint_10 = OpConstant %uint 10
1525 ; CHECK: %uint_4 = OpConstant %uint 4
1526 ; CHECK: %uint_1 = OpConstant %uint 1
1527 ; CHECK: %uint_23 = OpConstant %uint 23
1528 ; CHECK: %uint_2 = OpConstant %uint 2
1529 ; CHECK: %uint_3 = OpConstant %uint 3
1530 ; CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float
1531 ; CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
1532 ; CHECK: %v4uint = OpTypeVector %uint 4
1533 ; CHECK: %uint_5 = OpConstant %uint 5
1534 ; CHECK: %uint_7 = OpConstant %uint 7
1535 ; CHECK: %uint_8 = OpConstant %uint 8
1536 ; CHECK: %uint_9 = OpConstant %uint 9
1537 ; CHECK: %uint_109 = OpConstant %uint 109
1538 ; CHECK: %125 = OpConstantNull %v4float
1539 )";
1540   // clang-format on
1541 
1542   const std::string func1 = R"(
1543 %MainPs = OpFunction %void None %4
1544 %6 = OpLabel
1545 %i_0 = OpVariable %_ptr_Function_PS_INPUT Function
1546 %param = OpVariable %_ptr_Function_PS_INPUT Function
1547 OpLine %1 21 0
1548 %54 = OpLoad %v2float %i_vTextureCoords
1549 %55 = OpAccessChain %_ptr_Function_v2float %i_0 %int_0
1550 OpStore %55 %54
1551 %59 = OpLoad %PS_INPUT %i_0
1552 OpStore %param %59
1553 %60 = OpFunctionCall %PS_OUTPUT %_MainPs_struct_PS_INPUT_vf21_ %param
1554 %61 = OpCompositeExtract %v4float %60 0
1555 OpStore %_entryPointOutput_vColor %61
1556 OpReturn
1557 OpFunctionEnd
1558 )";
1559 
1560   const std::string func2 = R"(
1561 %_MainPs_struct_PS_INPUT_vf21_ = OpFunction %PS_OUTPUT None %13
1562 %i = OpFunctionParameter %_ptr_Function_PS_INPUT
1563 %16 = OpLabel
1564 %ps_output = OpVariable %_ptr_Function_PS_OUTPUT Function
1565 OpLine %1 24 0
1566 %31 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0
1567 %32 = OpLoad %uint %31
1568 %34 = OpAccessChain %_ptr_UniformConstant_21 %g_tColor %32
1569 %35 = OpLoad %21 %34
1570 %39 = OpLoad %36 %g_sAniso
1571 %41 = OpSampledImage %40 %35 %39
1572 %43 = OpAccessChain %_ptr_Function_v2float %i %int_0
1573 %44 = OpLoad %v2float %43
1574 %45 = OpImageSampleImplicitLod %v4float %41 %44
1575 ; CHECK-NOT: %45 = OpImageSampleImplicitLod %v4float %41 %44
1576 ; CHECK: OpNoLine
1577 ; CHECK: %62 = OpULessThan %bool %50 %uint_128
1578 ; CHECK: OpSelectionMerge %63 None
1579 ; CHECK: OpBranchConditional %62 %64 %65
1580 ; CHECK: %64 = OpLabel
1581 ; CHECK: %66 = OpLoad %27 %51
1582 ; CHECK: %67 = OpSampledImage %37 %66 %53
1583 ; CHECK: OpLine %5 24 0
1584 ; CHECK: %68 = OpImageSampleImplicitLod %v4float %67 %56
1585 ; CHECK: OpNoLine
1586 ; CHECK: OpBranch %63
1587 ; CHECK: %65 = OpLabel
1588 ; CHECK: %124 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_109 %uint_0 %50 %uint_128
1589 ; CHECK: OpBranch %63
1590 ; CHECK: %63 = OpLabel
1591 ; CHECK: %126 = OpPhi %v4float %68 %64 %125 %65
1592 ; CHECK: OpLine %5 24 0
1593 %47 = OpAccessChain %_ptr_Function_v4float %ps_output %int_0
1594 OpStore %47 %45
1595 OpLine %1 25 0
1596 %48 = OpLoad %PS_OUTPUT %ps_output
1597 OpReturnValue %48
1598 OpFunctionEnd
1599 )";
1600 
1601   const std::string output_func = kStreamWrite4Frag;
1602 
1603   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1604   SinglePassRunAndMatch<InstBindlessCheckPass>(
1605       defs + func1 + func2 + output_func, true, 7u, 23u, false, false, false,
1606       false, false);
1607 }
1608 
TEST_F(InstBindlessTest,RuntimeArray)1609 TEST_F(InstBindlessTest, RuntimeArray) {
1610   // This test verifies that the pass will correctly instrument shader
1611   // with runtime descriptor array. This test was created by editing the
1612   // SPIR-V from the Simple test.
1613 
1614   // clang-format off
1615   const std::string defs = R"(
1616 OpCapability Shader
1617 OpCapability RuntimeDescriptorArray
1618 OpExtension "SPV_EXT_descriptor_indexing"
1619 ; CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class"
1620 %1 = OpExtInstImport "GLSL.std.450"
1621 OpMemoryModel Logical GLSL450
1622 OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor
1623 ; CHECK: OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord
1624 OpExecutionMode %MainPs OriginUpperLeft
1625 OpSource HLSL 500
1626 OpName %MainPs "MainPs"
1627 OpName %g_tColor "g_tColor"
1628 OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t"
1629 OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx"
1630 OpName %_ ""
1631 OpName %g_sAniso "g_sAniso"
1632 OpName %i_vTextureCoords "i.vTextureCoords"
1633 OpName %_entryPointOutput_vColor "@entryPointOutput.vColor"
1634 OpDecorate %g_tColor DescriptorSet 1
1635 OpDecorate %g_tColor Binding 2
1636 OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0
1637 OpDecorate %PerViewConstantBuffer_t Block
1638 OpDecorate %g_sAniso DescriptorSet 1
1639 OpDecorate %g_sAniso Binding 0
1640 OpDecorate %i_vTextureCoords Location 0
1641 OpDecorate %_entryPointOutput_vColor Location 0
1642 ; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
1643 )" + kInputDecorations + kOutputDecorations + R"(
1644 ; CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord
1645 %void = OpTypeVoid
1646 %3 = OpTypeFunction %void
1647 %float = OpTypeFloat 32
1648 %v2float = OpTypeVector %float 2
1649 %v4float = OpTypeVector %float 4
1650 %int = OpTypeInt 32 1
1651 %int_0 = OpConstant %int 0
1652 %20 = OpTypeImage %float 2D 0 0 0 1 Unknown
1653 %uint = OpTypeInt 32 0
1654 %uint_1 = OpConstant %uint 1
1655 %_rarr_20 = OpTypeRuntimeArray %20
1656 %_ptr_UniformConstant__arr_20 = OpTypePointer UniformConstant %_rarr_20
1657 %g_tColor = OpVariable %_ptr_UniformConstant__arr_20 UniformConstant
1658 %PerViewConstantBuffer_t = OpTypeStruct %uint
1659 %_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t
1660 %_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant
1661 %_ptr_PushConstant_uint = OpTypePointer PushConstant %uint
1662 %_ptr_UniformConstant_20 = OpTypePointer UniformConstant %20
1663 %35 = OpTypeSampler
1664 %_ptr_UniformConstant_35 = OpTypePointer UniformConstant %35
1665 %g_sAniso = OpVariable %_ptr_UniformConstant_35 UniformConstant
1666 %39 = OpTypeSampledImage %20
1667 %_ptr_Input_v2float = OpTypePointer Input %v2float
1668 %i_vTextureCoords = OpVariable %_ptr_Input_v2float Input
1669 %_ptr_Output_v4float = OpTypePointer Output %v4float
1670 %_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output
1671 ; CHECK: %uint_0 = OpConstant %uint 0
1672 ; CHECK: %uint_2 = OpConstant %uint 2
1673 ; CHECK: %41 = OpTypeFunction %uint %uint %uint
1674 ; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
1675 )" + kInputGlobals + R"(
1676 ; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
1677 ; CHECK: %bool = OpTypeBool
1678 ; CHECK: %65 = OpTypeFunction %void %uint %uint %uint %uint
1679 )" + kOutputGlobals + R"(
1680 ; CHECK: %uint_10 = OpConstant %uint 10
1681 ; CHECK: %uint_4 = OpConstant %uint 4
1682 ; CHECK: %uint_23 = OpConstant %uint 23
1683 ; CHECK: %uint_3 = OpConstant %uint 3
1684 ; CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float
1685 ; CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
1686 ; CHECK: %v4uint = OpTypeVector %uint 4
1687 ; CHECK: %uint_5 = OpConstant %uint 5
1688 ; CHECK: %uint_7 = OpConstant %uint 7
1689 ; CHECK: %uint_8 = OpConstant %uint 8
1690 ; CHECK: %uint_9 = OpConstant %uint 9
1691 ; CHECK: %uint_59 = OpConstant %uint 59
1692 ; CHECK: %116 = OpConstantNull %v4float
1693 ; CHECK: %119 = OpTypeFunction %uint %uint %uint %uint %uint
1694 )";
1695   // clang-format on
1696 
1697   const std::string main_func = R"(
1698 %MainPs = OpFunction %void None %3
1699 %5 = OpLabel
1700 %53 = OpLoad %v2float %i_vTextureCoords
1701 %63 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0
1702 %64 = OpLoad %uint %63
1703 %65 = OpAccessChain %_ptr_UniformConstant_20 %g_tColor %64
1704 %66 = OpLoad %20 %65
1705 %67 = OpLoad %35 %g_sAniso
1706 %68 = OpSampledImage %39 %66 %67
1707 %71 = OpImageSampleImplicitLod %v4float %68 %53
1708 OpStore %_entryPointOutput_vColor %71
1709 ; CHECK-NOT: %71 = OpImageSampleImplicitLod %v4float %68 %53
1710 ; CHECK-NOT: OpStore %_entryPointOutput_vColor %71
1711 ; CHECK: %55 = OpFunctionCall %uint %inst_bindless_direct_read_2 %uint_2 %uint_2
1712 ; CHECK: %57 = OpULessThan %bool %32 %55
1713 ; CHECK: OpSelectionMerge %58 None
1714 ; CHECK: OpBranchConditional %57 %59 %60
1715 ; CHECK: %59 = OpLabel
1716 ; CHECK: %61 = OpLoad %16 %33
1717 ; CHECK: %62 = OpSampledImage %26 %61 %35
1718 ; CHECK: %136 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_1 %uint_2 %32
1719 ; CHECK: %137 = OpULessThan %bool %uint_0 %136
1720 ; CHECK: OpSelectionMerge %138 None
1721 ; CHECK: OpBranchConditional %137 %139 %140
1722 ; CHECK: %139 = OpLabel
1723 ; CHECK: %141 = OpLoad %16 %33
1724 ; CHECK: %142 = OpSampledImage %26 %141 %35
1725 ; CHECK: %143 = OpImageSampleImplicitLod %v4float %142 %30
1726 ; CHECK: OpBranch %138
1727 ; CHECK: %140 = OpLabel
1728 ; CHECK: %144 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_59 %uint_1 %32 %uint_0
1729 ; CHECK: OpBranch %138
1730 ; CHECK: %138 = OpLabel
1731 ; CHECK: %145 = OpPhi %v4float %143 %139 %116 %140
1732 ; CHECK: OpBranch %58
1733 ; CHECK: %60 = OpLabel
1734 ; CHECK: %115 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_59 %uint_0 %32 %55
1735 ; CHECK: OpBranch %58
1736 ; CHECK: %58 = OpLabel
1737 ; CHECK: %117 = OpPhi %v4float %145 %138 %116 %60
1738 ; CHECK: OpStore %_entryPointOutput_vColor %117
1739 OpReturn
1740 OpFunctionEnd
1741 )";
1742 
1743   const std::string new_funcs = kDirectRead2 + kStreamWrite4Frag + kDirectRead4;
1744 
1745   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1746   SinglePassRunAndMatch<InstBindlessCheckPass>(defs + main_func + new_funcs,
1747                                                true, 7u, 23u, true, true, false,
1748                                                false, false);
1749 }
1750 
TEST_F(InstBindlessTest,InstrumentInitCheckOnScalarDescriptor)1751 TEST_F(InstBindlessTest, InstrumentInitCheckOnScalarDescriptor) {
1752   // This test verifies that the pass will correctly instrument vanilla
1753   // texture sample on a scalar descriptor with an initialization check if the
1754   // input_init_enable argument is set to true. This can happen when the
1755   // descriptor indexing extension is enabled in the API but the SPIR-V
1756   // does not have the extension enabled because it does not contain a
1757   // runtime array. This is the same shader as NoInstrumentNonBindless.
1758 
1759   // clang-format off
1760   const std::string defs = R"(
1761 OpCapability Shader
1762 ; CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class"
1763 %1 = OpExtInstImport "GLSL.std.450"
1764 OpMemoryModel Logical GLSL450
1765 OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor
1766 ; CHECK: OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord
1767 OpExecutionMode %MainPs OriginUpperLeft
1768 OpSource HLSL 500
1769 OpName %MainPs "MainPs"
1770 OpName %g_tColor "g_tColor"
1771 OpName %g_sAniso "g_sAniso"
1772 OpName %i_vTextureCoords "i.vTextureCoords"
1773 OpName %_entryPointOutput_vColor "@entryPointOutput.vColor"
1774 OpDecorate %g_tColor DescriptorSet 0
1775 OpDecorate %g_tColor Binding 0
1776 OpDecorate %g_sAniso DescriptorSet 0
1777 OpDecorate %g_sAniso Binding 0
1778 OpDecorate %i_vTextureCoords Location 0
1779 OpDecorate %_entryPointOutput_vColor Location 0
1780 ; check: OpDecorate %_runtimearr_uint ArrayStride 4
1781 )" + kInputDecorations + kOutputDecorations + R"(
1782 ; check: OpDecorate %gl_FragCoord BuiltIn FragCoord
1783 %void = OpTypeVoid
1784 %8 = OpTypeFunction %void
1785 %float = OpTypeFloat 32
1786 %v2float = OpTypeVector %float 2
1787 %v4float = OpTypeVector %float 4
1788 %12 = OpTypeImage %float 2D 0 0 0 1 Unknown
1789 %_ptr_UniformConstant_12 = OpTypePointer UniformConstant %12
1790 %g_tColor = OpVariable %_ptr_UniformConstant_12 UniformConstant
1791 %14 = OpTypeSampler
1792 %_ptr_UniformConstant_14 = OpTypePointer UniformConstant %14
1793 %g_sAniso = OpVariable %_ptr_UniformConstant_14 UniformConstant
1794 %16 = OpTypeSampledImage %12
1795 %_ptr_Input_v2float = OpTypePointer Input %v2float
1796 %i_vTextureCoords = OpVariable %_ptr_Input_v2float Input
1797 %_ptr_Output_v4float = OpTypePointer Output %v4float
1798 %_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output
1799 ; CHECK: %uint = OpTypeInt 32 0
1800 ; CHECK: %uint_0 = OpConstant %uint 0
1801 ; CHECK: %28 = OpTypeFunction %uint %uint %uint %uint %uint
1802 ; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
1803 )" + kInputGlobals + R"(
1804 ; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
1805 ; CHECK: %bool = OpTypeBool
1806 ; CHECK: %uint_1 = OpConstant %uint 1
1807 ; CHECK: %61 = OpTypeFunction %void %uint %uint %uint %uint
1808 )" + kOutputGlobals + R"(
1809 ; CHECK: %uint_10 = OpConstant %uint 10
1810 ; CHECK: %uint_4 = OpConstant %uint 4
1811 ; CHECK: %uint_23 = OpConstant %uint 23
1812 ; CHECK: %uint_2 = OpConstant %uint 2
1813 ; CHECK: %uint_3 = OpConstant %uint 3
1814 ; CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float
1815 ; CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
1816 ; CHECK: %v4uint = OpTypeVector %uint 4
1817 ; CHECK: %uint_5 = OpConstant %uint 5
1818 ; CHECK: %uint_7 = OpConstant %uint 7
1819 ; CHECK: %uint_8 = OpConstant %uint 8
1820 ; CHECK: %uint_9 = OpConstant %uint 9
1821 ; CHECK: %uint_39 = OpConstant %uint 39
1822 ; CHECK: %113 = OpConstantNull %v4float
1823 )";
1824   // clang-format on
1825 
1826   const std::string main_func = R"(
1827 %MainPs = OpFunction %void None %8
1828 %19 = OpLabel
1829 %20 = OpLoad %v2float %i_vTextureCoords
1830 %21 = OpLoad %12 %g_tColor
1831 %22 = OpLoad %14 %g_sAniso
1832 %23 = OpSampledImage %16 %21 %22
1833 %24 = OpImageSampleImplicitLod %v4float %23 %20
1834 OpStore %_entryPointOutput_vColor %24
1835 ; CHECK-NOT: %24 = OpImageSampleImplicitLod %v4float %23 %20
1836 ; CHECK-NOT: OpStore %_entryPointOutput_vColor %24
1837 ; CHECK: %50 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_0 %uint_0
1838 ; CHECK: %52 = OpULessThan %bool %uint_0 %50
1839 ; CHECK: OpSelectionMerge %54 None
1840 ; CHECK: OpBranchConditional %52 %55 %56
1841 ; CHECK: %55 = OpLabel
1842 ; CHECK: %57 = OpLoad %12 %g_tColor
1843 ; CHECK: %58 = OpSampledImage %16 %57 %22
1844 ; CHECK: %59 = OpImageSampleImplicitLod %v4float %58 %20
1845 ; CHECK: OpBranch %54
1846 ; CHECK: %56 = OpLabel
1847 ; CHECK: %112 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_39 %uint_1 %uint_0 %uint_0
1848 ; CHECK: OpBranch %54
1849 ; CHECK: %54 = OpLabel
1850 ; CHECK: %114 = OpPhi %v4float %59 %55 %113 %56
1851 ; CHECK: OpStore %_entryPointOutput_vColor %114
1852 OpReturn
1853 OpFunctionEnd
1854 )";
1855 
1856   const std::string new_funcs = kDirectRead4 + kStreamWrite4Frag;
1857 
1858   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1859   SinglePassRunAndMatch<InstBindlessCheckPass>(defs + main_func + new_funcs,
1860                                                true, 7u, 23u, true, true, false,
1861                                                false, false);
1862 }
1863 
TEST_F(InstBindlessTest,SPV14AddToEntryPoint)1864 TEST_F(InstBindlessTest, SPV14AddToEntryPoint) {
1865   const std::string text = R"(
1866 ; CHECK: OpEntryPoint Fragment {{%\w+}} "foo" {{%\w+}} {{%\w+}} {{%\w+}} [[v1:%\w+]] [[v2:%\w+]]
1867 ; CHECK: OpDecorate [[v1]] DescriptorSet 7
1868 ; CHECK: OpDecorate [[v2]] DescriptorSet 7
1869 ; CHECK: [[v1]] = OpVariable {{%\w+}} StorageBuffer
1870 ; CHECK: [[v2]] = OpVariable {{%\w+}} StorageBuffer
1871 OpCapability Shader
1872 OpExtension "SPV_EXT_descriptor_indexing"
1873 OpMemoryModel Logical GLSL450
1874 OpEntryPoint Fragment %foo "foo" %gid %image_var %sampler_var
1875 OpExecutionMode %foo OriginUpperLeft
1876 OpDecorate %image_var DescriptorSet 0
1877 OpDecorate %image_var Binding 0
1878 OpDecorate %sampler_var DescriptorSet 0
1879 OpDecorate %sampler_var Binding 1
1880 OpDecorate %gid DescriptorSet 0
1881 OpDecorate %gid Binding 2
1882 OpDecorate %struct Block
1883 OpMemberDecorate %struct 0 Offset 0
1884 %void = OpTypeVoid
1885 %int = OpTypeInt 32 0
1886 %int_0 = OpConstant %int 0
1887 %v3int = OpTypeVector %int 3
1888 %float = OpTypeFloat 32
1889 %v3float = OpTypeVector %float 3
1890 %v4float = OpTypeVector %float 4
1891 %struct = OpTypeStruct %v3int
1892 %ptr_ssbo_struct = OpTypePointer StorageBuffer %struct
1893 %ptr_ssbo_v3int = OpTypePointer StorageBuffer %v3int
1894 %gid = OpVariable %ptr_ssbo_struct StorageBuffer
1895 %image = OpTypeImage %float 3D 0 0 0 1 Unknown
1896 %ptr_uc_image = OpTypePointer UniformConstant %image
1897 %sampler = OpTypeSampler
1898 %ptr_uc_sampler = OpTypePointer UniformConstant %sampler
1899 %image_var = OpVariable %ptr_uc_image UniformConstant
1900 %sampler_var = OpVariable %ptr_uc_sampler UniformConstant
1901 %sampled = OpTypeSampledImage %image
1902 %void_fn = OpTypeFunction %void
1903 %foo = OpFunction %void None %void_fn
1904 %entry = OpLabel
1905 %ld_image = OpLoad %image %image_var
1906 %ld_sampler = OpLoad %sampler %sampler_var
1907 %gep = OpAccessChain %ptr_ssbo_v3int %gid %int_0
1908 %ld_gid = OpLoad %v3int %gep
1909 %convert = OpConvertUToF %v3float %ld_gid
1910 %sampled_image = OpSampledImage %sampled %ld_image %ld_sampler
1911 %sample = OpImageSampleImplicitLod %v4float %sampled_image %convert
1912 OpReturn
1913 OpFunctionEnd
1914 )";
1915 
1916   SetTargetEnv(SPV_ENV_VULKAN_1_1_SPIRV_1_4);
1917   SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 7u, 23u, true, true,
1918                                                false, false, false);
1919 }
1920 
TEST_F(InstBindlessTest,SPV14AddToEntryPoints)1921 TEST_F(InstBindlessTest, SPV14AddToEntryPoints) {
1922   const std::string text = R"(
1923 ; CHECK: OpEntryPoint Fragment {{%\w+}} "foo" {{%\w+}} {{%\w+}} {{%\w+}} [[v1:%\w+]] [[v2:%\w+]]
1924 ; CHECK: OpEntryPoint Fragment {{%\w+}} "bar" {{%\w+}} {{%\w+}} {{%\w+}} [[v1:%\w+]] [[v2:%\w+]]
1925 ; CHECK: OpDecorate [[v1]] DescriptorSet 7
1926 ; CHECK: OpDecorate [[v2]] DescriptorSet 7
1927 ; CHECK: [[v1]] = OpVariable {{%\w+}} StorageBuffer
1928 ; CHECK: [[v2]] = OpVariable {{%\w+}} StorageBuffer
1929 OpCapability Shader
1930 OpExtension "SPV_EXT_descriptor_indexing"
1931 OpMemoryModel Logical GLSL450
1932 OpEntryPoint Fragment %foo "foo" %gid %image_var %sampler_var
1933 OpEntryPoint Fragment %foo "bar" %gid %image_var %sampler_var
1934 OpExecutionMode %foo OriginUpperLeft
1935 OpDecorate %image_var DescriptorSet 0
1936 OpDecorate %image_var Binding 0
1937 OpDecorate %sampler_var DescriptorSet 0
1938 OpDecorate %sampler_var Binding 1
1939 OpDecorate %gid DescriptorSet 0
1940 OpDecorate %gid Binding 2
1941 OpDecorate %struct Block
1942 OpMemberDecorate %struct 0 Offset 0
1943 %void = OpTypeVoid
1944 %int = OpTypeInt 32 0
1945 %int_0 = OpConstant %int 0
1946 %v3int = OpTypeVector %int 3
1947 %float = OpTypeFloat 32
1948 %v3float = OpTypeVector %float 3
1949 %v4float = OpTypeVector %float 4
1950 %struct = OpTypeStruct %v3int
1951 %ptr_ssbo_struct = OpTypePointer StorageBuffer %struct
1952 %ptr_ssbo_v3int = OpTypePointer StorageBuffer %v3int
1953 %gid = OpVariable %ptr_ssbo_struct StorageBuffer
1954 %image = OpTypeImage %float 3D 0 0 0 1 Unknown
1955 %ptr_uc_image = OpTypePointer UniformConstant %image
1956 %sampler = OpTypeSampler
1957 %ptr_uc_sampler = OpTypePointer UniformConstant %sampler
1958 %image_var = OpVariable %ptr_uc_image UniformConstant
1959 %sampler_var = OpVariable %ptr_uc_sampler UniformConstant
1960 %sampled = OpTypeSampledImage %image
1961 %void_fn = OpTypeFunction %void
1962 %foo = OpFunction %void None %void_fn
1963 %entry = OpLabel
1964 %ld_image = OpLoad %image %image_var
1965 %ld_sampler = OpLoad %sampler %sampler_var
1966 %gep = OpAccessChain %ptr_ssbo_v3int %gid %int_0
1967 %ld_gid = OpLoad %v3int %gep
1968 %convert = OpConvertUToF %v3float %ld_gid
1969 %sampled_image = OpSampledImage %sampled %ld_image %ld_sampler
1970 %sample = OpImageSampleImplicitLod %v4float %sampled_image %convert
1971 OpReturn
1972 OpFunctionEnd
1973 )";
1974 
1975   SetTargetEnv(SPV_ENV_VULKAN_1_1_SPIRV_1_4);
1976   SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 7u, 23u, true, true,
1977                                                false, false, false);
1978 }
1979 
TEST_F(InstBindlessTest,InstBoundsAndInitLoadUnsizedUBOArray)1980 TEST_F(InstBindlessTest, InstBoundsAndInitLoadUnsizedUBOArray) {
1981   // #version 450
1982   // #extension GL_EXT_nonuniform_qualifier : enable
1983   //
1984   // layout(location=0) in nonuniformEXT flat int nu_ii;
1985   // layout(location=0) out float b;
1986   //
1987   // layout(binding=3)  uniform uname { float a; }  uniformBuffer[];
1988   //
1989   // void main()
1990   // {
1991   //     b = uniformBuffer[nu_ii].a;
1992   // }
1993 
1994   // clang-format off
1995   const std::string defs = R"(
1996 OpCapability Shader
1997 OpCapability ShaderNonUniform
1998 OpCapability RuntimeDescriptorArray
1999 OpCapability UniformBufferArrayNonUniformIndexing
2000 OpExtension "SPV_EXT_descriptor_indexing"
2001 ; CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class"
2002 %1 = OpExtInstImport "GLSL.std.450"
2003 OpMemoryModel Logical GLSL450
2004 OpEntryPoint Fragment %main "main" %b %nu_ii
2005 ; CHECK: OpEntryPoint Fragment %main "main" %b %nu_ii %gl_FragCoord
2006 OpExecutionMode %main OriginUpperLeft
2007 OpSource GLSL 450
2008 OpSourceExtension "GL_EXT_nonuniform_qualifier"
2009 OpName %main "main"
2010 OpName %b "b"
2011 OpName %uname "uname"
2012 OpMemberName %uname 0 "a"
2013 OpName %uniformBuffer "uniformBuffer"
2014 OpName %nu_ii "nu_ii"
2015 OpDecorate %b Location 0
2016 OpMemberDecorate %uname 0 Offset 0
2017 OpDecorate %uname Block
2018 OpDecorate %uniformBuffer DescriptorSet 0
2019 OpDecorate %uniformBuffer Binding 3
2020 OpDecorate %nu_ii Flat
2021 OpDecorate %nu_ii Location 0
2022 OpDecorate %nu_ii NonUniform
2023 OpDecorate %16 NonUniform
2024 OpDecorate %20 NonUniform
2025 ; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
2026 )" + kInputDecorations + R"(
2027 ; CHECK: OpDecorate %130 NonUniform
2028 )" + kOutputDecorations + R"(
2029 ; CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord
2030 ; CHECK: OpDecorate %127 NonUniform
2031 %void = OpTypeVoid
2032 %3 = OpTypeFunction %void
2033 %float = OpTypeFloat 32
2034 %_ptr_Output_float = OpTypePointer Output %float
2035 %b = OpVariable %_ptr_Output_float Output
2036 %uname = OpTypeStruct %float
2037 %_runtimearr_uname = OpTypeRuntimeArray %uname
2038 %_ptr_Uniform__runtimearr_uname = OpTypePointer Uniform %_runtimearr_uname
2039 %uniformBuffer = OpVariable %_ptr_Uniform__runtimearr_uname Uniform
2040 %int = OpTypeInt 32 1
2041 %_ptr_Input_int = OpTypePointer Input %int
2042 %nu_ii = OpVariable %_ptr_Input_int Input
2043 %int_0 = OpConstant %int 0
2044 %_ptr_Uniform_float = OpTypePointer Uniform %float
2045 ; CHECK: %uint = OpTypeInt 32 0
2046 ; CHECK: %uint_0 = OpConstant %uint 0
2047 ; CHECK: %uint_1 = OpConstant %uint 1
2048 ; CHECK: %uint_3 = OpConstant %uint 3
2049 ; CHECK: %26 = OpTypeFunction %uint %uint %uint
2050 ; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
2051 )" + kInputGlobals + R"(
2052 ; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
2053 ; CHECK: %bool = OpTypeBool
2054 ; CHECK: %49 = OpTypeFunction %void %uint %uint %uint %uint
2055 )" + kOutputGlobals + R"(
2056 ; CHECK: %uint_10 = OpConstant %uint 10
2057 ; CHECK: %uint_4 = OpConstant %uint 4
2058 ; CHECK: %uint_23 = OpConstant %uint 23
2059 ; CHECK: %uint_2 = OpConstant %uint 2
2060 ; CHECK: %v4float = OpTypeVector %float 4
2061 ; CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float
2062 ; CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
2063 ; CHECK: %v4uint = OpTypeVector %uint 4
2064 ; CHECK: %uint_5 = OpConstant %uint 5
2065 ; CHECK: %uint_7 = OpConstant %uint 7
2066 ; CHECK: %uint_8 = OpConstant %uint 8
2067 ; CHECK: %uint_9 = OpConstant %uint 9
2068 ; CHECK: %uint_45 = OpConstant %uint 45
2069 ; CHECK: %101 = OpConstantNull %float
2070 ; CHECK: %105 = OpTypeFunction %uint %uint %uint %uint %uint
2071 )";
2072   // clang-format on
2073 
2074   const std::string main_func = R"(
2075 %main = OpFunction %void None %3
2076 %5 = OpLabel
2077 %16 = OpLoad %int %nu_ii
2078 %19 = OpAccessChain %_ptr_Uniform_float %uniformBuffer %16 %int_0
2079 %20 = OpLoad %float %19
2080 OpStore %b %20
2081 ; CHECK-NOT: %20 = OpLoad %float %19
2082 ; CHECK-NOT: OpStore %b %20
2083 ; CHECK: %40 = OpFunctionCall %uint %inst_bindless_direct_read_2 %uint_1 %uint_3
2084 ; CHECK: %42 = OpULessThan %bool %7 %40
2085 ; CHECK: OpSelectionMerge %43 None
2086 ; CHECK: OpBranchConditional %42 %44 %45
2087 ; CHECK: %44 = OpLabel
2088 ; CHECK: %103 = OpBitcast %uint %7
2089 ; CHECK: %122 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_3 %103
2090 ; CHECK: %123 = OpULessThan %bool %uint_0 %122
2091 ; CHECK: OpSelectionMerge %124 None
2092 ; CHECK: OpBranchConditional %123 %125 %126
2093 ; CHECK: %125 = OpLabel
2094 ; CHECK: %127 = OpLoad %float %20
2095 ; CHECK: OpBranch %124
2096 ; CHECK: %126 = OpLabel
2097 ; CHECK: %128 = OpBitcast %uint %7
2098 ; CHECK: %129 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_45 %uint_1 %128 %uint_0
2099 ; CHECK: OpBranch %124
2100 ; CHECK: %124 = OpLabel
2101 ; CHECK: %130 = OpPhi %float %127 %125 %101 %126
2102 ; CHECK: OpBranch %43
2103 ; CHECK: %45 = OpLabel
2104 ; CHECK: %47 = OpBitcast %uint %7
2105 ; CHECK: %100 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_45 %uint_0 %47 %40
2106 ; CHECK: OpBranch %43
2107 ; CHECK: %43 = OpLabel
2108 ; CHECK: %102 = OpPhi %float %130 %124 %101 %45
2109 ; CHECK: OpStore %b %102
2110 OpReturn
2111 OpFunctionEnd
2112 )";
2113 
2114   const std::string new_funcs = kDirectRead2 + kStreamWrite4Frag + kDirectRead4;
2115 
2116   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
2117   SinglePassRunAndMatch<InstBindlessCheckPass>(defs + main_func + new_funcs,
2118                                                true, 7u, 23u, true, true, false,
2119                                                false, false);
2120 }
2121 
TEST_F(InstBindlessTest,InstBoundsAndInitLoadUnsizedSSBOArrayDeprecated)2122 TEST_F(InstBindlessTest, InstBoundsAndInitLoadUnsizedSSBOArrayDeprecated) {
2123   // #version 450
2124   // #extension GL_EXT_nonuniform_qualifier : enable
2125   //
2126   // layout(location=0) in nonuniformEXT flat int nu_ii;
2127   // layout(location=0) out float b;
2128   //
2129   // layout(binding=3)  buffer bname { float b; }  storageBuffer[];
2130   //
2131   // void main()
2132   // {
2133   //     b = storageBuffer[nu_ii].b;
2134   // }
2135 
2136   // clang-format off
2137   const std::string defs = R"(
2138 OpCapability Shader
2139 OpCapability ShaderNonUniform
2140 OpCapability RuntimeDescriptorArray
2141 OpCapability StorageBufferArrayNonUniformIndexing
2142 OpExtension "SPV_EXT_descriptor_indexing"
2143 ; CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class"
2144 %1 = OpExtInstImport "GLSL.std.450"
2145 OpMemoryModel Logical GLSL450
2146 OpEntryPoint Fragment %main "main" %b %nu_ii
2147 ; CHECK: OpEntryPoint Fragment %main "main" %b %nu_ii %gl_FragCoord
2148 OpExecutionMode %main OriginUpperLeft
2149 OpSource GLSL 450
2150 OpSourceExtension "GL_EXT_nonuniform_qualifier"
2151 OpName %main "main"
2152 OpName %b "b"
2153 OpName %bname "bname"
2154 OpMemberName %bname 0 "a"
2155 OpName %storageBuffer "storageBuffer"
2156 OpName %nu_ii "nu_ii"
2157 OpDecorate %b Location 0
2158 OpMemberDecorate %bname 0 Offset 0
2159 OpDecorate %bname Block
2160 OpDecorate %storageBuffer DescriptorSet 0
2161 OpDecorate %storageBuffer Binding 3
2162 OpDecorate %nu_ii Flat
2163 OpDecorate %nu_ii Location 0
2164 OpDecorate %nu_ii NonUniform
2165 OpDecorate %16 NonUniform
2166 OpDecorate %20 NonUniform
2167 ; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
2168 )" + kInputDecorations + R"(
2169 ; CHECK: OpDecorate %130 NonUniform
2170 )" + kOutputDecorations + R"(
2171 ; CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord
2172 ; CHECK: OpDecorate %127 NonUniform
2173 %void = OpTypeVoid
2174 %3 = OpTypeFunction %void
2175 %float = OpTypeFloat 32
2176 %_ptr_Output_float = OpTypePointer Output %float
2177 %b = OpVariable %_ptr_Output_float Output
2178 %bname = OpTypeStruct %float
2179 %_runtimearr_bname = OpTypeRuntimeArray %bname
2180 %_ptr_StorageBuffer__runtimearr_bname = OpTypePointer StorageBuffer %_runtimearr_bname
2181 %storageBuffer = OpVariable %_ptr_StorageBuffer__runtimearr_bname StorageBuffer
2182 %int = OpTypeInt 32 1
2183 %_ptr_Input_int = OpTypePointer Input %int
2184 %nu_ii = OpVariable %_ptr_Input_int Input
2185 %int_0 = OpConstant %int 0
2186 %_ptr_StorageBuffer_float = OpTypePointer StorageBuffer %float
2187 ; CHECK: %uint = OpTypeInt 32 0
2188 ; CHECK: %uint_0 = OpConstant %uint 0
2189 ; CHECK: %uint_1 = OpConstant %uint 1
2190 ; CHECK: %uint_3 = OpConstant %uint 3
2191 ; CHECK: %26 = OpTypeFunction %uint %uint %uint
2192 ; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
2193 )" + kInputGlobals + R"(
2194 ; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
2195 ; CHECK: %bool = OpTypeBool
2196 ; CHECK: %49 = OpTypeFunction %void %uint %uint %uint %uint
2197 )" + kOutputGlobals + R"(
2198 ; CHECK: %uint_10 = OpConstant %uint 10
2199 ; CHECK: %uint_4 = OpConstant %uint 4
2200 ; CHECK: %uint_23 = OpConstant %uint 23
2201 ; CHECK: %uint_2 = OpConstant %uint 2
2202 ; CHECK: %v4float = OpTypeVector %float 4
2203 ; CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float
2204 ; CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
2205 ; CHECK: %v4uint = OpTypeVector %uint 4
2206 ; CHECK: %uint_5 = OpConstant %uint 5
2207 ; CHECK: %uint_7 = OpConstant %uint 7
2208 ; CHECK: %uint_8 = OpConstant %uint 8
2209 ; CHECK: %uint_9 = OpConstant %uint 9
2210 ; CHECK: %uint_45 = OpConstant %uint 45
2211 ; CHECK: %101 = OpConstantNull %float
2212 ; CHECK: %105 = OpTypeFunction %uint %uint %uint %uint %uint
2213 )";
2214   // clang-format on
2215 
2216   const std::string main_func = R"(
2217 %main = OpFunction %void None %3
2218 %5 = OpLabel
2219 %16 = OpLoad %int %nu_ii
2220 %19 = OpAccessChain %_ptr_StorageBuffer_float %storageBuffer %16 %int_0
2221 %20 = OpLoad %float %19
2222 OpStore %b %20
2223 ; CHECK-NOT: %20 = OpLoad %float %19
2224 ; CHECK-NOT: OpStore %b %20
2225 ; CHECK: %40 = OpFunctionCall %uint %inst_bindless_direct_read_2 %uint_1 %uint_3
2226 ; CHECK: %42 = OpULessThan %bool %7 %40
2227 ; CHECK: OpSelectionMerge %43 None
2228 ; CHECK: OpBranchConditional %42 %44 %45
2229 ; CHECK: %44 = OpLabel
2230 ; CHECK: %103 = OpBitcast %uint %7
2231 ; CHECK: %122 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_3 %103
2232 ; CHECK: %123 = OpULessThan %bool %uint_0 %122
2233 ; CHECK: OpSelectionMerge %124 None
2234 ; CHECK: OpBranchConditional %123 %125 %126
2235 ; CHECK: %125 = OpLabel
2236 ; CHECK: %127 = OpLoad %float %20
2237 ; CHECK: OpBranch %124
2238 ; CHECK: %126 = OpLabel
2239 ; CHECK: %128 = OpBitcast %uint %7
2240 ; CHECK: %129 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_45 %uint_1 %128 %uint_0
2241 ; CHECK: OpBranch %124
2242 ; CHECK: %124 = OpLabel
2243 ; CHECK: %130 = OpPhi %float %127 %125 %101 %126
2244 ; CHECK: OpBranch %43
2245 ; CHECK: %45 = OpLabel
2246 ; CHECK: %47 = OpBitcast %uint %7
2247 ; CHECK: %100 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_45 %uint_0 %47 %40
2248 ; CHECK: OpBranch %43
2249 ; CHECK: %43 = OpLabel
2250 ; CHECK: %102 = OpPhi %float %130 %124 %101 %45
2251 ; CHECK: OpStore %b %102
2252 OpReturn
2253 OpFunctionEnd
2254 )";
2255 
2256   const std::string new_funcs = kDirectRead2 + kStreamWrite4Frag + kDirectRead4;
2257 
2258   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
2259   SinglePassRunAndMatch<InstBindlessCheckPass>(defs + main_func + new_funcs,
2260                                                true, 7u, 23u, true, true, false,
2261                                                false, false);
2262 }
2263 
TEST_F(InstBindlessTest,InstBoundsAndInitLoadUnsizedSSBOArray)2264 TEST_F(InstBindlessTest, InstBoundsAndInitLoadUnsizedSSBOArray) {
2265   // Same as Deprecated but declaring as StorageBuffer Block
2266 
2267   // clang-format off
2268   const std::string defs = R"(
2269 OpCapability Shader
2270 OpCapability ShaderNonUniform
2271 OpCapability RuntimeDescriptorArray
2272 OpCapability StorageBufferArrayNonUniformIndexing
2273 OpExtension "SPV_EXT_descriptor_indexing"
2274 ; CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class"
2275 %1 = OpExtInstImport "GLSL.std.450"
2276 OpMemoryModel Logical GLSL450
2277 OpEntryPoint Fragment %main "main" %b %nu_ii
2278 ; CHECK: OpEntryPoint Fragment %main "main" %b %nu_ii %gl_FragCoord
2279 OpExecutionMode %main OriginUpperLeft
2280 OpSource GLSL 450
2281 OpSourceExtension "GL_EXT_nonuniform_qualifier"
2282 OpName %main "main"
2283 OpName %b "b"
2284 OpName %bname "bname"
2285 OpMemberName %bname 0 "a"
2286 OpName %storageBuffer "storageBuffer"
2287 OpName %nu_ii "nu_ii"
2288 OpDecorate %b Location 0
2289 OpMemberDecorate %bname 0 Offset 0
2290 OpDecorate %bname Block
2291 OpDecorate %storageBuffer DescriptorSet 0
2292 OpDecorate %storageBuffer Binding 3
2293 OpDecorate %nu_ii Flat
2294 OpDecorate %nu_ii Location 0
2295 OpDecorate %nu_ii NonUniform
2296 OpDecorate %16 NonUniform
2297 OpDecorate %20 NonUniform
2298 ; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
2299 )" + kInputDecorations + R"(
2300 ; CHECK: OpDecorate %130 NonUniform
2301 )" + kOutputDecorations + R"(
2302 ; CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord
2303 ; CHECK: OpDecorate %127 NonUniform
2304 %void = OpTypeVoid
2305 %3 = OpTypeFunction %void
2306 %float = OpTypeFloat 32
2307 %_ptr_Output_float = OpTypePointer Output %float
2308 %b = OpVariable %_ptr_Output_float Output
2309 %bname = OpTypeStruct %float
2310 %_runtimearr_bname = OpTypeRuntimeArray %bname
2311 %_ptr_StorageBuffer__runtimearr_bname = OpTypePointer StorageBuffer %_runtimearr_bname
2312 %storageBuffer = OpVariable %_ptr_StorageBuffer__runtimearr_bname StorageBuffer
2313 %int = OpTypeInt 32 1
2314 %_ptr_Input_int = OpTypePointer Input %int
2315 %nu_ii = OpVariable %_ptr_Input_int Input
2316 %int_0 = OpConstant %int 0
2317 %_ptr_StorageBuffer_float = OpTypePointer StorageBuffer %float
2318 ; CHECK: %uint = OpTypeInt 32 0
2319 ; CHECK: %uint_0 = OpConstant %uint 0
2320 ; CHECK: %uint_1 = OpConstant %uint 1
2321 ; CHECK: %uint_3 = OpConstant %uint 3
2322 ; CHECK: %26 = OpTypeFunction %uint %uint %uint
2323 ; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
2324 )" + kInputGlobals + R"(
2325 ; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
2326 ; CHECK: %bool = OpTypeBool
2327 ; CHECK: %49 = OpTypeFunction %void %uint %uint %uint %uint
2328 )" + kOutputGlobals + R"(
2329 ; CHECK: %uint_10 = OpConstant %uint 10
2330 ; CHECK: %uint_4 = OpConstant %uint 4
2331 ; CHECK: %uint_23 = OpConstant %uint 23
2332 ; CHECK: %uint_2 = OpConstant %uint 2
2333 ; CHECK: %v4float = OpTypeVector %float 4
2334 ; CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float
2335 ; CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
2336 ; CHECK: %v4uint = OpTypeVector %uint 4
2337 ; CHECK: %uint_5 = OpConstant %uint 5
2338 ; CHECK: %uint_7 = OpConstant %uint 7
2339 ; CHECK: %uint_8 = OpConstant %uint 8
2340 ; CHECK: %uint_9 = OpConstant %uint 9
2341 ; CHECK: %uint_45 = OpConstant %uint 45
2342 ; CHECK: %101 = OpConstantNull %float
2343 ; CHECK: %105 = OpTypeFunction %uint %uint %uint %uint %uint
2344 )";
2345   // clang-format on
2346 
2347   const std::string main_func = R"(
2348 %main = OpFunction %void None %3
2349 %5 = OpLabel
2350 %16 = OpLoad %int %nu_ii
2351 %19 = OpAccessChain %_ptr_StorageBuffer_float %storageBuffer %16 %int_0
2352 %20 = OpLoad %float %19
2353 OpStore %b %20
2354 ; CHECK-NOT: %20 = OpLoad %float %19
2355 ; CHECK-NOT: OpStore %b %20
2356 ; CHECK: %40 = OpFunctionCall %uint %inst_bindless_direct_read_2 %uint_1 %uint_3
2357 ; CHECK: %42 = OpULessThan %bool %7 %40
2358 ; CHECK: OpSelectionMerge %43 None
2359 ; CHECK: OpBranchConditional %42 %44 %45
2360 ; CHECK: %44 = OpLabel
2361 ; CHECK: %103 = OpBitcast %uint %7
2362 ; CHECK: %122 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_3 %103
2363 ; CHECK: %123 = OpULessThan %bool %uint_0 %122
2364 ; CHECK: OpSelectionMerge %124 None
2365 ; CHECK: OpBranchConditional %123 %125 %126
2366 ; CHECK: %125 = OpLabel
2367 ; CHECK: %127 = OpLoad %float %20
2368 ; CHECK: OpBranch %124
2369 ; CHECK: %126 = OpLabel
2370 ; CHECK: %128 = OpBitcast %uint %7
2371 ; CHECK: %129 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_45 %uint_1 %128 %uint_0
2372 ; CHECK: OpBranch %124
2373 ; CHECK: %124 = OpLabel
2374 ; CHECK: %130 = OpPhi %float %127 %125 %101 %126
2375 ; CHECK: OpBranch %43
2376 ; CHECK: %45 = OpLabel
2377 ; CHECK: %47 = OpBitcast %uint %7
2378 ; CHECK: %100 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_45 %uint_0 %47 %40
2379 ; CHECK: OpBranch %43
2380 ; CHECK: %43 = OpLabel
2381 ; CHECK: %102 = OpPhi %float %130 %124 %101 %45
2382 ; CHECK: OpStore %b %102
2383 OpReturn
2384 OpFunctionEnd
2385 )";
2386 
2387   const std::string new_funcs = kDirectRead2 + kStreamWrite4Frag + kDirectRead4;
2388 
2389   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
2390   SinglePassRunAndMatch<InstBindlessCheckPass>(defs + main_func + new_funcs,
2391                                                true, 7u, 23u, true, true, false,
2392                                                false, false);
2393 }
2394 
TEST_F(InstBindlessTest,InstInitLoadUBOScalar)2395 TEST_F(InstBindlessTest, InstInitLoadUBOScalar) {
2396   // #version 450
2397   // #extension GL_EXT_nonuniform_qualifier : enable
2398   //
2399   // layout(location=0) out float b;
2400   // layout(binding=3)  uniform uname { float a; }  uniformBuffer;
2401   //
2402   // void main()
2403   // {
2404   //     b = uniformBuffer.a;
2405   // }
2406 
2407   // clang-format off
2408   const std::string defs = R"(
2409 OpCapability Shader
2410 OpExtension "SPV_EXT_descriptor_indexing"
2411 ; CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class"
2412 %1 = OpExtInstImport "GLSL.std.450"
2413 OpMemoryModel Logical GLSL450
2414 OpEntryPoint Fragment %main "main" %b
2415 ; CHECK: OpEntryPoint Fragment %main "main" %b %gl_FragCoord
2416 OpExecutionMode %main OriginUpperLeft
2417 OpSource GLSL 450
2418 OpSourceExtension "GL_EXT_nonuniform_qualifier"
2419 OpName %main "main"
2420 OpName %b "b"
2421 OpName %uname "uname"
2422 OpMemberName %uname 0 "a"
2423 OpName %uniformBuffer "uniformBuffer"
2424 OpDecorate %b Location 0
2425 OpMemberDecorate %uname 0 Offset 0
2426 OpDecorate %uname Block
2427 OpDecorate %uniformBuffer DescriptorSet 0
2428 OpDecorate %uniformBuffer Binding 3
2429 ; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
2430 )" + kInputDecorations + kOutputDecorations + R"(
2431 ; CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord
2432 %void = OpTypeVoid
2433 %3 = OpTypeFunction %void
2434 %float = OpTypeFloat 32
2435 %_ptr_Output_float = OpTypePointer Output %float
2436 %b = OpVariable %_ptr_Output_float Output
2437 %uname = OpTypeStruct %float
2438 %_ptr_Uniform_uname = OpTypePointer Uniform %uname
2439 %uniformBuffer = OpVariable %_ptr_Uniform_uname Uniform
2440 %int = OpTypeInt 32 1
2441 %int_0 = OpConstant %int 0
2442 %_ptr_Uniform_float = OpTypePointer Uniform %float
2443 ; CHECK: %int = OpTypeInt 32 1
2444 ; CHECK: %int_0 = OpConstant %int 0
2445 ; CHECK: %_ptr_Uniform_float = OpTypePointer Uniform %float
2446 ; CHECK: %uint = OpTypeInt 32 0
2447 ; CHECK: %uint_0 = OpConstant %uint 0
2448 ; CHECK: %uint_3 = OpConstant %uint 3
2449 ; CHECK: %21 = OpTypeFunction %uint %uint %uint %uint %uint
2450 ; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
2451 )" + kInputGlobals + R"(
2452 ; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
2453 ; CHECK: %bool = OpTypeBool
2454 ; CHECK: %uint_1 = OpConstant %uint 1
2455 ; CHECK: %52 = OpTypeFunction %void %uint %uint %uint %uint
2456 )" + kOutputGlobals + R"(
2457 ; CHECK: %uint_10 = OpConstant %uint 10
2458 ; CHECK: %uint_4 = OpConstant %uint 4
2459 ; CHECK: %uint_23 = OpConstant %uint 23
2460 ; CHECK: %uint_2 = OpConstant %uint 2
2461 ; CHECK: %v4float = OpTypeVector %float 4
2462 ; CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float
2463 ; CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
2464 ; CHECK: %v4uint = OpTypeVector %uint 4
2465 ; CHECK: %uint_5 = OpConstant %uint 5
2466 ; CHECK: %uint_7 = OpConstant %uint 7
2467 ; CHECK: %uint_8 = OpConstant %uint 8
2468 ; CHECK: %uint_9 = OpConstant %uint 9
2469 ; CHECK: %uint_32 = OpConstant %uint 32
2470 ; CHECK: %104 = OpConstantNull %float
2471 )";
2472   // clang-format on
2473 
2474   const std::string main_func = R"(
2475 %main = OpFunction %void None %3
2476 %5 = OpLabel
2477 %15 = OpAccessChain %_ptr_Uniform_float %uniformBuffer %int_0
2478 %16 = OpLoad %float %15
2479 OpStore %b %16
2480 ; CHECK-NOT: %16 = OpLoad %float %15
2481 ; CHECK-NOT: OpStore %b %16
2482 ; CHECK: %43 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_3 %uint_0
2483 ; CHECK: %45 = OpULessThan %bool %uint_0 %43
2484 ; CHECK: OpSelectionMerge %47 None
2485 ; CHECK: OpBranchConditional %45 %48 %49
2486 ; CHECK: %48 = OpLabel
2487 ; CHECK: %50 = OpLoad %float %15
2488 ; CHECK: OpBranch %47
2489 ; CHECK: %49 = OpLabel
2490 ; CHECK: %103 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_32 %uint_1 %uint_0 %uint_0
2491 ; CHECK: OpBranch %47
2492 ; CHECK: %47 = OpLabel
2493 ; CHECK: %105 = OpPhi %float %50 %48 %104 %49
2494 ; CHECK: OpStore %b %105
2495 OpReturn
2496 OpFunctionEnd
2497 )";
2498 
2499   const std::string new_funcs = kDirectRead4 + kStreamWrite4Frag;
2500 
2501   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
2502   SinglePassRunAndMatch<InstBindlessCheckPass>(defs + main_func + new_funcs,
2503                                                true, 7u, 23u, true, true, false,
2504                                                false, false);
2505 }
2506 
TEST_F(InstBindlessTest,InstBoundsInitStoreUnsizedSSBOArray)2507 TEST_F(InstBindlessTest, InstBoundsInitStoreUnsizedSSBOArray) {
2508   // #version 450
2509   // #extension GL_EXT_nonuniform_qualifier : enable
2510   //
2511   // layout(location=0) in nonuniformEXT flat int nu_ii;
2512   // layout(location=1) in float b;
2513   //
2514   // layout(binding=4)  buffer bname { float b; }  storageBuffer[];
2515   //
2516   // void main()
2517   // {
2518   //     storageBuffer[nu_ii].b = b;
2519   // }
2520 
2521   // clang-format off
2522   const std::string defs = R"(OpCapability Shader
2523 OpCapability ShaderNonUniform
2524 OpCapability RuntimeDescriptorArray
2525 OpCapability StorageBufferArrayNonUniformIndexing
2526 OpExtension "SPV_EXT_descriptor_indexing"
2527 ; CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class"
2528 %1 = OpExtInstImport "GLSL.std.450"
2529 OpMemoryModel Logical GLSL450
2530 OpEntryPoint Fragment %main "main" %nu_ii %b
2531 ; CHECK: OpEntryPoint Fragment %main "main" %nu_ii %b %gl_FragCoord
2532 OpExecutionMode %main OriginUpperLeft
2533 OpSource GLSL 450
2534 OpSourceExtension "GL_EXT_nonuniform_qualifier"
2535 OpName %main "main"
2536 OpName %bname "bname"
2537 OpMemberName %bname 0 "b"
2538 OpName %storageBuffer "storageBuffer"
2539 OpName %nu_ii "nu_ii"
2540 OpName %b "b"
2541 OpMemberDecorate %bname 0 Offset 0
2542 OpDecorate %bname BufferBlock
2543 OpDecorate %storageBuffer DescriptorSet 0
2544 OpDecorate %storageBuffer Binding 4
2545 OpDecorate %nu_ii Flat
2546 OpDecorate %nu_ii Location 0
2547 OpDecorate %nu_ii NonUniform
2548 OpDecorate %14 NonUniform
2549 OpDecorate %b Location 1
2550 ; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
2551 )" + kInputDecorations + kOutputDecorations + R"(
2552 ; CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord
2553 %void = OpTypeVoid
2554 %3 = OpTypeFunction %void
2555 %float = OpTypeFloat 32
2556 %bname = OpTypeStruct %float
2557 %_runtimearr_bname = OpTypeRuntimeArray %bname
2558 %_ptr_Uniform__runtimearr_bname = OpTypePointer Uniform %_runtimearr_bname
2559 %storageBuffer = OpVariable %_ptr_Uniform__runtimearr_bname Uniform
2560 %int = OpTypeInt 32 1
2561 %_ptr_Input_int = OpTypePointer Input %int
2562 %nu_ii = OpVariable %_ptr_Input_int Input
2563 %int_0 = OpConstant %int 0
2564 %_ptr_Input_float = OpTypePointer Input %float
2565 %b = OpVariable %_ptr_Input_float Input
2566 %_ptr_Uniform_float = OpTypePointer Uniform %float
2567 ; CHECK: %uint = OpTypeInt 32 0
2568 ; CHECK: %uint_0 = OpConstant %uint 0
2569 ; CHECK: %uint_1 = OpConstant %uint 1
2570 ; CHECK: %uint_4 = OpConstant %uint 4
2571 ; CHECK: %26 = OpTypeFunction %uint %uint %uint
2572 ; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
2573 )" + kInputGlobals + R"(
2574 ; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
2575 ; CHECK: %bool = OpTypeBool
2576 ; CHECK: %48 = OpTypeFunction %void %uint %uint %uint %uint
2577 )" + kOutputGlobals + R"(
2578 ; CHECK: %uint_10 = OpConstant %uint 10
2579 ; CHECK: %uint_23 = OpConstant %uint 23
2580 ; CHECK: %uint_2 = OpConstant %uint 2
2581 ; CHECK: %uint_3 = OpConstant %uint 3
2582 ; CHECK: %v4float = OpTypeVector %float 4
2583 ; CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float
2584 ; CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
2585 ; CHECK: %v4uint = OpTypeVector %uint 4
2586 ; CHECK: %uint_5 = OpConstant %uint 5
2587 ; CHECK: %uint_7 = OpConstant %uint 7
2588 ; CHECK: %uint_8 = OpConstant %uint 8
2589 ; CHECK: %uint_9 = OpConstant %uint 9
2590 ; CHECK: %uint_45 = OpConstant %uint 45
2591 ; CHECK: %102 = OpTypeFunction %uint %uint %uint %uint %uint
2592 )";
2593   // clang-format on
2594 
2595   const std::string main_func = R"(
2596 %main = OpFunction %void None %3
2597 %5 = OpLabel
2598 %14 = OpLoad %int %nu_ii
2599 %18 = OpLoad %float %b
2600 %20 = OpAccessChain %_ptr_Uniform_float %storageBuffer %14 %int_0
2601 OpStore %20 %18
2602 ; CHECK-NOT: OpStore %20 %18
2603 ; CHECK: %40 = OpFunctionCall %uint %inst_bindless_direct_read_2 %uint_1 %uint_4
2604 ; CHECK: %42 = OpULessThan %bool %7 %40
2605 ; CHECK: OpSelectionMerge %43 None
2606 ; CHECK: OpBranchConditional %42 %44 %45
2607 ; CHECK: %44 = OpLabel
2608 ; CHECK: %100 = OpBitcast %uint %7
2609 ; CHECK: %119 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_4 %100
2610 ; CHECK: %120 = OpULessThan %bool %uint_0 %119
2611 ; CHECK: OpSelectionMerge %121 None
2612 ; CHECK: OpBranchConditional %120 %122 %123
2613 ; CHECK: %122 = OpLabel
2614 ; CHECK: OpStore %20 %19
2615 ; CHECK: OpBranch %121
2616 ; CHECK: %123 = OpLabel
2617 ; CHECK: %124 = OpBitcast %uint %7
2618 ; CHECK: %125 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_45 %uint_1 %124 %uint_0
2619 ; CHECK: OpBranch %121
2620 ; CHECK: %121 = OpLabel
2621 ; CHECK: OpBranch %43
2622 ; CHECK: %45 = OpLabel
2623 ; CHECK: %46 = OpBitcast %uint %7
2624 ; CHECK: %99 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_45 %uint_0 %46 %40
2625 ; CHECK: OpBranch %43
2626 ; CHECK: %43 = OpLabel
2627 OpReturn
2628 OpFunctionEnd
2629 )";
2630 
2631   const std::string new_funcs = kDirectRead2 + kStreamWrite4Frag + kDirectRead4;
2632 
2633   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
2634   SinglePassRunAndMatch<InstBindlessCheckPass>(defs + main_func + new_funcs,
2635                                                true, 7u, 23u, true, true, false,
2636                                                false, false);
2637 }
2638 
TEST_F(InstBindlessTest,InstBoundsInitLoadSizedUBOArray)2639 TEST_F(InstBindlessTest, InstBoundsInitLoadSizedUBOArray) {
2640   // #version 450
2641   // #extension GL_EXT_nonuniform_qualifier : enable
2642   //
2643   // layout(location=0) in nonuniformEXT flat int nu_ii;
2644   // layout(location=0) out float b;
2645   //
2646   // layout(binding=3)  uniform uname { float a; }  uniformBuffer[128];
2647   //
2648   // void main()
2649   // {
2650   //     b = uniformBuffer[nu_ii].a;
2651   // }
2652 
2653   // clang-format off
2654   const std::string defs = R"(
2655 OpCapability Shader
2656 OpCapability ShaderNonUniform
2657 OpCapability UniformBufferArrayNonUniformIndexing
2658 OpExtension "SPV_EXT_descriptor_indexing"
2659 ; CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class"
2660 %1 = OpExtInstImport "GLSL.std.450"
2661 OpMemoryModel Logical GLSL450
2662 OpEntryPoint Fragment %main "main" %b %nu_ii
2663 ; CHECK: OpEntryPoint Fragment %main "main" %b %nu_ii %gl_FragCoord
2664 OpExecutionMode %main OriginUpperLeft
2665 OpSource GLSL 450
2666 OpSourceExtension "GL_EXT_nonuniform_qualifier"
2667 OpName %main "main"
2668 OpName %b "b"
2669 OpName %uname "uname"
2670 OpMemberName %uname 0 "a"
2671 OpName %uniformBuffer "uniformBuffer"
2672 OpName %nu_ii "nu_ii"
2673 OpDecorate %b Location 0
2674 OpMemberDecorate %uname 0 Offset 0
2675 OpDecorate %uname Block
2676 OpDecorate %uniformBuffer DescriptorSet 0
2677 OpDecorate %uniformBuffer Binding 3
2678 OpDecorate %nu_ii Flat
2679 OpDecorate %nu_ii Location 0
2680 OpDecorate %nu_ii NonUniform
2681 OpDecorate %18 NonUniform
2682 OpDecorate %22 NonUniform
2683 ; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
2684 )" + kOutputDecorations + R"(
2685 ; CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord
2686 )" + kInputDecorations + R"(
2687 ; CHECK: OpDecorate %117 NonUniform
2688 %void = OpTypeVoid
2689 %3 = OpTypeFunction %void
2690 %float = OpTypeFloat 32
2691 %_ptr_Output_float = OpTypePointer Output %float
2692 %b = OpVariable %_ptr_Output_float Output
2693 %uname = OpTypeStruct %float
2694 %uint = OpTypeInt 32 0
2695 %uint_128 = OpConstant %uint 128
2696 %_arr_uname_uint_128 = OpTypeArray %uname %uint_128
2697 %_ptr_Uniform__arr_uname_uint_128 = OpTypePointer Uniform %_arr_uname_uint_128
2698 %uniformBuffer = OpVariable %_ptr_Uniform__arr_uname_uint_128 Uniform
2699 %int = OpTypeInt 32 1
2700 %_ptr_Input_int = OpTypePointer Input %int
2701 %nu_ii = OpVariable %_ptr_Input_int Input
2702 %int_0 = OpConstant %int 0
2703 %_ptr_Uniform_float = OpTypePointer Uniform %float
2704 ; CHECK: %uint_0 = OpConstant %uint 0
2705 ; CHECK: %bool = OpTypeBool
2706 ; CHECK: %32 = OpTypeFunction %void %uint %uint %uint %uint
2707 ; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
2708 )" + kOutputGlobals + R"(
2709 ; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
2710 ; CHECK: %uint_10 = OpConstant %uint 10
2711 ; CHECK: %uint_4 = OpConstant %uint 4
2712 ; CHECK: %uint_1 = OpConstant %uint 1
2713 ; CHECK: %uint_23 = OpConstant %uint 23
2714 ; CHECK: %uint_2 = OpConstant %uint 2
2715 ; CHECK: %uint_3 = OpConstant %uint 3
2716 ; CHECK: %v4float = OpTypeVector %float 4
2717 ; CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float
2718 ; CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
2719 ; CHECK: %v4uint = OpTypeVector %uint 4
2720 ; CHECK: %uint_5 = OpConstant %uint 5
2721 ; CHECK: %uint_7 = OpConstant %uint 7
2722 ; CHECK: %uint_8 = OpConstant %uint 8
2723 ; CHECK: %uint_9 = OpConstant %uint 9
2724 ; CHECK: %uint_46 = OpConstant %uint 46
2725 ; CHECK: %88 = OpConstantNull %float
2726 ; CHECK: %92 = OpTypeFunction %uint %uint %uint %uint %uint
2727 )" + kInputGlobals;
2728   // clang-format on
2729 
2730   const std::string main_func = R"(
2731 %main = OpFunction %void None %3
2732 %5 = OpLabel
2733 %18 = OpLoad %int %nu_ii
2734 %21 = OpAccessChain %_ptr_Uniform_float %uniformBuffer %18 %int_0
2735 %22 = OpLoad %float %21
2736 OpStore %b %22
2737 ; CHECK-NOT: %22 = OpLoad %float %21
2738 ; CHECK-NOT: OpStore %b %22
2739 ; CHECK: %25 = OpULessThan %bool %7 %uint_128
2740 ; CHECK: OpSelectionMerge %26 None
2741 ; CHECK: OpBranchConditional %25 %27 %28
2742 ; CHECK: %27 = OpLabel
2743 ; CHECK: %90 = OpBitcast %uint %7
2744 ; CHECK: %112 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_3 %90
2745 ; CHECK: %113 = OpULessThan %bool %uint_0 %112
2746 ; CHECK: OpSelectionMerge %114 None
2747 ; CHECK: OpBranchConditional %113 %115 %116
2748 ; CHECK: %115 = OpLabel
2749 ; CHECK: %117 = OpLoad %float %22
2750 ; CHECK: OpBranch %114
2751 ; CHECK: %116 = OpLabel
2752 ; CHECK: %118 = OpBitcast %uint %7
2753 ; CHECK: %119 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_46 %uint_1 %118 %uint_0
2754 ; CHECK: OpBranch %114
2755 ; CHECK: %114 = OpLabel
2756 ; CHECK: %120 = OpPhi %float %117 %115 %88 %116
2757 ; CHECK: OpBranch %26
2758 ; CHECK: %28 = OpLabel
2759 ; CHECK: %30 = OpBitcast %uint %7
2760 ; CHECK: %87 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_46 %uint_0 %30 %uint_128
2761 ; CHECK: OpBranch %26
2762 ; CHECK: %26 = OpLabel
2763 ; CHECK: %89 = OpPhi %float %120 %114 %88 %28
2764 ; CHECK: OpStore %b %89
2765 OpReturn
2766 OpFunctionEnd
2767 )";
2768 
2769   const std::string new_funcs = kStreamWrite4Frag + kDirectRead4;
2770 
2771   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
2772   SinglePassRunAndMatch<InstBindlessCheckPass>(defs + main_func + new_funcs,
2773                                                true, 7u, 23u, true, true, false,
2774                                                false, false);
2775 }
2776 
TEST_F(InstBindlessTest,InstBoundsComputeShaderInitLoadVariableSizedSampledImagesArray)2777 TEST_F(InstBindlessTest,
2778        InstBoundsComputeShaderInitLoadVariableSizedSampledImagesArray) {
2779   // #version 450
2780   // #extension GL_EXT_nonuniform_qualifier : enable
2781   //
2782   // layout (local_size_x = 1, local_size_y = 1) in;
2783   //
2784   // layout(set = 0, binding = 0, std140) buffer Input {
2785   //   uint index;
2786   //   float red;
2787   // } sbo;
2788   //
2789   // layout(set = 0, binding = 1, rgba32f) readonly uniform image2D images[];
2790   //
2791   // void main()
2792   // {
2793   //    sbo.red = imageLoad(images[sbo.index], ivec2(0, 0)).r;
2794   // }
2795 
2796   // clang-format off
2797   const std::string defs = R"(
2798 OpCapability Shader
2799 OpCapability RuntimeDescriptorArray
2800 OpExtension "SPV_EXT_descriptor_indexing"
2801 ; CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class"
2802 %1 = OpExtInstImport "GLSL.std.450"
2803 OpMemoryModel Logical GLSL450
2804 OpEntryPoint GLCompute %main "main"
2805 ; CHECK: OpEntryPoint GLCompute %main "main" %gl_GlobalInvocationID
2806 OpExecutionMode %main LocalSize 1 1 1
2807 OpSource GLSL 450
2808 OpSourceExtension "GL_EXT_nonuniform_qualifier"
2809 OpName %main "main"
2810 OpName %Input "Input"
2811 OpMemberName %Input 0 "index"
2812 OpMemberName %Input 1 "red"
2813 OpName %sbo "sbo"
2814 OpName %images "images"
2815 OpMemberDecorate %Input 0 Offset 0
2816 OpMemberDecorate %Input 1 Offset 4
2817 OpDecorate %Input BufferBlock
2818 OpDecorate %sbo DescriptorSet 0
2819 OpDecorate %sbo Binding 0
2820 OpDecorate %images DescriptorSet 0
2821 OpDecorate %images Binding 1
2822 OpDecorate %images NonWritable
2823 ; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
2824 )" + kInputDecorations + kOutputDecorations + R"(
2825 ; CHECK: OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
2826 %void = OpTypeVoid
2827 %3 = OpTypeFunction %void
2828 %uint = OpTypeInt 32 0
2829 %float = OpTypeFloat 32
2830 %Input = OpTypeStruct %uint %float
2831 %_ptr_Uniform_Input = OpTypePointer Uniform %Input
2832 %sbo = OpVariable %_ptr_Uniform_Input Uniform
2833 %int = OpTypeInt 32 1
2834 %int_1 = OpConstant %int 1
2835 %13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f
2836 %_runtimearr_13 = OpTypeRuntimeArray %13
2837 %_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13
2838 %images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant
2839 %int_0 = OpConstant %int 0
2840 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
2841 %_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
2842 %v2int = OpTypeVector %int 2
2843 %25 = OpConstantComposite %v2int %int_0 %int_0
2844 %v4float = OpTypeVector %float 4
2845 %uint_0 = OpConstant %uint 0
2846 %_ptr_Uniform_float = OpTypePointer Uniform %float
2847 ; CHECK: %uint_1 = OpConstant %uint 1
2848 ; CHECK: %34 = OpTypeFunction %uint %uint %uint
2849 ; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
2850 )" + kInputGlobals + R"(
2851 ; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
2852 ; CHECK: %bool = OpTypeBool
2853 ; CHECK: %57 = OpTypeFunction %void %uint %uint %uint %uint
2854 )" + kOutputGlobals + R"(
2855 ; CHECK: %uint_10 = OpConstant %uint 10
2856 ; CHECK: %uint_4 = OpConstant %uint 4
2857 ; CHECK: %uint_23 = OpConstant %uint 23
2858 ; CHECK: %uint_2 = OpConstant %uint 2
2859 ; CHECK: %uint_5 = OpConstant %uint 5
2860 ; CHECK: %uint_3 = OpConstant %uint 3
2861 ; CHECK: %v3uint = OpTypeVector %uint 3
2862 ; CHECK: %_ptr_Input_v3uint = OpTypePointer Input %v3uint
2863 ; CHECK: %gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
2864 ; CHECK: %uint_6 = OpConstant %uint 6
2865 ; CHECK: %uint_7 = OpConstant %uint 7
2866 ; CHECK: %uint_8 = OpConstant %uint 8
2867 ; CHECK: %uint_9 = OpConstant %uint 9
2868 ; CHECK: %uint_50 = OpConstant %uint 50
2869 ; CHECK: %112 = OpConstantNull %v4float
2870 ; CHECK: %115 = OpTypeFunction %uint %uint %uint %uint %uint
2871 ; CHECK: %uint_47 = OpConstant %uint 47
2872 ; CHECK: %140 = OpConstantNull %uint
2873 ; CHECK: %uint_53 = OpConstant %uint 53
2874 )";
2875   // clang-format on
2876 
2877   const std::string main_func = R"(
2878 %main = OpFunction %void None %3
2879 %5 = OpLabel
2880 %19 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0
2881 %20 = OpLoad %uint %19
2882 %22 = OpAccessChain %_ptr_UniformConstant_13 %images %20
2883 %23 = OpLoad %13 %22
2884 %27 = OpImageRead %v4float %23 %25
2885 %29 = OpCompositeExtract %float %27 0
2886 %31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1
2887 OpStore %31 %29
2888 ; CHECK-NOT: OpStore %31 %29
2889 ; CHECK: %132 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_0 %uint_0
2890 ; CHECK: %133 = OpULessThan %bool %uint_0 %132
2891 ; CHECK: OpSelectionMerge %134 None
2892 ; CHECK: OpBranchConditional %133 %135 %136
2893 ; CHECK: %135 = OpLabel
2894 ; CHECK: %137 = OpLoad %uint %25
2895 ; CHECK: OpBranch %134
2896 ; CHECK: %136 = OpLabel
2897 ; CHECK: %139 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_47 %uint_1 %uint_0 %uint_0
2898 ; CHECK: OpBranch %134
2899 ; CHECK: %134 = OpLabel
2900 ; CHECK: %141 = OpPhi %uint %137 %135 %140 %136
2901 ; CHECK: %27 = OpAccessChain %_ptr_UniformConstant_13 %images %141
2902 ; CHECK: %28 = OpLoad %13 %27
2903 ; CHECK: %48 = OpFunctionCall %uint %inst_bindless_direct_read_2 %uint_1 %uint_1
2904 ; CHECK: %50 = OpULessThan %bool %141 %48
2905 ; CHECK: OpSelectionMerge %51 None
2906 ; CHECK: OpBranchConditional %50 %52 %53
2907 ; CHECK: %52 = OpLabel
2908 ; CHECK: %54 = OpLoad %13 %27
2909 ; CHECK: %142 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_1 %141
2910 ; CHECK: %143 = OpULessThan %bool %uint_0 %142
2911 ; CHECK: OpSelectionMerge %144 None
2912 ; CHECK: OpBranchConditional %143 %145 %146
2913 ; CHECK: %145 = OpLabel
2914 ; CHECK: %147 = OpLoad %13 %27
2915 ; CHECK: %148 = OpImageRead %v4float %147 %20
2916 ; CHECK: OpBranch %144
2917 ; CHECK: %146 = OpLabel
2918 ; CHECK: %149 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_50 %uint_1 %141 %uint_0
2919 ; CHECK: OpBranch %144
2920 ; CHECK: %144 = OpLabel
2921 ; CHECK: %150 = OpPhi %v4float %148 %145 %112 %146
2922 ; CHECK: OpBranch %51
2923 ; CHECK: %53 = OpLabel
2924 ; CHECK: %111 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_50 %uint_0 %141 %48
2925 ; CHECK: OpBranch %51
2926 ; CHECK: %51 = OpLabel
2927 ; CHECK: %113 = OpPhi %v4float %150 %144 %112 %53
2928 ; CHECK: %30 = OpCompositeExtract %float %113 0
2929 ; CHECK: %31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1
2930 ; CHECK: %151 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_0 %uint_0
2931 ; CHECK: %152 = OpULessThan %bool %uint_0 %151
2932 ; CHECK: OpSelectionMerge %153 None
2933 ; CHECK: OpBranchConditional %152 %154 %155
2934 ; CHECK: %154 = OpLabel
2935 ; CHECK: OpStore %31 %30
2936 ; CHECK: OpBranch %153
2937 ; CHECK: %155 = OpLabel
2938 ; CHECK: %157 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_53 %uint_1 %uint_0 %uint_0
2939 ; CHECK: OpBranch %153
2940 ; CHECK: %153 = OpLabel
2941 OpReturn
2942 OpFunctionEnd
2943 )";
2944 
2945   const std::string new_funcs =
2946       kDirectRead2 + kStreamWrite4Compute + kDirectRead4;
2947 
2948   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
2949   SinglePassRunAndMatch<InstBindlessCheckPass>(defs + main_func + new_funcs,
2950                                                true, 7u, 23u, true, true, false,
2951                                                false, false);
2952 }
2953 
TEST_F(InstBindlessTest,InstBoundsRayGenerationInitLoadVariableSizedSampledImagesArray)2954 TEST_F(InstBindlessTest,
2955        InstBoundsRayGenerationInitLoadVariableSizedSampledImagesArray) {
2956   // #version 460
2957   // #extension GL_EXT_nonuniform_qualifier : require
2958   // #extension GL_NV_ray_tracing : require
2959   //
2960   // layout(set = 0, binding = 0, std140) buffer StorageBuffer {
2961   //   uint index;
2962   //   float red;
2963   // } sbo;
2964   //
2965   // layout(set = 0, binding = 1, rgba32f) readonly uniform image2D images[];
2966   //
2967   // void main()
2968   // {
2969   //    sbo.red = imageLoad(images[sbo.index], ivec2(0, 0)).r;
2970   // }
2971 
2972   // clang-format off
2973   const std::string defs = R"(
2974 OpCapability RuntimeDescriptorArray
2975 OpCapability RayTracingNV
2976 OpExtension "SPV_EXT_descriptor_indexing"
2977 OpExtension "SPV_NV_ray_tracing"
2978 ; CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class"
2979 %1 = OpExtInstImport "GLSL.std.450"
2980 OpMemoryModel Logical GLSL450
2981 OpEntryPoint RayGenerationNV %main "main"
2982 ; CHECK: OpEntryPoint RayGenerationNV %main "main" %89
2983 OpSource GLSL 460
2984 OpSourceExtension "GL_EXT_nonuniform_qualifier"
2985 OpSourceExtension "GL_NV_ray_tracing"
2986 OpName %main "main"
2987 OpName %StorageBuffer "StorageBuffer"
2988 OpMemberName %StorageBuffer 0 "index"
2989 OpMemberName %StorageBuffer 1 "red"
2990 OpName %sbo "sbo"
2991 OpName %images "images"
2992 OpMemberDecorate %StorageBuffer 0 Offset 0
2993 OpMemberDecorate %StorageBuffer 1 Offset 4
2994 OpDecorate %StorageBuffer BufferBlock
2995 OpDecorate %sbo DescriptorSet 0
2996 OpDecorate %sbo Binding 0
2997 OpDecorate %images DescriptorSet 0
2998 OpDecorate %images Binding 1
2999 OpDecorate %images NonWritable
3000 ; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
3001 )" + kInputDecorations + kOutputDecorations + R"(
3002 ; CHECK: OpDecorate %89 BuiltIn LaunchIdNV
3003 %void = OpTypeVoid
3004 %3 = OpTypeFunction %void
3005 %uint = OpTypeInt 32 0
3006 %float = OpTypeFloat 32
3007 %StorageBuffer = OpTypeStruct %uint %float
3008 %_ptr_Uniform_StorageBuffer = OpTypePointer Uniform %StorageBuffer
3009 %sbo = OpVariable %_ptr_Uniform_StorageBuffer Uniform
3010 %int = OpTypeInt 32 1
3011 %int_1 = OpConstant %int 1
3012 %13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f
3013 %_runtimearr_13 = OpTypeRuntimeArray %13
3014 %_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13
3015 %images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant
3016 %int_0 = OpConstant %int 0
3017 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
3018 %_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
3019 %v2int = OpTypeVector %int 2
3020 %25 = OpConstantComposite %v2int %int_0 %int_0
3021 %v4float = OpTypeVector %float 4
3022 %uint_0 = OpConstant %uint 0
3023 %_ptr_Uniform_float = OpTypePointer Uniform %float
3024 ; CHECK: %uint_1 = OpConstant %uint 1
3025 ; CHECK: %34 = OpTypeFunction %uint %uint %uint
3026 ; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
3027 )" + kInputGlobals + R"(
3028 ; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
3029 ; CHECK: %bool = OpTypeBool
3030 ; CHECK: %57 = OpTypeFunction %void %uint %uint %uint %uint
3031 )" + kOutputGlobals + R"(
3032 ; CHECK: %uint_10 = OpConstant %uint 10
3033 ; CHECK: %uint_4 = OpConstant %uint 4
3034 ; CHECK: %uint_23 = OpConstant %uint 23
3035 ; CHECK: %uint_2 = OpConstant %uint 2
3036 ; CHECK: %uint_5313 = OpConstant %uint 5313
3037 ; CHECK: %uint_3 = OpConstant %uint 3
3038 ; CHECK: %v3uint = OpTypeVector %uint 3
3039 ; CHECK: %_ptr_Input_v3uint = OpTypePointer Input %v3uint
3040 ; CHECK: %89 = OpVariable %_ptr_Input_v3uint Input
3041 ; CHECK: %uint_5 = OpConstant %uint 5
3042 ; CHECK: %uint_6 = OpConstant %uint 6
3043 ; CHECK: %uint_7 = OpConstant %uint 7
3044 ; CHECK: %uint_8 = OpConstant %uint 8
3045 ; CHECK: %uint_9 = OpConstant %uint 9
3046 ; CHECK: %uint_51 = OpConstant %uint 51
3047 ; CHECK: %113 = OpConstantNull %v4float
3048 ; CHECK: %116 = OpTypeFunction %uint %uint %uint %uint %uint
3049 ; CHECK: %uint_48 = OpConstant %uint 48
3050 ; CHECK: %141 = OpConstantNull %uint
3051 ; CHECK: %uint_54 = OpConstant %uint 54
3052 )";
3053   // clang-format on
3054 
3055   const std::string main_func = R"(
3056 %main = OpFunction %void None %3
3057 %5 = OpLabel
3058 %19 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0
3059 %20 = OpLoad %uint %19
3060 %22 = OpAccessChain %_ptr_UniformConstant_13 %images %20
3061 %23 = OpLoad %13 %22
3062 %27 = OpImageRead %v4float %23 %25
3063 %29 = OpCompositeExtract %float %27 0
3064 %31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1
3065 OpStore %31 %29
3066 ; CHECK-NOT: OpStore %31 %29
3067 ; CHECK: %133 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_0 %uint_0
3068 ; CHECK: %134 = OpULessThan %bool %uint_0 %133
3069 ; CHECK: OpSelectionMerge %135 None
3070 ; CHECK: OpBranchConditional %134 %136 %137
3071 ; CHECK: %136 = OpLabel
3072 ; CHECK: %138 = OpLoad %uint %25
3073 ; CHECK: OpBranch %135
3074 ; CHECK: %137 = OpLabel
3075 ; CHECK: %140 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_48 %uint_1 %uint_0 %uint_0
3076 ; CHECK: OpBranch %135
3077 ; CHECK: %135 = OpLabel
3078 ; CHECK: %142 = OpPhi %uint %138 %136 %141 %137
3079 ; CHECK: %27 = OpAccessChain %_ptr_UniformConstant_13 %images %142
3080 ; CHECK: %28 = OpLoad %13 %27
3081 ; CHECK: %48 = OpFunctionCall %uint %inst_bindless_direct_read_2 %uint_1 %uint_1
3082 ; CHECK: %50 = OpULessThan %bool %142 %48
3083 ; CHECK: OpSelectionMerge %51 None
3084 ; CHECK: OpBranchConditional %50 %52 %53
3085 ; CHECK: %52 = OpLabel
3086 ; CHECK: %54 = OpLoad %13 %27
3087 ; CHECK: %143 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_1 %142
3088 ; CHECK: %144 = OpULessThan %bool %uint_0 %143
3089 ; CHECK: OpSelectionMerge %145 None
3090 ; CHECK: OpBranchConditional %144 %146 %147
3091 ; CHECK: %146 = OpLabel
3092 ; CHECK: %148 = OpLoad %13 %27
3093 ; CHECK: %149 = OpImageRead %v4float %148 %20
3094 ; CHECK: OpBranch %145
3095 ; CHECK: %147 = OpLabel
3096 ; CHECK: %150 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_51 %uint_1 %142 %uint_0
3097 ; CHECK: OpBranch %145
3098 ; CHECK: %145 = OpLabel
3099 ; CHECK: %151 = OpPhi %v4float %149 %146 %113 %147
3100 ; CHECK: OpBranch %51
3101 ; CHECK: %53 = OpLabel
3102 ; CHECK: %112 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_51 %uint_0 %142 %48
3103 ; CHECK: OpBranch %51
3104 ; CHECK: %51 = OpLabel
3105 ; CHECK: %114 = OpPhi %v4float %151 %145 %113 %53
3106 ; CHECK: %30 = OpCompositeExtract %float %114 0
3107 ; CHECK: %31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1
3108 ; CHECK: %152 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_0 %uint_0
3109 ; CHECK: %153 = OpULessThan %bool %uint_0 %152
3110 ; CHECK: OpSelectionMerge %154 None
3111 ; CHECK: OpBranchConditional %153 %155 %156
3112 ; CHECK: %155 = OpLabel
3113 ; CHECK: OpStore %31 %30
3114 ; CHECK: OpBranch %154
3115 ; CHECK: %156 = OpLabel
3116 ; CHECK: %158 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_54 %uint_1 %uint_0 %uint_0
3117 ; CHECK: OpBranch %154
3118 ; CHECK: %154 = OpLabel
3119 OpReturn
3120 OpFunctionEnd
3121 )";
3122 
3123   const std::string new_funcs = kDirectRead2 + kStreamWrite4Ray + kDirectRead4;
3124 
3125   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
3126   SinglePassRunAndMatch<InstBindlessCheckPass>(defs + main_func + new_funcs,
3127                                                true, 7u, 23u, true, true, false,
3128                                                false, false);
3129 }
3130 
TEST_F(InstBindlessTest,InstBoundsIntersectionInitLoadVariableSizedSampledImagesArray)3131 TEST_F(InstBindlessTest,
3132        InstBoundsIntersectionInitLoadVariableSizedSampledImagesArray) {
3133   // #version 460
3134   // #extension GL_EXT_nonuniform_qualifier : require
3135   // #extension GL_NV_ray_tracing : require
3136   //
3137   // layout(set = 0, binding = 0, std140) buffer StorageBuffer {
3138   //   uint index;
3139   //   float red;
3140   // } sbo;
3141   //
3142   // layout(set = 0, binding = 1, rgba32f) readonly uniform image2D images[];
3143   //
3144   // void main()
3145   // {
3146   //    sbo.red = imageLoad(images[sbo.index], ivec2(0, 0)).r;
3147   // }
3148 
3149   // clang-format off
3150   const std::string defs = R"(
3151 OpCapability RuntimeDescriptorArray
3152 OpCapability RayTracingNV
3153 OpExtension "SPV_EXT_descriptor_indexing"
3154 OpExtension "SPV_NV_ray_tracing"
3155 ; CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class"
3156 %1 = OpExtInstImport "GLSL.std.450"
3157 OpMemoryModel Logical GLSL450
3158 OpEntryPoint IntersectionNV %main "main"
3159 ; CHECK: OpEntryPoint IntersectionNV %main "main" %89
3160 OpSource GLSL 460
3161 OpSourceExtension "GL_EXT_nonuniform_qualifier"
3162 OpSourceExtension "GL_NV_ray_tracing"
3163 OpName %main "main"
3164 OpName %StorageBuffer "StorageBuffer"
3165 OpMemberName %StorageBuffer 0 "index"
3166 OpMemberName %StorageBuffer 1 "red"
3167 OpName %sbo "sbo"
3168 OpName %images "images"
3169 OpMemberDecorate %StorageBuffer 0 Offset 0
3170 OpMemberDecorate %StorageBuffer 1 Offset 4
3171 OpDecorate %StorageBuffer BufferBlock
3172 OpDecorate %sbo DescriptorSet 0
3173 OpDecorate %sbo Binding 0
3174 OpDecorate %images DescriptorSet 0
3175 OpDecorate %images Binding 1
3176 OpDecorate %images NonWritable
3177 ; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
3178 )" + kInputDecorations + kOutputDecorations + R"(
3179 ; CHECK: OpDecorate %89 BuiltIn LaunchIdNV
3180 %void = OpTypeVoid
3181 %3 = OpTypeFunction %void
3182 %uint = OpTypeInt 32 0
3183 %float = OpTypeFloat 32
3184 %StorageBuffer = OpTypeStruct %uint %float
3185 %_ptr_Uniform_StorageBuffer = OpTypePointer Uniform %StorageBuffer
3186 %sbo = OpVariable %_ptr_Uniform_StorageBuffer Uniform
3187 %int = OpTypeInt 32 1
3188 %int_1 = OpConstant %int 1
3189 %13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f
3190 %_runtimearr_13 = OpTypeRuntimeArray %13
3191 %_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13
3192 %images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant
3193 %int_0 = OpConstant %int 0
3194 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
3195 %_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
3196 %v2int = OpTypeVector %int 2
3197 %25 = OpConstantComposite %v2int %int_0 %int_0
3198 %v4float = OpTypeVector %float 4
3199 %uint_0 = OpConstant %uint 0
3200 %_ptr_Uniform_float = OpTypePointer Uniform %float
3201 ; CHECK: %uint_1 = OpConstant %uint 1
3202 ; CHECK: %34 = OpTypeFunction %uint %uint %uint
3203 ; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
3204 )" + kInputGlobals + R"(
3205 ; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
3206 ; CHECK: %bool = OpTypeBool
3207 )" + kOutputGlobals + R"(
3208 ; CHECK: %uint_10 = OpConstant %uint 10
3209 ; CHECK: %uint_4 = OpConstant %uint 4
3210 ; CHECK: %uint_23 = OpConstant %uint 23
3211 ; CHECK: %uint_2 = OpConstant %uint 2
3212 ; CHECK: %uint_5314 = OpConstant %uint 5314
3213 ; CHECK: %uint_3 = OpConstant %uint 3
3214 ; CHECK: %v3uint = OpTypeVector %uint 3
3215 ; CHECK: %_ptr_Input_v3uint = OpTypePointer Input %v3uint
3216 ; CHECK: %89 = OpVariable %_ptr_Input_v3uint Input
3217 ; CHECK: %uint_5 = OpConstant %uint 5
3218 ; CHECK: %uint_6 = OpConstant %uint 6
3219 ; CHECK: %uint_7 = OpConstant %uint 7
3220 ; CHECK: %uint_8 = OpConstant %uint 8
3221 ; CHECK: %uint_9 = OpConstant %uint 9
3222 ; CHECK: %uint_51 = OpConstant %uint 51
3223 ; CHECK: %113 = OpConstantNull %v4float
3224 ; CHECK: %116 = OpTypeFunction %uint %uint %uint %uint %uint
3225 ; CHECK: %uint_48 = OpConstant %uint 48
3226 ; CHECK: %141 = OpConstantNull %uint
3227 ; CHECK: %uint_54 = OpConstant %uint 54
3228 )";
3229   // clang-format on
3230 
3231   const std::string main_func = R"(
3232 %main = OpFunction %void None %3
3233 %5 = OpLabel
3234 %19 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0
3235 %20 = OpLoad %uint %19
3236 %22 = OpAccessChain %_ptr_UniformConstant_13 %images %20
3237 %23 = OpLoad %13 %22
3238 %27 = OpImageRead %v4float %23 %25
3239 %29 = OpCompositeExtract %float %27 0
3240 %31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1
3241 OpStore %31 %29
3242 ; CHECK-NOT: OpStore %31 %29
3243 ; CHECK: %133 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_0 %uint_0
3244 ; CHECK: %134 = OpULessThan %bool %uint_0 %133
3245 ; CHECK: OpSelectionMerge %135 None
3246 ; CHECK: OpBranchConditional %134 %136 %137
3247 ; CHECK: %136 = OpLabel
3248 ; CHECK: %138 = OpLoad %uint %25
3249 ; CHECK: OpBranch %135
3250 ; CHECK: %137 = OpLabel
3251 ; CHECK: %140 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_48 %uint_1 %uint_0 %uint_0
3252 ; CHECK: OpBranch %135
3253 ; CHECK: %135 = OpLabel
3254 ; CHECK: %142 = OpPhi %uint %138 %136 %141 %137
3255 ; CHECK: %27 = OpAccessChain %_ptr_UniformConstant_13 %images %142
3256 ; CHECK: %28 = OpLoad %13 %27
3257 ; CHECK: %48 = OpFunctionCall %uint %inst_bindless_direct_read_2 %uint_1 %uint_1
3258 ; CHECK: %50 = OpULessThan %bool %142 %48
3259 ; CHECK: OpSelectionMerge %51 None
3260 ; CHECK: OpBranchConditional %50 %52 %53
3261 ; CHECK: %52 = OpLabel
3262 ; CHECK: %54 = OpLoad %13 %27
3263 ; CHECK: %143 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_1 %142
3264 ; CHECK: %144 = OpULessThan %bool %uint_0 %143
3265 ; CHECK: OpSelectionMerge %145 None
3266 ; CHECK: OpBranchConditional %144 %146 %147
3267 ; CHECK: %146 = OpLabel
3268 ; CHECK: %148 = OpLoad %13 %27
3269 ; CHECK: %149 = OpImageRead %v4float %148 %20
3270 ; CHECK: OpBranch %145
3271 ; CHECK: %147 = OpLabel
3272 ; CHECK: %150 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_51 %uint_1 %142 %uint_0
3273 ; CHECK: OpBranch %145
3274 ; CHECK: %145 = OpLabel
3275 ; CHECK: %151 = OpPhi %v4float %149 %146 %113 %147
3276 ; CHECK: OpBranch %51
3277 ; CHECK: %53 = OpLabel
3278 ; CHECK: %112 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_51 %uint_0 %142 %48
3279 ; CHECK: OpBranch %51
3280 ; CHECK: %51 = OpLabel
3281 ; CHECK: %114 = OpPhi %v4float %151 %145 %113 %53
3282 ; CHECK: %30 = OpCompositeExtract %float %114 0
3283 ; CHECK: %31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1
3284 ; CHECK: %152 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_0 %uint_0
3285 ; CHECK: %153 = OpULessThan %bool %uint_0 %152
3286 ; CHECK: OpSelectionMerge %154 None
3287 ; CHECK: OpBranchConditional %153 %155 %156
3288 ; CHECK: %155 = OpLabel
3289 ; CHECK: OpStore %31 %30
3290 ; CHECK: OpBranch %154
3291 ; CHECK: %156 = OpLabel
3292 ; CHECK: %158 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_54 %uint_1 %uint_0 %uint_0
3293 ; CHECK: OpBranch %154
3294 ; CHECK: %154 = OpLabel
3295 OpReturn
3296 OpFunctionEnd
3297 )";
3298 
3299   const std::string new_funcs = kDirectRead2 + kStreamWrite4Ray + kDirectRead4;
3300 
3301   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
3302   SinglePassRunAndMatch<InstBindlessCheckPass>(defs + main_func + new_funcs,
3303                                                true, 7u, 23u, true, true, false,
3304                                                false, false);
3305 }
3306 
TEST_F(InstBindlessTest,InstBoundsAnyHitInitLoadVariableSizedSampledImagesArray)3307 TEST_F(InstBindlessTest,
3308        InstBoundsAnyHitInitLoadVariableSizedSampledImagesArray) {
3309   // #version 460
3310   // #extension GL_EXT_nonuniform_qualifier : require
3311   // #extension GL_NV_ray_tracing : require
3312   //
3313   // layout(set = 0, binding = 0, std140) buffer StorageBuffer {
3314   //   uint index;
3315   //   float red;
3316   // } sbo;
3317   //
3318   // layout(set = 0, binding = 1, rgba32f) readonly uniform image2D images[];
3319   //
3320   // void main()
3321   // {
3322   //    sbo.red = imageLoad(images[sbo.index], ivec2(0, 0)).r;
3323   // }
3324 
3325   // clang-format off
3326   const std::string defs = R"(
3327 OpCapability RuntimeDescriptorArray
3328 OpCapability RayTracingNV
3329 OpExtension "SPV_EXT_descriptor_indexing"
3330 OpExtension "SPV_NV_ray_tracing"
3331 ; CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class"
3332 %1 = OpExtInstImport "GLSL.std.450"
3333 OpMemoryModel Logical GLSL450
3334 OpEntryPoint AnyHitNV %main "main"
3335 ; CHECK: OpEntryPoint AnyHitNV %main "main" %89
3336 OpSource GLSL 460
3337 OpSourceExtension "GL_EXT_nonuniform_qualifier"
3338 OpSourceExtension "GL_NV_ray_tracing"
3339 OpName %main "main"
3340 OpName %StorageBuffer "StorageBuffer"
3341 OpMemberName %StorageBuffer 0 "index"
3342 OpMemberName %StorageBuffer 1 "red"
3343 OpName %sbo "sbo"
3344 OpName %images "images"
3345 OpMemberDecorate %StorageBuffer 0 Offset 0
3346 OpMemberDecorate %StorageBuffer 1 Offset 4
3347 OpDecorate %StorageBuffer BufferBlock
3348 OpDecorate %sbo DescriptorSet 0
3349 OpDecorate %sbo Binding 0
3350 OpDecorate %images DescriptorSet 0
3351 OpDecorate %images Binding 1
3352 OpDecorate %images NonWritable
3353 ; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
3354 )" + kInputDecorations + kOutputDecorations + R"(
3355 ; CHECK: OpDecorate %89 BuiltIn LaunchIdNV
3356 %void = OpTypeVoid
3357 %3 = OpTypeFunction %void
3358 %uint = OpTypeInt 32 0
3359 %float = OpTypeFloat 32
3360 %StorageBuffer = OpTypeStruct %uint %float
3361 %_ptr_Uniform_StorageBuffer = OpTypePointer Uniform %StorageBuffer
3362 %sbo = OpVariable %_ptr_Uniform_StorageBuffer Uniform
3363 %int = OpTypeInt 32 1
3364 %int_1 = OpConstant %int 1
3365 %13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f
3366 %_runtimearr_13 = OpTypeRuntimeArray %13
3367 %_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13
3368 %images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant
3369 %int_0 = OpConstant %int 0
3370 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
3371 %_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
3372 %v2int = OpTypeVector %int 2
3373 %25 = OpConstantComposite %v2int %int_0 %int_0
3374 %v4float = OpTypeVector %float 4
3375 %uint_0 = OpConstant %uint 0
3376 %_ptr_Uniform_float = OpTypePointer Uniform %float
3377 ; CHECK: %uint_1 = OpConstant %uint 1
3378 ; CHECK: %34 = OpTypeFunction %uint %uint %uint
3379 ; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
3380 )" + kInputGlobals + R"(
3381 ; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
3382 ; CHECK: %bool = OpTypeBool
3383 ; CHECK: %57 = OpTypeFunction %void %uint %uint %uint %uint
3384 )" + kOutputGlobals + R"(
3385 ; CHECK: %uint_10 = OpConstant %uint 10
3386 ; CHECK: %uint_4 = OpConstant %uint 4
3387 ; CHECK: %uint_23 = OpConstant %uint 23
3388 ; CHECK: %uint_2 = OpConstant %uint 2
3389 ; CHECK: %uint_5315 = OpConstant %uint 5315
3390 ; CHECK: %uint_3 = OpConstant %uint 3
3391 ; CHECK: %v3uint = OpTypeVector %uint 3
3392 ; CHECK: %_ptr_Input_v3uint = OpTypePointer Input %v3uint
3393 ; CHECK: %89 = OpVariable %_ptr_Input_v3uint Input
3394 ; CHECK: %uint_5 = OpConstant %uint 5
3395 ; CHECK: %uint_6 = OpConstant %uint 6
3396 ; CHECK: %uint_7 = OpConstant %uint 7
3397 ; CHECK: %uint_8 = OpConstant %uint 8
3398 ; CHECK: %uint_9 = OpConstant %uint 9
3399 ; CHECK: %uint_51 = OpConstant %uint 51
3400 ; CHECK: %113 = OpConstantNull %v4float
3401 ; CHECK: %116 = OpTypeFunction %uint %uint %uint %uint %uint
3402 ; CHECK: %uint_48 = OpConstant %uint 48
3403 ; CHECK: %141 = OpConstantNull %uint
3404 ; CHECK: %uint_54 = OpConstant %uint 54
3405 )";
3406   // clang-format on
3407 
3408   const std::string main_func = R"(
3409 %main = OpFunction %void None %3
3410 %5 = OpLabel
3411 %19 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0
3412 %20 = OpLoad %uint %19
3413 %22 = OpAccessChain %_ptr_UniformConstant_13 %images %20
3414 %23 = OpLoad %13 %22
3415 %27 = OpImageRead %v4float %23 %25
3416 %29 = OpCompositeExtract %float %27 0
3417 %31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1
3418 OpStore %31 %29
3419 ; CHECK-NOT: OpStore %31 %29
3420 ; CHECK: %133 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_0 %uint_0
3421 ; CHECK: %134 = OpULessThan %bool %uint_0 %133
3422 ; CHECK: OpSelectionMerge %135 None
3423 ; CHECK: OpBranchConditional %134 %136 %137
3424 ; CHECK: %136 = OpLabel
3425 ; CHECK: %138 = OpLoad %uint %25
3426 ; CHECK: OpBranch %135
3427 ; CHECK: %137 = OpLabel
3428 ; CHECK: %140 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_48 %uint_1 %uint_0 %uint_0
3429 ; CHECK: OpBranch %135
3430 ; CHECK: %135 = OpLabel
3431 ; CHECK: %142 = OpPhi %uint %138 %136 %141 %137
3432 ; CHECK: %27 = OpAccessChain %_ptr_UniformConstant_13 %images %142
3433 ; CHECK: %28 = OpLoad %13 %27
3434 ; CHECK: %48 = OpFunctionCall %uint %inst_bindless_direct_read_2 %uint_1 %uint_1
3435 ; CHECK: %50 = OpULessThan %bool %142 %48
3436 ; CHECK: OpSelectionMerge %51 None
3437 ; CHECK: OpBranchConditional %50 %52 %53
3438 ; CHECK: %52 = OpLabel
3439 ; CHECK: %54 = OpLoad %13 %27
3440 ; CHECK: %143 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_1 %142
3441 ; CHECK: %144 = OpULessThan %bool %uint_0 %143
3442 ; CHECK: OpSelectionMerge %145 None
3443 ; CHECK: OpBranchConditional %144 %146 %147
3444 ; CHECK: %146 = OpLabel
3445 ; CHECK: %148 = OpLoad %13 %27
3446 ; CHECK: %149 = OpImageRead %v4float %148 %20
3447 ; CHECK: OpBranch %145
3448 ; CHECK: %147 = OpLabel
3449 ; CHECK: %150 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_51 %uint_1 %142 %uint_0
3450 ; CHECK: OpBranch %145
3451 ; CHECK: %145 = OpLabel
3452 ; CHECK: %151 = OpPhi %v4float %149 %146 %113 %147
3453 ; CHECK: OpBranch %51
3454 ; CHECK: %53 = OpLabel
3455 ; CHECK: %112 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_51 %uint_0 %142 %48
3456 ; CHECK: OpBranch %51
3457 ; CHECK: %51 = OpLabel
3458 ; CHECK: %114 = OpPhi %v4float %151 %145 %113 %53
3459 ; CHECK: %30 = OpCompositeExtract %float %114 0
3460 ; CHECK: %31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1
3461 ; CHECK: %152 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_0 %uint_0
3462 ; CHECK: %153 = OpULessThan %bool %uint_0 %152
3463 ; CHECK: OpSelectionMerge %154 None
3464 ; CHECK: OpBranchConditional %153 %155 %156
3465 ; CHECK: %155 = OpLabel
3466 ; CHECK: OpStore %31 %30
3467 ; CHECK: OpBranch %154
3468 ; CHECK: %156 = OpLabel
3469 ; CHECK: %158 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_54 %uint_1 %uint_0 %uint_0
3470 ; CHECK: OpBranch %154
3471 ; CHECK: %154 = OpLabel
3472 OpReturn
3473 OpFunctionEnd
3474 )";
3475 
3476   const std::string new_funcs = kDirectRead2 + kStreamWrite4Ray + kDirectRead4;
3477 
3478   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
3479   SinglePassRunAndMatch<InstBindlessCheckPass>(defs + main_func + new_funcs,
3480                                                true, 7u, 23u, true, true, false,
3481                                                false, false);
3482 }
3483 
TEST_F(InstBindlessTest,InstBoundsClosestHitInitLoadVariableSizedSampledImagesArray)3484 TEST_F(InstBindlessTest,
3485        InstBoundsClosestHitInitLoadVariableSizedSampledImagesArray) {
3486   // #version 460
3487   // #extension GL_EXT_nonuniform_qualifier : require
3488   // #extension GL_NV_ray_tracing : require
3489   //
3490   // layout(set = 0, binding = 0, std140) buffer StorageBuffer {
3491   //   uint index;
3492   //   float red;
3493   // } sbo;
3494   //
3495   // layout(set = 0, binding = 1, rgba32f) readonly uniform image2D images[];
3496   //
3497   // void main()
3498   // {
3499   //    sbo.red = imageLoad(images[sbo.index], ivec2(0, 0)).r;
3500   // }
3501 
3502   // clang-format off
3503   const std::string defs = R"(
3504 OpCapability RuntimeDescriptorArray
3505 OpCapability RayTracingNV
3506 OpExtension "SPV_EXT_descriptor_indexing"
3507 OpExtension "SPV_NV_ray_tracing"
3508 ; CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class"
3509 %1 = OpExtInstImport "GLSL.std.450"
3510 OpMemoryModel Logical GLSL450
3511 OpEntryPoint ClosestHitNV %main "main"
3512 ; CHECK: OpEntryPoint ClosestHitNV %main "main" %89
3513 OpSource GLSL 460
3514 OpSourceExtension "GL_EXT_nonuniform_qualifier"
3515 OpSourceExtension "GL_NV_ray_tracing"
3516 OpName %main "main"
3517 OpName %StorageBuffer "StorageBuffer"
3518 OpMemberName %StorageBuffer 0 "index"
3519 OpMemberName %StorageBuffer 1 "red"
3520 OpName %sbo "sbo"
3521 OpName %images "images"
3522 OpMemberDecorate %StorageBuffer 0 Offset 0
3523 OpMemberDecorate %StorageBuffer 1 Offset 4
3524 OpDecorate %StorageBuffer BufferBlock
3525 OpDecorate %sbo DescriptorSet 0
3526 OpDecorate %sbo Binding 0
3527 OpDecorate %images DescriptorSet 0
3528 OpDecorate %images Binding 1
3529 OpDecorate %images NonWritable
3530 ; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
3531 )" + kInputDecorations + kOutputDecorations + R"(
3532 ; CHECK: OpDecorate %89 BuiltIn LaunchIdNV
3533 %void = OpTypeVoid
3534 %3 = OpTypeFunction %void
3535 %uint = OpTypeInt 32 0
3536 %float = OpTypeFloat 32
3537 %StorageBuffer = OpTypeStruct %uint %float
3538 %_ptr_Uniform_StorageBuffer = OpTypePointer Uniform %StorageBuffer
3539 %sbo = OpVariable %_ptr_Uniform_StorageBuffer Uniform
3540 %int = OpTypeInt 32 1
3541 %int_1 = OpConstant %int 1
3542 %13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f
3543 %_runtimearr_13 = OpTypeRuntimeArray %13
3544 %_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13
3545 %images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant
3546 %int_0 = OpConstant %int 0
3547 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
3548 %_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
3549 %v2int = OpTypeVector %int 2
3550 %25 = OpConstantComposite %v2int %int_0 %int_0
3551 %v4float = OpTypeVector %float 4
3552 %uint_0 = OpConstant %uint 0
3553 %_ptr_Uniform_float = OpTypePointer Uniform %float
3554 ; CHECK: %uint_1 = OpConstant %uint 1
3555 ; CHECK: %34 = OpTypeFunction %uint %uint %uint
3556 ; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
3557 )" + kInputGlobals + R"(
3558 ; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
3559 ; CHECK: %bool = OpTypeBool
3560 ; CHECK: %57 = OpTypeFunction %void %uint %uint %uint %uint
3561 )" + kOutputGlobals + R"(
3562 ; CHECK: %uint_10 = OpConstant %uint 10
3563 ; CHECK: %uint_4 = OpConstant %uint 4
3564 ; CHECK: %uint_23 = OpConstant %uint 23
3565 ; CHECK: %uint_2 = OpConstant %uint 2
3566 ; CHECK: %uint_5316 = OpConstant %uint 5316
3567 ; CHECK: %uint_3 = OpConstant %uint 3
3568 ; CHECK: %v3uint = OpTypeVector %uint 3
3569 ; CHECK: %_ptr_Input_v3uint = OpTypePointer Input %v3uint
3570 ; CHECK: %89 = OpVariable %_ptr_Input_v3uint Input
3571 ; CHECK: %uint_5 = OpConstant %uint 5
3572 ; CHECK: %uint_6 = OpConstant %uint 6
3573 ; CHECK: %uint_7 = OpConstant %uint 7
3574 ; CHECK: %uint_8 = OpConstant %uint 8
3575 ; CHECK: %uint_9 = OpConstant %uint 9
3576 ; CHECK: %uint_51 = OpConstant %uint 51
3577 ; CHECK: %113 = OpConstantNull %v4float
3578 ; CHECK: %116 = OpTypeFunction %uint %uint %uint %uint %uint
3579 ; CHECK: %uint_48 = OpConstant %uint 48
3580 ; CHECK: %141 = OpConstantNull %uint
3581 ; CHECK: %uint_54 = OpConstant %uint 54
3582 )";
3583   // clang-format on
3584 
3585   const std::string main_func = R"(
3586 %main = OpFunction %void None %3
3587 %5 = OpLabel
3588 %19 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0
3589 %20 = OpLoad %uint %19
3590 %22 = OpAccessChain %_ptr_UniformConstant_13 %images %20
3591 %23 = OpLoad %13 %22
3592 %27 = OpImageRead %v4float %23 %25
3593 %29 = OpCompositeExtract %float %27 0
3594 %31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1
3595 OpStore %31 %29
3596 ; CHECK-NOT: OpStore %31 %29
3597 ; CHECK: %133 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_0 %uint_0
3598 ; CHECK: %134 = OpULessThan %bool %uint_0 %133
3599 ; CHECK: OpSelectionMerge %135 None
3600 ; CHECK: OpBranchConditional %134 %136 %137
3601 ; CHECK: %136 = OpLabel
3602 ; CHECK: %138 = OpLoad %uint %25
3603 ; CHECK: OpBranch %135
3604 ; CHECK: %137 = OpLabel
3605 ; CHECK: %140 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_48 %uint_1 %uint_0 %uint_0
3606 ; CHECK: OpBranch %135
3607 ; CHECK: %135 = OpLabel
3608 ; CHECK: %142 = OpPhi %uint %138 %136 %141 %137
3609 ; CHECK: %27 = OpAccessChain %_ptr_UniformConstant_13 %images %142
3610 ; CHECK: %28 = OpLoad %13 %27
3611 ; CHECK: %48 = OpFunctionCall %uint %inst_bindless_direct_read_2 %uint_1 %uint_1
3612 ; CHECK: %50 = OpULessThan %bool %142 %48
3613 ; CHECK: OpSelectionMerge %51 None
3614 ; CHECK: OpBranchConditional %50 %52 %53
3615 ; CHECK: %52 = OpLabel
3616 ; CHECK: %54 = OpLoad %13 %27
3617 ; CHECK: %143 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_1 %142
3618 ; CHECK: %144 = OpULessThan %bool %uint_0 %143
3619 ; CHECK: OpSelectionMerge %145 None
3620 ; CHECK: OpBranchConditional %144 %146 %147
3621 ; CHECK: %146 = OpLabel
3622 ; CHECK: %148 = OpLoad %13 %27
3623 ; CHECK: %149 = OpImageRead %v4float %148 %20
3624 ; CHECK: OpBranch %145
3625 ; CHECK: %147 = OpLabel
3626 ; CHECK: %150 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_51 %uint_1 %142 %uint_0
3627 ; CHECK: OpBranch %145
3628 ; CHECK: %145 = OpLabel
3629 ; CHECK: %151 = OpPhi %v4float %149 %146 %113 %147
3630 ; CHECK: OpBranch %51
3631 ; CHECK: %53 = OpLabel
3632 ; CHECK: %112 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_51 %uint_0 %142 %48
3633 ; CHECK: OpBranch %51
3634 ; CHECK: %51 = OpLabel
3635 ; CHECK: %114 = OpPhi %v4float %151 %145 %113 %53
3636 ; CHECK: %30 = OpCompositeExtract %float %114 0
3637 ; CHECK: %31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1
3638 ; CHECK: %152 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_0 %uint_0
3639 ; CHECK: %153 = OpULessThan %bool %uint_0 %152
3640 ; CHECK: OpSelectionMerge %154 None
3641 ; CHECK: OpBranchConditional %153 %155 %156
3642 ; CHECK: %155 = OpLabel
3643 ; CHECK: OpStore %31 %30
3644 ; CHECK: OpBranch %154
3645 ; CHECK: %156 = OpLabel
3646 ; CHECK: %158 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_54 %uint_1 %uint_0 %uint_0
3647 ; CHECK: OpBranch %154
3648 ; CHECK: %154 = OpLabel
3649 OpReturn
3650 OpFunctionEnd
3651 )";
3652 
3653   const std::string new_funcs = kDirectRead2 + kStreamWrite4Ray + kDirectRead4;
3654 
3655   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
3656   SinglePassRunAndMatch<InstBindlessCheckPass>(defs + main_func + new_funcs,
3657                                                true, 7u, 23u, true, true, false,
3658                                                false, false);
3659 }
3660 
TEST_F(InstBindlessTest,InstBoundsMissInitLoadVariableSizedSampledImagesArray)3661 TEST_F(InstBindlessTest,
3662        InstBoundsMissInitLoadVariableSizedSampledImagesArray) {
3663   // #version 460
3664   // #extension GL_EXT_nonuniform_qualifier : require
3665   // #extension GL_NV_ray_tracing : require
3666   //
3667   // layout(set = 0, binding = 0, std140) buffer StorageBuffer {
3668   //   uint index;
3669   //   float red;
3670   // } sbo;
3671   //
3672   // layout(set = 0, binding = 1, rgba32f) readonly uniform image2D images[];
3673   //
3674   // void main()
3675   // {
3676   //    sbo.red = imageLoad(images[sbo.index], ivec2(0, 0)).r;
3677   // }
3678 
3679   // clang-format off
3680   const std::string defs = R"(
3681 OpCapability RuntimeDescriptorArray
3682 OpCapability RayTracingNV
3683 OpExtension "SPV_EXT_descriptor_indexing"
3684 OpExtension "SPV_NV_ray_tracing"
3685 ; CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class"
3686 %1 = OpExtInstImport "GLSL.std.450"
3687 OpMemoryModel Logical GLSL450
3688 OpEntryPoint MissNV %main "main"
3689 ; CHECK: OpEntryPoint MissNV %main "main" %89
3690 OpSource GLSL 460
3691 OpSourceExtension "GL_EXT_nonuniform_qualifier"
3692 OpSourceExtension "GL_NV_ray_tracing"
3693 OpName %main "main"
3694 OpName %StorageBuffer "StorageBuffer"
3695 OpMemberName %StorageBuffer 0 "index"
3696 OpMemberName %StorageBuffer 1 "red"
3697 OpName %sbo "sbo"
3698 OpName %images "images"
3699 OpMemberDecorate %StorageBuffer 0 Offset 0
3700 OpMemberDecorate %StorageBuffer 1 Offset 4
3701 OpDecorate %StorageBuffer BufferBlock
3702 OpDecorate %sbo DescriptorSet 0
3703 OpDecorate %sbo Binding 0
3704 OpDecorate %images DescriptorSet 0
3705 OpDecorate %images Binding 1
3706 OpDecorate %images NonWritable
3707 ; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
3708 )" + kInputDecorations + kOutputDecorations + R"(
3709 ; CHECK: OpDecorate %89 BuiltIn LaunchIdNV
3710 %void = OpTypeVoid
3711 %3 = OpTypeFunction %void
3712 %uint = OpTypeInt 32 0
3713 %float = OpTypeFloat 32
3714 %StorageBuffer = OpTypeStruct %uint %float
3715 %_ptr_Uniform_StorageBuffer = OpTypePointer Uniform %StorageBuffer
3716 %sbo = OpVariable %_ptr_Uniform_StorageBuffer Uniform
3717 %int = OpTypeInt 32 1
3718 %int_1 = OpConstant %int 1
3719 %13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f
3720 %_runtimearr_13 = OpTypeRuntimeArray %13
3721 %_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13
3722 %images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant
3723 %int_0 = OpConstant %int 0
3724 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
3725 %_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
3726 %v2int = OpTypeVector %int 2
3727 %25 = OpConstantComposite %v2int %int_0 %int_0
3728 %v4float = OpTypeVector %float 4
3729 %uint_0 = OpConstant %uint 0
3730 %_ptr_Uniform_float = OpTypePointer Uniform %float
3731 ; CHECK: %uint_1 = OpConstant %uint 1
3732 ; CHECK: %34 = OpTypeFunction %uint %uint %uint
3733 ; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
3734 )" + kInputGlobals + R"(
3735 ; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
3736 ; CHECK: %bool = OpTypeBool
3737 ; CHECK: %57 = OpTypeFunction %void %uint %uint %uint %uint
3738 )" + kOutputGlobals + R"(
3739 ; CHECK: %uint_10 = OpConstant %uint 10
3740 ; CHECK: %uint_4 = OpConstant %uint 4
3741 ; CHECK: %uint_23 = OpConstant %uint 23
3742 ; CHECK: %uint_2 = OpConstant %uint 2
3743 ; CHECK: %uint_5317 = OpConstant %uint 5317
3744 ; CHECK: %uint_3 = OpConstant %uint 3
3745 ; CHECK: %v3uint = OpTypeVector %uint 3
3746 ; CHECK: %_ptr_Input_v3uint = OpTypePointer Input %v3uint
3747 ; CHECK: %89 = OpVariable %_ptr_Input_v3uint Input
3748 ; CHECK: %uint_5 = OpConstant %uint 5
3749 ; CHECK: %uint_6 = OpConstant %uint 6
3750 ; CHECK: %uint_7 = OpConstant %uint 7
3751 ; CHECK: %uint_8 = OpConstant %uint 8
3752 ; CHECK: %uint_9 = OpConstant %uint 9
3753 ; CHECK: %uint_51 = OpConstant %uint 51
3754 ; CHECK: %113 = OpConstantNull %v4float
3755 ; CHECK: %116 = OpTypeFunction %uint %uint %uint %uint %uint
3756 ; CHECK: %uint_48 = OpConstant %uint 48
3757 ; CHECK: %141 = OpConstantNull %uint
3758 ; CHECK: %uint_54 = OpConstant %uint 54
3759 )";
3760   // clang-format on
3761 
3762   const std::string main_func = R"(
3763 %main = OpFunction %void None %3
3764 %5 = OpLabel
3765 %19 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0
3766 %20 = OpLoad %uint %19
3767 %22 = OpAccessChain %_ptr_UniformConstant_13 %images %20
3768 %23 = OpLoad %13 %22
3769 %27 = OpImageRead %v4float %23 %25
3770 %29 = OpCompositeExtract %float %27 0
3771 %31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1
3772 OpStore %31 %29
3773 ; CHECK-NOT OpStore %31 %29
3774 ; CHECK: %133 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_0 %uint_0
3775 ; CHECK: %134 = OpULessThan %bool %uint_0 %133
3776 ; CHECK: OpSelectionMerge %135 None
3777 ; CHECK: OpBranchConditional %134 %136 %137
3778 ; CHECK: %136 = OpLabel
3779 ; CHECK: %138 = OpLoad %uint %25
3780 ; CHECK: OpBranch %135
3781 ; CHECK: %137 = OpLabel
3782 ; CHECK: %140 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_48 %uint_1 %uint_0 %uint_0
3783 ; CHECK: OpBranch %135
3784 ; CHECK: %135 = OpLabel
3785 ; CHECK: %142 = OpPhi %uint %138 %136 %141 %137
3786 ; CHECK: %27 = OpAccessChain %_ptr_UniformConstant_13 %images %142
3787 ; CHECK: %28 = OpLoad %13 %27
3788 ; CHECK: %48 = OpFunctionCall %uint %inst_bindless_direct_read_2 %uint_1 %uint_1
3789 ; CHECK: %50 = OpULessThan %bool %142 %48
3790 ; CHECK: OpSelectionMerge %51 None
3791 ; CHECK: OpBranchConditional %50 %52 %53
3792 ; CHECK: %52 = OpLabel
3793 ; CHECK: %54 = OpLoad %13 %27
3794 ; CHECK: %143 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_1 %142
3795 ; CHECK: %144 = OpULessThan %bool %uint_0 %143
3796 ; CHECK: OpSelectionMerge %145 None
3797 ; CHECK: OpBranchConditional %144 %146 %147
3798 ; CHECK: %146 = OpLabel
3799 ; CHECK: %148 = OpLoad %13 %27
3800 ; CHECK: %149 = OpImageRead %v4float %148 %20
3801 ; CHECK: OpBranch %145
3802 ; CHECK: %147 = OpLabel
3803 ; CHECK: %150 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_51 %uint_1 %142 %uint_0
3804 ; CHECK: OpBranch %145
3805 ; CHECK: %145 = OpLabel
3806 ; CHECK: %151 = OpPhi %v4float %149 %146 %113 %147
3807 ; CHECK: OpBranch %51
3808 ; CHECK: %53 = OpLabel
3809 ; CHECK: %112 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_51 %uint_0 %142 %48
3810 ; CHECK: OpBranch %51
3811 ; CHECK: %51 = OpLabel
3812 ; CHECK: %114 = OpPhi %v4float %151 %145 %113 %53
3813 ; CHECK: %30 = OpCompositeExtract %float %114 0
3814 ; CHECK: %31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1
3815 ; CHECK: %152 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_0 %uint_0
3816 ; CHECK: %153 = OpULessThan %bool %uint_0 %152
3817 ; CHECK: OpSelectionMerge %154 None
3818 ; CHECK: OpBranchConditional %153 %155 %156
3819 ; CHECK: %155 = OpLabel
3820 ; CHECK: OpStore %31 %30
3821 ; CHECK: OpBranch %154
3822 ; CHECK: %156 = OpLabel
3823 ; CHECK: %158 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_54 %uint_1 %uint_0 %uint_0
3824 ; CHECK: OpBranch %154
3825 ; CHECK: %154 = OpLabel
3826 OpReturn
3827 OpFunctionEnd
3828 )";
3829 
3830   const std::string new_funcs = kDirectRead2 + kStreamWrite4Ray + kDirectRead4;
3831 
3832   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
3833   SinglePassRunAndMatch<InstBindlessCheckPass>(defs + main_func + new_funcs,
3834                                                true, 7u, 23u, true, true, false,
3835                                                false, false);
3836 }
3837 
TEST_F(InstBindlessTest,InstBoundsCallableInitLoadVariableSizedSampledImagesArray)3838 TEST_F(InstBindlessTest,
3839        InstBoundsCallableInitLoadVariableSizedSampledImagesArray) {
3840   // #version 460
3841   // #extension GL_EXT_nonuniform_qualifier : require
3842   // #extension GL_NV_ray_tracing : require
3843   //
3844   // layout(set = 0, binding = 0, std140) buffer StorageBuffer {
3845   //   uint index;
3846   //   float red;
3847   // } sbo;
3848   //
3849   // layout(set = 0, binding = 1, rgba32f) readonly uniform image2D images[];
3850   //
3851   // void main()
3852   // {
3853   //    sbo.red = imageLoad(images[sbo.index], ivec2(0, 0)).r;
3854   // }
3855 
3856   // clang-format off
3857   const std::string defs = R"(
3858 OpCapability RuntimeDescriptorArray
3859 OpCapability RayTracingNV
3860 OpExtension "SPV_EXT_descriptor_indexing"
3861 OpExtension "SPV_NV_ray_tracing"
3862 ; CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class"
3863 %1 = OpExtInstImport "GLSL.std.450"
3864 OpMemoryModel Logical GLSL450
3865 OpEntryPoint CallableNV %main "main"
3866 ; CHECK: OpEntryPoint CallableNV %main "main" %89
3867 OpSource GLSL 460
3868 OpSourceExtension "GL_EXT_nonuniform_qualifier"
3869 OpSourceExtension "GL_NV_ray_tracing"
3870 OpName %main "main"
3871 OpName %StorageBuffer "StorageBuffer"
3872 OpMemberName %StorageBuffer 0 "index"
3873 OpMemberName %StorageBuffer 1 "red"
3874 OpName %sbo "sbo"
3875 OpName %images "images"
3876 OpMemberDecorate %StorageBuffer 0 Offset 0
3877 OpMemberDecorate %StorageBuffer 1 Offset 4
3878 OpDecorate %StorageBuffer BufferBlock
3879 OpDecorate %sbo DescriptorSet 0
3880 OpDecorate %sbo Binding 0
3881 OpDecorate %images DescriptorSet 0
3882 OpDecorate %images Binding 1
3883 OpDecorate %images NonWritable
3884 ; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
3885 )" + kInputDecorations + kOutputDecorations + R"(
3886 ; CHECK: OpDecorate %89 BuiltIn LaunchIdNV
3887 %void = OpTypeVoid
3888 %3 = OpTypeFunction %void
3889 %uint = OpTypeInt 32 0
3890 %float = OpTypeFloat 32
3891 %StorageBuffer = OpTypeStruct %uint %float
3892 %_ptr_Uniform_StorageBuffer = OpTypePointer Uniform %StorageBuffer
3893 %sbo = OpVariable %_ptr_Uniform_StorageBuffer Uniform
3894 %int = OpTypeInt 32 1
3895 %int_1 = OpConstant %int 1
3896 %13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f
3897 %_runtimearr_13 = OpTypeRuntimeArray %13
3898 %_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13
3899 %images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant
3900 %int_0 = OpConstant %int 0
3901 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
3902 %_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
3903 %v2int = OpTypeVector %int 2
3904 %25 = OpConstantComposite %v2int %int_0 %int_0
3905 %v4float = OpTypeVector %float 4
3906 %uint_0 = OpConstant %uint 0
3907 %_ptr_Uniform_float = OpTypePointer Uniform %float
3908 ; CHECK: %uint_1 = OpConstant %uint 1
3909 ; CHECK: %34 = OpTypeFunction %uint %uint %uint
3910 ; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
3911 )" + kInputGlobals + R"(
3912 ; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
3913 ; CHECK: %bool = OpTypeBool
3914 ; CHECK: %57 = OpTypeFunction %void %uint %uint %uint %uint
3915 )" + kOutputGlobals + R"(
3916 ; CHECK: %uint_10 = OpConstant %uint 10
3917 ; CHECK: %uint_4 = OpConstant %uint 4
3918 ; CHECK: %uint_23 = OpConstant %uint 23
3919 ; CHECK: %uint_2 = OpConstant %uint 2
3920 ; CHECK: %uint_5318 = OpConstant %uint 5318
3921 ; CHECK: %uint_3 = OpConstant %uint 3
3922 ; CHECK: %v3uint = OpTypeVector %uint 3
3923 ; CHECK: %_ptr_Input_v3uint = OpTypePointer Input %v3uint
3924 ; CHECK: %89 = OpVariable %_ptr_Input_v3uint Input
3925 ; CHECK: %uint_5 = OpConstant %uint 5
3926 ; CHECK: %uint_6 = OpConstant %uint 6
3927 ; CHECK: %uint_7 = OpConstant %uint 7
3928 ; CHECK: %uint_8 = OpConstant %uint 8
3929 ; CHECK: %uint_9 = OpConstant %uint 9
3930 ; CHECK: %uint_51 = OpConstant %uint 51
3931 ; CHECK: %113 = OpConstantNull %v4float
3932 ; CHECK: %116 = OpTypeFunction %uint %uint %uint %uint %uint
3933 ; CHECK: %uint_48 = OpConstant %uint 48
3934 ; CHECK: %141 = OpConstantNull %uint
3935 ; CHECK: %uint_54 = OpConstant %uint 54
3936 )";
3937   // clang-format on
3938 
3939   const std::string main_func = R"(
3940 %main = OpFunction %void None %3
3941 %5 = OpLabel
3942 %19 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0
3943 %20 = OpLoad %uint %19
3944 %22 = OpAccessChain %_ptr_UniformConstant_13 %images %20
3945 %23 = OpLoad %13 %22
3946 %27 = OpImageRead %v4float %23 %25
3947 %29 = OpCompositeExtract %float %27 0
3948 %31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1
3949 OpStore %31 %29
3950 ; CHECK-NOT: OpStore %31 %29
3951 ; CHECK: %133 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_0 %uint_0
3952 ; CHECK: %134 = OpULessThan %bool %uint_0 %133
3953 ; CHECK: OpSelectionMerge %135 None
3954 ; CHECK: OpBranchConditional %134 %136 %137
3955 ; CHECK: %136 = OpLabel
3956 ; CHECK: %138 = OpLoad %uint %25
3957 ; CHECK: OpBranch %135
3958 ; CHECK: %137 = OpLabel
3959 ; CHECK: %140 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_48 %uint_1 %uint_0 %uint_0
3960 ; CHECK: OpBranch %135
3961 ; CHECK: %135 = OpLabel
3962 ; CHECK: %142 = OpPhi %uint %138 %136 %141 %137
3963 ; CHECK: %27 = OpAccessChain %_ptr_UniformConstant_13 %images %142
3964 ; CHECK: %28 = OpLoad %13 %27
3965 ; CHECK: %48 = OpFunctionCall %uint %inst_bindless_direct_read_2 %uint_1 %uint_1
3966 ; CHECK: %50 = OpULessThan %bool %142 %48
3967 ; CHECK: OpSelectionMerge %51 None
3968 ; CHECK: OpBranchConditional %50 %52 %53
3969 ; CHECK: %52 = OpLabel
3970 ; CHECK: %54 = OpLoad %13 %27
3971 ; CHECK: %143 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_1 %142
3972 ; CHECK: %144 = OpULessThan %bool %uint_0 %143
3973 ; CHECK: OpSelectionMerge %145 None
3974 ; CHECK: OpBranchConditional %144 %146 %147
3975 ; CHECK: %146 = OpLabel
3976 ; CHECK: %148 = OpLoad %13 %27
3977 ; CHECK: %149 = OpImageRead %v4float %148 %20
3978 ; CHECK: OpBranch %145
3979 ; CHECK: %147 = OpLabel
3980 ; CHECK: %150 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_51 %uint_1 %142 %uint_0
3981 ; CHECK: OpBranch %145
3982 ; CHECK: %145 = OpLabel
3983 ; CHECK: %151 = OpPhi %v4float %149 %146 %113 %147
3984 ; CHECK: OpBranch %51
3985 ; CHECK: %53 = OpLabel
3986 ; CHECK: %112 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_51 %uint_0 %142 %48
3987 ; CHECK: OpBranch %51
3988 ; CHECK: %51 = OpLabel
3989 ; CHECK: %114 = OpPhi %v4float %151 %145 %113 %53
3990 ; CHECK: %30 = OpCompositeExtract %float %114 0
3991 ; CHECK: %31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1
3992 ; CHECK: %152 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_0 %uint_0
3993 ; CHECK: %153 = OpULessThan %bool %uint_0 %152
3994 ; CHECK: OpSelectionMerge %154 None
3995 ; CHECK: OpBranchConditional %153 %155 %156
3996 ; CHECK: %155 = OpLabel
3997 ; CHECK: OpStore %31 %30
3998 ; CHECK: OpBranch %154
3999 ; CHECK: %156 = OpLabel
4000 ; CHECK: %158 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_54 %uint_1 %uint_0 %uint_0
4001 ; CHECK: OpBranch %154
4002 ; CHECK: %154 = OpLabel
4003 OpReturn
4004 OpFunctionEnd
4005 )";
4006 
4007   const std::string new_funcs = kDirectRead2 + kStreamWrite4Ray + kDirectRead4;
4008 
4009   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
4010   SinglePassRunAndMatch<InstBindlessCheckPass>(defs + main_func + new_funcs,
4011                                                true, 7u, 23u, true, true, false,
4012                                                false, false);
4013 }
4014 
TEST_F(InstBindlessTest,InstBoundsInitSameBlockOpReplication)4015 TEST_F(InstBindlessTest, InstBoundsInitSameBlockOpReplication) {
4016   // Test that same block ops like OpSampledImage are replicated properly
4017   // where needed.
4018   //
4019   // clang-format off
4020   //
4021   // #version 450 core
4022   // #extension GL_EXT_nonuniform_qualifier : enable
4023   //
4024   // layout(location = 0) in vec2 inTexcoord;
4025   // layout(location = 0) out vec4 outColor;
4026   //
4027   // layout(set = 0, binding = 0) uniform Uniforms {
4028   //   vec2 var0;
4029   // } uniforms;
4030   //
4031   // layout(set = 0, binding = 1) uniform sampler uniformSampler;
4032   // layout(set = 0, binding = 2) uniform texture2D uniformTex;
4033   // layout(set = 0, binding = 3) uniform texture2D uniformTexArr[8];
4034   //
4035   // void main() {
4036   //   int index = 0;
4037   //   float x = texture(sampler2D(uniformTexArr[nonuniformEXT(index)], uniformSampler), inTexcoord.xy).x;
4038   //   float y = texture(sampler2D(uniformTex, uniformSampler), inTexcoord.xy * uniforms.var0.xy).x;
4039   //   outColor = vec4(x, y, 0.0, 0.0);
4040   // }
4041   //
4042 
4043   const std::string defs = R"(
4044 OpCapability Shader
4045 OpCapability ShaderNonUniformEXT
4046 OpCapability SampledImageArrayNonUniformIndexingEXT
4047 OpExtension "SPV_EXT_descriptor_indexing"
4048 ; CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class"
4049 %1 = OpExtInstImport "GLSL.std.450"
4050 OpMemoryModel Logical GLSL450
4051 OpEntryPoint Fragment %main "main" %inTexcoord %outColor
4052 ; CHECK: OpEntryPoint Fragment %main "main" %inTexcoord %outColor %gl_FragCoord
4053 OpExecutionMode %main OriginUpperLeft
4054 OpSource GLSL 450
4055 OpSourceExtension "GL_EXT_nonuniform_qualifier"
4056 OpName %main "main"
4057 OpName %index "index"
4058 OpName %x "x"
4059 OpName %uniformTexArr "uniformTexArr"
4060 OpName %uniformSampler "uniformSampler"
4061 OpName %inTexcoord "inTexcoord"
4062 OpName %y "y"
4063 OpName %uniformTex "uniformTex"
4064 OpName %Uniforms "Uniforms"
4065 OpMemberName %Uniforms 0 "var0"
4066 OpName %uniforms "uniforms"
4067 OpName %outColor "outColor"
4068 OpDecorate %uniformTexArr DescriptorSet 0
4069 OpDecorate %uniformTexArr Binding 3
4070 OpDecorate %19 NonUniformEXT
4071 OpDecorate %22 NonUniformEXT
4072 OpDecorate %uniformSampler DescriptorSet 0
4073 OpDecorate %uniformSampler Binding 1
4074 OpDecorate %inTexcoord Location 0
4075 OpDecorate %uniformTex DescriptorSet 0
4076 OpDecorate %uniformTex Binding 2
4077 OpMemberDecorate %Uniforms 0 Offset 0
4078 OpDecorate %Uniforms Block
4079 OpDecorate %uniforms DescriptorSet 0
4080 OpDecorate %uniforms Binding 0
4081 OpDecorate %outColor Location 0
4082 ; CHECK: OpDecorate %63 NonUniform
4083 ; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
4084 )" + kOutputDecorations + R"(
4085 ; CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord
4086 )" + kInputDecorations + R"(
4087 ; CHECK: OpDecorate %151 NonUniform
4088 %void = OpTypeVoid
4089 %3 = OpTypeFunction %void
4090 %int = OpTypeInt 32 1
4091 %_ptr_Function_int = OpTypePointer Function %int
4092 %int_0 = OpConstant %int 0
4093 %float = OpTypeFloat 32
4094 %_ptr_Function_float = OpTypePointer Function %float
4095 %13 = OpTypeImage %float 2D 0 0 0 1 Unknown
4096 %uint = OpTypeInt 32 0
4097 %uint_8 = OpConstant %uint 8
4098 %_arr_13_uint_8 = OpTypeArray %13 %uint_8
4099 %_ptr_UniformConstant__arr_13_uint_8 = OpTypePointer UniformConstant %_arr_13_uint_8
4100 %uniformTexArr = OpVariable %_ptr_UniformConstant__arr_13_uint_8 UniformConstant
4101 %_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
4102 %23 = OpTypeSampler
4103 %_ptr_UniformConstant_23 = OpTypePointer UniformConstant %23
4104 %uniformSampler = OpVariable %_ptr_UniformConstant_23 UniformConstant
4105 %27 = OpTypeSampledImage %13
4106 %v2float = OpTypeVector %float 2
4107 %_ptr_Input_v2float = OpTypePointer Input %v2float
4108 %inTexcoord = OpVariable %_ptr_Input_v2float Input
4109 %v4float = OpTypeVector %float 4
4110 %uint_0 = OpConstant %uint 0
4111 %uniformTex = OpVariable %_ptr_UniformConstant_13 UniformConstant
4112 %Uniforms = OpTypeStruct %v2float
4113 %_ptr_Uniform_Uniforms = OpTypePointer Uniform %Uniforms
4114 %uniforms = OpVariable %_ptr_Uniform_Uniforms Uniform
4115 %_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
4116 %_ptr_Output_v4float = OpTypePointer Output %v4float
4117 %outColor = OpVariable %_ptr_Output_v4float Output
4118 %float_0 = OpConstant %float 0
4119 ; CHECK: %bool = OpTypeBool
4120 ; CHECK: %68 = OpTypeFunction %void %uint %uint %uint %uint
4121 ; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
4122 )" + kOutputGlobals + R"(
4123 ; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
4124 ; CHECK: %uint_10 = OpConstant %uint 10
4125 ; CHECK: %uint_4 = OpConstant %uint 4
4126 ; CHECK: %uint_1 = OpConstant %uint 1
4127 ; CHECK: %uint_23 = OpConstant %uint 23
4128 ; CHECK: %uint_2 = OpConstant %uint 2
4129 ; CHECK: %uint_3 = OpConstant %uint 3
4130 ; CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float
4131 ; CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
4132 ; CHECK: %v4uint = OpTypeVector %uint 4
4133 ; CHECK: %uint_5 = OpConstant %uint 5
4134 ; CHECK: %uint_7 = OpConstant %uint 7
4135 ; CHECK: %uint_9 = OpConstant %uint 9
4136 ; CHECK: %uint_79 = OpConstant %uint 79
4137 ; CHECK: %122 = OpConstantNull %v4float
4138 ; CHECK: %126 = OpTypeFunction %uint %uint %uint %uint %uint
4139 )" + kInputGlobals + R"(
4140 ; CHECK: %uint_87 = OpConstant %uint 87
4141 ; CHECK: %165 = OpConstantNull %v2float
4142 ; CHECK: %uint_89 = OpConstant %uint 89
4143 )";
4144   // clang-format on
4145 
4146   const std::string main_func = R"(
4147 %main = OpFunction %void None %3
4148 %5 = OpLabel
4149 %index = OpVariable %_ptr_Function_int Function
4150 %x = OpVariable %_ptr_Function_float Function
4151 %y = OpVariable %_ptr_Function_float Function
4152 OpStore %index %int_0
4153 %19 = OpLoad %int %index
4154 %21 = OpAccessChain %_ptr_UniformConstant_13 %uniformTexArr %19
4155 %22 = OpLoad %13 %21
4156 %26 = OpLoad %23 %uniformSampler
4157 %28 = OpSampledImage %27 %22 %26
4158 %32 = OpLoad %v2float %inTexcoord
4159 %34 = OpImageSampleImplicitLod %v4float %28 %32
4160 %36 = OpCompositeExtract %float %34 0
4161 OpStore %x %36
4162 %39 = OpLoad %13 %uniformTex
4163 %40 = OpLoad %23 %uniformSampler
4164 %41 = OpSampledImage %27 %39 %40
4165 %42 = OpLoad %v2float %inTexcoord
4166 %47 = OpAccessChain %_ptr_Uniform_v2float %uniforms %int_0
4167 %48 = OpLoad %v2float %47
4168 %49 = OpFMul %v2float %42 %48
4169 %50 = OpImageSampleImplicitLod %v4float %41 %49
4170 %51 = OpCompositeExtract %float %50 0
4171 ; CHECK-NOT: %51 = OpCompositeExtract %float %50 0
4172 ; CHECK: %157 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_0 %uint_0
4173 ; CHECK: %158 = OpULessThan %bool %uint_0 %157
4174 ; CHECK: OpSelectionMerge %159 None
4175 ; CHECK: OpBranchConditional %158 %160 %161
4176 ; CHECK: %160 = OpLabel
4177 ; CHECK: %162 = OpLoad %v2float %47
4178 ; CHECK: OpBranch %159
4179 ; CHECK: %161 = OpLabel
4180 ; CHECK: %164 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_87 %uint_1 %uint_0 %uint_0
4181 ; CHECK: OpBranch %159
4182 ; CHECK: %159 = OpLabel
4183 ; CHECK: %166 = OpPhi %v2float %162 %160 %165 %161
4184 ; CHECK: %49 = OpFMul %v2float %42 %166
4185 ; CHECK: %167 = OpSampledImage %27 %39 %40
4186 ; CHECK: %168 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_2 %uint_0
4187 ; CHECK: %169 = OpULessThan %bool %uint_0 %168
4188 ; CHECK: OpSelectionMerge %170 None
4189 ; CHECK: OpBranchConditional %169 %171 %172
4190 ; CHECK: %171 = OpLabel
4191 ; CHECK: %173 = OpLoad %13 %uniformTex
4192 ; CHECK: %174 = OpSampledImage %27 %173 %40
4193 ; CHECK: %175 = OpImageSampleImplicitLod %v4float %174 %49
4194 ; CHECK: OpBranch %170
4195 ; CHECK: %172 = OpLabel
4196 ; CHECK: %177 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_89 %uint_1 %uint_0 %uint_0
4197 ; CHECK: OpBranch %170
4198 ; CHECK: %170 = OpLabel
4199 ; CHECK: %178 = OpPhi %v4float %175 %171 %122 %172
4200 ; CHECK: %51 = OpCompositeExtract %float %178 0
4201 OpStore %y %51
4202 %54 = OpLoad %float %x
4203 %55 = OpLoad %float %y
4204 %57 = OpCompositeConstruct %v4float %54 %55 %float_0 %float_0
4205 OpStore %outColor %57
4206 OpReturn
4207 OpFunctionEnd
4208 )";
4209 
4210   const std::string new_funcs = kStreamWrite4Frag + kDirectRead4;
4211 
4212   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
4213   SinglePassRunAndMatch<InstBindlessCheckPass>(defs + main_func + new_funcs,
4214                                                true, 7u, 23u, true, true, false,
4215                                                false, false);
4216 }
4217 
TEST_F(InstBindlessTest,MultipleUniformNonAggregateRefsNoDescInit)4218 TEST_F(InstBindlessTest, MultipleUniformNonAggregateRefsNoDescInit) {
4219   // Check that uniform refs do not go out-of-bounds. All checks use same input
4220   // buffer read function call result at top of function for uniform buffer
4221   // length. Because descriptor indexing is not being checked, we can avoid one
4222   // buffer load.
4223   //
4224   // Texture2D g_tColor;
4225   // SamplerState g_sAniso;
4226   //
4227   // layout(push_constant) cbuffer PerViewPushConst_t { bool g_B; };
4228   //
4229   // cbuffer PerViewConstantBuffer_t {
4230   //   float2 g_TexOff0;
4231   //   float2 g_TexOff1;
4232   // };
4233   //
4234   // struct PS_INPUT {
4235   //   float2 vTextureCoords : TEXCOORD2;
4236   // };
4237   //
4238   // struct PS_OUTPUT {
4239   //   float4 vColor : SV_Target0;
4240   // };
4241   //
4242   // PS_OUTPUT MainPs(PS_INPUT i) {
4243   //   PS_OUTPUT ps_output;
4244   //   float2 off;
4245   //   float2 vtc;
4246   //   if (g_B)
4247   //     off = g_TexOff0;
4248   //   else
4249   //     off = g_TexOff1;
4250   //   vtc = i.vTextureCoords.xy + off;
4251   //   ps_output.vColor = g_tColor.Sample(g_sAniso, vtc);
4252   //   return ps_output;
4253   // }
4254 
4255   // clang-format off
4256   const std::string text = R"(
4257                OpCapability Shader
4258 ;CHECK:        OpExtension "SPV_KHR_storage_buffer_storage_class"
4259           %1 = OpExtInstImport "GLSL.std.450"
4260                OpMemoryModel Logical GLSL450
4261                OpEntryPoint Fragment %MainPs "MainPs" %_ %__0 %g_tColor %g_sAniso %i_vTextureCoords %_entryPointOutput_vColor
4262 ;CHECK:        OpEntryPoint Fragment %MainPs "MainPs" %_ %__0 %g_tColor %g_sAniso %i_vTextureCoords %_entryPointOutput_vColor %inst_bindless_input_buffer %inst_bindless_output_buffer %gl_FragCoord
4263                OpExecutionMode %MainPs OriginUpperLeft
4264                OpSource HLSL 500
4265                OpName %MainPs "MainPs"
4266                OpName %PerViewPushConst_t "PerViewPushConst_t"
4267                OpMemberName %PerViewPushConst_t 0 "g_B"
4268                OpName %_ ""
4269                OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t"
4270                OpMemberName %PerViewConstantBuffer_t 0 "g_TexOff0"
4271                OpMemberName %PerViewConstantBuffer_t 1 "g_TexOff1"
4272                OpName %__0 ""
4273                OpName %g_tColor "g_tColor"
4274                OpName %g_sAniso "g_sAniso"
4275                OpName %i_vTextureCoords "i.vTextureCoords"
4276                OpName %_entryPointOutput_vColor "@entryPointOutput.vColor"
4277                OpMemberDecorate %PerViewPushConst_t 0 Offset 0
4278                OpDecorate %PerViewPushConst_t Block
4279                OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0
4280                OpMemberDecorate %PerViewConstantBuffer_t 1 Offset 8
4281                OpDecorate %PerViewConstantBuffer_t Block
4282                OpDecorate %__0 DescriptorSet 0
4283                OpDecorate %__0 Binding 1
4284                OpDecorate %g_tColor DescriptorSet 0
4285                OpDecorate %g_tColor Binding 0
4286                OpDecorate %g_sAniso DescriptorSet 0
4287                OpDecorate %g_sAniso Binding 2
4288                OpDecorate %i_vTextureCoords Location 0
4289                OpDecorate %_entryPointOutput_vColor Location 0
4290  ;CHECK:       OpDecorate %_runtimearr_uint ArrayStride 4
4291 )" + kInputDecorations + kOutputDecorations + R"(
4292  ;CHECK:       OpDecorate %gl_FragCoord BuiltIn FragCoord
4293        %void = OpTypeVoid
4294           %3 = OpTypeFunction %void
4295       %float = OpTypeFloat 32
4296     %v2float = OpTypeVector %float 2
4297     %v4float = OpTypeVector %float 4
4298        %uint = OpTypeInt 32 0
4299 %PerViewPushConst_t = OpTypeStruct %uint
4300 %_ptr_PushConstant_PerViewPushConst_t = OpTypePointer PushConstant %PerViewPushConst_t
4301           %_ = OpVariable %_ptr_PushConstant_PerViewPushConst_t PushConstant
4302         %int = OpTypeInt 32 1
4303       %int_0 = OpConstant %int 0
4304 %_ptr_PushConstant_uint = OpTypePointer PushConstant %uint
4305        %bool = OpTypeBool
4306      %uint_0 = OpConstant %uint 0
4307 %PerViewConstantBuffer_t = OpTypeStruct %v2float %v2float
4308 %_ptr_Uniform_PerViewConstantBuffer_t = OpTypePointer Uniform %PerViewConstantBuffer_t
4309         %__0 = OpVariable %_ptr_Uniform_PerViewConstantBuffer_t Uniform
4310 %_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
4311       %int_1 = OpConstant %int 1
4312          %49 = OpTypeImage %float 2D 0 0 0 1 Unknown
4313 %_ptr_UniformConstant_49 = OpTypePointer UniformConstant %49
4314    %g_tColor = OpVariable %_ptr_UniformConstant_49 UniformConstant
4315          %53 = OpTypeSampler
4316 %_ptr_UniformConstant_53 = OpTypePointer UniformConstant %53
4317    %g_sAniso = OpVariable %_ptr_UniformConstant_53 UniformConstant
4318          %57 = OpTypeSampledImage %49
4319 %_ptr_Input_v2float = OpTypePointer Input %v2float
4320 %i_vTextureCoords = OpVariable %_ptr_Input_v2float Input
4321 %_ptr_Output_v4float = OpTypePointer Output %v4float
4322 %_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output
4323  ;CHECK:      %uint_7 = OpConstant %uint 7
4324  ;CHECK:      %uint_1 = OpConstant %uint 1
4325  ;CHECK:         %122 = OpTypeFunction %uint %uint %uint %uint
4326  ;CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
4327  )" + kInputGlobals + R"(
4328  ;CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
4329  ;CHECK:     %uint_4 = OpConstant %uint 4
4330  ;CHECK:         %148 = OpTypeFunction %void %uint %uint %uint %uint %uint
4331  )" + kOutputGlobals + R"(
4332  ;CHECK:    %uint_11 = OpConstant %uint 11
4333  ;CHECK:    %uint_23 = OpConstant %uint 23
4334  ;CHECK:     %uint_2 = OpConstant %uint 2
4335  ;CHECK:      %uint_3 = OpConstant %uint 3
4336  ;CHECK:%_ptr_Input_v4float = OpTypePointer Input %v4float
4337  ;CHECK:%gl_FragCoord = OpVariable %_ptr_Input_v4float Input
4338  ;CHECK:     %v4uint = OpTypeVector %uint 4
4339  ;CHECK:     %uint_5 = OpConstant %uint 5
4340  ;CHECK:     %uint_8 = OpConstant %uint 8
4341  ;CHECK:     %uint_9 = OpConstant %uint 9
4342  ;CHECK:    %uint_10 = OpConstant %uint 10
4343  ;CHECK:    %uint_71 = OpConstant %uint 71
4344  ;CHECK:        %202 = OpConstantNull %v2float
4345  ;CHECK:    %uint_75 = OpConstant %uint 75
4346      %MainPs = OpFunction %void None %3
4347           %5 = OpLabel
4348  ;CHECK: %140 = OpFunctionCall %uint %inst_bindless_direct_read_3 %uint_1 %uint_1 %uint_0
4349  ;CHECK:        OpBranch %117
4350  ;CHECK: %117 = OpLabel
4351  ;CHECK:        OpBranch %116
4352  ;CHECK: %116 = OpLabel
4353          %69 = OpLoad %v2float %i_vTextureCoords
4354          %82 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0
4355          %83 = OpLoad %uint %82
4356          %84 = OpINotEqual %bool %83 %uint_0
4357                OpSelectionMerge %91 None
4358                OpBranchConditional %84 %85 %88
4359          %85 = OpLabel
4360          %86 = OpAccessChain %_ptr_Uniform_v2float %__0 %int_0
4361          %87 = OpLoad %v2float %86
4362  ;CHECK-NOT:     %87 = OpLoad %v2float %86
4363  ;CHECK:        %119 = OpIAdd %uint %uint_0 %uint_7
4364  ;CHECK:        %141 = OpULessThan %bool %119 %140
4365  ;CHECK:               OpSelectionMerge %143 None
4366  ;CHECK:               OpBranchConditional %141 %144 %145
4367  ;CHECK:        %144 = OpLabel
4368  ;CHECK:        %146 = OpLoad %v2float %86
4369  ;CHECK:               OpBranch %143
4370  ;CHECK:        %145 = OpLabel
4371  ;CHECK:        %201 = OpFunctionCall %void %inst_bindless_stream_write_5 %uint_71 %uint_4 %uint_0 %119 %140
4372  ;CHECK:               OpBranch %143
4373  ;CHECK:        %143 = OpLabel
4374  ;CHECK:        %203 = OpPhi %v2float %146 %144 %202 %145
4375                OpBranch %91
4376          %88 = OpLabel
4377          %89 = OpAccessChain %_ptr_Uniform_v2float %__0 %int_1
4378          %90 = OpLoad %v2float %89
4379  ;CHECK-NOT:     %90 = OpLoad %v2float %89
4380  ;CHECK:        %204 = OpIAdd %uint %uint_8 %uint_7
4381  ;CHECK:        %205 = OpULessThan %bool %204 %140
4382  ;CHECK:               OpSelectionMerge %206 None
4383  ;CHECK:               OpBranchConditional %205 %207 %208
4384  ;CHECK:        %207 = OpLabel
4385  ;CHECK:        %209 = OpLoad %v2float %89
4386  ;CHECK:               OpBranch %206
4387  ;CHECK:        %208 = OpLabel
4388  ;CHECK:        %211 = OpFunctionCall %void %inst_bindless_stream_write_5 %uint_75 %uint_4 %uint_0 %204 %140
4389  ;CHECK:               OpBranch %206
4390  ;CHECK:        %206 = OpLabel
4391  ;CHECK:        %212 = OpPhi %v2float %209 %207 %202 %208
4392                OpBranch %91
4393          %91 = OpLabel
4394         %115 = OpPhi %v2float %87 %85 %90 %88
4395  ;CHECK-NOT:       %115 = OpPhi %v2float %87 %85 %90 %88
4396  ;CHECK:           %115 = OpPhi %v2float %203 %143 %212 %206
4397          %95 = OpFAdd %v2float %69 %115
4398          %96 = OpLoad %49 %g_tColor
4399          %97 = OpLoad %53 %g_sAniso
4400          %98 = OpSampledImage %57 %96 %97
4401         %100 = OpImageSampleImplicitLod %v4float %98 %95
4402                OpStore %_entryPointOutput_vColor %100
4403                OpReturn
4404                OpFunctionEnd
4405 )" + kDirectRead3 + kStreamWrite5Frag;
4406   // clang-format on
4407 
4408   SetTargetEnv(SPV_ENV_VULKAN_1_2);
4409   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
4410   SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 7u, 23u, false,
4411                                                false, true, false, true);
4412 }
4413 
TEST_F(InstBindlessTest,UniformArrayRefNoDescInit)4414 TEST_F(InstBindlessTest, UniformArrayRefNoDescInit) {
4415   // Check that uniform array ref does not go out-of-bounds.
4416   //
4417   // Texture2D g_tColor;
4418   // SamplerState g_sAniso;
4419   //
4420   // layout(push_constant) cbuffer PerViewPushConst_t { uint g_c; };
4421   //
4422   // struct PerBatchEnvMapConstantBuffer_t {
4423   //   float4x3 g_matEnvMapWorldToLocal;
4424   //   float4 g_vEnvironmentMapBoxMins;
4425   //   float2 g_TexOff;
4426   // };
4427   //
4428   // cbuffer _BindlessFastEnvMapCB_PS_t {
4429   //   PerBatchEnvMapConstantBuffer_t g_envMapConstants[128];
4430   // };
4431   //
4432   // struct PS_INPUT {
4433   //   float2 vTextureCoords : TEXCOORD2;
4434   // };
4435   //
4436   // struct PS_OUTPUT {
4437   //   float4 vColor : SV_Target0;
4438   // };
4439   //
4440   // PS_OUTPUT MainPs(PS_INPUT i) {
4441   //   PS_OUTPUT ps_output;
4442   //   float2 off;
4443   //   float2 vtc;
4444   //   off = g_envMapConstants[g_c].g_TexOff;
4445   //   vtc = i.vTextureCoords.xy + off;
4446   //   ps_output.vColor = g_tColor.Sample(g_sAniso, vtc);
4447   //   return ps_output;
4448   // }
4449 
4450   // clang-format off
4451   const std::string text = R"(
4452                OpCapability Shader
4453 ;CHECK:               OpExtension "SPV_KHR_storage_buffer_storage_class"
4454           %1 = OpExtInstImport "GLSL.std.450"
4455                OpMemoryModel Logical GLSL450
4456                OpEntryPoint Fragment %MainPs "MainPs" %_ %__0 %g_tColor %g_sAniso %i_vTextureCoords %_entryPointOutput_vColor
4457                OpExecutionMode %MainPs OriginUpperLeft
4458                OpSource HLSL 500
4459                OpName %MainPs "MainPs"
4460                OpName %PerBatchEnvMapConstantBuffer_t "PerBatchEnvMapConstantBuffer_t"
4461                OpMemberName %PerBatchEnvMapConstantBuffer_t 0 "g_matEnvMapWorldToLocal"
4462                OpMemberName %PerBatchEnvMapConstantBuffer_t 1 "g_vEnvironmentMapBoxMins"
4463                OpMemberName %PerBatchEnvMapConstantBuffer_t 2 "g_TexOff"
4464                OpName %_BindlessFastEnvMapCB_PS_t "_BindlessFastEnvMapCB_PS_t"
4465                OpMemberName %_BindlessFastEnvMapCB_PS_t 0 "g_envMapConstants"
4466                OpName %_ ""
4467                OpName %PerViewPushConst_t "PerViewPushConst_t"
4468                OpMemberName %PerViewPushConst_t 0 "g_c"
4469                OpName %__0 ""
4470                OpName %g_tColor "g_tColor"
4471                OpName %g_sAniso "g_sAniso"
4472                OpName %i_vTextureCoords "i.vTextureCoords"
4473                OpName %_entryPointOutput_vColor "@entryPointOutput.vColor"
4474                OpMemberDecorate %PerBatchEnvMapConstantBuffer_t 0 RowMajor
4475                OpMemberDecorate %PerBatchEnvMapConstantBuffer_t 0 Offset 0
4476                OpMemberDecorate %PerBatchEnvMapConstantBuffer_t 0 MatrixStride 16
4477                OpMemberDecorate %PerBatchEnvMapConstantBuffer_t 1 Offset 48
4478                OpMemberDecorate %PerBatchEnvMapConstantBuffer_t 2 Offset 64
4479                OpDecorate %_arr_PerBatchEnvMapConstantBuffer_t_uint_128 ArrayStride 80
4480                OpMemberDecorate %_BindlessFastEnvMapCB_PS_t 0 Offset 0
4481                OpDecorate %_BindlessFastEnvMapCB_PS_t Block
4482                OpDecorate %_ DescriptorSet 0
4483                OpDecorate %_ Binding 2
4484                OpMemberDecorate %PerViewPushConst_t 0 Offset 0
4485                OpDecorate %PerViewPushConst_t Block
4486                OpDecorate %g_tColor DescriptorSet 0
4487                OpDecorate %g_tColor Binding 0
4488                OpDecorate %g_sAniso DescriptorSet 0
4489                OpDecorate %g_sAniso Binding 1
4490                OpDecorate %i_vTextureCoords Location 0
4491                OpDecorate %_entryPointOutput_vColor Location 0
4492 ;CHECK:               OpDecorate %_runtimearr_uint ArrayStride 4
4493 )" + kInputDecorations + kOutputDecorations + R"(
4494 ;CHECK:               OpDecorate %gl_FragCoord BuiltIn FragCoord
4495        %void = OpTypeVoid
4496           %3 = OpTypeFunction %void
4497       %float = OpTypeFloat 32
4498     %v2float = OpTypeVector %float 2
4499     %v4float = OpTypeVector %float 4
4500     %v3float = OpTypeVector %float 3
4501 %mat4v3float = OpTypeMatrix %v3float 4
4502 %PerBatchEnvMapConstantBuffer_t = OpTypeStruct %mat4v3float %v4float %v2float
4503        %uint = OpTypeInt 32 0
4504    %uint_128 = OpConstant %uint 128
4505 %_arr_PerBatchEnvMapConstantBuffer_t_uint_128 = OpTypeArray %PerBatchEnvMapConstantBuffer_t %uint_128
4506 %_BindlessFastEnvMapCB_PS_t = OpTypeStruct %_arr_PerBatchEnvMapConstantBuffer_t_uint_128
4507 %_ptr_Uniform__BindlessFastEnvMapCB_PS_t = OpTypePointer Uniform %_BindlessFastEnvMapCB_PS_t
4508           %_ = OpVariable %_ptr_Uniform__BindlessFastEnvMapCB_PS_t Uniform
4509         %int = OpTypeInt 32 1
4510       %int_0 = OpConstant %int 0
4511 %PerViewPushConst_t = OpTypeStruct %uint
4512 %_ptr_PushConstant_PerViewPushConst_t = OpTypePointer PushConstant %PerViewPushConst_t
4513         %__0 = OpVariable %_ptr_PushConstant_PerViewPushConst_t PushConstant
4514 %_ptr_PushConstant_uint = OpTypePointer PushConstant %uint
4515       %int_2 = OpConstant %int 2
4516 %_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
4517          %46 = OpTypeImage %float 2D 0 0 0 1 Unknown
4518 %_ptr_UniformConstant_46 = OpTypePointer UniformConstant %46
4519    %g_tColor = OpVariable %_ptr_UniformConstant_46 UniformConstant
4520          %50 = OpTypeSampler
4521 %_ptr_UniformConstant_50 = OpTypePointer UniformConstant %50
4522    %g_sAniso = OpVariable %_ptr_UniformConstant_50 UniformConstant
4523          %54 = OpTypeSampledImage %46
4524 %_ptr_Input_v2float = OpTypePointer Input %v2float
4525 %i_vTextureCoords = OpVariable %_ptr_Input_v2float Input
4526 %_ptr_Output_v4float = OpTypePointer Output %v4float
4527 %_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output
4528 ;CHECK:     %uint_0 = OpConstant %uint 0
4529 ;CHECK:    %uint_80 = OpConstant %uint 80
4530 ;CHECK:    %uint_64 = OpConstant %uint 64
4531 ;CHECK:     %uint_7 = OpConstant %uint 7
4532 ;CHECK:     %uint_2 = OpConstant %uint 2
4533 ;CHECK:     %uint_1 = OpConstant %uint 1
4534 ;CHECK:        %105 = OpTypeFunction %uint %uint %uint %uint
4535 ;CHECK:%_runtimearr_uint = OpTypeRuntimeArray %uint
4536 )" + kInputGlobals + R"(
4537 ;CHECK:%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
4538 ;CHECK:       %bool = OpTypeBool
4539 ;CHECK:     %uint_4 = OpConstant %uint 4
4540 ;CHECK:        %132 = OpTypeFunction %void %uint %uint %uint %uint %uint
4541 )" + kOutputGlobals + R"(
4542 ;CHECK:    %uint_11 = OpConstant %uint 11
4543 ;CHECK:    %uint_23 = OpConstant %uint 23
4544 ;CHECK:     %uint_3 = OpConstant %uint 3
4545 ;CHECK:%_ptr_Input_v4float = OpTypePointer Input %v4float
4546 ;CHECK:%gl_FragCoord = OpVariable %_ptr_Input_v4float Input
4547 ;CHECK:     %v4uint = OpTypeVector %uint 4
4548 ;CHECK:     %uint_5 = OpConstant %uint 5
4549 ;CHECK:     %uint_8 = OpConstant %uint 8
4550 ;CHECK:     %uint_9 = OpConstant %uint 9
4551 ;CHECK:    %uint_10 = OpConstant %uint 10
4552 ;CHECK:    %uint_78 = OpConstant %uint 78
4553 ;CHECK:        %185 = OpConstantNull %v2float
4554      %MainPs = OpFunction %void None %3
4555           %5 = OpLabel
4556 ;CHECK:        %123 = OpFunctionCall %uint %inst_bindless_direct_read_3 %uint_1 %uint_2 %uint_0
4557 ;CHECK:               OpBranch %93
4558 ;CHECK:         %93 = OpLabel
4559 ;CHECK:               OpBranch %92
4560 ;CHECK:         %92 = OpLabel
4561          %66 = OpLoad %v2float %i_vTextureCoords
4562          %79 = OpAccessChain %_ptr_PushConstant_uint %__0 %int_0
4563          %80 = OpLoad %uint %79
4564          %81 = OpAccessChain %_ptr_Uniform_v2float %_ %int_0 %80 %int_2
4565          %82 = OpLoad %v2float %81
4566 ;CHECK-NOT:     %82 = OpLoad %v2float %81
4567 ;CHECK:         %96 = OpIMul %uint %uint_80 %80
4568 ;CHECK:         %97 = OpIAdd %uint %uint_0 %96
4569 ;CHECK:         %99 = OpIAdd %uint %97 %uint_64
4570 ;CHECK:        %101 = OpIAdd %uint %99 %uint_7
4571 ;CHECK:        %125 = OpULessThan %bool %101 %123
4572 ;CHECK:               OpSelectionMerge %127 None
4573 ;CHECK:               OpBranchConditional %125 %128 %129
4574 ;CHECK:        %128 = OpLabel
4575 ;CHECK:        %130 = OpLoad %v2float %81
4576 ;CHECK:               OpBranch %127
4577 ;CHECK:        %129 = OpLabel
4578 ;CHECK:        %184 = OpFunctionCall %void %inst_bindless_stream_write_5 %uint_78 %uint_4 %uint_0 %101 %123
4579 ;CHECK:               OpBranch %127
4580 ;CHECK:        %127 = OpLabel
4581 ;CHECK:        %186 = OpPhi %v2float %130 %128 %185 %129
4582          %86 = OpFAdd %v2float %66 %82
4583 ;CHECK-NOT:         %86 = OpFAdd %v2float %66 %82
4584 ;CHECK:             %86 = OpFAdd %v2float %66 %186
4585          %87 = OpLoad %46 %g_tColor
4586          %88 = OpLoad %50 %g_sAniso
4587          %89 = OpSampledImage %54 %87 %88
4588          %91 = OpImageSampleImplicitLod %v4float %89 %86
4589                OpStore %_entryPointOutput_vColor %91
4590                OpReturn
4591                OpFunctionEnd
4592 )" + kDirectRead3 + kStreamWrite5Frag;
4593   // clang-format on
4594 
4595   SetTargetEnv(SPV_ENV_VULKAN_1_2);
4596   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
4597   SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 7u, 23u, false,
4598                                                false, true, false, true);
4599 }
4600 
TEST_F(InstBindlessTest,UniformArrayRefWithDescInit)4601 TEST_F(InstBindlessTest, UniformArrayRefWithDescInit) {
4602   // The buffer-oob and desc-init checks should use the same debug
4603   // output buffer write function.
4604   //
4605   // Same source as UniformArrayRefNoDescInit
4606 
4607   // clang-format off
4608   const std::string text = R"(
4609                OpCapability Shader
4610 ;CHECK:               OpExtension "SPV_KHR_storage_buffer_storage_class"
4611           %1 = OpExtInstImport "GLSL.std.450"
4612                OpMemoryModel Logical GLSL450
4613                OpEntryPoint Fragment %MainPs "MainPs" %_ %__0 %g_tColor %g_sAniso %i_vTextureCoords %_entryPointOutput_vColor
4614 ;CHECK:        OpEntryPoint Fragment %MainPs "MainPs" %_ %__0 %g_tColor %g_sAniso %i_vTextureCoords %_entryPointOutput_vColor %inst_bindless_input_buffer %inst_bindless_output_buffer %gl_FragCoord
4615                OpExecutionMode %MainPs OriginUpperLeft
4616                OpSource HLSL 500
4617                OpName %MainPs "MainPs"
4618                OpName %PerBatchEnvMapConstantBuffer_t "PerBatchEnvMapConstantBuffer_t"
4619                OpMemberName %PerBatchEnvMapConstantBuffer_t 0 "g_matEnvMapWorldToLocal"
4620                OpMemberName %PerBatchEnvMapConstantBuffer_t 1 "g_vEnvironmentMapBoxMins"
4621                OpMemberName %PerBatchEnvMapConstantBuffer_t 2 "g_TexOff"
4622                OpName %_BindlessFastEnvMapCB_PS_t "_BindlessFastEnvMapCB_PS_t"
4623                OpMemberName %_BindlessFastEnvMapCB_PS_t 0 "g_envMapConstants"
4624                OpName %_ ""
4625                OpName %PerViewPushConst_t "PerViewPushConst_t"
4626                OpMemberName %PerViewPushConst_t 0 "g_c"
4627                OpName %__0 ""
4628                OpName %g_tColor "g_tColor"
4629                OpName %g_sAniso "g_sAniso"
4630                OpName %i_vTextureCoords "i.vTextureCoords"
4631                OpName %_entryPointOutput_vColor "@entryPointOutput.vColor"
4632                OpMemberDecorate %PerBatchEnvMapConstantBuffer_t 0 RowMajor
4633                OpMemberDecorate %PerBatchEnvMapConstantBuffer_t 0 Offset 0
4634                OpMemberDecorate %PerBatchEnvMapConstantBuffer_t 0 MatrixStride 16
4635                OpMemberDecorate %PerBatchEnvMapConstantBuffer_t 1 Offset 48
4636                OpMemberDecorate %PerBatchEnvMapConstantBuffer_t 2 Offset 64
4637                OpDecorate %_arr_PerBatchEnvMapConstantBuffer_t_uint_128 ArrayStride 80
4638                OpMemberDecorate %_BindlessFastEnvMapCB_PS_t 0 Offset 0
4639                OpDecorate %_BindlessFastEnvMapCB_PS_t Block
4640                OpDecorate %_ DescriptorSet 0
4641                OpDecorate %_ Binding 2
4642                OpMemberDecorate %PerViewPushConst_t 0 Offset 0
4643                OpDecorate %PerViewPushConst_t Block
4644                OpDecorate %g_tColor DescriptorSet 0
4645                OpDecorate %g_tColor Binding 0
4646                OpDecorate %g_sAniso DescriptorSet 0
4647                OpDecorate %g_sAniso Binding 1
4648                OpDecorate %i_vTextureCoords Location 0
4649                OpDecorate %_entryPointOutput_vColor Location 0
4650 ;CHECK:               OpDecorate %_runtimearr_uint ArrayStride 4
4651 )" + kInputDecorations + kOutputDecorations + R"(
4652 ;CHECK:               OpDecorate %gl_FragCoord BuiltIn FragCoord
4653        %void = OpTypeVoid
4654           %3 = OpTypeFunction %void
4655       %float = OpTypeFloat 32
4656     %v2float = OpTypeVector %float 2
4657     %v4float = OpTypeVector %float 4
4658     %v3float = OpTypeVector %float 3
4659 %mat4v3float = OpTypeMatrix %v3float 4
4660 %PerBatchEnvMapConstantBuffer_t = OpTypeStruct %mat4v3float %v4float %v2float
4661        %uint = OpTypeInt 32 0
4662    %uint_128 = OpConstant %uint 128
4663 %_arr_PerBatchEnvMapConstantBuffer_t_uint_128 = OpTypeArray %PerBatchEnvMapConstantBuffer_t %uint_128
4664 %_BindlessFastEnvMapCB_PS_t = OpTypeStruct %_arr_PerBatchEnvMapConstantBuffer_t_uint_128
4665 %_ptr_Uniform__BindlessFastEnvMapCB_PS_t = OpTypePointer Uniform %_BindlessFastEnvMapCB_PS_t
4666           %_ = OpVariable %_ptr_Uniform__BindlessFastEnvMapCB_PS_t Uniform
4667         %int = OpTypeInt 32 1
4668       %int_0 = OpConstant %int 0
4669 %PerViewPushConst_t = OpTypeStruct %uint
4670 %_ptr_PushConstant_PerViewPushConst_t = OpTypePointer PushConstant %PerViewPushConst_t
4671         %__0 = OpVariable %_ptr_PushConstant_PerViewPushConst_t PushConstant
4672 %_ptr_PushConstant_uint = OpTypePointer PushConstant %uint
4673       %int_2 = OpConstant %int 2
4674 %_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
4675          %46 = OpTypeImage %float 2D 0 0 0 1 Unknown
4676 %_ptr_UniformConstant_46 = OpTypePointer UniformConstant %46
4677    %g_tColor = OpVariable %_ptr_UniformConstant_46 UniformConstant
4678          %50 = OpTypeSampler
4679 %_ptr_UniformConstant_50 = OpTypePointer UniformConstant %50
4680    %g_sAniso = OpVariable %_ptr_UniformConstant_50 UniformConstant
4681          %54 = OpTypeSampledImage %46
4682 %_ptr_Input_v2float = OpTypePointer Input %v2float
4683 %i_vTextureCoords = OpVariable %_ptr_Input_v2float Input
4684 %_ptr_Output_v4float = OpTypePointer Output %v4float
4685 %_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output
4686 ;CHECK:     %uint_0 = OpConstant %uint 0
4687 ;CHECK:    %uint_80 = OpConstant %uint 80
4688 ;CHECK:    %uint_64 = OpConstant %uint 64
4689 ;CHECK:     %uint_7 = OpConstant %uint 7
4690 ;CHECK:     %uint_2 = OpConstant %uint 2
4691 ;CHECK:        %104 = OpTypeFunction %uint %uint %uint %uint %uint
4692 ;CHECK:%_runtimearr_uint = OpTypeRuntimeArray %uint
4693 )" + kInputGlobals + R"(
4694 ;CHECK:%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
4695 ;CHECK:       %bool = OpTypeBool
4696 ;CHECK:     %uint_4 = OpConstant %uint 4
4697 ;CHECK:        %135 = OpTypeFunction %void %uint %uint %uint %uint %uint
4698 )" + kOutputGlobals + R"(
4699 ;CHECK:    %uint_11 = OpConstant %uint 11
4700 ;CHECK:     %uint_1 = OpConstant %uint 1
4701 ;CHECK:    %uint_23 = OpConstant %uint 23
4702 ;CHECK:     %uint_3 = OpConstant %uint 3
4703 ;CHECK:%_ptr_Input_v4float = OpTypePointer Input %v4float
4704 ;CHECK:%gl_FragCoord = OpVariable %_ptr_Input_v4float Input
4705 ;CHECK:     %v4uint = OpTypeVector %uint 4
4706 ;CHECK:     %uint_5 = OpConstant %uint 5
4707 ;CHECK:     %uint_8 = OpConstant %uint 8
4708 ;CHECK:     %uint_9 = OpConstant %uint 9
4709 ;CHECK:    %uint_10 = OpConstant %uint 10
4710 ;CHECK:    %uint_78 = OpConstant %uint 78
4711 ;CHECK:        %189 = OpConstantNull %v2float
4712 ;CHECK:    %uint_83 = OpConstant %uint 83
4713 ;CHECK:        %201 = OpConstantNull %v4float
4714      %MainPs = OpFunction %void None %3
4715           %5 = OpLabel
4716 ;CHECK:        %126 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_2 %uint_0
4717 ;CHECK:        %191 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_0 %uint_0
4718 ;CHECK:               OpBranch %93
4719 ;CHECK:         %93 = OpLabel
4720 ;CHECK:               OpBranch %92
4721 ;CHECK:         %92 = OpLabel
4722          %66 = OpLoad %v2float %i_vTextureCoords
4723          %79 = OpAccessChain %_ptr_PushConstant_uint %__0 %int_0
4724          %80 = OpLoad %uint %79
4725          %81 = OpAccessChain %_ptr_Uniform_v2float %_ %int_0 %80 %int_2
4726          %82 = OpLoad %v2float %81
4727          %86 = OpFAdd %v2float %66 %82
4728 ;CHECK-NOT: %82 = OpLoad %v2float %81
4729 ;CHECK-NOT: %86 = OpFAdd %v2float %66 %82
4730 ;CHECK:         %96 = OpIMul %uint %uint_80 %80
4731 ;CHECK:         %97 = OpIAdd %uint %uint_0 %96
4732 ;CHECK:         %99 = OpIAdd %uint %97 %uint_64
4733 ;CHECK:        %101 = OpIAdd %uint %99 %uint_7
4734 ;CHECK:        %128 = OpULessThan %bool %101 %126
4735 ;CHECK:               OpSelectionMerge %130 None
4736 ;CHECK:               OpBranchConditional %128 %131 %132
4737 ;CHECK:        %131 = OpLabel
4738 ;CHECK:        %133 = OpLoad %v2float %81
4739 ;CHECK:               OpBranch %130
4740 ;CHECK:        %132 = OpLabel
4741 ;CHECK:        %188 = OpFunctionCall %void %inst_bindless_stream_write_5 %uint_78 %uint_4 %uint_0 %101 %126
4742 ;CHECK:               OpBranch %130
4743 ;CHECK:        %130 = OpLabel
4744 ;CHECK:        %190 = OpPhi %v2float %133 %131 %189 %132
4745 ;CHECK:         %86 = OpFAdd %v2float %66 %190
4746          %87 = OpLoad %46 %g_tColor
4747          %88 = OpLoad %50 %g_sAniso
4748          %89 = OpSampledImage %54 %87 %88
4749          %91 = OpImageSampleImplicitLod %v4float %89 %86
4750                OpStore %_entryPointOutput_vColor %91
4751 ;CHECK-NOT: %91 = OpImageSampleImplicitLod %v4float %89 %86
4752 ;CHECK-NOT:       OpStore %_entryPointOutput_vColor %91
4753 ;CHECK:        %192 = OpULessThan %bool %uint_0 %191
4754 ;CHECK:               OpSelectionMerge %193 None
4755 ;CHECK:               OpBranchConditional %192 %194 %195
4756 ;CHECK:        %194 = OpLabel
4757 ;CHECK:        %196 = OpLoad %46 %g_tColor
4758 ;CHECK:        %197 = OpSampledImage %54 %196 %88
4759 ;CHECK:        %198 = OpImageSampleImplicitLod %v4float %197 %86
4760 ;CHECK:               OpBranch %193
4761 ;CHECK:        %195 = OpLabel
4762 ;CHECK:        %200 = OpFunctionCall %void %inst_bindless_stream_write_5 %uint_83 %uint_1 %uint_0 %uint_0 %uint_0
4763 ;CHECK:               OpBranch %193
4764 ;CHECK:        %193 = OpLabel
4765 ;CHECK:        %202 = OpPhi %v4float %198 %194 %201 %195
4766 ;CHECK:               OpStore %_entryPointOutput_vColor %202
4767                OpReturn
4768                OpFunctionEnd
4769 )" + kDirectRead4 + kStreamWrite5Frag;
4770   // clang-format on
4771 
4772   SetTargetEnv(SPV_ENV_VULKAN_1_2);
4773   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
4774   SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 7u, 23u, true, true,
4775                                                true, false, true);
4776 }
4777 
TEST_F(InstBindlessTest,Descriptor16BitIdxRef)4778 TEST_F(InstBindlessTest, Descriptor16BitIdxRef) {
4779   // Check that descriptor indexed with 16bit index is inbounds and
4780   // initialized
4781   //
4782   // Use Simple source with min16uint g_nDataIdx
4783 
4784   // clang-format off
4785   const std::string text = R"(
4786                OpCapability Shader
4787                OpCapability Int16
4788                OpCapability StoragePushConstant16
4789 ;CHECK:               OpExtension "SPV_KHR_storage_buffer_storage_class"
4790           %1 = OpExtInstImport "GLSL.std.450"
4791                OpMemoryModel Logical GLSL450
4792                OpEntryPoint Fragment %MainPs "MainPs" %g_tColor %_ %g_sAniso %i_vTextureCoords %_entryPointOutput_vColor
4793 ;CHECK:        OpEntryPoint Fragment %MainPs "MainPs" %g_tColor %_ %g_sAniso %i_vTextureCoords %_entryPointOutput_vColor %inst_bindless_output_buffer %gl_FragCoord %inst_bindless_input_buffer
4794                OpExecutionMode %MainPs OriginUpperLeft
4795                OpSource HLSL 500
4796                OpName %MainPs "MainPs"
4797                OpName %g_tColor "g_tColor"
4798                OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t"
4799                OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx"
4800                OpName %_ ""
4801                OpName %g_sAniso "g_sAniso"
4802                OpName %i_vTextureCoords "i.vTextureCoords"
4803                OpName %_entryPointOutput_vColor "@entryPointOutput.vColor"
4804                OpDecorate %g_tColor DescriptorSet 0
4805                OpDecorate %g_tColor Binding 0
4806                OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0
4807                OpDecorate %PerViewConstantBuffer_t Block
4808                OpDecorate %g_sAniso DescriptorSet 0
4809                OpDecorate %g_sAniso Binding 0
4810                OpDecorate %i_vTextureCoords Location 0
4811                OpDecorate %_entryPointOutput_vColor Location 0
4812 ;CHECK:               OpDecorate %_runtimearr_uint ArrayStride 4
4813 )" + kOutputDecorations + R"(
4814 ;CHECK:               OpDecorate %gl_FragCoord BuiltIn FragCoord
4815 )" + kInputDecorations + R"(
4816        %void = OpTypeVoid
4817          %10 = OpTypeFunction %void
4818       %float = OpTypeFloat 32
4819     %v2float = OpTypeVector %float 2
4820     %v4float = OpTypeVector %float 4
4821         %int = OpTypeInt 32 1
4822       %int_0 = OpConstant %int 0
4823          %16 = OpTypeImage %float 2D 0 0 0 1 Unknown
4824        %uint = OpTypeInt 32 0
4825    %uint_128 = OpConstant %uint 128
4826 %_arr_16_uint_128 = OpTypeArray %16 %uint_128
4827 %_ptr_UniformConstant__arr_16_uint_128 = OpTypePointer UniformConstant %_arr_16_uint_128
4828    %g_tColor = OpVariable %_ptr_UniformConstant__arr_16_uint_128 UniformConstant
4829      %ushort = OpTypeInt 16 0
4830 %PerViewConstantBuffer_t = OpTypeStruct %ushort
4831 %_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t
4832           %_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant
4833 %_ptr_PushConstant_ushort = OpTypePointer PushConstant %ushort
4834 %_ptr_UniformConstant_16 = OpTypePointer UniformConstant %16
4835          %25 = OpTypeSampler
4836 %_ptr_UniformConstant_25 = OpTypePointer UniformConstant %25
4837    %g_sAniso = OpVariable %_ptr_UniformConstant_25 UniformConstant
4838          %27 = OpTypeSampledImage %16
4839 %_ptr_Input_v2float = OpTypePointer Input %v2float
4840 %i_vTextureCoords = OpVariable %_ptr_Input_v2float Input
4841 %_ptr_Output_v4float = OpTypePointer Output %v4float
4842 %_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output
4843 ;CHECK:     %uint_0 = OpConstant %uint 0
4844 ;CHECK:       %bool = OpTypeBool
4845 ;CHECK:         %51 = OpTypeFunction %void %uint %uint %uint %uint
4846 ;CHECK:%_runtimearr_uint = OpTypeRuntimeArray %uint
4847 )" + kOutputGlobals + R"(
4848 ;CHECK:%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
4849 ;CHECK:    %uint_10 = OpConstant %uint 10
4850 ;CHECK:     %uint_4 = OpConstant %uint 4
4851 ;CHECK:     %uint_1 = OpConstant %uint 1
4852 ;CHECK:    %uint_23 = OpConstant %uint 23
4853 ;CHECK:     %uint_2 = OpConstant %uint 2
4854 ;CHECK:     %uint_3 = OpConstant %uint 3
4855 ;CHECK:%_ptr_Input_v4float = OpTypePointer Input %v4float
4856 ;CHECK:%gl_FragCoord = OpVariable %_ptr_Input_v4float Input
4857 ;CHECK:     %v4uint = OpTypeVector %uint 4
4858 ;CHECK:     %uint_5 = OpConstant %uint 5
4859 ;CHECK:     %uint_7 = OpConstant %uint 7
4860 ;CHECK:     %uint_8 = OpConstant %uint 8
4861 ;CHECK:     %uint_9 = OpConstant %uint 9
4862 ;CHECK:    %uint_60 = OpConstant %uint 60
4863 ;CHECK:        %106 = OpConstantNull %v4float
4864 ;CHECK:        %111 = OpTypeFunction %uint %uint %uint %uint %uint
4865 )" + kInputGlobals + R"(
4866      %MainPs = OpFunction %void None %10
4867          %30 = OpLabel
4868 ;CHECK:               OpBranch %108
4869 ;CHECK:        %108 = OpLabel
4870 ;CHECK:               OpBranch %39
4871 ;CHECK:         %39 = OpLabel
4872          %31 = OpLoad %v2float %i_vTextureCoords
4873          %32 = OpAccessChain %_ptr_PushConstant_ushort %_ %int_0
4874          %33 = OpLoad %ushort %32
4875          %34 = OpAccessChain %_ptr_UniformConstant_16 %g_tColor %33
4876          %35 = OpLoad %16 %34
4877          %36 = OpLoad %25 %g_sAniso
4878          %37 = OpSampledImage %27 %35 %36
4879          %38 = OpImageSampleImplicitLod %v4float %37 %31
4880                OpStore %_entryPointOutput_vColor %38
4881 ;CHECK-NOT:         %38 = OpImageSampleImplicitLod %v4float %37 %31
4882 ;CHECK-NOT:               OpStore %_entryPointOutput_vColor %38
4883 ;CHECK:         %41 = OpUConvert %uint %33
4884 ;CHECK:         %43 = OpULessThan %bool %41 %uint_128
4885 ;CHECK:               OpSelectionMerge %44 None
4886 ;CHECK:               OpBranchConditional %43 %45 %46
4887 ;CHECK:         %45 = OpLabel
4888 ;CHECK:         %47 = OpLoad %16 %34
4889 ;CHECK:         %48 = OpSampledImage %27 %47 %36
4890 ;CHECK:        %109 = OpUConvert %uint %33
4891 ;CHECK:        %131 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_0 %109
4892 ;CHECK:        %132 = OpULessThan %bool %uint_0 %131
4893 ;CHECK:               OpSelectionMerge %133 None
4894 ;CHECK:               OpBranchConditional %132 %134 %135
4895 ;CHECK:        %134 = OpLabel
4896 ;CHECK:        %136 = OpLoad %16 %34
4897 ;CHECK:        %137 = OpSampledImage %27 %136 %36
4898 ;CHECK:        %138 = OpImageSampleImplicitLod %v4float %137 %31
4899 ;CHECK:               OpBranch %133
4900 ;CHECK:        %135 = OpLabel
4901 ;CHECK:        %139 = OpUConvert %uint %33
4902 ;CHECK:        %140 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_60 %uint_1 %139 %uint_0
4903 ;CHECK:               OpBranch %133
4904 ;CHECK:        %133 = OpLabel
4905 ;CHECK:        %141 = OpPhi %v4float %138 %134 %106 %135
4906 ;CHECK:               OpBranch %44
4907 ;CHECK:         %46 = OpLabel
4908 ;CHECK:        %105 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_60 %uint_0 %41 %uint_128
4909 ;CHECK:               OpBranch %44
4910 ;CHECK:         %44 = OpLabel
4911 ;CHECK:        %107 = OpPhi %v4float %141 %133 %106 %46
4912 ;CHECK:               OpStore %_entryPointOutput_vColor %107
4913                OpReturn
4914                OpFunctionEnd
4915 )" + kStreamWrite4Frag + kDirectRead4;
4916   // clang-format on
4917 
4918   SetTargetEnv(SPV_ENV_VULKAN_1_2);
4919   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
4920   SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 7u, 23u, true, true,
4921                                                false, false, true);
4922 }
4923 
TEST_F(InstBindlessTest,UniformArray16bitIdxRef)4924 TEST_F(InstBindlessTest, UniformArray16bitIdxRef) {
4925   // Check that uniform array ref with 16bit index does not go out-of-bounds.
4926   //
4927   // Texture2D g_tColor;
4928   // SamplerState g_sAniso;
4929   //
4930   // layout(push_constant) cbuffer PerViewPushConst_t { min16uint g_c; };
4931   //
4932   // struct PerBatchEnvMapConstantBuffer_t {
4933   //   float4x3 g_matEnvMapWorldToLocal;
4934   //   float4 g_vEnvironmentMapBoxMins;
4935   //   float2 g_TexOff;
4936   // };
4937   //
4938   // cbuffer _BindlessFastEnvMapCB_PS_t {
4939   //   PerBatchEnvMapConstantBuffer_t g_envMapConstants[128];
4940   // };
4941   //
4942   // struct PS_INPUT {
4943   //   float2 vTextureCoords : TEXCOORD2;
4944   // };
4945   //
4946   // struct PS_OUTPUT {
4947   //   float4 vColor : SV_Target0;
4948   // };
4949   //
4950   // PS_OUTPUT MainPs(PS_INPUT i) {
4951   //   PS_OUTPUT ps_output;
4952   //   float2 off;
4953   //   float2 vtc;
4954   //   off = g_envMapConstants[g_c].g_TexOff;
4955   //   vtc = i.vTextureCoords.xy + off;
4956   //   ps_output.vColor = g_tColor.Sample(g_sAniso, vtc);
4957   //   return ps_output;
4958   // }
4959 
4960   // clang-format off
4961   const std::string text = R"(
4962                OpCapability Shader
4963                OpCapability Int16
4964                OpCapability StoragePushConstant16
4965 ;CHECK:               OpExtension "SPV_KHR_storage_buffer_storage_class"
4966           %1 = OpExtInstImport "GLSL.std.450"
4967                OpMemoryModel Logical GLSL450
4968                OpEntryPoint Fragment %MainPs "MainPs" %_ %__0 %g_tColor %g_sAniso %i_vTextureCoords %_entryPointOutput_vColor
4969 ;CHECK:        OpEntryPoint Fragment %MainPs "MainPs" %_ %__0 %g_tColor %g_sAniso %i_vTextureCoords %_entryPointOutput_vColor %inst_bindless_input_buffer %inst_bindless_output_buffer %gl_FragCoord
4970                OpExecutionMode %MainPs OriginUpperLeft
4971                OpSource HLSL 500
4972                OpName %MainPs "MainPs"
4973                OpName %PerBatchEnvMapConstantBuffer_t "PerBatchEnvMapConstantBuffer_t"
4974                OpMemberName %PerBatchEnvMapConstantBuffer_t 0 "g_matEnvMapWorldToLocal"
4975                OpMemberName %PerBatchEnvMapConstantBuffer_t 1 "g_vEnvironmentMapBoxMins"
4976                OpMemberName %PerBatchEnvMapConstantBuffer_t 2 "g_TexOff"
4977                OpName %_BindlessFastEnvMapCB_PS_t "_BindlessFastEnvMapCB_PS_t"
4978                OpMemberName %_BindlessFastEnvMapCB_PS_t 0 "g_envMapConstants"
4979                OpName %_ ""
4980                OpName %PerViewPushConst_t "PerViewPushConst_t"
4981                OpMemberName %PerViewPushConst_t 0 "g_c"
4982                OpName %__0 ""
4983                OpName %g_tColor "g_tColor"
4984                OpName %g_sAniso "g_sAniso"
4985                OpName %i_vTextureCoords "i.vTextureCoords"
4986                OpName %_entryPointOutput_vColor "@entryPointOutput.vColor"
4987                OpMemberDecorate %PerBatchEnvMapConstantBuffer_t 0 RowMajor
4988                OpMemberDecorate %PerBatchEnvMapConstantBuffer_t 0 Offset 0
4989                OpMemberDecorate %PerBatchEnvMapConstantBuffer_t 0 MatrixStride 16
4990                OpMemberDecorate %PerBatchEnvMapConstantBuffer_t 1 Offset 48
4991                OpMemberDecorate %PerBatchEnvMapConstantBuffer_t 2 Offset 64
4992                OpDecorate %_arr_PerBatchEnvMapConstantBuffer_t_uint_128 ArrayStride 80
4993                OpMemberDecorate %_BindlessFastEnvMapCB_PS_t 0 Offset 0
4994                OpDecorate %_BindlessFastEnvMapCB_PS_t Block
4995                OpDecorate %_ DescriptorSet 0
4996                OpDecorate %_ Binding 0
4997                OpMemberDecorate %PerViewPushConst_t 0 Offset 0
4998                OpDecorate %PerViewPushConst_t Block
4999                OpDecorate %g_tColor DescriptorSet 0
5000                OpDecorate %g_tColor Binding 0
5001                OpDecorate %g_sAniso DescriptorSet 0
5002                OpDecorate %g_sAniso Binding 0
5003                OpDecorate %i_vTextureCoords Location 0
5004                OpDecorate %_entryPointOutput_vColor Location 0
5005 ;CHECK:               OpDecorate %_runtimearr_uint ArrayStride 4
5006 )" + kInputDecorations + kOutputDecorations + R"(
5007 ;CHECK:               OpDecorate %gl_FragCoord BuiltIn FragCoord
5008        %void = OpTypeVoid
5009          %14 = OpTypeFunction %void
5010       %float = OpTypeFloat 32
5011     %v2float = OpTypeVector %float 2
5012     %v4float = OpTypeVector %float 4
5013     %v3float = OpTypeVector %float 3
5014 %mat4v3float = OpTypeMatrix %v3float 4
5015 %PerBatchEnvMapConstantBuffer_t = OpTypeStruct %mat4v3float %v4float %v2float
5016        %uint = OpTypeInt 32 0
5017    %uint_128 = OpConstant %uint 128
5018 %_arr_PerBatchEnvMapConstantBuffer_t_uint_128 = OpTypeArray %PerBatchEnvMapConstantBuffer_t %uint_128
5019 %_BindlessFastEnvMapCB_PS_t = OpTypeStruct %_arr_PerBatchEnvMapConstantBuffer_t_uint_128
5020 %_ptr_Uniform__BindlessFastEnvMapCB_PS_t = OpTypePointer Uniform %_BindlessFastEnvMapCB_PS_t
5021           %_ = OpVariable %_ptr_Uniform__BindlessFastEnvMapCB_PS_t Uniform
5022         %int = OpTypeInt 32 1
5023       %int_0 = OpConstant %int 0
5024      %ushort = OpTypeInt 16 0
5025 %PerViewPushConst_t = OpTypeStruct %ushort
5026 %_ptr_PushConstant_PerViewPushConst_t = OpTypePointer PushConstant %PerViewPushConst_t
5027         %__0 = OpVariable %_ptr_PushConstant_PerViewPushConst_t PushConstant
5028 %_ptr_PushConstant_ushort = OpTypePointer PushConstant %ushort
5029       %int_2 = OpConstant %int 2
5030 %_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
5031          %30 = OpTypeImage %float 2D 0 0 0 1 Unknown
5032 %_ptr_UniformConstant_30 = OpTypePointer UniformConstant %30
5033    %g_tColor = OpVariable %_ptr_UniformConstant_30 UniformConstant
5034          %32 = OpTypeSampler
5035 %_ptr_UniformConstant_32 = OpTypePointer UniformConstant %32
5036    %g_sAniso = OpVariable %_ptr_UniformConstant_32 UniformConstant
5037          %34 = OpTypeSampledImage %30
5038 %_ptr_Input_v2float = OpTypePointer Input %v2float
5039 %i_vTextureCoords = OpVariable %_ptr_Input_v2float Input
5040 %_ptr_Output_v4float = OpTypePointer Output %v4float
5041 %_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output
5042 ;CHECK:     %uint_0 = OpConstant %uint 0
5043 ;CHECK:    %uint_80 = OpConstant %uint 80
5044 ;CHECK:    %uint_64 = OpConstant %uint 64
5045 ;CHECK:     %uint_7 = OpConstant %uint 7
5046 ;CHECK:     %uint_1 = OpConstant %uint 1
5047 ;CHECK:         %61 = OpTypeFunction %uint %uint %uint %uint
5048 ;CHECK:%_runtimearr_uint = OpTypeRuntimeArray %uint
5049 )" + kInputGlobals + R"(
5050 ;CHECK:%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
5051 ;CHECK:       %bool = OpTypeBool
5052 ;CHECK:     %uint_4 = OpConstant %uint 4
5053 ;CHECK:         %88 = OpTypeFunction %void %uint %uint %uint %uint %uint
5054 )" + kOutputGlobals + R"(
5055 ;CHECK:    %uint_11 = OpConstant %uint 11
5056 ;CHECK:    %uint_23 = OpConstant %uint 23
5057 ;CHECK:     %uint_2 = OpConstant %uint 2
5058 ;CHECK:     %uint_3 = OpConstant %uint 3
5059 ;CHECK:%_ptr_Input_v4float = OpTypePointer Input %v4float
5060 ;CHECK:%gl_FragCoord = OpVariable %_ptr_Input_v4float Input
5061 ;CHECK:     %v4uint = OpTypeVector %uint 4
5062 ;CHECK:     %uint_5 = OpConstant %uint 5
5063 ;CHECK:     %uint_8 = OpConstant %uint 8
5064 ;CHECK:     %uint_9 = OpConstant %uint 9
5065 ;CHECK:    %uint_10 = OpConstant %uint 10
5066 ;CHECK:    %uint_81 = OpConstant %uint 81
5067 ;CHECK:        %142 = OpConstantNull %v2float
5068      %MainPs = OpFunction %void None %14
5069          %37 = OpLabel
5070 ;CHECK:         %79 = OpFunctionCall %uint %inst_bindless_direct_read_3 %uint_1 %uint_0 %uint_0
5071 ;CHECK:               OpBranch %49
5072 ;CHECK:         %49 = OpLabel
5073 ;CHECK:               OpBranch %48
5074 ;CHECK:         %48 = OpLabel
5075          %38 = OpLoad %v2float %i_vTextureCoords
5076          %39 = OpAccessChain %_ptr_PushConstant_ushort %__0 %int_0
5077          %40 = OpLoad %ushort %39
5078          %41 = OpAccessChain %_ptr_Uniform_v2float %_ %int_0 %40 %int_2
5079          %42 = OpLoad %v2float %41
5080          %43 = OpFAdd %v2float %38 %42
5081 ;CHECK-NOT:     %42 = OpLoad %v2float %41
5082 ;CHECK-NOT:     %43 = OpFAdd %v2float %38 %42
5083 ;CHECK:         %52 = OpUConvert %uint %40
5084 ;CHECK:         %53 = OpIMul %uint %uint_80 %52
5085 ;CHECK:         %54 = OpIAdd %uint %uint_0 %53
5086 ;CHECK:         %56 = OpIAdd %uint %54 %uint_64
5087 ;CHECK:         %58 = OpIAdd %uint %56 %uint_7
5088 ;CHECK:         %81 = OpULessThan %bool %58 %79
5089 ;CHECK:               OpSelectionMerge %83 None
5090 ;CHECK:               OpBranchConditional %81 %84 %85
5091 ;CHECK:         %84 = OpLabel
5092 ;CHECK:         %86 = OpLoad %v2float %41
5093 ;CHECK:               OpBranch %83
5094 ;CHECK:         %85 = OpLabel
5095 ;CHECK:        %141 = OpFunctionCall %void %inst_bindless_stream_write_5 %uint_81 %uint_4 %uint_0 %58 %79
5096 ;CHECK:               OpBranch %83
5097 ;CHECK:         %83 = OpLabel
5098 ;CHECK:        %143 = OpPhi %v2float %86 %84 %142 %85
5099 ;CHECK:         %43 = OpFAdd %v2float %38 %143
5100          %44 = OpLoad %30 %g_tColor
5101          %45 = OpLoad %32 %g_sAniso
5102          %46 = OpSampledImage %34 %44 %45
5103          %47 = OpImageSampleImplicitLod %v4float %46 %43
5104                OpStore %_entryPointOutput_vColor %47
5105                OpReturn
5106                OpFunctionEnd
5107                )" + kDirectRead3 + kStreamWrite5Frag;
5108   // clang-format on
5109 
5110   SetTargetEnv(SPV_ENV_VULKAN_1_2);
5111   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
5112   SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 7u, 23u, false,
5113                                                false, true, false, true);
5114 }
5115 
TEST_F(InstBindlessTest,UniformMatrixRefRowMajor)5116 TEST_F(InstBindlessTest, UniformMatrixRefRowMajor) {
5117   // The buffer-oob row major matrix check
5118   //
5119   // #version 450
5120   // #extension GL_EXT_scalar_block_layout : enable
5121   //
5122   // layout(location = 0) in highp vec4 a_position;
5123   // layout(location = 0) out mediump float v_vtxResult;
5124   //
5125   // layout(set = 0, binding = 0, std430, row_major) uniform Block
5126   // {
5127   //    lowp mat4x2 var;
5128   // };
5129   //
5130   // void main (void)
5131   // {
5132   //    v_vtxResult = var[2][1];
5133   // }
5134 
5135   // clang-format off
5136   std::string text = R"(
5137                OpCapability Shader
5138 ;CHECK:               OpExtension "SPV_KHR_storage_buffer_storage_class"
5139           %1 = OpExtInstImport "GLSL.std.450"
5140                OpMemoryModel Logical GLSL450
5141                OpEntryPoint Vertex %main "main" %v_vtxResult %_ %a_position
5142 ;CHECK:        OpEntryPoint Vertex %main "main" %v_vtxResult %_ %a_position %inst_bindless_input_buffer %inst_bindless_output_buffer %gl_VertexIndex %gl_InstanceIndex
5143                OpSource GLSL 450
5144                OpSourceExtension "GL_EXT_scalar_block_layout"
5145                OpName %main "main"
5146                OpName %v_vtxResult "v_vtxResult"
5147                OpName %Block "Block"
5148                OpMemberName %Block 0 "var"
5149                OpName %_ ""
5150                OpName %a_position "a_position"
5151                OpDecorate %v_vtxResult RelaxedPrecision
5152                OpDecorate %v_vtxResult Location 0
5153                OpMemberDecorate %Block 0 RowMajor
5154                OpMemberDecorate %Block 0 RelaxedPrecision
5155                OpMemberDecorate %Block 0 Offset 0
5156                OpMemberDecorate %Block 0 MatrixStride 16
5157                OpDecorate %Block Block
5158                OpDecorate %_ DescriptorSet 0
5159                OpDecorate %_ Binding 0
5160                OpDecorate %21 RelaxedPrecision
5161 ;CHECK-NOT:           OpDecorate %21 RelaxedPrecision
5162 ;CHECK:               OpDecorate %116 RelaxedPrecision
5163                OpDecorate %a_position Location 0
5164 ;CHECK:               OpDecorate %_runtimearr_uint ArrayStride 4
5165 )" + kInputDecorations + R"(
5166 ;CHECK:               OpDecorate %61 RelaxedPrecision
5167 )" + kOutputDecorations + R"(
5168 ;CHECK:               OpDecorate %gl_VertexIndex BuiltIn VertexIndex
5169 ;CHECK:               OpDecorate %gl_InstanceIndex BuiltIn InstanceIndex
5170        %void = OpTypeVoid
5171           %3 = OpTypeFunction %void
5172       %float = OpTypeFloat 32
5173 %_ptr_Output_float = OpTypePointer Output %float
5174 %v_vtxResult = OpVariable %_ptr_Output_float Output
5175     %v2float = OpTypeVector %float 2
5176 %mat4v2float = OpTypeMatrix %v2float 4
5177       %Block = OpTypeStruct %mat4v2float
5178 %_ptr_Uniform_Block = OpTypePointer Uniform %Block
5179           %_ = OpVariable %_ptr_Uniform_Block Uniform
5180         %int = OpTypeInt 32 1
5181       %int_0 = OpConstant %int 0
5182       %int_2 = OpConstant %int 2
5183        %uint = OpTypeInt 32 0
5184      %uint_1 = OpConstant %uint 1
5185 %_ptr_Uniform_float = OpTypePointer Uniform %float
5186     %v4float = OpTypeVector %float 4
5187 %_ptr_Input_v4float = OpTypePointer Input %v4float
5188  %a_position = OpVariable %_ptr_Input_v4float Input
5189 ;CHECK;     %uint_0 = OpConstant %uint 0
5190 ;CHECK;     %uint_16 = OpConstant %uint 16
5191 ;CHECK;     %uint_4 = OpConstant %uint 4
5192 ;CHECK;     %uint_3 = OpConstant %uint 3
5193 ;CHECK;         %37 = OpTypeFunction %uint %uint %uint %uint
5194 ;CHECK;%_runtimearr_uint = OpTypeRuntimeArray %uint
5195 )" + kInputGlobals + R"(
5196 ;CHECK;%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
5197 ;CHECK;       %bool = OpTypeBool
5198 ;CHECK;         %63 = OpTypeFunction %void %uint %uint %uint %uint %uint
5199 )" + kOutputGlobals + R"(
5200 ;CHECK;    %uint_11 = OpConstant %uint 11
5201 ;CHECK;    %uint_23 = OpConstant %uint 23
5202 ;CHECK;     %uint_2 = OpConstant %uint 2
5203 ;CHECK;%_ptr_Input_uint = OpTypePointer Input %uint
5204 ;CHECK;%gl_VertexIndex = OpVariable %_ptr_Input_uint Input
5205 ;CHECK;%gl_InstanceIndex = OpVariable %_ptr_Input_uint Input
5206 ;CHECK;     %uint_5 = OpConstant %uint 5
5207 ;CHECK;     %uint_7 = OpConstant %uint 7
5208 ;CHECK;     %uint_8 = OpConstant %uint 8
5209 ;CHECK;     %uint_9 = OpConstant %uint 9
5210 ;CHECK;    %uint_10 = OpConstant %uint 10
5211 ;CHECK;    %uint_45 = OpConstant %uint 45
5212 ;CHECK;        %115 = OpConstantNull %float
5213        %main = OpFunction %void None %3
5214           %5 = OpLabel
5215 ;CHECK:         %55 = OpFunctionCall %uint %inst_bindless_direct_read_3 %uint_1 %uint_0 %uint_0
5216 ;CHECK:               OpBranch %26
5217 ;CHECK:         %26 = OpLabel
5218 ;CHECK:               OpBranch %25
5219 ;CHECK:         %25 = OpLabel
5220          %20 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %int_2 %uint_1
5221          %21 = OpLoad %float %20
5222 ;CHECK-NOT:     %21 = OpLoad %float %20
5223 ;CHECK:         %30 = OpIMul %uint %uint_4 %int_2
5224 ;CHECK:         %31 = OpIAdd %uint %uint_0 %30
5225 ;CHECK:         %32 = OpIMul %uint %uint_16 %uint_1
5226 ;CHECK:         %33 = OpIAdd %uint %31 %32
5227 ;CHECK:         %35 = OpIAdd %uint %33 %uint_3
5228 ;CHECK:         %57 = OpULessThan %bool %35 %55
5229 ;CHECK:               OpSelectionMerge %58 None
5230 ;CHECK:               OpBranchConditional %57 %59 %60
5231 ;CHECK:         %59 = OpLabel
5232 ;CHECK:         %61 = OpLoad %float %20
5233 ;CHECK:               OpBranch %58
5234 ;CHECK:         %60 = OpLabel
5235 ;CHECK:        %114 = OpFunctionCall %void %inst_bindless_stream_write_5 %uint_45 %uint_4 %uint_0 %35 %55
5236 ;CHECK:               OpBranch %58
5237 ;CHECK:         %58 = OpLabel
5238 ;CHECK:        %116 = OpPhi %float %61 %59 %115 %60
5239                OpStore %v_vtxResult %21
5240 ;CHECK-NOT:           OpStore %v_vtxResult %21
5241 ;CHECK:               OpStore %v_vtxResult %116
5242                OpReturn
5243                OpFunctionEnd
5244                )" + kDirectRead3 + kStreamWrite5Vert;
5245   // clang-format on
5246 
5247   SetTargetEnv(SPV_ENV_VULKAN_1_2);
5248   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
5249   SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 7u, 23u, false,
5250                                                false, true, false, true);
5251 }
5252 
TEST_F(InstBindlessTest,UniformMatrixRefColumnMajor)5253 TEST_F(InstBindlessTest, UniformMatrixRefColumnMajor) {
5254   // The buffer-oob column major matrix check
5255   //
5256   // #version 450
5257   // #extension GL_EXT_scalar_block_layout : enable
5258   //
5259   // layout(location = 0) in highp vec4 a_position;
5260   // layout(location = 0) out mediump float v_vtxResult;
5261   //
5262   // layout(set = 0, binding = 0, std430, column_major) uniform Block
5263   // {
5264   //    lowp mat4x2 var;
5265   // };
5266   //
5267   // void main (void)
5268   // {
5269   //    v_vtxResult = var[2][1];
5270   // }
5271 
5272   // clang-format off
5273   const std::string text = R"(
5274                OpCapability Shader
5275 ;CHECK:               OpExtension "SPV_KHR_storage_buffer_storage_class"
5276           %1 = OpExtInstImport "GLSL.std.450"
5277                OpMemoryModel Logical GLSL450
5278                OpEntryPoint Vertex %main "main" %v_vtxResult %_ %a_position
5279 ;CHECK:        OpEntryPoint Vertex %main "main" %v_vtxResult %_ %a_position %inst_bindless_input_buffer %inst_bindless_output_buffer %gl_VertexIndex %gl_InstanceIndex
5280                OpSource GLSL 450
5281                OpSourceExtension "GL_EXT_scalar_block_layout"
5282                OpName %main "main"
5283                OpName %v_vtxResult "v_vtxResult"
5284                OpName %Block "Block"
5285                OpMemberName %Block 0 "var"
5286                OpName %_ ""
5287                OpName %a_position "a_position"
5288                OpDecorate %v_vtxResult RelaxedPrecision
5289                OpDecorate %v_vtxResult Location 0
5290                OpMemberDecorate %Block 0 ColMajor
5291                OpMemberDecorate %Block 0 RelaxedPrecision
5292                OpMemberDecorate %Block 0 Offset 0
5293                OpMemberDecorate %Block 0 MatrixStride 8
5294                OpDecorate %Block Block
5295                OpDecorate %_ DescriptorSet 0
5296                OpDecorate %_ Binding 0
5297                OpDecorate %21 RelaxedPrecision
5298 ;CHECK-NOT:           OpDecorate %21 RelaxedPrecision
5299 ;CHECK:               OpDecorate %115 RelaxedPrecision
5300                OpDecorate %a_position Location 0
5301 ;CHECK:               OpDecorate %_runtimearr_uint ArrayStride 4
5302 )" + kInputDecorations + R"(
5303 ;CHECK:               OpDecorate %61 RelaxedPrecision
5304 )" + kOutputDecorations + R"(
5305 ;CHECK:               OpDecorate %gl_VertexIndex BuiltIn VertexIndex
5306 ;CHECK:               OpDecorate %gl_InstanceIndex BuiltIn InstanceIndex
5307        %void = OpTypeVoid
5308           %3 = OpTypeFunction %void
5309       %float = OpTypeFloat 32
5310 %_ptr_Output_float = OpTypePointer Output %float
5311 %v_vtxResult = OpVariable %_ptr_Output_float Output
5312     %v2float = OpTypeVector %float 2
5313 %mat4v2float = OpTypeMatrix %v2float 4
5314       %Block = OpTypeStruct %mat4v2float
5315 %_ptr_Uniform_Block = OpTypePointer Uniform %Block
5316           %_ = OpVariable %_ptr_Uniform_Block Uniform
5317         %int = OpTypeInt 32 1
5318       %int_0 = OpConstant %int 0
5319       %int_2 = OpConstant %int 2
5320        %uint = OpTypeInt 32 0
5321      %uint_1 = OpConstant %uint 1
5322 %_ptr_Uniform_float = OpTypePointer Uniform %float
5323     %v4float = OpTypeVector %float 4
5324 %_ptr_Input_v4float = OpTypePointer Input %v4float
5325  %a_position = OpVariable %_ptr_Input_v4float Input
5326 ;CHECK:     %uint_0 = OpConstant %uint 0
5327 ;CHECK:     %uint_8 = OpConstant %uint 8
5328 ;CHECK:     %uint_4 = OpConstant %uint 4
5329 ;CHECK:     %uint_3 = OpConstant %uint 3
5330 ;CHECK:         %37 = OpTypeFunction %uint %uint %uint %uint
5331 ;CHECK:%_runtimearr_uint = OpTypeRuntimeArray %uint
5332 )" + kInputGlobals + R"(
5333 ;CHECK:%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
5334 ;CHECK:       %bool = OpTypeBool
5335 ;CHECK:         %63 = OpTypeFunction %void %uint %uint %uint %uint %uint
5336 )" + kOutputGlobals + R"(
5337 ;CHECK:    %uint_11 = OpConstant %uint 11
5338 ;CHECK:    %uint_23 = OpConstant %uint 23
5339 ;CHECK:     %uint_2 = OpConstant %uint 2
5340 ;CHECK:%_ptr_Input_uint = OpTypePointer Input %uint
5341 ;CHECK:%gl_VertexIndex = OpVariable %_ptr_Input_uint Input
5342 ;CHECK:%gl_InstanceIndex = OpVariable %_ptr_Input_uint Input
5343 ;CHECK:     %uint_5 = OpConstant %uint 5
5344 ;CHECK:     %uint_7 = OpConstant %uint 7
5345 ;CHECK:     %uint_9 = OpConstant %uint 9
5346 ;CHECK:    %uint_10 = OpConstant %uint 10
5347 ;CHECK:    %uint_45 = OpConstant %uint 45
5348 ;CHECK:        %114 = OpConstantNull %float
5349 %main = OpFunction %void None %3
5350           %5 = OpLabel
5351 ;CHECK:         %55 = OpFunctionCall %uint %inst_bindless_direct_read_3 %uint_1 %uint_0 %uint_0
5352 ;CHECK:               OpBranch %26
5353 ;CHECK:         %26 = OpLabel
5354 ;CHECK:               OpBranch %25
5355 ;CHECK:         %25 = OpLabel
5356          %20 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %int_2 %uint_1
5357          %21 = OpLoad %float %20
5358 ;CHECK-NOT:     %21 = OpLoad %float %20
5359 ;CHECK:         %29 = OpIMul %uint %uint_8 %int_2
5360 ;CHECK:         %30 = OpIAdd %uint %uint_0 %29
5361 ;CHECK:         %32 = OpIMul %uint %uint_4 %uint_1
5362 ;CHECK:         %33 = OpIAdd %uint %30 %32
5363 ;CHECK:         %35 = OpIAdd %uint %33 %uint_3
5364 ;CHECK:         %57 = OpULessThan %bool %35 %55
5365 ;CHECK:               OpSelectionMerge %58 None
5366 ;CHECK:               OpBranchConditional %57 %59 %60
5367 ;CHECK:         %59 = OpLabel
5368 ;CHECK:         %61 = OpLoad %float %20
5369 ;CHECK:               OpBranch %58
5370 ;CHECK:         %60 = OpLabel
5371 ;CHECK:        %113 = OpFunctionCall %void %inst_bindless_stream_write_5 %uint_45 %uint_4 %uint_0 %35 %55
5372 ;CHECK:               OpBranch %58
5373 ;CHECK:         %58 = OpLabel
5374 ;CHECK:        %115 = OpPhi %float %61 %59 %114 %60
5375                OpStore %v_vtxResult %21
5376 ;CHECK-NOT:           OpStore %v_vtxResult %21
5377 ;CHECK:               OpStore %v_vtxResult %115
5378                OpReturn
5379                OpFunctionEnd
5380                )" + kDirectRead3 + kStreamWrite5Vert;
5381   // clang-format on
5382 
5383   SetTargetEnv(SPV_ENV_VULKAN_1_2);
5384   ValidatorOptions()->uniform_buffer_standard_layout = true;
5385   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
5386   SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 7u, 23u, false,
5387                                                false, true, false, true);
5388 }
5389 
TEST_F(InstBindlessTest,UniformMatrixVecRefRowMajor)5390 TEST_F(InstBindlessTest, UniformMatrixVecRefRowMajor) {
5391   // The buffer-oob row major matrix vector ref check
5392   //
5393   // #version 450
5394   // #extension GL_EXT_scalar_block_layout : enable
5395   //
5396   // layout(location = 0) in highp vec4 a_position;
5397   // layout(location = 0) out highp vec2 v_vtxResult;
5398   //
5399   // layout(set = 0, binding = 0, std430, row_major) uniform Block
5400   // {
5401   //    lowp mat2 var[3][4];
5402   // };
5403   //
5404   // void main (void)
5405   // {
5406   //    v_vtxResult = var[2][3][1];
5407   // }
5408 
5409   // clang-format off
5410   const std::string text = R"(
5411                OpCapability Shader
5412 ;CHECK:               OpExtension "SPV_KHR_storage_buffer_storage_class"
5413           %1 = OpExtInstImport "GLSL.std.450"
5414                OpMemoryModel Logical GLSL450
5415                OpEntryPoint Vertex %main "main" %v_vtxResult %_ %a_position
5416 ;CHECK:        OpEntryPoint Vertex %main "main" %v_vtxResult %_ %a_position %inst_bindless_input_buffer %inst_bindless_output_buffer %gl_VertexIndex %gl_InstanceIndex
5417                OpSource GLSL 450
5418                OpSourceExtension "GL_EXT_scalar_block_layout"
5419                OpName %main "main"
5420                OpName %v_vtxResult "v_vtxResult"
5421                OpName %Block "Block"
5422                OpMemberName %Block 0 "var"
5423                OpName %_ ""
5424                OpName %a_position "a_position"
5425                OpDecorate %v_vtxResult Location 0
5426                OpDecorate %_arr_mat2v2float_uint_4 ArrayStride 32
5427                OpDecorate %_arr__arr_mat2v2float_uint_4_uint_3 ArrayStride 128
5428                OpMemberDecorate %Block 0 RowMajor
5429                OpMemberDecorate %Block 0 RelaxedPrecision
5430                OpMemberDecorate %Block 0 Offset 0
5431                OpMemberDecorate %Block 0 MatrixStride 16
5432                OpDecorate %Block Block
5433                OpDecorate %_ DescriptorSet 0
5434                OpDecorate %_ Binding 0
5435                OpDecorate %26 RelaxedPrecision
5436 ;CHECK-NOT:               OpDecorate %26 RelaxedPrecision
5437 ;CHECK:               OpDecorate %125 RelaxedPrecision
5438                OpDecorate %a_position Location 0
5439 ;CHECK:               OpDecorate %_runtimearr_uint ArrayStride 4
5440 )" + kInputDecorations + R"(
5441 ;CHECK:               OpDecorate %70 RelaxedPrecision
5442 )" + kOutputDecorations + R"(
5443 ;CHECK:               OpDecorate %gl_VertexIndex BuiltIn VertexIndex
5444 ;CHECK:               OpDecorate %gl_InstanceIndex BuiltIn InstanceIndex
5445        %void = OpTypeVoid
5446           %3 = OpTypeFunction %void
5447       %float = OpTypeFloat 32
5448     %v2float = OpTypeVector %float 2
5449 %_ptr_Output_v2float = OpTypePointer Output %v2float
5450 %v_vtxResult = OpVariable %_ptr_Output_v2float Output
5451 %mat2v2float = OpTypeMatrix %v2float 2
5452        %uint = OpTypeInt 32 0
5453      %uint_4 = OpConstant %uint 4
5454 %_arr_mat2v2float_uint_4 = OpTypeArray %mat2v2float %uint_4
5455      %uint_3 = OpConstant %uint 3
5456 %_arr__arr_mat2v2float_uint_4_uint_3 = OpTypeArray %_arr_mat2v2float_uint_4 %uint_3
5457       %Block = OpTypeStruct %_arr__arr_mat2v2float_uint_4_uint_3
5458 %_ptr_Uniform_Block = OpTypePointer Uniform %Block
5459           %_ = OpVariable %_ptr_Uniform_Block Uniform
5460         %int = OpTypeInt 32 1
5461       %int_0 = OpConstant %int 0
5462       %int_2 = OpConstant %int 2
5463       %int_3 = OpConstant %int 3
5464       %int_1 = OpConstant %int 1
5465 %_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
5466     %v4float = OpTypeVector %float 4
5467 %_ptr_Input_v4float = OpTypePointer Input %v4float
5468  %a_position = OpVariable %_ptr_Input_v4float Input
5469 ;CHECK:     %uint_0 = OpConstant %uint 0
5470 ;CHECK:   %uint_128 = OpConstant %uint 128
5471 ;CHECK:    %uint_32 = OpConstant %uint 32
5472 ;CHECK:    %uint_16 = OpConstant %uint 16
5473 ;CHECK:    %uint_19 = OpConstant %uint 19
5474 ;CHECK:     %uint_1 = OpConstant %uint 1
5475 ;CHECK:         %46 = OpTypeFunction %uint %uint %uint %uint
5476 ;CHECK:%_runtimearr_uint = OpTypeRuntimeArray %uint
5477 )" + kInputGlobals + R"(
5478 ;CHECK:%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
5479 ;CHECK:       %bool = OpTypeBool
5480 ;CHECK:         %72 = OpTypeFunction %void %uint %uint %uint %uint %uint
5481 )" + kOutputGlobals + R"(
5482 ;CHECK:    %uint_11 = OpConstant %uint 11
5483 ;CHECK:    %uint_23 = OpConstant %uint 23
5484 ;CHECK:     %uint_2 = OpConstant %uint 2
5485 ;CHECK:%_ptr_Input_uint = OpTypePointer Input %uint
5486 ;CHECK:%gl_VertexIndex = OpVariable %_ptr_Input_uint Input
5487 ;CHECK:%gl_InstanceIndex = OpVariable %_ptr_Input_uint Input
5488 ;CHECK:     %uint_5 = OpConstant %uint 5
5489 ;CHECK:     %uint_7 = OpConstant %uint 7
5490 ;CHECK:     %uint_8 = OpConstant %uint 8
5491 ;CHECK:     %uint_9 = OpConstant %uint 9
5492 ;CHECK:    %uint_10 = OpConstant %uint 10
5493 ;CHECK:    %uint_51 = OpConstant %uint 51
5494 ;CHECK:        %124 = OpConstantNull %v2float
5495        %main = OpFunction %void None %3
5496           %5 = OpLabel
5497 ;CHECK:         %64 = OpFunctionCall %uint %inst_bindless_direct_read_3 %uint_1 %uint_0 %uint_0
5498 ;CHECK:               OpBranch %31
5499 ;CHECK:         %31 = OpLabel
5500 ;CHECK:               OpBranch %30
5501 ;CHECK:         %30 = OpLabel
5502          %25 = OpAccessChain %_ptr_Uniform_v2float %_ %int_0 %int_2 %int_3 %int_1
5503          %26 = OpLoad %v2float %25
5504                OpStore %v_vtxResult %26
5505 ;CHECK-NOT:         %26 = OpLoad %v2float %25
5506 ;CHECK-NOT:               OpStore %v_vtxResult %26
5507 ;CHECK:         %34 = OpIMul %uint %uint_128 %int_2
5508 ;CHECK:         %35 = OpIAdd %uint %uint_0 %34
5509 ;CHECK:         %37 = OpIMul %uint %uint_32 %int_3
5510 ;CHECK:         %38 = OpIAdd %uint %35 %37
5511 ;CHECK:         %40 = OpIMul %uint %uint_4 %int_1
5512 ;CHECK:         %41 = OpIAdd %uint %38 %40
5513 ;CHECK:         %43 = OpIAdd %uint %41 %uint_19
5514 ;CHECK:         %66 = OpULessThan %bool %43 %64
5515 ;CHECK:               OpSelectionMerge %67 None
5516 ;CHECK:               OpBranchConditional %66 %68 %69
5517 ;CHECK:         %68 = OpLabel
5518 ;CHECK:         %70 = OpLoad %v2float %25
5519 ;CHECK:               OpBranch %67
5520 ;CHECK:         %69 = OpLabel
5521 ;CHECK:        %123 = OpFunctionCall %void %inst_bindless_stream_write_5 %uint_51 %uint_4 %uint_0 %43 %64
5522 ;CHECK:               OpBranch %67
5523 ;CHECK:         %67 = OpLabel
5524 ;CHECK:        %125 = OpPhi %v2float %70 %68 %124 %69
5525 ;CHECK:               OpStore %v_vtxResult %125
5526                OpReturn
5527                OpFunctionEnd
5528                )" + kDirectRead3 + kStreamWrite5Vert;
5529   // clang-format on
5530 
5531   SetTargetEnv(SPV_ENV_VULKAN_1_2);
5532   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
5533   SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 7u, 23u, false,
5534                                                false, true, false, true);
5535 }
5536 
TEST_F(InstBindlessTest,ImageBufferOOBRead)5537 TEST_F(InstBindlessTest, ImageBufferOOBRead) {
5538   // Texel buffer (imagebuffer) oob check for ImageRead
5539   //
5540   // #version 450
5541   // layout(set=3, binding=7, r32f) uniform readonly imageBuffer s;
5542   // layout(location=11) out vec4 x;
5543   // layout(location=13) in flat int ii;
5544   //
5545   // void main(){
5546   //    x = imageLoad(s, ii);
5547   // }
5548 
5549   // clang-format off
5550   const std::string text = R"(
5551                           OpCapability Shader
5552                           OpCapability ImageBuffer
5553 ;CHECK:                   OpCapability ImageQuery
5554 ;CHECK:                   OpExtension "SPV_KHR_storage_buffer_storage_class"
5555                      %1 = OpExtInstImport "GLSL.std.450"
5556                           OpMemoryModel Logical GLSL450
5557                           OpEntryPoint Fragment %main "main" %x %s %ii
5558                           OpExecutionMode %main OriginUpperLeft
5559                           OpSource GLSL 450
5560                           OpName %main "main"
5561                           OpName %x "x"
5562                           OpName %s "s"
5563                           OpName %ii "ii"
5564                           OpDecorate %x Location 11
5565                           OpDecorate %s DescriptorSet 3
5566                           OpDecorate %s Binding 7
5567                           OpDecorate %s NonWritable
5568                           OpDecorate %ii Flat
5569                           OpDecorate %ii Location 13
5570 ;CHECK:                   OpDecorate %_runtimearr_uint ArrayStride 4
5571 )" + kOutputDecorations + R"(
5572 ;CHECK:                   OpDecorate %gl_FragCoord BuiltIn FragCoord
5573                   %void = OpTypeVoid
5574                      %3 = OpTypeFunction %void
5575                  %float = OpTypeFloat 32
5576                %v4float = OpTypeVector %float 4
5577            %_ptr_Output_v4float = OpTypePointer Output %v4float
5578                      %x = OpVariable %_ptr_Output_v4float Output
5579                     %10 = OpTypeImage %float Buffer 0 0 0 2 R32f
5580            %_ptr_UniformConstant_10 = OpTypePointer UniformConstant %10
5581                      %s = OpVariable %_ptr_UniformConstant_10 UniformConstant
5582                    %int = OpTypeInt 32 1
5583            %_ptr_Input_int = OpTypePointer Input %int
5584                     %ii = OpVariable %_ptr_Input_int Input
5585 ;CHECK:           %uint = OpTypeInt 32 0
5586 ;CHECK:         %uint_0 = OpConstant %uint 0
5587 ;CHECK:           %bool = OpTypeBool
5588 ;CHECK:         %uint_7 = OpConstant %uint 7
5589 ;CHECK:             %35 = OpTypeFunction %void %uint %uint %uint %uint %uint
5590 ;CHECK:    %_runtimearr_uint = OpTypeRuntimeArray %uint
5591 )" + kOutputGlobals + R"(
5592 ;CHECK:    %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
5593 ;CHECK:        %uint_11 = OpConstant %uint 11
5594 ;CHECK:         %uint_4 = OpConstant %uint 4
5595 ;CHECK:         %uint_1 = OpConstant %uint 1
5596 ;CHECK:        %uint_23 = OpConstant %uint 23
5597 ;CHECK:         %uint_2 = OpConstant %uint 2
5598 ;CHECK:         %uint_3 = OpConstant %uint 3
5599 ;CHECK:    %_ptr_Input_v4float = OpTypePointer Input %v4float
5600 ;CHECK:    %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
5601 ;CHECK:         %v4uint = OpTypeVector %uint 4
5602 ;CHECK:         %uint_5 = OpConstant %uint 5
5603 ;CHECK:         %uint_8 = OpConstant %uint 8
5604 ;CHECK:         %uint_9 = OpConstant %uint 9
5605 ;CHECK:        %uint_10 = OpConstant %uint 10
5606 ;CHECK:        %uint_33 = OpConstant %uint 33
5607 ;CHECK:             %93 = OpConstantNull %v4float
5608                   %main = OpFunction %void None %3
5609                      %5 = OpLabel
5610 ;CHECK:                   OpBranch %21
5611 ;CHECK:             %21 = OpLabel
5612 ;CHECK:                   OpBranch %20
5613 ;CHECK:             %20 = OpLabel
5614 ;CHECK:                   OpBranch %19
5615 ;CHECK:             %19 = OpLabel
5616                     %13 = OpLoad %10 %s
5617                     %17 = OpLoad %int %ii
5618                     %18 = OpImageRead %v4float %13 %17
5619                           OpStore %x %18
5620 ;CHECK-NOT:         %18 = OpImageRead %v4float %13 %17
5621 ;CHECK-NOT:               OpStore %x %18
5622 ;CHECK:             %23 = OpBitcast %uint %17
5623 ;CHECK:             %25 = OpImageQuerySize %uint %13
5624 ;CHECK:             %27 = OpULessThan %bool %23 %25
5625 ;CHECK:                   OpSelectionMerge %29 None
5626 ;CHECK:                   OpBranchConditional %27 %30 %31
5627 ;CHECK:             %30 = OpLabel
5628 ;CHECK:             %32 = OpLoad %10 %s
5629 ;CHECK:             %33 = OpImageRead %v4float %32 %17
5630 ;CHECK:                   OpBranch %29
5631 ;CHECK:             %31 = OpLabel
5632 ;CHECK:             %92 = OpFunctionCall %void %inst_bindless_stream_write_5 %uint_33 %uint_7 %uint_0 %23 %25
5633 ;CHECK:                   OpBranch %29
5634 ;CHECK:             %29 = OpLabel
5635 ;CHECK:             %94 = OpPhi %v4float %33 %30 %93 %31
5636 ;CHECK:                   OpStore %x %94
5637                           OpReturn
5638                           OpFunctionEnd
5639                           )" + kStreamWrite5Frag;
5640   // clang-format on
5641 
5642   SetTargetEnv(SPV_ENV_VULKAN_1_2);
5643   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
5644   SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 7u, 23u, false,
5645                                                false, true, true, true);
5646 }
5647 
TEST_F(InstBindlessTest,ImageBufferOOBWrite)5648 TEST_F(InstBindlessTest, ImageBufferOOBWrite) {
5649   // Texel buffer (imagebuffer) oob check for ImageWrite
5650   //
5651   // #version 450
5652   // layout(set=3, binding=7, r32f) uniform readonly imageBuffer s;
5653   // layout(location=11) out vec4 x;
5654   // layout(location=13) in flat int ii;
5655   //
5656   // void main(){
5657   //    imageStore(s, ii, x);
5658   // }
5659 
5660   // clang-format off
5661   const std::string text = R"(
5662                           OpCapability Shader
5663                           OpCapability ImageBuffer
5664 ;CHECK:                   OpCapability ImageQuery
5665 ;CHECK:                   OpExtension "SPV_KHR_storage_buffer_storage_class"
5666                      %1 = OpExtInstImport "GLSL.std.450"
5667                           OpMemoryModel Logical GLSL450
5668                           OpEntryPoint Fragment %main "main" %s %ii %x
5669 ;CHECK:                   OpEntryPoint Fragment %main "main" %s %ii %x %inst_bindless_output_buffer %gl_FragCoord
5670                           OpExecutionMode %main OriginUpperLeft
5671                           OpSource GLSL 450
5672                           OpName %main "main"
5673                           OpName %s "s"
5674                           OpName %ii "ii"
5675                           OpName %x "x"
5676                           OpDecorate %s DescriptorSet 3
5677                           OpDecorate %s Binding 7
5678                           OpDecorate %s NonReadable
5679                           OpDecorate %ii Flat
5680                           OpDecorate %ii Location 13
5681                           OpDecorate %x Location 11
5682 ;CHECK:                   OpDecorate %_runtimearr_uint ArrayStride 4
5683 )" + kOutputDecorations + R"(
5684 ;CHECK:                   OpDecorate %gl_FragCoord BuiltIn FragCoord
5685                   %void = OpTypeVoid
5686                      %3 = OpTypeFunction %void
5687                  %float = OpTypeFloat 32
5688                      %7 = OpTypeImage %float Buffer 0 0 0 2 R32f
5689            %_ptr_UniformConstant_7 = OpTypePointer UniformConstant %7
5690                      %s = OpVariable %_ptr_UniformConstant_7 UniformConstant
5691                    %int = OpTypeInt 32 1
5692            %_ptr_Input_int = OpTypePointer Input %int
5693                     %ii = OpVariable %_ptr_Input_int Input
5694                %v4float = OpTypeVector %float 4
5695            %_ptr_Output_v4float = OpTypePointer Output %v4float
5696                      %x = OpVariable %_ptr_Output_v4float Output
5697 ;CHECK:           %uint = OpTypeInt 32 0
5698 ;CHECK:         %uint_0 = OpConstant %uint 0
5699 ;CHECK:           %bool = OpTypeBool
5700 ;CHECK:         %uint_7 = OpConstant %uint 7
5701 ;CHECK:             %34 = OpTypeFunction %void %uint %uint %uint %uint %uint
5702 ;CHECK:    %_runtimearr_uint = OpTypeRuntimeArray %uint
5703 )" + kOutputGlobals + R"(
5704 ;CHECK:    %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
5705 ;CHECK:        %uint_11 = OpConstant %uint 11
5706 ;CHECK:         %uint_4 = OpConstant %uint 4
5707 ;CHECK:         %uint_1 = OpConstant %uint 1
5708 ;CHECK:        %uint_23 = OpConstant %uint 23
5709 ;CHECK:         %uint_2 = OpConstant %uint 2
5710 ;CHECK:         %uint_3 = OpConstant %uint 3
5711 ;CHECK:    %_ptr_Input_v4float = OpTypePointer Input %v4float
5712 ;CHECK:    %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
5713 ;CHECK:         %v4uint = OpTypeVector %uint 4
5714 ;CHECK:         %uint_5 = OpConstant %uint 5
5715 ;CHECK:         %uint_8 = OpConstant %uint 8
5716 ;CHECK:         %uint_9 = OpConstant %uint 9
5717 ;CHECK:        %uint_10 = OpConstant %uint 10
5718 ;CHECK:        %uint_34 = OpConstant %uint 34
5719                   %main = OpFunction %void None %3
5720                      %5 = OpLabel
5721 ;CHECK:                   OpBranch %21
5722 ;CHECK:             %21 = OpLabel
5723 ;CHECK:                   OpBranch %20
5724 ;CHECK:             %20 = OpLabel
5725 ;CHECK:                   OpBranch %19
5726 ;CHECK:             %19 = OpLabel
5727                     %10 = OpLoad %7 %s
5728                     %14 = OpLoad %int %ii
5729                     %18 = OpLoad %v4float %x
5730                           OpImageWrite %10 %14 %18
5731 ;CHECK-NOT:               OpImageWrite %10 %14 %18
5732 ;CHECK:             %23 = OpBitcast %uint %14
5733 ;CHECK:             %25 = OpImageQuerySize %uint %10
5734 ;CHECK:             %27 = OpULessThan %bool %23 %25
5735 ;CHECK:                   OpSelectionMerge %29 None
5736 ;CHECK:                   OpBranchConditional %27 %30 %31
5737 ;CHECK:             %30 = OpLabel
5738 ;CHECK:             %32 = OpLoad %7 %s
5739 ;CHECK:                   OpImageWrite %32 %14 %18
5740 ;CHECK:                   OpBranch %29
5741 ;CHECK:             %31 = OpLabel
5742 ;CHECK:             %91 = OpFunctionCall %void %inst_bindless_stream_write_5 %uint_34 %uint_7 %uint_0 %23 %25
5743 ;CHECK:                   OpBranch %29
5744 ;CHECK:             %29 = OpLabel
5745                           OpReturn
5746                           OpFunctionEnd
5747                           )" + kStreamWrite5Frag;
5748   // clang-format on
5749 
5750   SetTargetEnv(SPV_ENV_VULKAN_1_2);
5751   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
5752   SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 7u, 23u, false,
5753                                                false, true, true, true);
5754 }
5755 
TEST_F(InstBindlessTest,TextureBufferOOBFetch)5756 TEST_F(InstBindlessTest, TextureBufferOOBFetch) {
5757   // Texel buffer (texturebuffer) oob check for ImageFetch
5758   //
5759   // #version 450
5760   // layout(set=3, binding=7) uniform textureBuffer s;
5761   // layout(location=11) out vec4 x;
5762   // layout(location=13) in flat int ii;
5763   //
5764   // void main(){
5765   //    x = texelFetch(s, ii);
5766   // }
5767 
5768   // clang-format off
5769   const std::string text = R"(
5770                           OpCapability Shader
5771                           OpCapability SampledBuffer
5772 ;CHECK:                   OpCapability ImageQuery
5773 ;CHECK:                   OpExtension "SPV_KHR_storage_buffer_storage_class"
5774                      %1 = OpExtInstImport "GLSL.std.450"
5775                           OpMemoryModel Logical GLSL450
5776                           OpEntryPoint Fragment %main "main" %x %s %ii
5777 ;CHECK:                   OpEntryPoint Fragment %main "main" %x %s %ii %inst_bindless_output_buffer %gl_FragCoord
5778                           OpExecutionMode %main OriginUpperLeft
5779                           OpSource GLSL 450
5780                           OpName %main "main"
5781                           OpName %x "x"
5782                           OpName %s "s"
5783                           OpName %ii "ii"
5784                           OpDecorate %x Location 11
5785                           OpDecorate %s DescriptorSet 3
5786                           OpDecorate %s Binding 7
5787                           OpDecorate %ii Flat
5788                           OpDecorate %ii Location 13
5789 ;CHECK:                   OpDecorate %_runtimearr_uint ArrayStride 4
5790 )" + kOutputDecorations + R"(
5791 ;CHECK:                   OpDecorate %gl_FragCoord BuiltIn FragCoord
5792                   %void = OpTypeVoid
5793                      %3 = OpTypeFunction %void
5794                  %float = OpTypeFloat 32
5795                %v4float = OpTypeVector %float 4
5796            %_ptr_Output_v4float = OpTypePointer Output %v4float
5797                      %x = OpVariable %_ptr_Output_v4float Output
5798                     %10 = OpTypeImage %float Buffer 0 0 0 1 Unknown
5799            %_ptr_UniformConstant_10 = OpTypePointer UniformConstant %10
5800                      %s = OpVariable %_ptr_UniformConstant_10 UniformConstant
5801                    %int = OpTypeInt 32 1
5802            %_ptr_Input_int = OpTypePointer Input %int
5803                     %ii = OpVariable %_ptr_Input_int Input
5804 ;CHECK:           %uint = OpTypeInt 32 0
5805 ;CHECK:         %uint_0 = OpConstant %uint 0
5806 ;CHECK:           %bool = OpTypeBool
5807 ;CHECK:         %uint_6 = OpConstant %uint 6
5808 ;CHECK:             %35 = OpTypeFunction %void %uint %uint %uint %uint %uint
5809 ;CHECK:    %_runtimearr_uint = OpTypeRuntimeArray %uint
5810 )" + kOutputGlobals + R"(
5811 ;CHECK:    %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
5812 ;CHECK:        %uint_11 = OpConstant %uint 11
5813 ;CHECK:         %uint_4 = OpConstant %uint 4
5814 ;CHECK:         %uint_1 = OpConstant %uint 1
5815 ;CHECK:        %uint_23 = OpConstant %uint 23
5816 ;CHECK:         %uint_2 = OpConstant %uint 2
5817 ;CHECK:         %uint_3 = OpConstant %uint 3
5818 ;CHECK:    %_ptr_Input_v4float = OpTypePointer Input %v4float
5819 ;CHECK:    %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
5820 ;CHECK:         %v4uint = OpTypeVector %uint 4
5821 ;CHECK:         %uint_5 = OpConstant %uint 5
5822 ;CHECK:         %uint_7 = OpConstant %uint 7
5823 ;CHECK:         %uint_8 = OpConstant %uint 8
5824 ;CHECK:         %uint_9 = OpConstant %uint 9
5825 ;CHECK:        %uint_10 = OpConstant %uint 10
5826 ;CHECK:        %uint_32 = OpConstant %uint 32
5827 ;CHECK:             %94 = OpConstantNull %v4float
5828                   %main = OpFunction %void None %3
5829                      %5 = OpLabel
5830 ;CHECK:                   OpBranch %21
5831 ;CHECK:             %21 = OpLabel
5832 ;CHECK:                   OpBranch %20
5833 ;CHECK:             %20 = OpLabel
5834 ;CHECK:                   OpBranch %19
5835 ;CHECK:             %19 = OpLabel
5836                     %13 = OpLoad %10 %s
5837                     %17 = OpLoad %int %ii
5838                     %18 = OpImageFetch %v4float %13 %17
5839                           OpStore %x %18
5840 ;CHECK-NOT:         %18 = OpImageFetch %v4float %13 %17
5841 ;CHECK-NOT:               OpStore %x %18
5842 ;CHECK:             %23 = OpBitcast %uint %17
5843 ;CHECK:             %25 = OpImageQuerySize %uint %13
5844 ;CHECK:             %27 = OpULessThan %bool %23 %25
5845 ;CHECK:                   OpSelectionMerge %29 None
5846 ;CHECK:                   OpBranchConditional %27 %30 %31
5847 ;CHECK:             %30 = OpLabel
5848 ;CHECK:             %32 = OpLoad %10 %s
5849 ;CHECK:             %33 = OpImageFetch %v4float %32 %17
5850 ;CHECK:                   OpBranch %29
5851 ;CHECK:             %31 = OpLabel
5852 ;CHECK:             %93 = OpFunctionCall %void %inst_bindless_stream_write_5 %uint_32 %uint_6 %uint_0 %23 %25
5853 ;CHECK:                   OpBranch %29
5854 ;CHECK:             %29 = OpLabel
5855 ;CHECK:             %95 = OpPhi %v4float %33 %30 %94 %31
5856 ;CHECK:                   OpStore %x %95
5857                           OpReturn
5858                           OpFunctionEnd
5859                           )" + kStreamWrite5Frag;
5860   // clang-format on
5861 
5862   SetTargetEnv(SPV_ENV_VULKAN_1_2);
5863   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
5864   SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 7u, 23u, false,
5865                                                false, true, true, true);
5866 }
5867 
TEST_F(InstBindlessTest,SamplerBufferOOBFetch)5868 TEST_F(InstBindlessTest, SamplerBufferOOBFetch) {
5869   // Texel buffer (samplerbuffer) oob check for ImageFetch
5870   //
5871   // #version 450
5872   // layout(set=3, binding=7) uniform samplerBuffer s;
5873   // layout(location=11) out vec4 x;
5874   // layout(location=13) in flat int ii;
5875   //
5876   // void main(){
5877   //    x = texelFetch(s, ii);
5878   // }
5879 
5880   // clang-format off
5881   const std::string text = R"(
5882                           OpCapability Shader
5883                           OpCapability SampledBuffer
5884 ;CHECK:                   OpCapability ImageQuery
5885 ;CHECK:                   OpExtension "SPV_KHR_storage_buffer_storage_class"
5886                      %1 = OpExtInstImport "GLSL.std.450"
5887                           OpMemoryModel Logical GLSL450
5888                           OpEntryPoint Fragment %main "main" %x %s %ii
5889 ;CHECK:                   OpEntryPoint Fragment %main "main" %x %s %ii %inst_bindless_output_buffer %gl_FragCoord
5890                           OpExecutionMode %main OriginUpperLeft
5891                           OpSource GLSL 450
5892                           OpName %main "main"
5893                           OpName %x "x"
5894                           OpName %s "s"
5895                           OpName %ii "ii"
5896                           OpDecorate %x Location 11
5897                           OpDecorate %s DescriptorSet 3
5898                           OpDecorate %s Binding 7
5899                           OpDecorate %ii Flat
5900                           OpDecorate %ii Location 13
5901 ;CHECK:                   OpDecorate %_runtimearr_uint ArrayStride 4
5902 )" + kOutputDecorations + R"(
5903 ;CHECK:                   OpDecorate %gl_FragCoord BuiltIn FragCoord
5904                   %void = OpTypeVoid
5905                      %3 = OpTypeFunction %void
5906                  %float = OpTypeFloat 32
5907                %v4float = OpTypeVector %float 4
5908            %_ptr_Output_v4float = OpTypePointer Output %v4float
5909                      %x = OpVariable %_ptr_Output_v4float Output
5910                     %10 = OpTypeImage %float Buffer 0 0 0 1 Unknown
5911                     %11 = OpTypeSampledImage %10
5912            %_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
5913                      %s = OpVariable %_ptr_UniformConstant_11 UniformConstant
5914                    %int = OpTypeInt 32 1
5915            %_ptr_Input_int = OpTypePointer Input %int
5916                     %ii = OpVariable %_ptr_Input_int Input
5917 ;CHECK:           %uint = OpTypeInt 32 0
5918 ;CHECK:         %uint_0 = OpConstant %uint 0
5919 ;CHECK:           %bool = OpTypeBool
5920 ;CHECK:         %uint_6 = OpConstant %uint 6
5921 ;CHECK:             %38 = OpTypeFunction %void %uint %uint %uint %uint %uint
5922 ;CHECK:    %_runtimearr_uint = OpTypeRuntimeArray %uint
5923 )" + kOutputGlobals + R"(
5924 ;CHECK:    %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
5925 ;CHECK:        %uint_11 = OpConstant %uint 11
5926 ;CHECK:         %uint_4 = OpConstant %uint 4
5927 ;CHECK:         %uint_1 = OpConstant %uint 1
5928 ;CHECK:        %uint_23 = OpConstant %uint 23
5929 ;CHECK:         %uint_2 = OpConstant %uint 2
5930 ;CHECK:         %uint_3 = OpConstant %uint 3
5931 ;CHECK:    %_ptr_Input_v4float = OpTypePointer Input %v4float
5932 ;CHECK:    %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
5933 ;CHECK:         %v4uint = OpTypeVector %uint 4
5934 ;CHECK:         %uint_5 = OpConstant %uint 5
5935 ;CHECK:         %uint_7 = OpConstant %uint 7
5936 ;CHECK:         %uint_8 = OpConstant %uint 8
5937 ;CHECK:         %uint_9 = OpConstant %uint 9
5938 ;CHECK:        %uint_10 = OpConstant %uint 10
5939 ;CHECK:        %uint_34 = OpConstant %uint 34
5940 ;CHECK:             %97 = OpConstantNull %v4float
5941                   %main = OpFunction %void None %3
5942                      %5 = OpLabel
5943 ;CHECK:                   OpBranch %23
5944 ;CHECK:             %23 = OpLabel
5945 ;CHECK:                   OpBranch %22
5946 ;CHECK:             %22 = OpLabel
5947 ;CHECK:                   OpBranch %21
5948 ;CHECK:             %21 = OpLabel
5949                     %14 = OpLoad %11 %s
5950                     %18 = OpLoad %int %ii
5951                     %19 = OpImage %10 %14
5952                     %20 = OpImageFetch %v4float %19 %18
5953                           OpStore %x %20
5954 ;CHECK-NOT:         %20 = OpImageFetch %v4float %19 %18
5955 ;CHECK-NOT:               OpStore %x %20
5956 ;CHECK:             %25 = OpBitcast %uint %18
5957 ;CHECK:             %27 = OpImageQuerySize %uint %19
5958 ;CHECK:             %29 = OpULessThan %bool %25 %27
5959 ;CHECK:                   OpSelectionMerge %31 None
5960 ;CHECK:                   OpBranchConditional %29 %32 %33
5961 ;CHECK:             %32 = OpLabel
5962 ;CHECK:             %34 = OpLoad %11 %s
5963 ;CHECK:             %35 = OpImage %10 %34
5964 ;CHECK:             %36 = OpImageFetch %v4float %35 %18
5965 ;CHECK:                   OpBranch %31
5966 ;CHECK:             %33 = OpLabel
5967 ;CHECK:             %96 = OpFunctionCall %void %inst_bindless_stream_write_5 %uint_34 %uint_6 %uint_0 %25 %27
5968 ;CHECK:                   OpBranch %31
5969 ;CHECK:             %31 = OpLabel
5970 ;CHECK:             %98 = OpPhi %v4float %36 %32 %97 %33
5971 ;CHECK:                   OpStore %x %98
5972                           OpReturn
5973                           OpFunctionEnd
5974                           )" + kStreamWrite5Frag;
5975   // clang-format on
5976 
5977   SetTargetEnv(SPV_ENV_VULKAN_1_2);
5978   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
5979   SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 7u, 23u, false,
5980                                                false, true, true, true);
5981 }
5982 
TEST_F(InstBindlessTest,SamplerBufferConstructorOOBFetch)5983 TEST_F(InstBindlessTest, SamplerBufferConstructorOOBFetch) {
5984   // Texel buffer (samplerbuffer constructor) oob check for ImageFetch
5985   //
5986   // #version 450
5987   // layout(set=3, binding=7) uniform textureBuffer tBuf;
5988   // layout(set=3, binding=8) uniform sampler s;
5989   // layout(location=11) out vec4 x;
5990   // layout(location=13) in flat int ii;
5991   //
5992   // void main(){
5993   //    x = texelFetch(samplerBuffer(tBuf, s), ii);
5994   // }
5995 
5996   // clang-format off
5997   const std::string text = R"(
5998                           OpCapability Shader
5999                           OpCapability SampledBuffer
6000 ;CHECK:                   OpCapability ImageQuery
6001 ;CHECK:                   OpExtension "SPV_KHR_storage_buffer_storage_class"
6002                      %1 = OpExtInstImport "GLSL.std.450"
6003                           OpMemoryModel Logical GLSL450
6004                           OpEntryPoint Fragment %main "main" %x %tBuf %s %ii
6005 ;CHECK:                   OpEntryPoint Fragment %main "main" %x %tBuf %s %ii %inst_bindless_output_buffer %gl_FragCoord
6006                           OpExecutionMode %main OriginUpperLeft
6007                           OpSource GLSL 450
6008                           OpName %main "main"
6009                           OpName %x "x"
6010                           OpName %tBuf "tBuf"
6011                           OpName %s "s"
6012                           OpName %ii "ii"
6013                           OpDecorate %x Location 11
6014                           OpDecorate %tBuf DescriptorSet 3
6015                           OpDecorate %tBuf Binding 7
6016                           OpDecorate %s DescriptorSet 3
6017                           OpDecorate %s Binding 8
6018                           OpDecorate %ii Flat
6019                           OpDecorate %ii Location 13
6020 ;CHECK:                   OpDecorate %_runtimearr_uint ArrayStride 4
6021 )" + kOutputDecorations + R"(
6022 ;CHECK:                   OpDecorate %gl_FragCoord BuiltIn FragCoord
6023                   %void = OpTypeVoid
6024                      %3 = OpTypeFunction %void
6025                  %float = OpTypeFloat 32
6026                %v4float = OpTypeVector %float 4
6027            %_ptr_Output_v4float = OpTypePointer Output %v4float
6028                      %x = OpVariable %_ptr_Output_v4float Output
6029                     %10 = OpTypeImage %float Buffer 0 0 0 1 Unknown
6030            %_ptr_UniformConstant_10 = OpTypePointer UniformConstant %10
6031                   %tBuf = OpVariable %_ptr_UniformConstant_10 UniformConstant
6032                     %14 = OpTypeSampler
6033            %_ptr_UniformConstant_14 = OpTypePointer UniformConstant %14
6034                      %s = OpVariable %_ptr_UniformConstant_14 UniformConstant
6035                     %18 = OpTypeSampledImage %10
6036                    %int = OpTypeInt 32 1
6037            %_ptr_Input_int = OpTypePointer Input %int
6038                     %ii = OpVariable %_ptr_Input_int Input
6039 ;CHECK:           %uint = OpTypeInt 32 0
6040 ;CHECK:         %uint_0 = OpConstant %uint 0
6041 ;CHECK:           %bool = OpTypeBool
6042 ;CHECK:         %uint_6 = OpConstant %uint 6
6043 ;CHECK:             %44 = OpTypeFunction %void %uint %uint %uint %uint %uint
6044 ;CHECK:    %_runtimearr_uint = OpTypeRuntimeArray %uint
6045 )" + kOutputGlobals + R"(
6046 ;CHECK:    %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
6047 ;CHECK:        %uint_11 = OpConstant %uint 11
6048 ;CHECK:         %uint_4 = OpConstant %uint 4
6049 ;CHECK:         %uint_1 = OpConstant %uint 1
6050 ;CHECK:        %uint_23 = OpConstant %uint 23
6051 ;CHECK:         %uint_2 = OpConstant %uint 2
6052 ;CHECK:         %uint_3 = OpConstant %uint 3
6053 ;CHECK:    %_ptr_Input_v4float = OpTypePointer Input %v4float
6054 ;CHECK:    %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
6055 ;CHECK:         %v4uint = OpTypeVector %uint 4
6056 ;CHECK:         %uint_5 = OpConstant %uint 5
6057 ;CHECK:         %uint_7 = OpConstant %uint 7
6058 ;CHECK:         %uint_8 = OpConstant %uint 8
6059 ;CHECK:         %uint_9 = OpConstant %uint 9
6060 ;CHECK:        %uint_10 = OpConstant %uint 10
6061 ;CHECK:        %uint_42 = OpConstant %uint 42
6062 ;CHECK:            %103 = OpConstantNull %v4float
6063                   %main = OpFunction %void None %3
6064                      %5 = OpLabel
6065 ;CHECK:                   OpBranch %28
6066 ;CHECK:             %28 = OpLabel
6067 ;CHECK:                   OpBranch %27
6068 ;CHECK:             %27 = OpLabel
6069 ;CHECK:                   OpBranch %26
6070 ;CHECK:             %26 = OpLabel
6071                     %13 = OpLoad %10 %tBuf
6072                     %17 = OpLoad %14 %s
6073                     %19 = OpSampledImage %18 %13 %17
6074                     %23 = OpLoad %int %ii
6075                     %24 = OpImage %10 %19
6076                     %25 = OpImageFetch %v4float %24 %23
6077                           OpStore %x %25
6078 ;CHECK-NOT:         %25 = OpImageFetch %v4float %24 %23
6079 ;CHECK-NOT:               OpStore %x %25
6080 ;CHECK:             %30 = OpBitcast %uint %23
6081 ;CHECK:             %32 = OpImageQuerySize %uint %24
6082 ;CHECK:             %34 = OpULessThan %bool %30 %32
6083 ;CHECK:                   OpSelectionMerge %36 None
6084 ;CHECK:                   OpBranchConditional %34 %37 %38
6085 ;CHECK:             %37 = OpLabel
6086 ;CHECK:             %39 = OpLoad %10 %tBuf
6087 ;CHECK:             %40 = OpSampledImage %18 %39 %17
6088 ;CHECK:             %41 = OpImage %10 %40
6089 ;CHECK:             %42 = OpImageFetch %v4float %41 %23
6090 ;CHECK:                   OpBranch %36
6091 ;CHECK:             %38 = OpLabel
6092 ;CHECK:            %102 = OpFunctionCall %void %inst_bindless_stream_write_5 %uint_42 %uint_6 %uint_0 %30 %32
6093 ;CHECK:                   OpBranch %36
6094 ;CHECK:             %36 = OpLabel
6095 ;CHECK:            %104 = OpPhi %v4float %42 %37 %103 %38
6096 ;CHECK:                   OpStore %x %104
6097                           OpReturn
6098                           OpFunctionEnd
6099                           )" + kStreamWrite5Frag;
6100   // clang-format on
6101 
6102   SetTargetEnv(SPV_ENV_VULKAN_1_2);
6103   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
6104   SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 7u, 23u, false,
6105                                                false, true, true, true);
6106 }
6107 
6108 // TODO(greg-lunarg): Add tests to verify handling of these cases:
6109 //
6110 //   Compute shader
6111 //   Geometry shader
6112 //   Tessellation control shader
6113 //   Tessellation eval shader
6114 //   OpImage
6115 //   SampledImage variable
6116 
6117 }  // namespace
6118 }  // namespace opt
6119 }  // namespace spvtools
6120