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