| // 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 |