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