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 <unordered_set>
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 ElimDeadOutputStoresTest = PassTest<::testing::Test>;
26
TEST_F(ElimDeadOutputStoresTest, VertMultipleLocations)27 TEST_F(ElimDeadOutputStoresTest, VertMultipleLocations) {
28 // #version 450
29 //
30 // layout(location = 2) out Vertex
31 // {
32 // vec4 color0;
33 // vec4 color1;
34 // vec4 color2[3];
35 // } oVert;
36 //
37 // void main()
38 // {
39 // oVert.color0 = vec4(0.0,0.0,0.0,0.0);
40 // oVert.color1 = vec4(0.1,0.0,0.0,0.0);
41 // oVert.color2[0] = vec4(0.2,0.0,0.0,0.0);
42 // oVert.color2[1] = vec4(0.3,0.0,0.0,0.0);
43 // oVert.color2[2] = vec4(0.4,0.0,0.0,0.0);
44 // }
45 const std::string text = R"(
46 OpCapability Shader
47 %1 = OpExtInstImport "GLSL.std.450"
48 OpMemoryModel Logical GLSL450
49 OpEntryPoint Vertex %main "main" %oVert
50 OpSource GLSL 450
51 OpName %main "main"
52 OpName %Vertex "Vertex"
53 OpMemberName %Vertex 0 "color0"
54 OpMemberName %Vertex 1 "color1"
55 OpMemberName %Vertex 2 "color2"
56 OpName %oVert "oVert"
57 OpDecorate %Vertex Block
58 OpDecorate %oVert Location 2
59 %void = OpTypeVoid
60 %3 = OpTypeFunction %void
61 %float = OpTypeFloat 32
62 %v4float = OpTypeVector %float 4
63 %uint = OpTypeInt 32 0
64 %uint_3 = OpConstant %uint 3
65 %_arr_v4float_uint_3 = OpTypeArray %v4float %uint_3
66 %Vertex = OpTypeStruct %v4float %v4float %_arr_v4float_uint_3
67 %_ptr_Output_Vertex = OpTypePointer Output %Vertex
68 %oVert = OpVariable %_ptr_Output_Vertex Output
69 %int = OpTypeInt 32 1
70 %int_0 = OpConstant %int 0
71 %float_0 = OpConstant %float 0
72 %17 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
73 %_ptr_Output_v4float = OpTypePointer Output %v4float
74 %int_1 = OpConstant %int 1
75 %float_0_100000001 = OpConstant %float 0.100000001
76 %22 = OpConstantComposite %v4float %float_0_100000001 %float_0 %float_0 %float_0
77 %int_2 = OpConstant %int 2
78 %float_0_200000003 = OpConstant %float 0.200000003
79 %26 = OpConstantComposite %v4float %float_0_200000003 %float_0 %float_0 %float_0
80 %float_0_300000012 = OpConstant %float 0.300000012
81 %29 = OpConstantComposite %v4float %float_0_300000012 %float_0 %float_0 %float_0
82 %float_0_400000006 = OpConstant %float 0.400000006
83 %32 = OpConstantComposite %v4float %float_0_400000006 %float_0 %float_0 %float_0
84 %main = OpFunction %void None %3
85 %5 = OpLabel
86 %19 = OpAccessChain %_ptr_Output_v4float %oVert %int_0
87 OpStore %19 %17
88 ;CHECK: OpStore %19 %17
89 %23 = OpAccessChain %_ptr_Output_v4float %oVert %int_1
90 OpStore %23 %22
91 ;CHECK-NOT: OpStore %23 %22
92 %27 = OpAccessChain %_ptr_Output_v4float %oVert %int_2 %int_0
93 OpStore %27 %26
94 ;CHECK-NOT: OpStore %27 %26
95 %30 = OpAccessChain %_ptr_Output_v4float %oVert %int_2 %int_1
96 OpStore %30 %29
97 ;CHECK: OpStore %30 %29
98 %33 = OpAccessChain %_ptr_Output_v4float %oVert %int_2 %int_2
99 OpStore %33 %32
100 ;CHECK-NOT: OpStore %33 %32
101 OpReturn
102 OpFunctionEnd
103 )";
104
105 SetTargetEnv(SPV_ENV_VULKAN_1_3);
106 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
107
108 std::unordered_set<uint32_t> live_inputs;
109 std::unordered_set<uint32_t> live_builtins;
110 live_inputs.insert(2);
111 live_inputs.insert(5);
112 SinglePassRunAndMatch<EliminateDeadOutputStoresPass>(text, true, &live_inputs,
113 &live_builtins);
114 }
115
TEST_F(ElimDeadOutputStoresTest, VertMatrix)116 TEST_F(ElimDeadOutputStoresTest, VertMatrix) {
117 // #version 450
118 //
119 // layout(location = 2) out Vertex
120 // {
121 // vec4 color0;
122 // vec4 color1;
123 // mat4 color2;
124 // mat4 color3;
125 // mat4 color4;
126 // } oVert;
127 //
128 // void main()
129 // {
130 // oVert.color0 = vec4(0.0,0.0,0.0,0.0);
131 // oVert.color1 = vec4(0.1,0.0,0.0,0.0);
132 // oVert.color2[2] = vec4(0.2,0.0,0.0,0.0);
133 // oVert.color3[1] = vec4(0.3,0.0,0.0,0.0);
134 // oVert.color4[0] = vec4(0.4,0.0,0.0,0.0);
135 // }
136 const std::string text = R"(
137 OpCapability Shader
138 %1 = OpExtInstImport "GLSL.std.450"
139 OpMemoryModel Logical GLSL450
140 OpEntryPoint Vertex %main "main" %oVert
141 OpSource GLSL 450
142 OpName %main "main"
143 OpName %Vertex "Vertex"
144 OpMemberName %Vertex 0 "color0"
145 OpMemberName %Vertex 1 "color1"
146 OpMemberName %Vertex 2 "color2"
147 OpMemberName %Vertex 3 "color3"
148 OpMemberName %Vertex 4 "color4"
149 OpName %oVert "oVert"
150 OpDecorate %Vertex Block
151 OpDecorate %oVert Location 2
152 %void = OpTypeVoid
153 %3 = OpTypeFunction %void
154 %float = OpTypeFloat 32
155 %v4float = OpTypeVector %float 4
156 %mat4v4float = OpTypeMatrix %v4float 4
157 %Vertex = OpTypeStruct %v4float %v4float %mat4v4float %mat4v4float %mat4v4float
158 %_ptr_Output_Vertex = OpTypePointer Output %Vertex
159 %oVert = OpVariable %_ptr_Output_Vertex Output
160 %int = OpTypeInt 32 1
161 %int_0 = OpConstant %int 0
162 %float_0 = OpConstant %float 0
163 %15 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
164 %_ptr_Output_v4float = OpTypePointer Output %v4float
165 %int_1 = OpConstant %int 1
166 %float_0_100000001 = OpConstant %float 0.100000001
167 %20 = OpConstantComposite %v4float %float_0_100000001 %float_0 %float_0 %float_0
168 %int_2 = OpConstant %int 2
169 %float_0_200000003 = OpConstant %float 0.200000003
170 %24 = OpConstantComposite %v4float %float_0_200000003 %float_0 %float_0 %float_0
171 %int_3 = OpConstant %int 3
172 %float_0_300000012 = OpConstant %float 0.300000012
173 %28 = OpConstantComposite %v4float %float_0_300000012 %float_0 %float_0 %float_0
174 %int_4 = OpConstant %int 4
175 %float_0_400000006 = OpConstant %float 0.400000006
176 %32 = OpConstantComposite %v4float %float_0_400000006 %float_0 %float_0 %float_0
177 %main = OpFunction %void None %3
178 %5 = OpLabel
179 %17 = OpAccessChain %_ptr_Output_v4float %oVert %int_0
180 OpStore %17 %15
181 ; CHECK: OpStore %17 %15
182 %21 = OpAccessChain %_ptr_Output_v4float %oVert %int_1
183 OpStore %21 %20
184 ; CHECK-NOT: OpStore %21 %20
185 %25 = OpAccessChain %_ptr_Output_v4float %oVert %int_2 %int_2
186 OpStore %25 %24
187 ; CHECK-NOT: OpStore %25 %24
188 %29 = OpAccessChain %_ptr_Output_v4float %oVert %int_3 %int_1
189 OpStore %29 %28
190 ; CHECK: OpStore %29 %28
191 %33 = OpAccessChain %_ptr_Output_v4float %oVert %int_4 %int_0
192 OpStore %33 %32
193 ; CHECK-NOT: OpStore %33 %32
194 OpReturn
195 OpFunctionEnd
196 )";
197
198 SetTargetEnv(SPV_ENV_VULKAN_1_3);
199 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
200
201 std::unordered_set<uint32_t> live_inputs;
202 std::unordered_set<uint32_t> live_builtins;
203 live_inputs.insert(2);
204 live_inputs.insert(8);
205 live_inputs.insert(9);
206 live_inputs.insert(10);
207 live_inputs.insert(11);
208 SinglePassRunAndMatch<EliminateDeadOutputStoresPass>(text, true, &live_inputs,
209 &live_builtins);
210 }
211
TEST_F(ElimDeadOutputStoresTest, VertMemberLocs)212 TEST_F(ElimDeadOutputStoresTest, VertMemberLocs) {
213 // #version 450
214 //
215 // out Vertex
216 // {
217 // layout (location = 1) vec4 Cd;
218 // layout (location = 0) vec2 uv;
219 // } oVert;
220 //
221 // layout (location = 0) in vec3 P;
222 //
223 // void main()
224 // {
225 // oVert.uv = vec2(0.1, 0.7);
226 // oVert.Cd = vec4(1, 0.5, 0, 1);
227 // gl_Position = vec4(P, 1);
228 // }
229 const std::string text = R"(
230 OpCapability Shader
231 %1 = OpExtInstImport "GLSL.std.450"
232 OpMemoryModel Logical GLSL450
233 OpEntryPoint Vertex %main "main" %oVert %_ %P
234 OpSource GLSL 450
235 OpName %main "main"
236 OpName %Vertex "Vertex"
237 OpMemberName %Vertex 0 "Cd"
238 OpMemberName %Vertex 1 "uv"
239 OpName %oVert "oVert"
240 OpName %gl_PerVertex "gl_PerVertex"
241 OpMemberName %gl_PerVertex 0 "gl_Position"
242 OpMemberName %gl_PerVertex 1 "gl_PointSize"
243 OpMemberName %gl_PerVertex 2 "gl_ClipDistance"
244 OpMemberName %gl_PerVertex 3 "gl_CullDistance"
245 OpName %_ ""
246 OpName %P "P"
247 OpMemberDecorate %Vertex 0 Location 1
248 OpMemberDecorate %Vertex 1 Location 0
249 OpDecorate %Vertex Block
250 OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
251 OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
252 OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
253 OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
254 OpDecorate %gl_PerVertex Block
255 OpDecorate %P Location 0
256 %void = OpTypeVoid
257 %3 = OpTypeFunction %void
258 %float = OpTypeFloat 32
259 %v4float = OpTypeVector %float 4
260 %v2float = OpTypeVector %float 2
261 %Vertex = OpTypeStruct %v4float %v2float
262 %_ptr_Output_Vertex = OpTypePointer Output %Vertex
263 %oVert = OpVariable %_ptr_Output_Vertex Output
264 %int = OpTypeInt 32 1
265 %int_1 = OpConstant %int 1
266 %float_0_100000001 = OpConstant %float 0.100000001
267 %float_0_699999988 = OpConstant %float 0.699999988
268 %16 = OpConstantComposite %v2float %float_0_100000001 %float_0_699999988
269 %_ptr_Output_v2float = OpTypePointer Output %v2float
270 %int_0 = OpConstant %int 0
271 %float_1 = OpConstant %float 1
272 %float_0_5 = OpConstant %float 0.5
273 %float_0 = OpConstant %float 0
274 %23 = OpConstantComposite %v4float %float_1 %float_0_5 %float_0 %float_1
275 %_ptr_Output_v4float = OpTypePointer Output %v4float
276 %uint = OpTypeInt 32 0
277 %uint_1 = OpConstant %uint 1
278 %_arr_float_uint_1 = OpTypeArray %float %uint_1
279 %gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
280 %_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
281 %_ = OpVariable %_ptr_Output_gl_PerVertex Output
282 %v3float = OpTypeVector %float 3
283 %_ptr_Input_v3float = OpTypePointer Input %v3float
284 %P = OpVariable %_ptr_Input_v3float Input
285 %main = OpFunction %void None %3
286 %5 = OpLabel
287 %18 = OpAccessChain %_ptr_Output_v2float %oVert %int_1
288 OpStore %18 %16
289 ; CHECK-NOT: OpStore %18 %16
290 %25 = OpAccessChain %_ptr_Output_v4float %oVert %int_0
291 OpStore %25 %23
292 ; CHECK: OpStore %25 %23
293 %35 = OpLoad %v3float %P
294 %36 = OpCompositeExtract %float %35 0
295 %37 = OpCompositeExtract %float %35 1
296 %38 = OpCompositeExtract %float %35 2
297 %39 = OpCompositeConstruct %v4float %36 %37 %38 %float_1
298 %40 = OpAccessChain %_ptr_Output_v4float %_ %int_0
299 OpStore %40 %39
300 OpReturn
301 OpFunctionEnd
302 )";
303
304 SetTargetEnv(SPV_ENV_VULKAN_1_3);
305 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
306
307 std::unordered_set<uint32_t> live_inputs;
308 std::unordered_set<uint32_t> live_builtins;
309 live_inputs.insert(1);
310 SinglePassRunAndMatch<EliminateDeadOutputStoresPass>(text, true, &live_inputs,
311 &live_builtins);
312 }
313
TEST_F(ElimDeadOutputStoresTest, ArrayedOutput)314 TEST_F(ElimDeadOutputStoresTest, ArrayedOutput) {
315 // Tests elimination of arrayed output as seen in Tesc shaders.
316 //
317 // #version 450
318 //
319 // layout (vertices = 4) out;
320 //
321 // layout (location = 0) in vec3 N[];
322 // layout (location = 1) in vec3 P[];
323 //
324 // layout (location = 5) out Vertex
325 // {
326 // vec4 c;
327 // vec3 n;
328 // vec3 f[10];
329 // } oVert[];
330 //
331 // void main()
332 // {
333 // oVert[gl_InvocationID].c = vec4(1, 0, 0, 1);
334 // oVert[gl_InvocationID].n = N[gl_InvocationID];
335 // oVert[gl_InvocationID].f[3] = vec3(0, 1, 0);
336 // vec4 worldSpacePos = vec4(P[gl_InvocationID], 1);
337 // gl_out[gl_InvocationID].gl_Position = worldSpacePos;
338 // }
339 const std::string text = R"(
340 OpCapability Tessellation
341 %1 = OpExtInstImport "GLSL.std.450"
342 OpMemoryModel Logical GLSL450
343 OpEntryPoint TessellationControl %main "main" %oVert %gl_InvocationID %N %P %gl_out
344 OpExecutionMode %main OutputVertices 4
345 OpSource GLSL 450
346 OpName %main "main"
347 OpName %Vertex "Vertex"
348 OpMemberName %Vertex 0 "c"
349 OpMemberName %Vertex 1 "n"
350 OpMemberName %Vertex 2 "f"
351 OpName %oVert "oVert"
352 OpName %gl_InvocationID "gl_InvocationID"
353 OpName %N "N"
354 OpName %P "P"
355 OpName %gl_PerVertex "gl_PerVertex"
356 OpMemberName %gl_PerVertex 0 "gl_Position"
357 OpMemberName %gl_PerVertex 1 "gl_PointSize"
358 OpMemberName %gl_PerVertex 2 "gl_ClipDistance"
359 OpMemberName %gl_PerVertex 3 "gl_CullDistance"
360 OpName %gl_out "gl_out"
361 OpDecorate %Vertex Block
362 OpDecorate %oVert Location 5
363 OpDecorate %gl_InvocationID BuiltIn InvocationId
364 OpDecorate %N Location 0
365 OpDecorate %P Location 1
366 OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
367 OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
368 OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
369 OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
370 OpDecorate %gl_PerVertex Block
371 %void = OpTypeVoid
372 %3 = OpTypeFunction %void
373 %float = OpTypeFloat 32
374 %v4float = OpTypeVector %float 4
375 %v3float = OpTypeVector %float 3
376 %uint = OpTypeInt 32 0
377 %uint_10 = OpConstant %uint 10
378 %_arr_v3float_uint_10 = OpTypeArray %v3float %uint_10
379 %Vertex = OpTypeStruct %v4float %v3float %_arr_v3float_uint_10
380 %uint_4 = OpConstant %uint 4
381 %_arr_Vertex_uint_4 = OpTypeArray %Vertex %uint_4
382 %_ptr_Output__arr_Vertex_uint_4 = OpTypePointer Output %_arr_Vertex_uint_4
383 %oVert = OpVariable %_ptr_Output__arr_Vertex_uint_4 Output
384 %int = OpTypeInt 32 1
385 %_ptr_Input_int = OpTypePointer Input %int
386 %gl_InvocationID = OpVariable %_ptr_Input_int Input
387 %int_0 = OpConstant %int 0
388 %float_1 = OpConstant %float 1
389 %float_0 = OpConstant %float 0
390 %24 = OpConstantComposite %v4float %float_1 %float_0 %float_0 %float_1
391 %_ptr_Output_v4float = OpTypePointer Output %v4float
392 %int_1 = OpConstant %int 1
393 %uint_32 = OpConstant %uint 32
394 %_arr_v3float_uint_32 = OpTypeArray %v3float %uint_32
395 %_ptr_Input__arr_v3float_uint_32 = OpTypePointer Input %_arr_v3float_uint_32
396 %N = OpVariable %_ptr_Input__arr_v3float_uint_32 Input
397 %_ptr_Input_v3float = OpTypePointer Input %v3float
398 %_ptr_Output_v3float = OpTypePointer Output %v3float
399 %int_2 = OpConstant %int 2
400 %int_3 = OpConstant %int 3
401 %42 = OpConstantComposite %v3float %float_0 %float_1 %float_0
402 %P = OpVariable %_ptr_Input__arr_v3float_uint_32 Input
403 %uint_1 = OpConstant %uint 1
404 %_arr_float_uint_1 = OpTypeArray %float %uint_1
405 %gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
406 %_arr_gl_PerVertex_uint_4 = OpTypeArray %gl_PerVertex %uint_4
407 %_ptr_Output__arr_gl_PerVertex_uint_4 = OpTypePointer Output %_arr_gl_PerVertex_uint_4
408 %gl_out = OpVariable %_ptr_Output__arr_gl_PerVertex_uint_4 Output
409 %main = OpFunction %void None %3
410 %5 = OpLabel
411 %20 = OpLoad %int %gl_InvocationID
412 %26 = OpAccessChain %_ptr_Output_v4float %oVert %20 %int_0
413 OpStore %26 %24
414 ; CHECK: OpStore %26 %24
415 %35 = OpAccessChain %_ptr_Input_v3float %N %20
416 %36 = OpLoad %v3float %35
417 %38 = OpAccessChain %_ptr_Output_v3float %oVert %20 %int_1
418 OpStore %38 %36
419 ; CHECK-NOT: OpStore %38 %36
420 %43 = OpAccessChain %_ptr_Output_v3float %oVert %20 %int_2 %int_3
421 OpStore %43 %42
422 ; CHECK: OpStore %43 %42
423 %48 = OpAccessChain %_ptr_Input_v3float %P %20
424 %49 = OpLoad %v3float %48
425 %50 = OpCompositeExtract %float %49 0
426 %51 = OpCompositeExtract %float %49 1
427 %52 = OpCompositeExtract %float %49 2
428 %53 = OpCompositeConstruct %v4float %50 %51 %52 %float_1
429 %62 = OpAccessChain %_ptr_Output_v4float %gl_out %20 %int_0
430 OpStore %62 %53
431 OpReturn
432 OpFunctionEnd
433 )";
434
435 SetTargetEnv(SPV_ENV_VULKAN_1_3);
436 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
437
438 std::unordered_set<uint32_t> live_inputs;
439 std::unordered_set<uint32_t> live_builtins;
440 live_inputs.insert(5);
441 live_inputs.insert(10);
442 SinglePassRunAndMatch<EliminateDeadOutputStoresPass>(text, true, &live_inputs,
443 &live_builtins);
444 }
445
TEST_F(ElimDeadOutputStoresTest, ArrayedOutputMemberLocs)446 TEST_F(ElimDeadOutputStoresTest, ArrayedOutputMemberLocs) {
447 // Tests elimination of member location with arrayed output as seen in
448 // Tesc shaders.
449 //
450 // #version 450
451 //
452 // layout (vertices = 4) out;
453 //
454 // layout (location = 0) in vec3 N[];
455 // layout (location = 1) in vec3 P[];
456 //
457 // out Vertex
458 // {
459 // layout (location = 1) vec4 c;
460 // layout (location = 3) vec3 n;
461 // layout (location = 5) vec3 f[10];
462 // } oVert[];
463 //
464 // void main()
465 // {
466 // oVert[gl_InvocationID].c = vec4(1, 0, 0, 1);
467 // oVert[gl_InvocationID].n = N[gl_InvocationID];
468 // oVert[gl_InvocationID].f[3] = vec3(0, 1, 0);
469 // vec4 worldSpacePos = vec4(P[gl_InvocationID], 1);
470 // gl_out[gl_InvocationID].gl_Position = worldSpacePos;
471 // }
472 const std::string text = R"(
473 OpCapability Tessellation
474 %1 = OpExtInstImport "GLSL.std.450"
475 OpMemoryModel Logical GLSL450
476 OpEntryPoint TessellationControl %main "main" %oVert %gl_InvocationID %N %P %gl_out
477 OpExecutionMode %main OutputVertices 4
478 OpSource GLSL 450
479 OpName %main "main"
480 OpName %Vertex "Vertex"
481 OpMemberName %Vertex 0 "c"
482 OpMemberName %Vertex 1 "n"
483 OpMemberName %Vertex 2 "f"
484 OpName %oVert "oVert"
485 OpName %gl_InvocationID "gl_InvocationID"
486 OpName %N "N"
487 OpName %P "P"
488 OpName %gl_PerVertex "gl_PerVertex"
489 OpMemberName %gl_PerVertex 0 "gl_Position"
490 OpMemberName %gl_PerVertex 1 "gl_PointSize"
491 OpMemberName %gl_PerVertex 2 "gl_ClipDistance"
492 OpMemberName %gl_PerVertex 3 "gl_CullDistance"
493 OpName %gl_out "gl_out"
494 OpMemberDecorate %Vertex 0 Location 1
495 OpMemberDecorate %Vertex 1 Location 3
496 OpMemberDecorate %Vertex 2 Location 5
497 OpDecorate %Vertex Block
498 OpDecorate %gl_InvocationID BuiltIn InvocationId
499 OpDecorate %N Location 0
500 OpDecorate %P Location 1
501 OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
502 OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
503 OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
504 OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
505 OpDecorate %gl_PerVertex Block
506 %void = OpTypeVoid
507 %3 = OpTypeFunction %void
508 %float = OpTypeFloat 32
509 %v4float = OpTypeVector %float 4
510 %v3float = OpTypeVector %float 3
511 %uint = OpTypeInt 32 0
512 %uint_10 = OpConstant %uint 10
513 %_arr_v3float_uint_10 = OpTypeArray %v3float %uint_10
514 %Vertex = OpTypeStruct %v4float %v3float %_arr_v3float_uint_10
515 %uint_4 = OpConstant %uint 4
516 %_arr_Vertex_uint_4 = OpTypeArray %Vertex %uint_4
517 %_ptr_Output__arr_Vertex_uint_4 = OpTypePointer Output %_arr_Vertex_uint_4
518 %oVert = OpVariable %_ptr_Output__arr_Vertex_uint_4 Output
519 %int = OpTypeInt 32 1
520 %_ptr_Input_int = OpTypePointer Input %int
521 %gl_InvocationID = OpVariable %_ptr_Input_int Input
522 %int_0 = OpConstant %int 0
523 %float_1 = OpConstant %float 1
524 %float_0 = OpConstant %float 0
525 %24 = OpConstantComposite %v4float %float_1 %float_0 %float_0 %float_1
526 %_ptr_Output_v4float = OpTypePointer Output %v4float
527 %int_1 = OpConstant %int 1
528 %uint_32 = OpConstant %uint 32
529 %_arr_v3float_uint_32 = OpTypeArray %v3float %uint_32
530 %_ptr_Input__arr_v3float_uint_32 = OpTypePointer Input %_arr_v3float_uint_32
531 %N = OpVariable %_ptr_Input__arr_v3float_uint_32 Input
532 %_ptr_Input_v3float = OpTypePointer Input %v3float
533 %_ptr_Output_v3float = OpTypePointer Output %v3float
534 %int_2 = OpConstant %int 2
535 %int_3 = OpConstant %int 3
536 %42 = OpConstantComposite %v3float %float_0 %float_1 %float_0
537 %P = OpVariable %_ptr_Input__arr_v3float_uint_32 Input
538 %uint_1 = OpConstant %uint 1
539 %_arr_float_uint_1 = OpTypeArray %float %uint_1
540 %gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
541 %_arr_gl_PerVertex_uint_4 = OpTypeArray %gl_PerVertex %uint_4
542 %_ptr_Output__arr_gl_PerVertex_uint_4 = OpTypePointer Output %_arr_gl_PerVertex_uint_4
543 %gl_out = OpVariable %_ptr_Output__arr_gl_PerVertex_uint_4 Output
544 %main = OpFunction %void None %3
545 %5 = OpLabel
546 %20 = OpLoad %int %gl_InvocationID
547 %26 = OpAccessChain %_ptr_Output_v4float %oVert %20 %int_0
548 OpStore %26 %24
549 ;CHECK: OpStore %26 %24
550 %35 = OpAccessChain %_ptr_Input_v3float %N %20
551 %36 = OpLoad %v3float %35
552 %38 = OpAccessChain %_ptr_Output_v3float %oVert %20 %int_1
553 OpStore %38 %36
554 ;CHECK-NOT: OpStore %38 %36
555 %43 = OpAccessChain %_ptr_Output_v3float %oVert %20 %int_2 %int_3
556 OpStore %43 %42
557 ;CHECK: OpStore %43 %42
558 %48 = OpAccessChain %_ptr_Input_v3float %P %20
559 %49 = OpLoad %v3float %48
560 %50 = OpCompositeExtract %float %49 0
561 %51 = OpCompositeExtract %float %49 1
562 %52 = OpCompositeExtract %float %49 2
563 %53 = OpCompositeConstruct %v4float %50 %51 %52 %float_1
564 %62 = OpAccessChain %_ptr_Output_v4float %gl_out %20 %int_0
565 OpStore %62 %53
566 OpReturn
567 OpFunctionEnd
568 )";
569
570 SetTargetEnv(SPV_ENV_VULKAN_1_3);
571 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
572
573 std::unordered_set<uint32_t> live_inputs;
574 std::unordered_set<uint32_t> live_builtins;
575 live_inputs.insert(1);
576 live_inputs.insert(8);
577 SinglePassRunAndMatch<EliminateDeadOutputStoresPass>(text, true, &live_inputs,
578 &live_builtins);
579 }
580
TEST_F(ElimDeadOutputStoresTest, ScalarBuiltins)581 TEST_F(ElimDeadOutputStoresTest, ScalarBuiltins) {
582 // Tests elimination of scalar builtins as seen in vert shaders.
583 //
584 // #version 460
585 //
586 // layout (location = 0) in vec3 P;
587 //
588 // void main()
589 // {
590 // gl_Position = vec4(P, 1.0);
591 // gl_PointSize = 1.0;
592 // }
593 const std::string text = R"(
594 OpCapability Shader
595 %1 = OpExtInstImport "GLSL.std.450"
596 OpMemoryModel Logical GLSL450
597 OpEntryPoint Vertex %main "main" %_ %P
598 OpSource GLSL 460
599 OpName %main "main"
600 OpName %gl_PerVertex "gl_PerVertex"
601 OpMemberName %gl_PerVertex 0 "gl_Position"
602 OpMemberName %gl_PerVertex 1 "gl_PointSize"
603 OpMemberName %gl_PerVertex 2 "gl_ClipDistance"
604 OpMemberName %gl_PerVertex 3 "gl_CullDistance"
605 OpName %_ ""
606 OpName %P "P"
607 OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
608 OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
609 OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
610 OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
611 OpDecorate %gl_PerVertex Block
612 OpDecorate %P Location 0
613 %void = OpTypeVoid
614 %3 = OpTypeFunction %void
615 %float = OpTypeFloat 32
616 %v4float = OpTypeVector %float 4
617 %uint = OpTypeInt 32 0
618 %uint_1 = OpConstant %uint 1
619 %_arr_float_uint_1 = OpTypeArray %float %uint_1
620 %gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
621 %_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
622 %_ = OpVariable %_ptr_Output_gl_PerVertex Output
623 %int = OpTypeInt 32 1
624 %int_0 = OpConstant %int 0
625 %v3float = OpTypeVector %float 3
626 %_ptr_Input_v3float = OpTypePointer Input %v3float
627 %P = OpVariable %_ptr_Input_v3float Input
628 %float_1 = OpConstant %float 1
629 %_ptr_Output_v4float = OpTypePointer Output %v4float
630 %int_1 = OpConstant %int 1
631 %_ptr_Output_float = OpTypePointer Output %float
632 %main = OpFunction %void None %3
633 %5 = OpLabel
634 %19 = OpLoad %v3float %P
635 %21 = OpCompositeExtract %float %19 0
636 %22 = OpCompositeExtract %float %19 1
637 %23 = OpCompositeExtract %float %19 2
638 %24 = OpCompositeConstruct %v4float %21 %22 %23 %float_1
639 %26 = OpAccessChain %_ptr_Output_v4float %_ %int_0
640 OpStore %26 %24
641 ;CHECK: OpStore %26 %24
642 %29 = OpAccessChain %_ptr_Output_float %_ %int_1
643 OpStore %29 %float_1
644 ;CHECK-NOT: OpStore %29 %float_1
645 OpReturn
646 OpFunctionEnd
647 )";
648
649 SetTargetEnv(SPV_ENV_VULKAN_1_3);
650 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
651
652 std::unordered_set<uint32_t> live_inputs;
653 std::unordered_set<uint32_t> live_builtins;
654 // Omit spv::BuiltIn::PointSize
655 live_builtins.insert((uint32_t)spv::BuiltIn::ClipDistance);
656 live_builtins.insert((uint32_t)spv::BuiltIn::CullDistance);
657 SinglePassRunAndMatch<EliminateDeadOutputStoresPass>(text, true, &live_inputs,
658 &live_builtins);
659 }
660
TEST_F(ElimDeadOutputStoresTest, ArrayedBuiltins)661 TEST_F(ElimDeadOutputStoresTest, ArrayedBuiltins) {
662 // Tests elimination of arrayed builtins as seen in geom, tesc, and tese
663 // shaders.
664 //
665 // #version 460
666 //
667 // layout(triangle_strip, max_vertices = 3) out;
668 // layout(triangles) in;
669 //
670 // void main()
671 // {
672 // for (int i = 0; i < 3; i++)
673 // {
674 // gl_Position = gl_in[i].gl_Position;
675 // gl_PointSize = gl_in[i].gl_PointSize;
676 //
677 // EmitVertex();
678 // }
679 //
680 // EndPrimitive();
681 // }
682 const std::string text = R"(
683 OpCapability Geometry
684 OpCapability GeometryPointSize
685 %1 = OpExtInstImport "GLSL.std.450"
686 OpMemoryModel Logical GLSL450
687 OpEntryPoint Geometry %main "main" %_ %gl_in
688 OpExecutionMode %main Triangles
689 OpExecutionMode %main Invocations 1
690 OpExecutionMode %main OutputTriangleStrip
691 OpExecutionMode %main OutputVertices 3
692 OpSource GLSL 460
693 OpName %main "main"
694 OpName %i "i"
695 OpName %gl_PerVertex "gl_PerVertex"
696 OpMemberName %gl_PerVertex 0 "gl_Position"
697 OpMemberName %gl_PerVertex 1 "gl_PointSize"
698 OpMemberName %gl_PerVertex 2 "gl_ClipDistance"
699 OpMemberName %gl_PerVertex 3 "gl_CullDistance"
700 OpName %_ ""
701 OpName %gl_PerVertex_0 "gl_PerVertex"
702 OpMemberName %gl_PerVertex_0 0 "gl_Position"
703 OpMemberName %gl_PerVertex_0 1 "gl_PointSize"
704 OpMemberName %gl_PerVertex_0 2 "gl_ClipDistance"
705 OpMemberName %gl_PerVertex_0 3 "gl_CullDistance"
706 OpName %gl_in "gl_in"
707 OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
708 OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
709 OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
710 OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
711 OpDecorate %gl_PerVertex Block
712 OpMemberDecorate %gl_PerVertex_0 0 BuiltIn Position
713 OpMemberDecorate %gl_PerVertex_0 1 BuiltIn PointSize
714 OpMemberDecorate %gl_PerVertex_0 2 BuiltIn ClipDistance
715 OpMemberDecorate %gl_PerVertex_0 3 BuiltIn CullDistance
716 OpDecorate %gl_PerVertex_0 Block
717 %void = OpTypeVoid
718 %3 = OpTypeFunction %void
719 %int = OpTypeInt 32 1
720 %_ptr_Function_int = OpTypePointer Function %int
721 %int_0 = OpConstant %int 0
722 %int_3 = OpConstant %int 3
723 %bool = OpTypeBool
724 %float = OpTypeFloat 32
725 %v4float = OpTypeVector %float 4
726 %uint = OpTypeInt 32 0
727 %uint_1 = OpConstant %uint 1
728 %_arr_float_uint_1 = OpTypeArray %float %uint_1
729 %gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
730 %_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
731 %_ = OpVariable %_ptr_Output_gl_PerVertex Output
732 %gl_PerVertex_0 = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
733 %uint_3 = OpConstant %uint 3
734 %_arr_gl_PerVertex_0_uint_3 = OpTypeArray %gl_PerVertex_0 %uint_3
735 %_ptr_Input__arr_gl_PerVertex_0_uint_3 = OpTypePointer Input %_arr_gl_PerVertex_0_uint_3
736 %gl_in = OpVariable %_ptr_Input__arr_gl_PerVertex_0_uint_3 Input
737 %_ptr_Input_v4float = OpTypePointer Input %v4float
738 %_ptr_Output_v4float = OpTypePointer Output %v4float
739 %int_1 = OpConstant %int 1
740 %_ptr_Input_float = OpTypePointer Input %float
741 %_ptr_Output_float = OpTypePointer Output %float
742 %main = OpFunction %void None %3
743 %5 = OpLabel
744 %i = OpVariable %_ptr_Function_int Function
745 OpStore %i %int_0
746 OpBranch %10
747 %10 = OpLabel
748 OpLoopMerge %12 %13 None
749 OpBranch %14
750 %14 = OpLabel
751 %15 = OpLoad %int %i
752 %18 = OpSLessThan %bool %15 %int_3
753 OpBranchConditional %18 %11 %12
754 %11 = OpLabel
755 %32 = OpLoad %int %i
756 %34 = OpAccessChain %_ptr_Input_v4float %gl_in %32 %int_0
757 %35 = OpLoad %v4float %34
758 %37 = OpAccessChain %_ptr_Output_v4float %_ %int_0
759 OpStore %37 %35
760 ;CHECK: OpStore %37 %35
761 %39 = OpLoad %int %i
762 %41 = OpAccessChain %_ptr_Input_float %gl_in %39 %int_1
763 %42 = OpLoad %float %41
764 %44 = OpAccessChain %_ptr_Output_float %_ %int_1
765 OpStore %44 %42
766 ;CHECK-NOT: OpStore %44 %42
767 OpEmitVertex
768 OpBranch %13
769 %13 = OpLabel
770 %45 = OpLoad %int %i
771 %46 = OpIAdd %int %45 %int_1
772 OpStore %i %46
773 OpBranch %10
774 %12 = OpLabel
775 OpEndPrimitive
776 OpReturn
777 OpFunctionEnd
778 )";
779
780 SetTargetEnv(SPV_ENV_VULKAN_1_3);
781 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
782
783 std::unordered_set<uint32_t> live_inputs;
784 std::unordered_set<uint32_t> live_builtins;
785 // Omit spv::BuiltIn::PointSize
786 live_builtins.insert((uint32_t)spv::BuiltIn::ClipDistance);
787 live_builtins.insert((uint32_t)spv::BuiltIn::CullDistance);
788 SinglePassRunAndMatch<EliminateDeadOutputStoresPass>(text, true, &live_inputs,
789 &live_builtins);
790 }
791
TEST_F(ElimDeadOutputStoresTest, ArrayedOutputPatchLocs)792 TEST_F(ElimDeadOutputStoresTest, ArrayedOutputPatchLocs) {
793 // Tests elimination of location with arrayed patch output as seen in
794 // Tesc shaders.
795 //
796 // #version 450 core
797 //
798 // layout(vertices = 4) out;
799 //
800 // layout(location=0) patch out float patchOut0[2];
801 // layout(location=2) patch out float patchOut1[2];
802 //
803 // void main()
804 // {
805 // patchOut0[1] = 0.0; // Dead loc 1
806 // patchOut1[1] = 1.0; // Live loc 3
807 // }
808 const std::string text = R"(
809 OpCapability Tessellation
810 %1 = OpExtInstImport "GLSL.std.450"
811 OpMemoryModel Logical GLSL450
812 OpEntryPoint TessellationControl %main "main" %patchOut0 %patchOut1
813 OpExecutionMode %main OutputVertices 4
814 OpSource GLSL 450
815 OpName %main "main"
816 OpName %patchOut0 "patchOut0"
817 OpName %patchOut1 "patchOut1"
818 OpDecorate %patchOut0 Patch
819 OpDecorate %patchOut0 Location 0
820 OpDecorate %patchOut1 Patch
821 OpDecorate %patchOut1 Location 2
822 %void = OpTypeVoid
823 %3 = OpTypeFunction %void
824 %float = OpTypeFloat 32
825 %uint = OpTypeInt 32 0
826 %uint_2 = OpConstant %uint 2
827 %_arr_float_uint_2 = OpTypeArray %float %uint_2
828 %_ptr_Output__arr_float_uint_2 = OpTypePointer Output %_arr_float_uint_2
829 %patchOut0 = OpVariable %_ptr_Output__arr_float_uint_2 Output
830 %int = OpTypeInt 32 1
831 %int_1 = OpConstant %int 1
832 %float_0 = OpConstant %float 0
833 %_ptr_Output_float = OpTypePointer Output %float
834 %patchOut1 = OpVariable %_ptr_Output__arr_float_uint_2 Output
835 %float_1 = OpConstant %float 1
836 %main = OpFunction %void None %3
837 %5 = OpLabel
838 %16 = OpAccessChain %_ptr_Output_float %patchOut0 %int_1
839 OpStore %16 %float_0
840 ;CHECK-NOT: OpStore %16 %float_0
841 %19 = OpAccessChain %_ptr_Output_float %patchOut1 %int_1
842 OpStore %19 %float_1
843 ;CHECK: OpStore %19 %float_1
844 OpReturn
845 OpFunctionEnd
846 )";
847
848 SetTargetEnv(SPV_ENV_VULKAN_1_3);
849 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
850
851 std::unordered_set<uint32_t> live_inputs;
852 std::unordered_set<uint32_t> live_builtins;
853 live_inputs.insert(3);
854 SinglePassRunAndMatch<EliminateDeadOutputStoresPass>(text, true, &live_inputs,
855 &live_builtins);
856 }
857
TEST_F(ElimDeadOutputStoresTest, VertMultipleLocationsF16)858 TEST_F(ElimDeadOutputStoresTest, VertMultipleLocationsF16) {
859 // #version 450
860 //
861 // layout(location = 2) out Vertex
862 // {
863 // f16vec4 color0;
864 // f16vec4 color1;
865 // f16vec4 color2[3];
866 // } oVert;
867 //
868 // void main()
869 // {
870 // oVert.color0 = f16vec4(0.0,0.0,0.0,0.0);
871 // oVert.color1 = f16vec4(0.1,0.0,0.0,0.0);
872 // oVert.color2[0] = f16vec4(0.2,0.0,0.0,0.0);
873 // oVert.color2[1] = f16vec4(0.3,0.0,0.0,0.0);
874 // oVert.color2[2] = f16vec4(0.4,0.0,0.0,0.0);
875 // }
876 const std::string text = R"(
877 OpCapability Shader
878 OpCapability Float16
879 OpCapability StorageInputOutput16
880 %1 = OpExtInstImport "GLSL.std.450"
881 OpMemoryModel Logical GLSL450
882 OpEntryPoint Vertex %main "main" %oVert
883 OpSource GLSL 450
884 OpName %main "main"
885 OpName %Vertex "Vertex"
886 OpMemberName %Vertex 0 "color0"
887 OpMemberName %Vertex 1 "color1"
888 OpMemberName %Vertex 2 "color2"
889 OpName %oVert "oVert"
890 OpDecorate %Vertex Block
891 OpDecorate %oVert Location 2
892 %void = OpTypeVoid
893 %3 = OpTypeFunction %void
894 %half = OpTypeFloat 32
895 %v4half = OpTypeVector %half 4
896 %uint = OpTypeInt 32 0
897 %uint_3 = OpConstant %uint 3
898 %_arr_v4half_uint_3 = OpTypeArray %v4half %uint_3
899 %Vertex = OpTypeStruct %v4half %v4half %_arr_v4half_uint_3
900 %_ptr_Output_Vertex = OpTypePointer Output %Vertex
901 %oVert = OpVariable %_ptr_Output_Vertex Output
902 %int = OpTypeInt 32 1
903 %int_0 = OpConstant %int 0
904 %half_0 = OpConstant %half 0
905 %17 = OpConstantComposite %v4half %half_0 %half_0 %half_0 %half_0
906 %_ptr_Output_v4half = OpTypePointer Output %v4half
907 %int_1 = OpConstant %int 1
908 %half_0_100000001 = OpConstant %half 0.100000001
909 %22 = OpConstantComposite %v4half %half_0_100000001 %half_0 %half_0 %half_0
910 %int_2 = OpConstant %int 2
911 %half_0_200000003 = OpConstant %half 0.200000003
912 %26 = OpConstantComposite %v4half %half_0_200000003 %half_0 %half_0 %half_0
913 %half_0_300000012 = OpConstant %half 0.300000012
914 %29 = OpConstantComposite %v4half %half_0_300000012 %half_0 %half_0 %half_0
915 %half_0_400000006 = OpConstant %half 0.400000006
916 %32 = OpConstantComposite %v4half %half_0_400000006 %half_0 %half_0 %half_0
917 %main = OpFunction %void None %3
918 %5 = OpLabel
919 %19 = OpAccessChain %_ptr_Output_v4half %oVert %int_0
920 OpStore %19 %17
921 ;CHECK: OpStore %19 %17
922 %23 = OpAccessChain %_ptr_Output_v4half %oVert %int_1
923 OpStore %23 %22
924 ;CHECK-NOT: OpStore %23 %22
925 %27 = OpAccessChain %_ptr_Output_v4half %oVert %int_2 %int_0
926 OpStore %27 %26
927 ;CHECK-NOT: OpStore %27 %26
928 %30 = OpAccessChain %_ptr_Output_v4half %oVert %int_2 %int_1
929 OpStore %30 %29
930 ;CHECK: OpStore %30 %29
931 %33 = OpAccessChain %_ptr_Output_v4half %oVert %int_2 %int_2
932 OpStore %33 %32
933 ;CHECK-NOT: OpStore %33 %32
934 OpReturn
935 OpFunctionEnd
936 )";
937
938 SetTargetEnv(SPV_ENV_VULKAN_1_3);
939 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
940
941 std::unordered_set<uint32_t> live_inputs;
942 std::unordered_set<uint32_t> live_builtins;
943 live_inputs.insert(2);
944 live_inputs.insert(5);
945 SinglePassRunAndMatch<EliminateDeadOutputStoresPass>(text, true, &live_inputs,
946 &live_builtins);
947 }
948
949 } // namespace
950 } // namespace opt
951 } // namespace spvtools
952