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