1 // Copyright (c) 2022 The Khronos Group Inc.
2 // Copyright (c) 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 #include <vector>
17
18 #include "test/opt/pass_fixture.h"
19 #include "test/opt/pass_utils.h"
20
21 namespace spvtools {
22 namespace opt {
23 namespace {
24
25 using ElimDeadIOComponentsTest = PassTest<::testing::Test>;
26
TEST_F(ElimDeadIOComponentsTest, ElimOneConstantIndex)27 TEST_F(ElimDeadIOComponentsTest, ElimOneConstantIndex) {
28 // Should reduce to uv[2]
29 //
30 // #version 450
31 //
32 // layout(location = 0) in vec4 uv[8];
33 //
34 // out gl_PerVertex {
35 // vec4 gl_Position;
36 // };
37 //
38 // void main()
39 // {
40 // gl_Position = uv[1];
41 // }
42 const std::string text = R"(
43 OpCapability Shader
44 %1 = OpExtInstImport "GLSL.std.450"
45 OpMemoryModel Logical GLSL450
46 OpEntryPoint Vertex %main "main" %_ %uv
47 OpSource GLSL 450
48 OpName %main "main"
49 OpName %gl_PerVertex "gl_PerVertex"
50 OpMemberName %gl_PerVertex 0 "gl_Position"
51 OpName %_ ""
52 OpName %uv "uv"
53 OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
54 OpDecorate %gl_PerVertex Block
55 OpDecorate %uv Location 0
56 %void = OpTypeVoid
57 %3 = OpTypeFunction %void
58 %float = OpTypeFloat 32
59 %v4float = OpTypeVector %float 4
60 %gl_PerVertex = OpTypeStruct %v4float
61 %_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
62 %_ = OpVariable %_ptr_Output_gl_PerVertex Output
63 %int = OpTypeInt 32 1
64 %int_0 = OpConstant %int 0
65 %uint = OpTypeInt 32 0
66 %uint_8 = OpConstant %uint 8
67 %_arr_v4float_uint_8 = OpTypeArray %v4float %uint_8
68 %_ptr_Input__arr_v4float_uint_8 = OpTypePointer Input %_arr_v4float_uint_8
69 %uv = OpVariable %_ptr_Input__arr_v4float_uint_8 Input
70 %int_1 = OpConstant %int 1
71 %_ptr_Input_v4float = OpTypePointer Input %v4float
72 %_ptr_Output_v4float = OpTypePointer Output %v4float
73 ;CHECK-NOT: %uv = OpVariable %_ptr_Input__arr_v4float_uint_8 Input
74 ;CHECK: %uv = OpVariable %_ptr_Input__arr_v4float_uint_2 Input
75 %main = OpFunction %void None %3
76 %5 = OpLabel
77 %20 = OpAccessChain %_ptr_Input_v4float %uv %int_1
78 %21 = OpLoad %v4float %20
79 %23 = OpAccessChain %_ptr_Output_v4float %_ %int_0
80 OpStore %23 %21
81 OpReturn
82 OpFunctionEnd
83 )";
84
85 SetTargetEnv(SPV_ENV_VULKAN_1_3);
86 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
87 SinglePassRunAndMatch<EliminateDeadIOComponentsPass>(
88 text, true, spv::StorageClass::Input, false);
89 }
90
TEST_F(ElimDeadIOComponentsTest, ElimOneConstantIndexInBounds)91 TEST_F(ElimDeadIOComponentsTest, ElimOneConstantIndexInBounds) {
92 // Same as ElimOneConstantIndex but with OpInBoundsAccessChain
93 const std::string text = R"(
94 OpCapability Shader
95 %1 = OpExtInstImport "GLSL.std.450"
96 OpMemoryModel Logical GLSL450
97 OpEntryPoint Vertex %main "main" %_ %uv
98 OpSource GLSL 450
99 OpName %main "main"
100 OpName %gl_PerVertex "gl_PerVertex"
101 OpMemberName %gl_PerVertex 0 "gl_Position"
102 OpName %_ ""
103 OpName %uv "uv"
104 OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
105 OpDecorate %gl_PerVertex Block
106 OpDecorate %uv Location 0
107 %void = OpTypeVoid
108 %3 = OpTypeFunction %void
109 %float = OpTypeFloat 32
110 %v4float = OpTypeVector %float 4
111 %gl_PerVertex = OpTypeStruct %v4float
112 %_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
113 %_ = OpVariable %_ptr_Output_gl_PerVertex Output
114 %int = OpTypeInt 32 1
115 %int_0 = OpConstant %int 0
116 %uint = OpTypeInt 32 0
117 %uint_8 = OpConstant %uint 8
118 %_arr_v4float_uint_8 = OpTypeArray %v4float %uint_8
119 %_ptr_Input__arr_v4float_uint_8 = OpTypePointer Input %_arr_v4float_uint_8
120 %uv = OpVariable %_ptr_Input__arr_v4float_uint_8 Input
121 %int_1 = OpConstant %int 1
122 %_ptr_Input_v4float = OpTypePointer Input %v4float
123 %_ptr_Output_v4float = OpTypePointer Output %v4float
124 ;CHECK-NOT: %uv = OpVariable %_ptr_Input__arr_v4float_uint_8 Input
125 ;CHECK: %uv = OpVariable %_ptr_Input__arr_v4float_uint_2 Input
126 %main = OpFunction %void None %3
127 %5 = OpLabel
128 %20 = OpInBoundsAccessChain %_ptr_Input_v4float %uv %int_1
129 %21 = OpLoad %v4float %20
130 %23 = OpAccessChain %_ptr_Output_v4float %_ %int_0
131 OpStore %23 %21
132 OpReturn
133 OpFunctionEnd
134 )";
135
136 SetTargetEnv(SPV_ENV_VULKAN_1_3);
137 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
138 SinglePassRunAndMatch<EliminateDeadIOComponentsPass>(
139 text, true, spv::StorageClass::Input, false);
140 }
141
TEST_F(ElimDeadIOComponentsTest, ElimTwoConstantIndices)142 TEST_F(ElimDeadIOComponentsTest, ElimTwoConstantIndices) {
143 // Should reduce to uv[4]
144 //
145 // #version 450
146 //
147 // layout(location = 0) in vec4 uv[8];
148 //
149 // out gl_PerVertex {
150 // vec4 gl_Position;
151 // };
152 //
153 // void main()
154 // {
155 // gl_Position = uv[1] + uv[3];
156 // }
157 const std::string text = R"(
158 OpCapability Shader
159 %1 = OpExtInstImport "GLSL.std.450"
160 OpMemoryModel Logical GLSL450
161 OpEntryPoint Vertex %main "main" %_ %uv
162 OpSource GLSL 450
163 OpName %main "main"
164 OpName %gl_PerVertex "gl_PerVertex"
165 OpMemberName %gl_PerVertex 0 "gl_Position"
166 OpName %_ ""
167 OpName %uv "uv"
168 OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
169 OpDecorate %gl_PerVertex Block
170 OpDecorate %uv Location 0
171 %void = OpTypeVoid
172 %3 = OpTypeFunction %void
173 %float = OpTypeFloat 32
174 %v4float = OpTypeVector %float 4
175 %gl_PerVertex = OpTypeStruct %v4float
176 %_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
177 %_ = OpVariable %_ptr_Output_gl_PerVertex Output
178 %int = OpTypeInt 32 1
179 %int_0 = OpConstant %int 0
180 %uint = OpTypeInt 32 0
181 %uint_8 = OpConstant %uint 8
182 %_arr_v4float_uint_8 = OpTypeArray %v4float %uint_8
183 %_ptr_Input__arr_v4float_uint_8 = OpTypePointer Input %_arr_v4float_uint_8
184 %uv = OpVariable %_ptr_Input__arr_v4float_uint_8 Input
185 %int_1 = OpConstant %int 1
186 %_ptr_Input_v4float = OpTypePointer Input %v4float
187 %int_3 = OpConstant %int 3
188 %_ptr_Output_v4float = OpTypePointer Output %v4float
189 ;CHECK-NOT: %uv = OpVariable %_ptr_Input__arr_v4float_uint_8 Input
190 ;CHECK: %uv = OpVariable %_ptr_Input__arr_v4float_uint_4 Input
191 %main = OpFunction %void None %3
192 %5 = OpLabel
193 %20 = OpAccessChain %_ptr_Input_v4float %uv %int_1
194 %21 = OpLoad %v4float %20
195 %23 = OpAccessChain %_ptr_Input_v4float %uv %int_3
196 %24 = OpLoad %v4float %23
197 %25 = OpFAdd %v4float %21 %24
198 %27 = OpAccessChain %_ptr_Output_v4float %_ %int_0
199 OpStore %27 %25
200 OpReturn
201 OpFunctionEnd
202 )";
203
204 SetTargetEnv(SPV_ENV_VULKAN_1_3);
205 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
206 SinglePassRunAndMatch<EliminateDeadIOComponentsPass>(
207 text, true, spv::StorageClass::Input, false);
208 }
209
TEST_F(ElimDeadIOComponentsTest, NoElimMaxConstantIndex)210 TEST_F(ElimDeadIOComponentsTest, NoElimMaxConstantIndex) {
211 // Should not reduce uv[8] because of max index of 7
212 //
213 // #version 450
214 //
215 // layout(location = 0) in vec4 uv[8];
216 //
217 // out gl_PerVertex {
218 // vec4 gl_Position;
219 // };
220 //
221 // void main()
222 // {
223 // gl_Position = uv[1] + uv[7];
224 // }
225 const std::string text = R"(
226 OpCapability Shader
227 %1 = OpExtInstImport "GLSL.std.450"
228 OpMemoryModel Logical GLSL450
229 OpEntryPoint Vertex %main "main" %_ %uv
230 OpSource GLSL 450
231 OpName %main "main"
232 OpName %gl_PerVertex "gl_PerVertex"
233 OpMemberName %gl_PerVertex 0 "gl_Position"
234 OpName %_ ""
235 OpName %uv "uv"
236 OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
237 OpDecorate %gl_PerVertex Block
238 OpDecorate %uv Location 0
239 %void = OpTypeVoid
240 %3 = OpTypeFunction %void
241 %float = OpTypeFloat 32
242 %v4float = OpTypeVector %float 4
243 %gl_PerVertex = OpTypeStruct %v4float
244 %_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
245 %_ = OpVariable %_ptr_Output_gl_PerVertex Output
246 %int = OpTypeInt 32 1
247 %int_0 = OpConstant %int 0
248 %uint = OpTypeInt 32 0
249 %uint_8 = OpConstant %uint 8
250 %_arr_v4float_uint_8 = OpTypeArray %v4float %uint_8
251 %_ptr_Input__arr_v4float_uint_8 = OpTypePointer Input %_arr_v4float_uint_8
252 %uv = OpVariable %_ptr_Input__arr_v4float_uint_8 Input
253 %int_1 = OpConstant %int 1
254 %_ptr_Input_v4float = OpTypePointer Input %v4float
255 %int_7 = OpConstant %int 7
256 %_ptr_Output_v4float = OpTypePointer Output %v4float
257 ;CHECK: %uv = OpVariable %_ptr_Input__arr_v4float_uint_8 Input
258 %main = OpFunction %void None %3
259 %5 = OpLabel
260 %20 = OpAccessChain %_ptr_Input_v4float %uv %int_1
261 %21 = OpLoad %v4float %20
262 %23 = OpAccessChain %_ptr_Input_v4float %uv %int_7
263 %24 = OpLoad %v4float %23
264 %25 = OpFAdd %v4float %21 %24
265 %27 = OpAccessChain %_ptr_Output_v4float %_ %int_0
266 OpStore %27 %25
267 OpReturn
268 OpFunctionEnd
269 )";
270
271 SetTargetEnv(SPV_ENV_VULKAN_1_3);
272 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
273 SinglePassRunAndMatch<EliminateDeadIOComponentsPass>(
274 text, true, spv::StorageClass::Input, false);
275 }
276
TEST_F(ElimDeadIOComponentsTest, NoElimNonConstantIndex)277 TEST_F(ElimDeadIOComponentsTest, NoElimNonConstantIndex) {
278 // Should not reduce uv[8] because of non-constant index of ui
279 //
280 // #version 450
281 //
282 // layout(location = 0) in vec4 uv[8];
283 //
284 // out gl_PerVertex {
285 // vec4 gl_Position;
286 // };
287 //
288 // uniform ubname {
289 // int ui;
290 // } ubinst;
291 //
292 // void main()
293 // {
294 // gl_Position = uv[1] + uv[ubinst.ui];
295 // }
296 const std::string text = R"(
297 OpCapability Shader
298 %1 = OpExtInstImport "GLSL.std.450"
299 OpMemoryModel Logical GLSL450
300 OpEntryPoint Vertex %main "main" %_ %uv %ubinst
301 OpSource GLSL 450
302 OpName %main "main"
303 OpName %gl_PerVertex "gl_PerVertex"
304 OpMemberName %gl_PerVertex 0 "gl_Position"
305 OpName %_ ""
306 OpName %uv "uv"
307 OpName %ubname "ubname"
308 OpMemberName %ubname 0 "ui"
309 OpName %ubinst "ubinst"
310 OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
311 OpDecorate %gl_PerVertex Block
312 OpDecorate %uv Location 0
313 OpMemberDecorate %ubname 0 Offset 0
314 OpDecorate %ubname Block
315 OpDecorate %ubinst DescriptorSet 0
316 OpDecorate %ubinst Binding 0
317 %void = OpTypeVoid
318 %3 = OpTypeFunction %void
319 %float = OpTypeFloat 32
320 %v4float = OpTypeVector %float 4
321 %gl_PerVertex = OpTypeStruct %v4float
322 %_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
323 %_ = OpVariable %_ptr_Output_gl_PerVertex Output
324 %int = OpTypeInt 32 1
325 %int_0 = OpConstant %int 0
326 %uint = OpTypeInt 32 0
327 %uint_8 = OpConstant %uint 8
328 %_arr_v4float_uint_8 = OpTypeArray %v4float %uint_8
329 %_ptr_Input__arr_v4float_uint_8 = OpTypePointer Input %_arr_v4float_uint_8
330 %uv = OpVariable %_ptr_Input__arr_v4float_uint_8 Input
331 %int_1 = OpConstant %int 1
332 %_ptr_Input_v4float = OpTypePointer Input %v4float
333 %ubname = OpTypeStruct %int
334 %_ptr_Uniform_ubname = OpTypePointer Uniform %ubname
335 %ubinst = OpVariable %_ptr_Uniform_ubname Uniform
336 %_ptr_Uniform_int = OpTypePointer Uniform %int
337 %_ptr_Output_v4float = OpTypePointer Output %v4float
338 ;CHECK: %uv = OpVariable %_ptr_Input__arr_v4float_uint_8 Input
339 %main = OpFunction %void None %3
340 %5 = OpLabel
341 %20 = OpAccessChain %_ptr_Input_v4float %uv %int_1
342 %21 = OpLoad %v4float %20
343 %26 = OpAccessChain %_ptr_Uniform_int %ubinst %int_0
344 %27 = OpLoad %int %26
345 %28 = OpAccessChain %_ptr_Input_v4float %uv %27
346 %29 = OpLoad %v4float %28
347 %30 = OpFAdd %v4float %21 %29
348 %32 = OpAccessChain %_ptr_Output_v4float %_ %int_0
349 OpStore %32 %30
350 OpReturn
351 OpFunctionEnd
352 )";
353
354 SetTargetEnv(SPV_ENV_VULKAN_1_3);
355 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
356 SinglePassRunAndMatch<EliminateDeadIOComponentsPass>(
357 text, true, spv::StorageClass::Input, false);
358 }
359
TEST_F(ElimDeadIOComponentsTest, NoElimNonIndexedAccessChain)360 TEST_F(ElimDeadIOComponentsTest, NoElimNonIndexedAccessChain) {
361 // Should not change due to non-indexed access chain
362 const std::string text = R"(
363 OpCapability Shader
364 %1 = OpExtInstImport "GLSL.std.450"
365 OpMemoryModel Logical GLSL450
366 OpEntryPoint Vertex %main "main" %_ %uv
367 OpSource GLSL 450
368 OpName %main "main"
369 OpName %gl_PerVertex "gl_PerVertex"
370 OpMemberName %gl_PerVertex 0 "gl_Position"
371 OpName %_ ""
372 OpName %uv "uv"
373 OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
374 OpDecorate %gl_PerVertex Block
375 OpDecorate %uv Location 0
376 %void = OpTypeVoid
377 %3 = OpTypeFunction %void
378 %float = OpTypeFloat 32
379 %v4float = OpTypeVector %float 4
380 %gl_PerVertex = OpTypeStruct %v4float
381 %_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
382 %_ = OpVariable %_ptr_Output_gl_PerVertex Output
383 %int = OpTypeInt 32 1
384 %int_0 = OpConstant %int 0
385 %uint = OpTypeInt 32 0
386 %uint_8 = OpConstant %uint 8
387 %_arr_v4float_uint_8 = OpTypeArray %v4float %uint_8
388 %_ptr_Input__arr_v4float_uint_8 = OpTypePointer Input %_arr_v4float_uint_8
389 %uv = OpVariable %_ptr_Input__arr_v4float_uint_8 Input
390 %int_1 = OpConstant %int 1
391 %_ptr_Input_v4float = OpTypePointer Input %v4float
392 %_ptr_Output_v4float = OpTypePointer Output %v4float
393 ;CHECK: %uv = OpVariable %_ptr_Input__arr_v4float_uint_8 Input
394 %main = OpFunction %void None %3
395 %5 = OpLabel
396 %20 = OpAccessChain %_ptr_Input__arr_v4float_uint_8 %uv
397 OpReturn
398 OpFunctionEnd
399 )";
400
401 SetTargetEnv(SPV_ENV_VULKAN_1_3);
402 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
403 SinglePassRunAndMatch<EliminateDeadIOComponentsPass>(
404 text, true, spv::StorageClass::Input, false);
405 }
406
TEST_F(ElimDeadIOComponentsTest, ElimStructMember)407 TEST_F(ElimDeadIOComponentsTest, ElimStructMember) {
408 // Should eliminate uv
409 //
410 // #version 450
411 //
412 // in Vertex {
413 // vec4 Cd;
414 // vec2 uv;
415 // } iVert;
416 //
417 // out vec4 fragColor;
418 //
419 // void main()
420 // {
421 // vec4 color = vec4(iVert.Cd);
422 // fragColor = color;
423 // }
424 const std::string text = R"(
425 OpCapability Shader
426 %1 = OpExtInstImport "GLSL.std.450"
427 OpMemoryModel Logical GLSL450
428 OpEntryPoint Fragment %main "main" %iVert %fragColor
429 OpExecutionMode %main OriginUpperLeft
430 OpSource GLSL 450
431 OpName %main "main"
432 OpName %Vertex "Vertex"
433 OpMemberName %Vertex 0 "Cd"
434 OpMemberName %Vertex 1 "uv"
435 OpName %iVert "iVert"
436 OpName %fragColor "fragColor"
437 OpDecorate %Vertex Block
438 OpDecorate %iVert Location 0
439 OpDecorate %fragColor Location 0
440 %void = OpTypeVoid
441 %3 = OpTypeFunction %void
442 %float = OpTypeFloat 32
443 %v4float = OpTypeVector %float 4
444 %v2float = OpTypeVector %float 2
445 %Vertex = OpTypeStruct %v4float %v2float
446 ; CHECK: %Vertex = OpTypeStruct %v4float %v2float
447 ; CHECK: %Vertex_0 = OpTypeStruct %v4float
448 %_ptr_Input_Vertex = OpTypePointer Input %Vertex
449 ; CHECK: [[pty:%\w+]] = OpTypePointer Input %Vertex_0
450 %iVert = OpVariable %_ptr_Input_Vertex Input
451 ; CHECK: %iVert = OpVariable [[pty]] Input
452 %int = OpTypeInt 32 1
453 %int_0 = OpConstant %int 0
454 %_ptr_Input_v4float = OpTypePointer Input %v4float
455 %_ptr_Output_v4float = OpTypePointer Output %v4float
456 %fragColor = OpVariable %_ptr_Output_v4float Output
457 %main = OpFunction %void None %3
458 %5 = OpLabel
459 %17 = OpAccessChain %_ptr_Input_v4float %iVert %int_0
460 %18 = OpLoad %v4float %17
461 OpStore %fragColor %18
462 OpReturn
463 OpFunctionEnd
464 )";
465
466 SetTargetEnv(SPV_ENV_VULKAN_1_3);
467 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
468 SinglePassRunAndMatch<EliminateDeadIOComponentsPass>(
469 text, true, spv::StorageClass::Input, false);
470 }
471
TEST_F(ElimDeadIOComponentsTest, ElimOutputStructMember)472 TEST_F(ElimDeadIOComponentsTest, ElimOutputStructMember) {
473 // Should eliminate uv from Vertex and all but gl_Position from gl_PerVertex
474 //
475 // #version 450
476 //
477 // out Vertex {
478 // vec4 Cd;
479 // vec2 uv;
480 // } oVert;
481 //
482 // in vec3 P;
483 //
484 // void main()
485 // {
486 // vec4 worldSpacePos = vec4(P, 1);
487 // oVert.Cd = vec4(1, 0.5, 0, 1);
488 // gl_Position = worldSpacePos;
489 // }
490
491 const std::string text = R"(
492 OpCapability Shader
493 %1 = OpExtInstImport "GLSL.std.450"
494 OpMemoryModel Logical GLSL450
495 OpEntryPoint Vertex %main "main" %P %oVert %_
496 OpSource GLSL 450
497 OpName %main "main"
498 OpName %P "P"
499 OpName %Vertex "Vertex"
500 OpMemberName %Vertex 0 "Cd"
501 OpMemberName %Vertex 1 "uv"
502 OpName %oVert "oVert"
503 OpName %gl_PerVertex "gl_PerVertex"
504 OpMemberName %gl_PerVertex 0 "gl_Position"
505 OpMemberName %gl_PerVertex 1 "gl_PointSize"
506 OpMemberName %gl_PerVertex 2 "gl_ClipDistance"
507 OpMemberName %gl_PerVertex 3 "gl_CullDistance"
508 OpName %_ ""
509 OpDecorate %P Location 0
510 OpDecorate %Vertex Block
511 OpDecorate %oVert Location 0
512 OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
513 OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
514 OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
515 OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
516 OpDecorate %gl_PerVertex Block
517 %void = OpTypeVoid
518 %3 = OpTypeFunction %void
519 %float = OpTypeFloat 32
520 %v4float = OpTypeVector %float 4
521 %v3float = OpTypeVector %float 3
522 %_ptr_Input_v3float = OpTypePointer Input %v3float
523 %P = OpVariable %_ptr_Input_v3float Input
524 %float_1 = OpConstant %float 1
525 %v2float = OpTypeVector %float 2
526 %Vertex = OpTypeStruct %v4float %v2float
527 %_ptr_Output_Vertex = OpTypePointer Output %Vertex
528 %oVert = OpVariable %_ptr_Output_Vertex Output
529 %int = OpTypeInt 32 1
530 %int_0 = OpConstant %int 0
531 %float_0_5 = OpConstant %float 0.5
532 %float_0 = OpConstant %float 0
533 %27 = OpConstantComposite %v4float %float_1 %float_0_5 %float_0 %float_1
534 %_ptr_Output_v4float = OpTypePointer Output %v4float
535 %uint = OpTypeInt 32 0
536 %uint_1 = OpConstant %uint 1
537 %_arr_float_uint_1 = OpTypeArray %float %uint_1
538 %gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
539 %_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
540 %_ = OpVariable %_ptr_Output_gl_PerVertex Output
541 ; CHECK: %Vertex = OpTypeStruct %v4float %v2float
542 ; CHECK: %gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
543 ; CHECK: %_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
544 ; CHECK: [[sty:%\w+]] = OpTypeStruct %v4float
545 ; CHECK: [[pty:%\w+]] = OpTypePointer Output [[sty]]
546 ; CHECK: %oVert = OpVariable [[pty]] Output
547 ; CHECK: [[sty2:%\w+]] = OpTypeStruct %v4float
548 ; CHECK: [[pty2:%\w+]] = OpTypePointer Output [[sty2]]
549 ; CHECK: %_ = OpVariable [[pty2]] Output
550 %main = OpFunction %void None %3
551 %5 = OpLabel
552 %13 = OpLoad %v3float %P
553 %15 = OpCompositeExtract %float %13 0
554 %16 = OpCompositeExtract %float %13 1
555 %17 = OpCompositeExtract %float %13 2
556 %18 = OpCompositeConstruct %v4float %15 %16 %17 %float_1
557 %29 = OpAccessChain %_ptr_Output_v4float %oVert %int_0
558 OpStore %29 %27
559 %37 = OpAccessChain %_ptr_Output_v4float %_ %int_0
560 OpStore %37 %18
561 OpReturn
562 OpFunctionEnd
563 )";
564
565 SetTargetEnv(SPV_ENV_VULKAN_1_3);
566 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
567 SinglePassRunAndMatch<EliminateDeadIOComponentsPass>(
568 text, true, spv::StorageClass::Output, false);
569 }
570
TEST_F(ElimDeadIOComponentsTest, ElimOutputArrayMembers)571 TEST_F(ElimDeadIOComponentsTest, ElimOutputArrayMembers) {
572 // Should reduce to uv[2]
573 //
574 // #version 450
575 //
576 // layout(location = 0) out vec2 uv[8];
577 //
578 // void main()
579 // {
580 // uv[1] = vec2(1, 0.5);
581 // }
582
583 const std::string text = R"(
584 OpCapability Shader
585 %1 = OpExtInstImport "GLSL.std.450"
586 OpMemoryModel Logical GLSL450
587 OpEntryPoint Fragment %main "main" %uv
588 OpExecutionMode %main OriginUpperLeft
589 OpSource GLSL 450
590 OpName %main "main"
591 OpName %uv "uv"
592 OpDecorate %uv Location 0
593 %void = OpTypeVoid
594 %3 = OpTypeFunction %void
595 %float = OpTypeFloat 32
596 %v2float = OpTypeVector %float 2
597 %uint = OpTypeInt 32 0
598 %uint_8 = OpConstant %uint 8
599 %_arr_v2float_uint_8 = OpTypeArray %v2float %uint_8
600 %_ptr_Output__arr_v2float_uint_8 = OpTypePointer Output %_arr_v2float_uint_8
601 %uv = OpVariable %_ptr_Output__arr_v2float_uint_8 Output
602 ;CHECK-NOT: %uv = OpVariable %_ptr_Output__arr_v2float_uint_8 Output
603 ;CHECK: %uv = OpVariable %_ptr_Output__arr_v2float_uint_2 Output
604 %int = OpTypeInt 32 1
605 %int_1 = OpConstant %int 1
606 %float_1 = OpConstant %float 1
607 %float_0_5 = OpConstant %float 0.5
608 %17 = OpConstantComposite %v2float %float_1 %float_0_5
609 %_ptr_Output_v2float = OpTypePointer Output %v2float
610 %main = OpFunction %void None %3
611 %5 = OpLabel
612 %19 = OpAccessChain %_ptr_Output_v2float %uv %int_1
613 OpStore %19 %17
614 OpReturn
615 OpFunctionEnd
616 )";
617
618 SetTargetEnv(SPV_ENV_VULKAN_1_3);
619 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
620 SinglePassRunAndMatch<EliminateDeadIOComponentsPass>(
621 text, true, spv::StorageClass::Output, false);
622 }
623
TEST_F(ElimDeadIOComponentsTest, VertexOnly)624 TEST_F(ElimDeadIOComponentsTest, VertexOnly) {
625 // Should NOT eliminate uv
626 //
627 // #version 450
628 //
629 // in Vertex {
630 // vec4 Cd;
631 // vec2 uv;
632 // } iVert;
633 //
634 // out vec4 fragColor;
635 //
636 // void main()
637 // {
638 // vec4 color = vec4(iVert.Cd);
639 // fragColor = color;
640 // }
641 const std::string text = R"(
642 OpCapability Shader
643 %1 = OpExtInstImport "GLSL.std.450"
644 OpMemoryModel Logical GLSL450
645 OpEntryPoint Fragment %main "main" %iVert %fragColor
646 OpExecutionMode %main OriginUpperLeft
647 OpSource GLSL 450
648 OpName %main "main"
649 OpName %Vertex "Vertex"
650 OpMemberName %Vertex 0 "Cd"
651 OpMemberName %Vertex 1 "uv"
652 OpName %iVert "iVert"
653 OpName %fragColor "fragColor"
654 OpDecorate %Vertex Block
655 OpDecorate %iVert Location 0
656 OpDecorate %fragColor Location 0
657 %void = OpTypeVoid
658 %3 = OpTypeFunction %void
659 %float = OpTypeFloat 32
660 %v4float = OpTypeVector %float 4
661 %v2float = OpTypeVector %float 2
662 %Vertex = OpTypeStruct %v4float %v2float
663 ; CHECK: %Vertex = OpTypeStruct %v4float %v2float
664 %_ptr_Input_Vertex = OpTypePointer Input %Vertex
665 ; CHECK: %_ptr_Input_Vertex = OpTypePointer Input %Vertex
666 %iVert = OpVariable %_ptr_Input_Vertex Input
667 ; CHECK: %iVert = OpVariable %_ptr_Input_Vertex Input
668 %int = OpTypeInt 32 1
669 %int_0 = OpConstant %int 0
670 %_ptr_Input_v4float = OpTypePointer Input %v4float
671 %_ptr_Output_v4float = OpTypePointer Output %v4float
672 %fragColor = OpVariable %_ptr_Output_v4float Output
673 %main = OpFunction %void None %3
674 %5 = OpLabel
675 %17 = OpAccessChain %_ptr_Input_v4float %iVert %int_0
676 %18 = OpLoad %v4float %17
677 OpStore %fragColor %18
678 OpReturn
679 OpFunctionEnd
680 )";
681
682 SetTargetEnv(SPV_ENV_VULKAN_1_3);
683 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
684 SinglePassRunAndMatch<EliminateDeadIOComponentsPass>(
685 text, true, spv::StorageClass::Input, true);
686 }
687
TEST_F(ElimDeadIOComponentsTest, TescInput)688 TEST_F(ElimDeadIOComponentsTest, TescInput) {
689 // Eliminate PointSize, ClipDistance, CullDistance from gl_in[]
690 //
691 // #version 450
692 //
693 // layout (vertices = 4) out;
694 //
695 // void main()
696 // {
697 // vec4 pos = gl_in[gl_InvocationID].gl_Position;
698 // gl_out[gl_InvocationID].gl_Position = pos;
699 // }
700 const std::string text = R"(
701 OpCapability Tessellation
702 %1 = OpExtInstImport "GLSL.std.450"
703 OpMemoryModel Logical GLSL450
704 OpEntryPoint TessellationControl %main "main" %gl_in %gl_InvocationID %gl_out
705 OpExecutionMode %main OutputVertices 4
706 OpSource GLSL 450
707 OpName %main "main"
708 OpName %pos "pos"
709 OpName %gl_PerVertex "gl_PerVertex"
710 OpMemberName %gl_PerVertex 0 "gl_Position"
711 OpMemberName %gl_PerVertex 1 "gl_PointSize"
712 OpMemberName %gl_PerVertex 2 "gl_ClipDistance"
713 OpMemberName %gl_PerVertex 3 "gl_CullDistance"
714 OpName %gl_in "gl_in"
715 OpName %gl_InvocationID "gl_InvocationID"
716 OpName %gl_PerVertex_0 "gl_PerVertex"
717 OpMemberName %gl_PerVertex_0 0 "gl_Position"
718 OpName %gl_out "gl_out"
719 OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
720 OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
721 OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
722 OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
723 OpDecorate %gl_PerVertex Block
724 OpDecorate %gl_InvocationID BuiltIn InvocationId
725 OpMemberDecorate %gl_PerVertex_0 0 BuiltIn Position
726 OpDecorate %gl_PerVertex_0 Block
727 %void = OpTypeVoid
728 %3 = OpTypeFunction %void
729 %float = OpTypeFloat 32
730 %v4float = OpTypeVector %float 4
731 %_ptr_Function_v4float = OpTypePointer Function %v4float
732 %uint = OpTypeInt 32 0
733 %uint_1 = OpConstant %uint 1
734 %_arr_float_uint_1 = OpTypeArray %float %uint_1
735 %gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
736 %uint_32 = OpConstant %uint 32
737 %_arr_gl_PerVertex_uint_32 = OpTypeArray %gl_PerVertex %uint_32
738 %_ptr_Input__arr_gl_PerVertex_uint_32 = OpTypePointer Input %_arr_gl_PerVertex_uint_32
739 %gl_in = OpVariable %_ptr_Input__arr_gl_PerVertex_uint_32 Input
740 %int = OpTypeInt 32 1
741 %_ptr_Input_int = OpTypePointer Input %int
742 %gl_InvocationID = OpVariable %_ptr_Input_int Input
743 %int_0 = OpConstant %int 0
744 %_ptr_Input_v4float = OpTypePointer Input %v4float
745 %gl_PerVertex_0 = OpTypeStruct %v4float
746 %uint_4 = OpConstant %uint 4
747 %_arr_gl_PerVertex_0_uint_4 = OpTypeArray %gl_PerVertex_0 %uint_4
748 %_ptr_Output__arr_gl_PerVertex_0_uint_4 = OpTypePointer Output %_arr_gl_PerVertex_0_uint_4
749 %gl_out = OpVariable %_ptr_Output__arr_gl_PerVertex_0_uint_4 Output
750 %_ptr_Output_v4float = OpTypePointer Output %v4float
751 ; CHECK: %gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
752 ; CHECK: [[sty:%\w+]] = OpTypeStruct %v4float
753 ; CHECK: [[asty:%\w+]] = OpTypeArray [[sty]] %uint_32
754 ; CHECK: [[pasty:%\w+]] = OpTypePointer Input [[asty]]
755 ; CHECK: %gl_in = OpVariable [[pasty]] Input
756 %main = OpFunction %void None %3
757 %5 = OpLabel
758 %pos = OpVariable %_ptr_Function_v4float Function
759 %21 = OpLoad %int %gl_InvocationID
760 %24 = OpAccessChain %_ptr_Input_v4float %gl_in %21 %int_0
761 %25 = OpLoad %v4float %24
762 OpStore %pos %25
763 %31 = OpLoad %int %gl_InvocationID
764 %32 = OpLoad %v4float %pos
765 %34 = OpAccessChain %_ptr_Output_v4float %gl_out %31 %int_0
766 OpStore %34 %32
767 OpReturn
768 OpFunctionEnd
769 )";
770
771 SetTargetEnv(SPV_ENV_VULKAN_1_3);
772 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
773 SinglePassRunAndMatch<EliminateDeadIOComponentsPass>(
774 text, true, spv::StorageClass::Input, false);
775 }
776
TEST_F(ElimDeadIOComponentsTest, TescOutput)777 TEST_F(ElimDeadIOComponentsTest, TescOutput) {
778 // Eliminate PointSize, ClipDistance, CullDistance from gl_out[]
779 //
780 // #version 450
781 //
782 // layout (vertices = 4) out;
783 //
784 // void main()
785 // {
786 // vec4 pos = gl_in[gl_InvocationID].gl_Position;
787 // gl_out[gl_InvocationID].gl_Position = pos;
788 // }
789 const std::string text = R"(
790 OpCapability Tessellation
791 %1 = OpExtInstImport "GLSL.std.450"
792 OpMemoryModel Logical GLSL450
793 OpEntryPoint TessellationControl %main "main" %gl_in %gl_InvocationID %gl_out
794 OpExecutionMode %main OutputVertices 4
795 OpSource GLSL 450
796 OpName %main "main"
797 OpName %pos "pos"
798 OpName %gl_PerVertex "gl_PerVertex"
799 OpMemberName %gl_PerVertex 0 "gl_Position"
800 OpName %gl_in "gl_in"
801 OpName %gl_InvocationID "gl_InvocationID"
802 OpName %gl_PerVertex_0 "gl_PerVertex"
803 OpMemberName %gl_PerVertex_0 0 "gl_Position"
804 OpMemberName %gl_PerVertex_0 1 "gl_PointSize"
805 OpMemberName %gl_PerVertex_0 2 "gl_ClipDistance"
806 OpMemberName %gl_PerVertex_0 3 "gl_CullDistance"
807 OpName %gl_out "gl_out"
808 OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
809 OpDecorate %gl_PerVertex Block
810 OpDecorate %gl_InvocationID BuiltIn InvocationId
811 OpMemberDecorate %gl_PerVertex_0 0 BuiltIn Position
812 OpMemberDecorate %gl_PerVertex_0 1 BuiltIn PointSize
813 OpMemberDecorate %gl_PerVertex_0 2 BuiltIn ClipDistance
814 OpMemberDecorate %gl_PerVertex_0 3 BuiltIn CullDistance
815 OpDecorate %gl_PerVertex_0 Block
816 %void = OpTypeVoid
817 %3 = OpTypeFunction %void
818 %float = OpTypeFloat 32
819 %v4float = OpTypeVector %float 4
820 %_ptr_Function_v4float = OpTypePointer Function %v4float
821 %uint = OpTypeInt 32 0
822 %uint_1 = OpConstant %uint 1
823 %_arr_float_uint_1 = OpTypeArray %float %uint_1
824 %gl_PerVertex = OpTypeStruct %v4float
825 %uint_32 = OpConstant %uint 32
826 %_arr_gl_PerVertex_uint_32 = OpTypeArray %gl_PerVertex %uint_32
827 %_ptr_Input__arr_gl_PerVertex_uint_32 = OpTypePointer Input %_arr_gl_PerVertex_uint_32
828 %gl_in = OpVariable %_ptr_Input__arr_gl_PerVertex_uint_32 Input
829 %int = OpTypeInt 32 1
830 %_ptr_Input_int = OpTypePointer Input %int
831 %gl_InvocationID = OpVariable %_ptr_Input_int Input
832 %int_0 = OpConstant %int 0
833 %_ptr_Input_v4float = OpTypePointer Input %v4float
834 %gl_PerVertex_0 = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
835 %uint_4 = OpConstant %uint 4
836 %_arr_gl_PerVertex_0_uint_4 = OpTypeArray %gl_PerVertex_0 %uint_4
837 %_ptr_Output__arr_gl_PerVertex_0_uint_4 = OpTypePointer Output %_arr_gl_PerVertex_0_uint_4
838 %gl_out = OpVariable %_ptr_Output__arr_gl_PerVertex_0_uint_4 Output
839 %_ptr_Output_v4float = OpTypePointer Output %v4float
840 ; CHECK: [[sty:%\w+]] = OpTypeStruct %v4float
841 ; CHECK: [[asty:%\w+]] = OpTypeArray [[sty]] %uint_4
842 ; CHECK: [[pasty:%\w+]] = OpTypePointer Output [[asty]]
843 ; CHECK: %gl_out = OpVariable [[pasty]] Output
844 %main = OpFunction %void None %3
845 %5 = OpLabel
846 %pos = OpVariable %_ptr_Function_v4float Function
847 %21 = OpLoad %int %gl_InvocationID
848 %24 = OpAccessChain %_ptr_Input_v4float %gl_in %21 %int_0
849 %25 = OpLoad %v4float %24
850 OpStore %pos %25
851 %31 = OpLoad %int %gl_InvocationID
852 %32 = OpLoad %v4float %pos
853 %34 = OpAccessChain %_ptr_Output_v4float %gl_out %31 %int_0
854 OpStore %34 %32
855 OpReturn
856 OpFunctionEnd
857 )";
858
859 SetTargetEnv(SPV_ENV_VULKAN_1_3);
860 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
861 SinglePassRunAndMatch<EliminateDeadIOComponentsPass>(
862 text, true, spv::StorageClass::Output, false);
863 }
864
TEST_F(ElimDeadIOComponentsTest, TeseInput)865 TEST_F(ElimDeadIOComponentsTest, TeseInput) {
866 // Eliminate PointSize, ClipDistance, CullDistance from gl_in[]
867 //
868 // #version 450
869 //
870 // layout(triangles, ccw) in;
871 // layout(fractional_odd_spacing) in;
872 // layout(point_mode) in;
873 //
874 // void main()
875 // {
876 // vec4 p = gl_in[1].gl_Position;
877 // gl_Position = p;
878 // }
879 const std::string text = R"(
880 OpCapability Tessellation
881 %1 = OpExtInstImport "GLSL.std.450"
882 OpMemoryModel Logical GLSL450
883 OpEntryPoint TessellationEvaluation %main "main" %gl_in %_
884 OpExecutionMode %main Triangles
885 OpExecutionMode %main SpacingFractionalOdd
886 OpExecutionMode %main VertexOrderCcw
887 OpExecutionMode %main PointMode
888 OpSource GLSL 450
889 OpName %main "main"
890 OpName %p "p"
891 OpName %gl_PerVertex "gl_PerVertex"
892 OpMemberName %gl_PerVertex 0 "gl_Position"
893 OpMemberName %gl_PerVertex 1 "gl_PointSize"
894 OpMemberName %gl_PerVertex 2 "gl_ClipDistance"
895 OpMemberName %gl_PerVertex 3 "gl_CullDistance"
896 OpName %gl_in "gl_in"
897 OpName %gl_PerVertex_0 "gl_PerVertex"
898 OpMemberName %gl_PerVertex_0 0 "gl_Position"
899 OpName %_ ""
900 OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
901 OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
902 OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
903 OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
904 OpDecorate %gl_PerVertex Block
905 OpMemberDecorate %gl_PerVertex_0 0 BuiltIn Position
906 OpDecorate %gl_PerVertex_0 Block
907 %void = OpTypeVoid
908 %3 = OpTypeFunction %void
909 %float = OpTypeFloat 32
910 %v4float = OpTypeVector %float 4
911 %_ptr_Function_v4float = OpTypePointer Function %v4float
912 %uint = OpTypeInt 32 0
913 %uint_1 = OpConstant %uint 1
914 %_arr_float_uint_1 = OpTypeArray %float %uint_1
915 %gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
916 %uint_32 = OpConstant %uint 32
917 %_arr_gl_PerVertex_uint_32 = OpTypeArray %gl_PerVertex %uint_32
918 %_ptr_Input__arr_gl_PerVertex_uint_32 = OpTypePointer Input %_arr_gl_PerVertex_uint_32
919 %gl_in = OpVariable %_ptr_Input__arr_gl_PerVertex_uint_32 Input
920 %int = OpTypeInt 32 1
921 %int_1 = OpConstant %int 1
922 %int_0 = OpConstant %int 0
923 %_ptr_Input_v4float = OpTypePointer Input %v4float
924 %gl_PerVertex_0 = OpTypeStruct %v4float
925 %_ptr_Output_gl_PerVertex_0 = OpTypePointer Output %gl_PerVertex_0
926 %_ = OpVariable %_ptr_Output_gl_PerVertex_0 Output
927 %_ptr_Output_v4float = OpTypePointer Output %v4float
928 ; CHECK: %gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
929 ; CHECK: [[sty:%\w+]] = OpTypeStruct %v4float
930 ; CHECK: [[asty:%\w+]] = OpTypeArray [[sty]] %uint_32
931 ; CHECK: [[pasty:%\w+]] = OpTypePointer Input [[asty]]
932 ; CHECK: %gl_in = OpVariable [[pasty]] Input
933 %main = OpFunction %void None %3
934 %5 = OpLabel
935 %p = OpVariable %_ptr_Function_v4float Function
936 %22 = OpAccessChain %_ptr_Input_v4float %gl_in %int_1 %int_0
937 %23 = OpLoad %v4float %22
938 OpStore %p %23
939 %27 = OpLoad %v4float %p
940 %29 = OpAccessChain %_ptr_Output_v4float %_ %int_0
941 OpStore %29 %27
942 OpReturn
943 OpFunctionEnd
944 )";
945
946 SetTargetEnv(SPV_ENV_VULKAN_1_3);
947 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
948 SinglePassRunAndMatch<EliminateDeadIOComponentsPass>(
949 text, true, spv::StorageClass::Input, false);
950 }
951
TEST_F(ElimDeadIOComponentsTest, TeseOutput)952 TEST_F(ElimDeadIOComponentsTest, TeseOutput) {
953 // Eliminate PointSize, ClipDistance, CullDistance from gl_out
954 //
955 // #version 450
956 //
957 // layout(triangles, ccw) in;
958 // layout(fractional_odd_spacing) in;
959 // layout(point_mode) in;
960 //
961 // void main()
962 // {
963 // vec4 p = gl_in[1].gl_Position;
964 // gl_Position = p;
965 // }
966 const std::string text = R"(
967 OpCapability Tessellation
968 %1 = OpExtInstImport "GLSL.std.450"
969 OpMemoryModel Logical GLSL450
970 OpEntryPoint TessellationEvaluation %main "main" %gl_in %_
971 OpExecutionMode %main Triangles
972 OpExecutionMode %main SpacingFractionalOdd
973 OpExecutionMode %main VertexOrderCcw
974 OpExecutionMode %main PointMode
975 OpSource GLSL 450
976 OpName %main "main"
977 OpName %p "p"
978 OpName %gl_PerVertex "gl_PerVertex"
979 OpMemberName %gl_PerVertex 0 "gl_Position"
980 OpName %gl_in "gl_in"
981 OpName %gl_PerVertex_0 "gl_PerVertex"
982 OpMemberName %gl_PerVertex_0 0 "gl_Position"
983 OpMemberName %gl_PerVertex_0 1 "gl_PointSize"
984 OpMemberName %gl_PerVertex_0 2 "gl_ClipDistance"
985 OpMemberName %gl_PerVertex_0 3 "gl_CullDistance"
986 OpName %_ ""
987 OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
988 OpDecorate %gl_PerVertex Block
989 OpMemberDecorate %gl_PerVertex_0 0 BuiltIn Position
990 OpMemberDecorate %gl_PerVertex_0 1 BuiltIn PointSize
991 OpMemberDecorate %gl_PerVertex_0 2 BuiltIn ClipDistance
992 OpMemberDecorate %gl_PerVertex_0 3 BuiltIn CullDistance
993 OpDecorate %gl_PerVertex_0 Block
994 %void = OpTypeVoid
995 %3 = OpTypeFunction %void
996 %float = OpTypeFloat 32
997 %v4float = OpTypeVector %float 4
998 %_ptr_Function_v4float = OpTypePointer Function %v4float
999 %uint = OpTypeInt 32 0
1000 %uint_1 = OpConstant %uint 1
1001 %_arr_float_uint_1 = OpTypeArray %float %uint_1
1002 %gl_PerVertex = OpTypeStruct %v4float
1003 %uint_32 = OpConstant %uint 32
1004 %_arr_gl_PerVertex_uint_32 = OpTypeArray %gl_PerVertex %uint_32
1005 %_ptr_Input__arr_gl_PerVertex_uint_32 = OpTypePointer Input %_arr_gl_PerVertex_uint_32
1006 %gl_in = OpVariable %_ptr_Input__arr_gl_PerVertex_uint_32 Input
1007 %int = OpTypeInt 32 1
1008 %int_1 = OpConstant %int 1
1009 %int_0 = OpConstant %int 0
1010 %_ptr_Input_v4float = OpTypePointer Input %v4float
1011 %gl_PerVertex_0 = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
1012 %_ptr_Output_gl_PerVertex_0 = OpTypePointer Output %gl_PerVertex_0
1013 %_ = OpVariable %_ptr_Output_gl_PerVertex_0 Output
1014 %_ptr_Output_v4float = OpTypePointer Output %v4float
1015 ; CHECK: %_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
1016 ; CHECK: %_ = OpVariable %_ptr_Output_gl_PerVertex Output
1017 %main = OpFunction %void None %3
1018 %5 = OpLabel
1019 %p = OpVariable %_ptr_Function_v4float Function
1020 %22 = OpAccessChain %_ptr_Input_v4float %gl_in %int_1 %int_0
1021 %23 = OpLoad %v4float %22
1022 OpStore %p %23
1023 %27 = OpLoad %v4float %p
1024 %29 = OpAccessChain %_ptr_Output_v4float %_ %int_0
1025 OpStore %29 %27
1026 OpReturn
1027 OpFunctionEnd
1028 )";
1029
1030 SetTargetEnv(SPV_ENV_VULKAN_1_3);
1031 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1032 SinglePassRunAndMatch<EliminateDeadIOComponentsPass>(
1033 text, true, spv::StorageClass::Output, false);
1034 }
1035
TEST_F(ElimDeadIOComponentsTest, GeomInput)1036 TEST_F(ElimDeadIOComponentsTest, GeomInput) {
1037 // Eliminate PointSize, ClipDistance, CullDistance from gl_in[]
1038 //
1039 // #version 450
1040 //
1041 // layout(triangle_strip, max_vertices = 3) out;
1042 // layout(triangles) in;
1043 //
1044 // void main()
1045 // {
1046 // for (int i = 0; i < 3; i++)
1047 // {
1048 // gl_Position = gl_in[i].gl_Position;
1049 // EmitVertex();
1050 // }
1051 // EndPrimitive();
1052 // }
1053 const std::string text = R"(
1054 OpCapability Geometry
1055 %1 = OpExtInstImport "GLSL.std.450"
1056 OpMemoryModel Logical GLSL450
1057 OpEntryPoint Geometry %main "main" %_ %gl_in
1058 OpExecutionMode %main Triangles
1059 OpExecutionMode %main Invocations 1
1060 OpExecutionMode %main OutputTriangleStrip
1061 OpExecutionMode %main OutputVertices 3
1062 OpSource GLSL 460
1063 OpName %main "main"
1064 OpName %i "i"
1065 OpName %gl_PerVertex "gl_PerVertex"
1066 OpMemberName %gl_PerVertex 0 "gl_Position"
1067 OpName %_ ""
1068 OpName %gl_PerVertex_0 "gl_PerVertex"
1069 OpMemberName %gl_PerVertex_0 0 "gl_Position"
1070 OpMemberName %gl_PerVertex_0 1 "gl_PointSize"
1071 OpMemberName %gl_PerVertex_0 2 "gl_ClipDistance"
1072 OpMemberName %gl_PerVertex_0 3 "gl_CullDistance"
1073 OpName %gl_in "gl_in"
1074 OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
1075 OpDecorate %gl_PerVertex Block
1076 OpMemberDecorate %gl_PerVertex_0 0 BuiltIn Position
1077 OpMemberDecorate %gl_PerVertex_0 1 BuiltIn PointSize
1078 OpMemberDecorate %gl_PerVertex_0 2 BuiltIn ClipDistance
1079 OpMemberDecorate %gl_PerVertex_0 3 BuiltIn CullDistance
1080 OpDecorate %gl_PerVertex_0 Block
1081 %void = OpTypeVoid
1082 %3 = OpTypeFunction %void
1083 %int = OpTypeInt 32 1
1084 %_ptr_Function_int = OpTypePointer Function %int
1085 %int_0 = OpConstant %int 0
1086 %int_3 = OpConstant %int 3
1087 %bool = OpTypeBool
1088 %float = OpTypeFloat 32
1089 %v4float = OpTypeVector %float 4
1090 %uint = OpTypeInt 32 0
1091 %uint_1 = OpConstant %uint 1
1092 %_arr_float_uint_1 = OpTypeArray %float %uint_1
1093 %gl_PerVertex = OpTypeStruct %v4float
1094 %_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
1095 %_ = OpVariable %_ptr_Output_gl_PerVertex Output
1096 %gl_PerVertex_0 = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
1097 %uint_3 = OpConstant %uint 3
1098 %_arr_gl_PerVertex_0_uint_3 = OpTypeArray %gl_PerVertex_0 %uint_3
1099 %_ptr_Input__arr_gl_PerVertex_0_uint_3 = OpTypePointer Input %_arr_gl_PerVertex_0_uint_3
1100 %gl_in = OpVariable %_ptr_Input__arr_gl_PerVertex_0_uint_3 Input
1101 %_ptr_Input_v4float = OpTypePointer Input %v4float
1102 %_ptr_Output_v4float = OpTypePointer Output %v4float
1103 %int_1 = OpConstant %int 1
1104 ; CHECK: [[asty:%\w+]] = OpTypeArray %gl_PerVertex %uint_3
1105 ; CHECK: [[pasty:%\w+]] = OpTypePointer Input [[asty]]
1106 ; CHECK: %gl_in = OpVariable [[pasty]] Input
1107 %main = OpFunction %void None %3
1108 %5 = OpLabel
1109 %i = OpVariable %_ptr_Function_int Function
1110 OpStore %i %int_0
1111 OpBranch %10
1112 %10 = OpLabel
1113 OpLoopMerge %12 %13 None
1114 OpBranch %14
1115 %14 = OpLabel
1116 %15 = OpLoad %int %i
1117 %18 = OpSLessThan %bool %15 %int_3
1118 OpBranchConditional %18 %11 %12
1119 %11 = OpLabel
1120 %32 = OpLoad %int %i
1121 %34 = OpAccessChain %_ptr_Input_v4float %gl_in %32 %int_0
1122 %35 = OpLoad %v4float %34
1123 %37 = OpAccessChain %_ptr_Output_v4float %_ %int_0
1124 OpStore %37 %35
1125 OpEmitVertex
1126 OpBranch %13
1127 %13 = OpLabel
1128 %38 = OpLoad %int %i
1129 %40 = OpIAdd %int %38 %int_1
1130 OpStore %i %40
1131 OpBranch %10
1132 %12 = OpLabel
1133 OpEndPrimitive
1134 OpReturn
1135 OpFunctionEnd
1136 )";
1137
1138 SetTargetEnv(SPV_ENV_VULKAN_1_3);
1139 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1140 SinglePassRunAndMatch<EliminateDeadIOComponentsPass>(
1141 text, true, spv::StorageClass::Input, false);
1142 }
1143
TEST_F(ElimDeadIOComponentsTest, GeomOutput)1144 TEST_F(ElimDeadIOComponentsTest, GeomOutput) {
1145 // Eliminate PointSize, ClipDistance, CullDistance from gl_out
1146 //
1147 // #version 450
1148 //
1149 // layout(triangle_strip, max_vertices = 3) out;
1150 // layout(triangles) in;
1151 //
1152 // void main()
1153 // {
1154 // for (int i = 0; i < 3; i++)
1155 // {
1156 // gl_Position = gl_in[i].gl_Position;
1157 // EmitVertex();
1158 // }
1159 // EndPrimitive();
1160 // }
1161 const std::string text = R"(
1162 OpCapability Geometry
1163 %1 = OpExtInstImport "GLSL.std.450"
1164 OpMemoryModel Logical GLSL450
1165 OpEntryPoint Geometry %main "main" %_ %gl_in
1166 OpExecutionMode %main Triangles
1167 OpExecutionMode %main Invocations 1
1168 OpExecutionMode %main OutputTriangleStrip
1169 OpExecutionMode %main OutputVertices 3
1170 OpSource GLSL 460
1171 OpName %main "main"
1172 OpName %i "i"
1173 OpName %gl_PerVertex "gl_PerVertex"
1174 OpMemberName %gl_PerVertex 0 "gl_Position"
1175 OpMemberName %gl_PerVertex 1 "gl_PointSize"
1176 OpMemberName %gl_PerVertex 2 "gl_ClipDistance"
1177 OpMemberName %gl_PerVertex 3 "gl_CullDistance"
1178 OpName %_ ""
1179 OpName %gl_PerVertex_0 "gl_PerVertex"
1180 OpMemberName %gl_PerVertex_0 0 "gl_Position"
1181 OpName %gl_in "gl_in"
1182 OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
1183 OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
1184 OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
1185 OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
1186 OpDecorate %gl_PerVertex Block
1187 OpMemberDecorate %gl_PerVertex_0 0 BuiltIn Position
1188 OpDecorate %gl_PerVertex_0 Block
1189 %void = OpTypeVoid
1190 %3 = OpTypeFunction %void
1191 %int = OpTypeInt 32 1
1192 %_ptr_Function_int = OpTypePointer Function %int
1193 %int_0 = OpConstant %int 0
1194 %int_3 = OpConstant %int 3
1195 %bool = OpTypeBool
1196 %float = OpTypeFloat 32
1197 %v4float = OpTypeVector %float 4
1198 %uint = OpTypeInt 32 0
1199 %uint_1 = OpConstant %uint 1
1200 %_arr_float_uint_1 = OpTypeArray %float %uint_1
1201 %gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
1202 %_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
1203 %_ = OpVariable %_ptr_Output_gl_PerVertex Output
1204 %gl_PerVertex_0 = OpTypeStruct %v4float
1205 %uint_3 = OpConstant %uint 3
1206 %_arr_gl_PerVertex_0_uint_3 = OpTypeArray %gl_PerVertex_0 %uint_3
1207 %_ptr_Input__arr_gl_PerVertex_0_uint_3 = OpTypePointer Input %_arr_gl_PerVertex_0_uint_3
1208 %gl_in = OpVariable %_ptr_Input__arr_gl_PerVertex_0_uint_3 Input
1209 %_ptr_Input_v4float = OpTypePointer Input %v4float
1210 %_ptr_Output_v4float = OpTypePointer Output %v4float
1211 %int_1 = OpConstant %int 1
1212 ; CHECK: %_ptr_Output_gl_PerVertex_0 = OpTypePointer Output %gl_PerVertex_0
1213 ; CHECK: %_ = OpVariable %_ptr_Output_gl_PerVertex_0 Output
1214 %main = OpFunction %void None %3
1215 %5 = OpLabel
1216 %i = OpVariable %_ptr_Function_int Function
1217 OpStore %i %int_0
1218 OpBranch %10
1219 %10 = OpLabel
1220 OpLoopMerge %12 %13 None
1221 OpBranch %14
1222 %14 = OpLabel
1223 %15 = OpLoad %int %i
1224 %18 = OpSLessThan %bool %15 %int_3
1225 OpBranchConditional %18 %11 %12
1226 %11 = OpLabel
1227 %32 = OpLoad %int %i
1228 %34 = OpAccessChain %_ptr_Input_v4float %gl_in %32 %int_0
1229 %35 = OpLoad %v4float %34
1230 %37 = OpAccessChain %_ptr_Output_v4float %_ %int_0
1231 OpStore %37 %35
1232 OpEmitVertex
1233 OpBranch %13
1234 %13 = OpLabel
1235 %38 = OpLoad %int %i
1236 %40 = OpIAdd %int %38 %int_1
1237 OpStore %i %40
1238 OpBranch %10
1239 %12 = OpLabel
1240 OpEndPrimitive
1241 OpReturn
1242 OpFunctionEnd
1243 )";
1244
1245 SetTargetEnv(SPV_ENV_VULKAN_1_3);
1246 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1247 SinglePassRunAndMatch<EliminateDeadIOComponentsPass>(
1248 text, true, spv::StorageClass::Output, false);
1249 }
1250
1251 } // namespace
1252 } // namespace opt
1253 } // namespace spvtools
1254