| // Copyright (c) 2017 Valve Corporation | |
| // Copyright (c) 2017 LunarG Inc. | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // you may not use this file except in compliance with the License. | |
| // You may obtain a copy of the License at | |
| // | |
| // http://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| // See the License for the specific language governing permissions and | |
| // limitations under the License. | |
| #include <string> | |
| #include "test/opt/pass_fixture.h" | |
| #include "test/opt/pass_utils.h" | |
| namespace spvtools { | |
| namespace opt { | |
| namespace { | |
| using InlineOpaqueTest = PassTest<::testing::Test>; | |
| TEST_F(InlineOpaqueTest, InlineCallWithStructArgContainingSampledImage) { | |
| // Function with opaque argument is inlined. | |
| // TODO(greg-lunarg): Add HLSL code | |
| const std::string predefs_1 = | |
| R"(OpCapability Shader | |
| %1 = OpExtInstImport "GLSL.std.450" | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint Fragment %main "main" %outColor %texCoords | |
| OpExecutionMode %main OriginUpperLeft | |
| OpSource GLSL 140 | |
| OpName %main "main" | |
| OpName %S_t "S_t" | |
| OpMemberName %S_t 0 "v0" | |
| OpMemberName %S_t 1 "v1" | |
| OpMemberName %S_t 2 "smp" | |
| OpName %foo_struct_S_t_vf2_vf21_ "foo(struct-S_t-vf2-vf21;" | |
| OpName %s "s" | |
| OpName %outColor "outColor" | |
| OpName %sampler15 "sampler15" | |
| OpName %s0 "s0" | |
| OpName %texCoords "texCoords" | |
| OpName %param "param" | |
| )"; | |
| const std::string name = R"(OpName %return_value "return_value" | |
| )"; | |
| const std::string predefs_2 = R"(OpDecorate %sampler15 DescriptorSet 0 | |
| %void = OpTypeVoid | |
| %13 = OpTypeFunction %void | |
| %float = OpTypeFloat 32 | |
| %v2float = OpTypeVector %float 2 | |
| %v4float = OpTypeVector %float 4 | |
| %_ptr_Output_v4float = OpTypePointer Output %v4float | |
| %outColor = OpVariable %_ptr_Output_v4float Output | |
| %18 = OpTypeImage %float 2D 0 0 0 1 Unknown | |
| %19 = OpTypeSampledImage %18 | |
| %S_t = OpTypeStruct %v2float %v2float %19 | |
| %_ptr_Function_S_t = OpTypePointer Function %S_t | |
| %21 = OpTypeFunction %void %_ptr_Function_S_t | |
| %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19 | |
| %_ptr_Function_19 = OpTypePointer Function %19 | |
| %sampler15 = OpVariable %_ptr_UniformConstant_19 UniformConstant | |
| %int = OpTypeInt 32 1 | |
| %int_0 = OpConstant %int 0 | |
| %int_2 = OpConstant %int 2 | |
| %_ptr_Function_v2float = OpTypePointer Function %v2float | |
| %_ptr_Input_v2float = OpTypePointer Input %v2float | |
| %texCoords = OpVariable %_ptr_Input_v2float Input | |
| )"; | |
| const std::string before = | |
| R"(%main = OpFunction %void None %13 | |
| %29 = OpLabel | |
| %s0 = OpVariable %_ptr_Function_S_t Function | |
| %param = OpVariable %_ptr_Function_S_t Function | |
| %30 = OpLoad %v2float %texCoords | |
| %31 = OpAccessChain %_ptr_Function_v2float %s0 %int_0 | |
| OpStore %31 %30 | |
| %32 = OpLoad %19 %sampler15 | |
| %33 = OpAccessChain %_ptr_Function_19 %s0 %int_2 | |
| OpStore %33 %32 | |
| %34 = OpLoad %S_t %s0 | |
| OpStore %param %34 | |
| %return_value = OpFunctionCall %void %foo_struct_S_t_vf2_vf21_ %param | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| const std::string after = | |
| R"(%main = OpFunction %void None %13 | |
| %29 = OpLabel | |
| %s0 = OpVariable %_ptr_Function_S_t Function | |
| %param = OpVariable %_ptr_Function_S_t Function | |
| %30 = OpLoad %v2float %texCoords | |
| %31 = OpAccessChain %_ptr_Function_v2float %s0 %int_0 | |
| OpStore %31 %30 | |
| %32 = OpLoad %19 %sampler15 | |
| %33 = OpAccessChain %_ptr_Function_19 %s0 %int_2 | |
| OpStore %33 %32 | |
| %34 = OpLoad %S_t %s0 | |
| OpStore %param %34 | |
| %42 = OpAccessChain %_ptr_Function_19 %param %int_2 | |
| %43 = OpLoad %19 %42 | |
| %44 = OpAccessChain %_ptr_Function_v2float %param %int_0 | |
| %45 = OpLoad %v2float %44 | |
| %46 = OpImageSampleImplicitLod %v4float %43 %45 | |
| OpStore %outColor %46 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| const std::string post_defs = | |
| R"(%foo_struct_S_t_vf2_vf21_ = OpFunction %void None %21 | |
| %s = OpFunctionParameter %_ptr_Function_S_t | |
| %35 = OpLabel | |
| %36 = OpAccessChain %_ptr_Function_19 %s %int_2 | |
| %37 = OpLoad %19 %36 | |
| %38 = OpAccessChain %_ptr_Function_v2float %s %int_0 | |
| %39 = OpLoad %v2float %38 | |
| %40 = OpImageSampleImplicitLod %v4float %37 %39 | |
| OpStore %outColor %40 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndCheck<InlineOpaquePass>( | |
| predefs_1 + name + predefs_2 + before + post_defs, | |
| predefs_1 + predefs_2 + after + post_defs, true, true); | |
| } | |
| TEST_F(InlineOpaqueTest, InlineOpaqueReturn) { | |
| // Function with opaque return value is inlined. | |
| // TODO(greg-lunarg): Add HLSL code | |
| const std::string predefs = | |
| R"(OpCapability Shader | |
| %1 = OpExtInstImport "GLSL.std.450" | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint Fragment %main "main" %texCoords %outColor | |
| OpExecutionMode %main OriginUpperLeft | |
| OpSource GLSL 140 | |
| OpName %main "main" | |
| OpName %foo_ "foo(" | |
| OpName %texCoords "texCoords" | |
| OpName %outColor "outColor" | |
| OpName %sampler15 "sampler15" | |
| OpName %sampler16 "sampler16" | |
| OpDecorate %sampler15 DescriptorSet 0 | |
| OpDecorate %sampler16 DescriptorSet 0 | |
| %void = OpTypeVoid | |
| %9 = OpTypeFunction %void | |
| %float = OpTypeFloat 32 | |
| %v2float = OpTypeVector %float 2 | |
| %bool = OpTypeBool | |
| %false = OpConstantFalse %bool | |
| %_ptr_Input_v2float = OpTypePointer Input %v2float | |
| %texCoords = OpVariable %_ptr_Input_v2float Input | |
| %float_0 = OpConstant %float 0 | |
| %16 = OpConstantComposite %v2float %float_0 %float_0 | |
| %v4float = OpTypeVector %float 4 | |
| %_ptr_Output_v4float = OpTypePointer Output %v4float | |
| %outColor = OpVariable %_ptr_Output_v4float Output | |
| %19 = OpTypeImage %float 2D 0 0 0 1 Unknown | |
| %20 = OpTypeSampledImage %19 | |
| %21 = OpTypeFunction %20 | |
| %_ptr_UniformConstant_20 = OpTypePointer UniformConstant %20 | |
| %_ptr_Function_20 = OpTypePointer Function %20 | |
| %sampler15 = OpVariable %_ptr_UniformConstant_20 UniformConstant | |
| %sampler16 = OpVariable %_ptr_UniformConstant_20 UniformConstant | |
| )"; | |
| const std::string before = | |
| R"(%main = OpFunction %void None %9 | |
| %24 = OpLabel | |
| %25 = OpVariable %_ptr_Function_20 Function | |
| %26 = OpFunctionCall %20 %foo_ | |
| OpStore %25 %26 | |
| %27 = OpLoad %20 %25 | |
| %28 = OpLoad %v2float %texCoords | |
| %29 = OpImageSampleImplicitLod %v4float %27 %28 | |
| OpStore %outColor %29 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| const std::string after = | |
| R"(%main = OpFunction %void None %9 | |
| %24 = OpLabel | |
| %34 = OpVariable %_ptr_Function_20 Function | |
| %35 = OpVariable %_ptr_Function_20 Function | |
| %25 = OpVariable %_ptr_Function_20 Function | |
| %37 = OpLoad %20 %sampler16 | |
| OpStore %34 %37 | |
| %38 = OpLoad %20 %34 | |
| OpStore %35 %38 | |
| %26 = OpLoad %20 %35 | |
| OpStore %25 %26 | |
| %27 = OpLoad %20 %25 | |
| %28 = OpLoad %v2float %texCoords | |
| %29 = OpImageSampleImplicitLod %v4float %27 %28 | |
| OpStore %outColor %29 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| const std::string post_defs = | |
| R"(%foo_ = OpFunction %20 None %21 | |
| %30 = OpLabel | |
| %31 = OpVariable %_ptr_Function_20 Function | |
| %32 = OpLoad %20 %sampler16 | |
| OpStore %31 %32 | |
| %33 = OpLoad %20 %31 | |
| OpReturnValue %33 | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndCheck<InlineOpaquePass>( | |
| predefs + before + post_defs, predefs + after + post_defs, true, true); | |
| } | |
| TEST_F(InlineOpaqueTest, InlineOpaqueForLinkage) { | |
| const std::string predefs_1 = | |
| R"(OpCapability Shader | |
| OpCapability Linkage | |
| %1 = OpExtInstImport "GLSL.std.450" | |
| OpMemoryModel Logical GLSL450 | |
| OpSource HLSL 630 | |
| OpName %main "main" | |
| OpName %S_t "S_t" | |
| OpMemberName %S_t 0 "v0" | |
| OpMemberName %S_t 1 "v1" | |
| OpMemberName %S_t 2 "smp" | |
| OpName %foo_struct_S_t_vf2_vf21_ "foo(struct-S_t-vf2-vf21;" | |
| OpName %s "s" | |
| OpName %outColor "outColor" | |
| OpName %sampler15 "sampler15" | |
| OpName %s0 "s0" | |
| OpName %texCoords "texCoords" | |
| OpName %param "param" | |
| OpDecorate %main LinkageAttributes "main" Export | |
| )"; | |
| const std::string name = R"(OpName %return_value "return_value" | |
| )"; | |
| const std::string predefs_2 = R"(OpDecorate %sampler15 DescriptorSet 0 | |
| %void = OpTypeVoid | |
| %13 = OpTypeFunction %void | |
| %float = OpTypeFloat 32 | |
| %v2float = OpTypeVector %float 2 | |
| %v4float = OpTypeVector %float 4 | |
| %_ptr_Output_v4float = OpTypePointer Output %v4float | |
| %outColor = OpVariable %_ptr_Output_v4float Output | |
| %18 = OpTypeImage %float 2D 0 0 0 1 Unknown | |
| %19 = OpTypeSampledImage %18 | |
| %S_t = OpTypeStruct %v2float %v2float %19 | |
| %_ptr_Function_S_t = OpTypePointer Function %S_t | |
| %21 = OpTypeFunction %void %_ptr_Function_S_t | |
| %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19 | |
| %_ptr_Function_19 = OpTypePointer Function %19 | |
| %sampler15 = OpVariable %_ptr_UniformConstant_19 UniformConstant | |
| %int = OpTypeInt 32 1 | |
| %int_0 = OpConstant %int 0 | |
| %int_2 = OpConstant %int 2 | |
| %_ptr_Function_v2float = OpTypePointer Function %v2float | |
| %_ptr_Input_v2float = OpTypePointer Input %v2float | |
| %texCoords = OpVariable %_ptr_Input_v2float Input | |
| )"; | |
| const std::string before = | |
| R"(%main = OpFunction %void None %13 | |
| %29 = OpLabel | |
| %s0 = OpVariable %_ptr_Function_S_t Function | |
| %param = OpVariable %_ptr_Function_S_t Function | |
| %30 = OpLoad %v2float %texCoords | |
| %31 = OpAccessChain %_ptr_Function_v2float %s0 %int_0 | |
| OpStore %31 %30 | |
| %32 = OpLoad %19 %sampler15 | |
| %33 = OpAccessChain %_ptr_Function_19 %s0 %int_2 | |
| OpStore %33 %32 | |
| %34 = OpLoad %S_t %s0 | |
| OpStore %param %34 | |
| %return_value = OpFunctionCall %void %foo_struct_S_t_vf2_vf21_ %param | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| const std::string after = | |
| R"(%main = OpFunction %void None %13 | |
| %29 = OpLabel | |
| %s0 = OpVariable %_ptr_Function_S_t Function | |
| %param = OpVariable %_ptr_Function_S_t Function | |
| %30 = OpLoad %v2float %texCoords | |
| %31 = OpAccessChain %_ptr_Function_v2float %s0 %int_0 | |
| OpStore %31 %30 | |
| %32 = OpLoad %19 %sampler15 | |
| %33 = OpAccessChain %_ptr_Function_19 %s0 %int_2 | |
| OpStore %33 %32 | |
| %34 = OpLoad %S_t %s0 | |
| OpStore %param %34 | |
| %42 = OpAccessChain %_ptr_Function_19 %param %int_2 | |
| %43 = OpLoad %19 %42 | |
| %44 = OpAccessChain %_ptr_Function_v2float %param %int_0 | |
| %45 = OpLoad %v2float %44 | |
| %46 = OpImageSampleImplicitLod %v4float %43 %45 | |
| OpStore %outColor %46 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| const std::string post_defs = | |
| R"(%foo_struct_S_t_vf2_vf21_ = OpFunction %void None %21 | |
| %s = OpFunctionParameter %_ptr_Function_S_t | |
| %35 = OpLabel | |
| %36 = OpAccessChain %_ptr_Function_19 %s %int_2 | |
| %37 = OpLoad %19 %36 | |
| %38 = OpAccessChain %_ptr_Function_v2float %s %int_0 | |
| %39 = OpLoad %v2float %38 | |
| %40 = OpImageSampleImplicitLod %v4float %37 %39 | |
| OpStore %outColor %40 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndCheck<InlineOpaquePass>( | |
| predefs_1 + name + predefs_2 + before + post_defs, | |
| predefs_1 + predefs_2 + after + post_defs, true, true); | |
| } | |
| TEST_F(InlineOpaqueTest, InlineInNonEntryPointFunction) { | |
| // This demonstrates opaque inlining in a function that is not | |
| // an entry point function (main2) but is in the call tree of an | |
| // entry point function (main). | |
| // TODO(greg-lunarg): Add HLSL code | |
| const std::string predefs = | |
| R"(OpCapability Shader | |
| %1 = OpExtInstImport "GLSL.std.450" | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint Fragment %main "main" %outColor %texCoords | |
| OpExecutionMode %main OriginUpperLeft | |
| OpSource GLSL 140 | |
| OpName %main "main" | |
| OpName %main2 "main2" | |
| OpName %S_t "S_t" | |
| OpMemberName %S_t 0 "v0" | |
| OpMemberName %S_t 1 "v1" | |
| OpMemberName %S_t 2 "smp" | |
| OpName %foo_struct_S_t_vf2_vf21_ "foo(struct-S_t-vf2-vf21;" | |
| OpName %s "s" | |
| OpName %outColor "outColor" | |
| OpName %sampler15 "sampler15" | |
| OpName %s0 "s0" | |
| OpName %texCoords "texCoords" | |
| OpName %param "param" | |
| OpDecorate %sampler15 DescriptorSet 0 | |
| %void = OpTypeVoid | |
| %13 = OpTypeFunction %void | |
| %float = OpTypeFloat 32 | |
| %v2float = OpTypeVector %float 2 | |
| %v4float = OpTypeVector %float 4 | |
| %_ptr_Output_v4float = OpTypePointer Output %v4float | |
| %outColor = OpVariable %_ptr_Output_v4float Output | |
| %18 = OpTypeImage %float 2D 0 0 0 1 Unknown | |
| %19 = OpTypeSampledImage %18 | |
| %S_t = OpTypeStruct %v2float %v2float %19 | |
| %_ptr_Function_S_t = OpTypePointer Function %S_t | |
| %21 = OpTypeFunction %void %_ptr_Function_S_t | |
| %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19 | |
| %_ptr_Function_19 = OpTypePointer Function %19 | |
| %sampler15 = OpVariable %_ptr_UniformConstant_19 UniformConstant | |
| %int = OpTypeInt 32 1 | |
| %int_0 = OpConstant %int 0 | |
| %int_2 = OpConstant %int 2 | |
| %_ptr_Function_v2float = OpTypePointer Function %v2float | |
| %_ptr_Input_v2float = OpTypePointer Input %v2float | |
| %texCoords = OpVariable %_ptr_Input_v2float Input | |
| )"; | |
| const std::string before = | |
| R"(%main2 = OpFunction %void None %13 | |
| %29 = OpLabel | |
| %s0 = OpVariable %_ptr_Function_S_t Function | |
| %param = OpVariable %_ptr_Function_S_t Function | |
| %30 = OpLoad %v2float %texCoords | |
| %31 = OpAccessChain %_ptr_Function_v2float %s0 %int_0 | |
| OpStore %31 %30 | |
| %32 = OpLoad %19 %sampler15 | |
| %33 = OpAccessChain %_ptr_Function_19 %s0 %int_2 | |
| OpStore %33 %32 | |
| %34 = OpLoad %S_t %s0 | |
| OpStore %param %34 | |
| %35 = OpFunctionCall %void %foo_struct_S_t_vf2_vf21_ %param | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| const std::string after = | |
| R"(%main2 = OpFunction %void None %13 | |
| %29 = OpLabel | |
| %s0 = OpVariable %_ptr_Function_S_t Function | |
| %param = OpVariable %_ptr_Function_S_t Function | |
| %30 = OpLoad %v2float %texCoords | |
| %31 = OpAccessChain %_ptr_Function_v2float %s0 %int_0 | |
| OpStore %31 %30 | |
| %32 = OpLoad %19 %sampler15 | |
| %33 = OpAccessChain %_ptr_Function_19 %s0 %int_2 | |
| OpStore %33 %32 | |
| %34 = OpLoad %S_t %s0 | |
| OpStore %param %34 | |
| %45 = OpAccessChain %_ptr_Function_19 %param %int_2 | |
| %46 = OpLoad %19 %45 | |
| %47 = OpAccessChain %_ptr_Function_v2float %param %int_0 | |
| %48 = OpLoad %v2float %47 | |
| %49 = OpImageSampleImplicitLod %v4float %46 %48 | |
| OpStore %outColor %49 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| const std::string post_defs = | |
| R"(%main = OpFunction %void None %13 | |
| %36 = OpLabel | |
| %37 = OpFunctionCall %void %main2 | |
| OpReturn | |
| OpFunctionEnd | |
| %foo_struct_S_t_vf2_vf21_ = OpFunction %void None %21 | |
| %s = OpFunctionParameter %_ptr_Function_S_t | |
| %38 = OpLabel | |
| %39 = OpAccessChain %_ptr_Function_19 %s %int_2 | |
| %40 = OpLoad %19 %39 | |
| %41 = OpAccessChain %_ptr_Function_v2float %s %int_0 | |
| %42 = OpLoad %v2float %41 | |
| %43 = OpImageSampleImplicitLod %v4float %40 %42 | |
| OpStore %outColor %43 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndCheck<InlineOpaquePass>( | |
| predefs + before + post_defs, predefs + after + post_defs, true, true); | |
| } | |
| TEST_F(InlineOpaqueTest, NoInlineNoOpaque) { | |
| // Function without opaque interface is not inlined. | |
| // #version 140 | |
| // | |
| // in vec4 BaseColor; | |
| // | |
| // float foo(vec4 bar) | |
| // { | |
| // return bar.x + bar.y; | |
| // } | |
| // | |
| // void main() | |
| // { | |
| // vec4 color = vec4(foo(BaseColor)); | |
| // gl_FragColor = color; | |
| // } | |
| const std::string assembly = | |
| R"(OpCapability Shader | |
| %1 = OpExtInstImport "GLSL.std.450" | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor | |
| OpExecutionMode %main OriginUpperLeft | |
| OpSource GLSL 140 | |
| OpName %main "main" | |
| OpName %foo_vf4_ "foo(vf4;" | |
| OpName %bar "bar" | |
| OpName %color "color" | |
| OpName %BaseColor "BaseColor" | |
| OpName %param "param" | |
| OpName %gl_FragColor "gl_FragColor" | |
| %void = OpTypeVoid | |
| %10 = OpTypeFunction %void | |
| %float = OpTypeFloat 32 | |
| %v4float = OpTypeVector %float 4 | |
| %_ptr_Function_v4float = OpTypePointer Function %v4float | |
| %14 = OpTypeFunction %float %_ptr_Function_v4float | |
| %uint = OpTypeInt 32 0 | |
| %uint_0 = OpConstant %uint 0 | |
| %_ptr_Function_float = OpTypePointer Function %float | |
| %uint_1 = OpConstant %uint 1 | |
| %_ptr_Input_v4float = OpTypePointer Input %v4float | |
| %BaseColor = OpVariable %_ptr_Input_v4float Input | |
| %_ptr_Output_v4float = OpTypePointer Output %v4float | |
| %gl_FragColor = OpVariable %_ptr_Output_v4float Output | |
| %main = OpFunction %void None %10 | |
| %21 = OpLabel | |
| %color = OpVariable %_ptr_Function_v4float Function | |
| %param = OpVariable %_ptr_Function_v4float Function | |
| %22 = OpLoad %v4float %BaseColor | |
| OpStore %param %22 | |
| %23 = OpFunctionCall %float %foo_vf4_ %param | |
| %24 = OpCompositeConstruct %v4float %23 %23 %23 %23 | |
| OpStore %color %24 | |
| %25 = OpLoad %v4float %color | |
| OpStore %gl_FragColor %25 | |
| OpReturn | |
| OpFunctionEnd | |
| %foo_vf4_ = OpFunction %float None %14 | |
| %bar = OpFunctionParameter %_ptr_Function_v4float | |
| %26 = OpLabel | |
| %27 = OpAccessChain %_ptr_Function_float %bar %uint_0 | |
| %28 = OpLoad %float %27 | |
| %29 = OpAccessChain %_ptr_Function_float %bar %uint_1 | |
| %30 = OpLoad %float %29 | |
| %31 = OpFAdd %float %28 %30 | |
| OpReturnValue %31 | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndCheck<InlineOpaquePass>(assembly, assembly, true, true); | |
| } | |
| } // namespace | |
| } // namespace opt | |
| } // namespace spvtools |