1 // Copyright (c) 2017 Valve Corporation
2 // Copyright (c) 2017 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 <string>
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 InlineOpaqueTest = PassTest<::testing::Test>;
26
TEST_F(InlineOpaqueTest,InlineCallWithStructArgContainingSampledImage)27 TEST_F(InlineOpaqueTest, InlineCallWithStructArgContainingSampledImage) {
28 // Function with opaque argument is inlined.
29 // TODO(greg-lunarg): Add HLSL code
30
31 const std::string predefs_1 =
32 R"(OpCapability Shader
33 %1 = OpExtInstImport "GLSL.std.450"
34 OpMemoryModel Logical GLSL450
35 OpEntryPoint Fragment %main "main" %outColor %texCoords
36 OpExecutionMode %main OriginUpperLeft
37 OpSource GLSL 140
38 OpName %main "main"
39 OpName %S_t "S_t"
40 OpMemberName %S_t 0 "v0"
41 OpMemberName %S_t 1 "v1"
42 OpMemberName %S_t 2 "smp"
43 OpName %foo_struct_S_t_vf2_vf21_ "foo(struct-S_t-vf2-vf21;"
44 OpName %s "s"
45 OpName %outColor "outColor"
46 OpName %sampler15 "sampler15"
47 OpName %s0 "s0"
48 OpName %texCoords "texCoords"
49 OpName %param "param"
50 )";
51
52 const std::string name = R"(OpName %return_value "return_value"
53 )";
54
55 const std::string predefs_2 = R"(OpDecorate %sampler15 DescriptorSet 0
56 %void = OpTypeVoid
57 %13 = OpTypeFunction %void
58 %float = OpTypeFloat 32
59 %v2float = OpTypeVector %float 2
60 %v4float = OpTypeVector %float 4
61 %_ptr_Output_v4float = OpTypePointer Output %v4float
62 %outColor = OpVariable %_ptr_Output_v4float Output
63 %18 = OpTypeImage %float 2D 0 0 0 1 Unknown
64 %19 = OpTypeSampledImage %18
65 %S_t = OpTypeStruct %v2float %v2float %19
66 %_ptr_Function_S_t = OpTypePointer Function %S_t
67 %21 = OpTypeFunction %void %_ptr_Function_S_t
68 %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19
69 %_ptr_Function_19 = OpTypePointer Function %19
70 %sampler15 = OpVariable %_ptr_UniformConstant_19 UniformConstant
71 %int = OpTypeInt 32 1
72 %int_0 = OpConstant %int 0
73 %int_2 = OpConstant %int 2
74 %_ptr_Function_v2float = OpTypePointer Function %v2float
75 %_ptr_Input_v2float = OpTypePointer Input %v2float
76 %texCoords = OpVariable %_ptr_Input_v2float Input
77 )";
78
79 const std::string before =
80 R"(%main = OpFunction %void None %13
81 %29 = OpLabel
82 %s0 = OpVariable %_ptr_Function_S_t Function
83 %param = OpVariable %_ptr_Function_S_t Function
84 %30 = OpLoad %v2float %texCoords
85 %31 = OpAccessChain %_ptr_Function_v2float %s0 %int_0
86 OpStore %31 %30
87 %32 = OpLoad %19 %sampler15
88 %33 = OpAccessChain %_ptr_Function_19 %s0 %int_2
89 OpStore %33 %32
90 %34 = OpLoad %S_t %s0
91 OpStore %param %34
92 %return_value = OpFunctionCall %void %foo_struct_S_t_vf2_vf21_ %param
93 OpReturn
94 OpFunctionEnd
95 )";
96
97 const std::string after =
98 R"(%main = OpFunction %void None %13
99 %29 = OpLabel
100 %s0 = OpVariable %_ptr_Function_S_t Function
101 %param = OpVariable %_ptr_Function_S_t Function
102 %30 = OpLoad %v2float %texCoords
103 %31 = OpAccessChain %_ptr_Function_v2float %s0 %int_0
104 OpStore %31 %30
105 %32 = OpLoad %19 %sampler15
106 %33 = OpAccessChain %_ptr_Function_19 %s0 %int_2
107 OpStore %33 %32
108 %34 = OpLoad %S_t %s0
109 OpStore %param %34
110 %42 = OpAccessChain %_ptr_Function_19 %param %int_2
111 %43 = OpLoad %19 %42
112 %44 = OpAccessChain %_ptr_Function_v2float %param %int_0
113 %45 = OpLoad %v2float %44
114 %46 = OpImageSampleImplicitLod %v4float %43 %45
115 OpStore %outColor %46
116 OpReturn
117 OpFunctionEnd
118 )";
119
120 const std::string post_defs =
121 R"(%foo_struct_S_t_vf2_vf21_ = OpFunction %void None %21
122 %s = OpFunctionParameter %_ptr_Function_S_t
123 %35 = OpLabel
124 %36 = OpAccessChain %_ptr_Function_19 %s %int_2
125 %37 = OpLoad %19 %36
126 %38 = OpAccessChain %_ptr_Function_v2float %s %int_0
127 %39 = OpLoad %v2float %38
128 %40 = OpImageSampleImplicitLod %v4float %37 %39
129 OpStore %outColor %40
130 OpReturn
131 OpFunctionEnd
132 )";
133
134 SinglePassRunAndCheck<InlineOpaquePass>(
135 predefs_1 + name + predefs_2 + before + post_defs,
136 predefs_1 + predefs_2 + after + post_defs, true, true);
137 }
138
TEST_F(InlineOpaqueTest,InlineOpaqueReturn)139 TEST_F(InlineOpaqueTest, InlineOpaqueReturn) {
140 // Function with opaque return value is inlined.
141 // TODO(greg-lunarg): Add HLSL code
142
143 const std::string predefs =
144 R"(OpCapability Shader
145 %1 = OpExtInstImport "GLSL.std.450"
146 OpMemoryModel Logical GLSL450
147 OpEntryPoint Fragment %main "main" %texCoords %outColor
148 OpExecutionMode %main OriginUpperLeft
149 OpSource GLSL 140
150 OpName %main "main"
151 OpName %foo_ "foo("
152 OpName %texCoords "texCoords"
153 OpName %outColor "outColor"
154 OpName %sampler15 "sampler15"
155 OpName %sampler16 "sampler16"
156 OpDecorate %sampler15 DescriptorSet 0
157 OpDecorate %sampler16 DescriptorSet 0
158 %void = OpTypeVoid
159 %9 = OpTypeFunction %void
160 %float = OpTypeFloat 32
161 %v2float = OpTypeVector %float 2
162 %bool = OpTypeBool
163 %false = OpConstantFalse %bool
164 %_ptr_Input_v2float = OpTypePointer Input %v2float
165 %texCoords = OpVariable %_ptr_Input_v2float Input
166 %float_0 = OpConstant %float 0
167 %16 = OpConstantComposite %v2float %float_0 %float_0
168 %v4float = OpTypeVector %float 4
169 %_ptr_Output_v4float = OpTypePointer Output %v4float
170 %outColor = OpVariable %_ptr_Output_v4float Output
171 %19 = OpTypeImage %float 2D 0 0 0 1 Unknown
172 %20 = OpTypeSampledImage %19
173 %21 = OpTypeFunction %20
174 %_ptr_UniformConstant_20 = OpTypePointer UniformConstant %20
175 %_ptr_Function_20 = OpTypePointer Function %20
176 %sampler15 = OpVariable %_ptr_UniformConstant_20 UniformConstant
177 %sampler16 = OpVariable %_ptr_UniformConstant_20 UniformConstant
178 )";
179
180 const std::string before =
181 R"(%main = OpFunction %void None %9
182 %24 = OpLabel
183 %25 = OpVariable %_ptr_Function_20 Function
184 %26 = OpFunctionCall %20 %foo_
185 OpStore %25 %26
186 %27 = OpLoad %20 %25
187 %28 = OpLoad %v2float %texCoords
188 %29 = OpImageSampleImplicitLod %v4float %27 %28
189 OpStore %outColor %29
190 OpReturn
191 OpFunctionEnd
192 )";
193
194 const std::string after =
195 R"(%main = OpFunction %void None %9
196 %24 = OpLabel
197 %34 = OpVariable %_ptr_Function_20 Function
198 %35 = OpVariable %_ptr_Function_20 Function
199 %25 = OpVariable %_ptr_Function_20 Function
200 %37 = OpLoad %20 %sampler16
201 OpStore %34 %37
202 %38 = OpLoad %20 %34
203 OpStore %35 %38
204 %26 = OpLoad %20 %35
205 OpStore %25 %26
206 %27 = OpLoad %20 %25
207 %28 = OpLoad %v2float %texCoords
208 %29 = OpImageSampleImplicitLod %v4float %27 %28
209 OpStore %outColor %29
210 OpReturn
211 OpFunctionEnd
212 )";
213
214 const std::string post_defs =
215 R"(%foo_ = OpFunction %20 None %21
216 %30 = OpLabel
217 %31 = OpVariable %_ptr_Function_20 Function
218 %32 = OpLoad %20 %sampler16
219 OpStore %31 %32
220 %33 = OpLoad %20 %31
221 OpReturnValue %33
222 OpFunctionEnd
223 )";
224
225 SinglePassRunAndCheck<InlineOpaquePass>(
226 predefs + before + post_defs, predefs + after + post_defs, true, true);
227 }
228
TEST_F(InlineOpaqueTest,InlineInNonEntryPointFunction)229 TEST_F(InlineOpaqueTest, InlineInNonEntryPointFunction) {
230 // This demonstrates opaque inlining in a function that is not
231 // an entry point function (main2) but is in the call tree of an
232 // entry point function (main).
233 // TODO(greg-lunarg): Add HLSL code
234
235 const std::string predefs =
236 R"(OpCapability Shader
237 %1 = OpExtInstImport "GLSL.std.450"
238 OpMemoryModel Logical GLSL450
239 OpEntryPoint Fragment %main "main" %outColor %texCoords
240 OpExecutionMode %main OriginUpperLeft
241 OpSource GLSL 140
242 OpName %main "main"
243 OpName %main2 "main2"
244 OpName %S_t "S_t"
245 OpMemberName %S_t 0 "v0"
246 OpMemberName %S_t 1 "v1"
247 OpMemberName %S_t 2 "smp"
248 OpName %foo_struct_S_t_vf2_vf21_ "foo(struct-S_t-vf2-vf21;"
249 OpName %s "s"
250 OpName %outColor "outColor"
251 OpName %sampler15 "sampler15"
252 OpName %s0 "s0"
253 OpName %texCoords "texCoords"
254 OpName %param "param"
255 OpDecorate %sampler15 DescriptorSet 0
256 %void = OpTypeVoid
257 %13 = OpTypeFunction %void
258 %float = OpTypeFloat 32
259 %v2float = OpTypeVector %float 2
260 %v4float = OpTypeVector %float 4
261 %_ptr_Output_v4float = OpTypePointer Output %v4float
262 %outColor = OpVariable %_ptr_Output_v4float Output
263 %18 = OpTypeImage %float 2D 0 0 0 1 Unknown
264 %19 = OpTypeSampledImage %18
265 %S_t = OpTypeStruct %v2float %v2float %19
266 %_ptr_Function_S_t = OpTypePointer Function %S_t
267 %21 = OpTypeFunction %void %_ptr_Function_S_t
268 %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19
269 %_ptr_Function_19 = OpTypePointer Function %19
270 %sampler15 = OpVariable %_ptr_UniformConstant_19 UniformConstant
271 %int = OpTypeInt 32 1
272 %int_0 = OpConstant %int 0
273 %int_2 = OpConstant %int 2
274 %_ptr_Function_v2float = OpTypePointer Function %v2float
275 %_ptr_Input_v2float = OpTypePointer Input %v2float
276 %texCoords = OpVariable %_ptr_Input_v2float Input
277 )";
278
279 const std::string before =
280 R"(%main2 = OpFunction %void None %13
281 %29 = OpLabel
282 %s0 = OpVariable %_ptr_Function_S_t Function
283 %param = OpVariable %_ptr_Function_S_t Function
284 %30 = OpLoad %v2float %texCoords
285 %31 = OpAccessChain %_ptr_Function_v2float %s0 %int_0
286 OpStore %31 %30
287 %32 = OpLoad %19 %sampler15
288 %33 = OpAccessChain %_ptr_Function_19 %s0 %int_2
289 OpStore %33 %32
290 %34 = OpLoad %S_t %s0
291 OpStore %param %34
292 %35 = OpFunctionCall %void %foo_struct_S_t_vf2_vf21_ %param
293 OpReturn
294 OpFunctionEnd
295 )";
296
297 const std::string after =
298 R"(%main2 = OpFunction %void None %13
299 %29 = OpLabel
300 %s0 = OpVariable %_ptr_Function_S_t Function
301 %param = OpVariable %_ptr_Function_S_t Function
302 %30 = OpLoad %v2float %texCoords
303 %31 = OpAccessChain %_ptr_Function_v2float %s0 %int_0
304 OpStore %31 %30
305 %32 = OpLoad %19 %sampler15
306 %33 = OpAccessChain %_ptr_Function_19 %s0 %int_2
307 OpStore %33 %32
308 %34 = OpLoad %S_t %s0
309 OpStore %param %34
310 %45 = OpAccessChain %_ptr_Function_19 %param %int_2
311 %46 = OpLoad %19 %45
312 %47 = OpAccessChain %_ptr_Function_v2float %param %int_0
313 %48 = OpLoad %v2float %47
314 %49 = OpImageSampleImplicitLod %v4float %46 %48
315 OpStore %outColor %49
316 OpReturn
317 OpFunctionEnd
318 )";
319
320 const std::string post_defs =
321 R"(%main = OpFunction %void None %13
322 %36 = OpLabel
323 %37 = OpFunctionCall %void %main2
324 OpReturn
325 OpFunctionEnd
326 %foo_struct_S_t_vf2_vf21_ = OpFunction %void None %21
327 %s = OpFunctionParameter %_ptr_Function_S_t
328 %38 = OpLabel
329 %39 = OpAccessChain %_ptr_Function_19 %s %int_2
330 %40 = OpLoad %19 %39
331 %41 = OpAccessChain %_ptr_Function_v2float %s %int_0
332 %42 = OpLoad %v2float %41
333 %43 = OpImageSampleImplicitLod %v4float %40 %42
334 OpStore %outColor %43
335 OpReturn
336 OpFunctionEnd
337 )";
338
339 SinglePassRunAndCheck<InlineOpaquePass>(
340 predefs + before + post_defs, predefs + after + post_defs, true, true);
341 }
342
TEST_F(InlineOpaqueTest,NoInlineNoOpaque)343 TEST_F(InlineOpaqueTest, NoInlineNoOpaque) {
344 // Function without opaque interface is not inlined.
345 // #version 140
346 //
347 // in vec4 BaseColor;
348 //
349 // float foo(vec4 bar)
350 // {
351 // return bar.x + bar.y;
352 // }
353 //
354 // void main()
355 // {
356 // vec4 color = vec4(foo(BaseColor));
357 // gl_FragColor = color;
358 // }
359
360 const std::string assembly =
361 R"(OpCapability Shader
362 %1 = OpExtInstImport "GLSL.std.450"
363 OpMemoryModel Logical GLSL450
364 OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
365 OpExecutionMode %main OriginUpperLeft
366 OpSource GLSL 140
367 OpName %main "main"
368 OpName %foo_vf4_ "foo(vf4;"
369 OpName %bar "bar"
370 OpName %color "color"
371 OpName %BaseColor "BaseColor"
372 OpName %param "param"
373 OpName %gl_FragColor "gl_FragColor"
374 %void = OpTypeVoid
375 %10 = OpTypeFunction %void
376 %float = OpTypeFloat 32
377 %v4float = OpTypeVector %float 4
378 %_ptr_Function_v4float = OpTypePointer Function %v4float
379 %14 = OpTypeFunction %float %_ptr_Function_v4float
380 %uint = OpTypeInt 32 0
381 %uint_0 = OpConstant %uint 0
382 %_ptr_Function_float = OpTypePointer Function %float
383 %uint_1 = OpConstant %uint 1
384 %_ptr_Input_v4float = OpTypePointer Input %v4float
385 %BaseColor = OpVariable %_ptr_Input_v4float Input
386 %_ptr_Output_v4float = OpTypePointer Output %v4float
387 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
388 %main = OpFunction %void None %10
389 %21 = OpLabel
390 %color = OpVariable %_ptr_Function_v4float Function
391 %param = OpVariable %_ptr_Function_v4float Function
392 %22 = OpLoad %v4float %BaseColor
393 OpStore %param %22
394 %23 = OpFunctionCall %float %foo_vf4_ %param
395 %24 = OpCompositeConstruct %v4float %23 %23 %23 %23
396 OpStore %color %24
397 %25 = OpLoad %v4float %color
398 OpStore %gl_FragColor %25
399 OpReturn
400 OpFunctionEnd
401 %foo_vf4_ = OpFunction %float None %14
402 %bar = OpFunctionParameter %_ptr_Function_v4float
403 %26 = OpLabel
404 %27 = OpAccessChain %_ptr_Function_float %bar %uint_0
405 %28 = OpLoad %float %27
406 %29 = OpAccessChain %_ptr_Function_float %bar %uint_1
407 %30 = OpLoad %float %29
408 %31 = OpFAdd %float %28 %30
409 OpReturnValue %31
410 OpFunctionEnd
411 )";
412
413 SinglePassRunAndCheck<InlineOpaquePass>(assembly, assembly, true, true);
414 }
415
416 } // namespace
417 } // namespace opt
418 } // namespace spvtools
419