| // Copyright (c) 2019 Valve Corporation |
| // Copyright (c) 2019 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. |
| |
| // Convert Relaxed to Half tests |
| |
| #include <string> |
| #include <vector> |
| |
| #include "test/opt/assembly_builder.h" |
| #include "test/opt/pass_fixture.h" |
| #include "test/opt/pass_utils.h" |
| |
| namespace spvtools { |
| namespace opt { |
| namespace { |
| |
| using ConvertToHalfTest = PassTest<::testing::Test>; |
| |
| TEST_F(ConvertToHalfTest, ConvertToHalfBasic) { |
| // The resulting SPIR-V was processed with --relax-float-ops. |
| // |
| // clang-format off |
| // |
| // SamplerState g_sSamp : register(s0); |
| // uniform Texture1D <float4> g_tTex1df4 : register(t0); |
| // |
| // struct PS_INPUT |
| // { |
| // float Tex0 : TEXCOORD0; |
| // }; |
| // |
| // struct PS_OUTPUT |
| // { |
| // float4 Color : SV_Target0; |
| // }; |
| // |
| // cbuffer cbuff{ |
| // float c; |
| // } |
| // |
| // PS_OUTPUT main(PS_INPUT i) |
| // { |
| // PS_OUTPUT psout; |
| // psout.Color = g_tTex1df4.Sample(g_sSamp, i.Tex0) * c; |
| // return psout; |
| // } |
| // |
| // clang-format on |
| |
| const std::string defs_before = |
| R"(OpCapability Shader |
| OpCapability Sampled1D |
| %1 = OpExtInstImport "GLSL.std.450" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Fragment %main "main" %i_Tex0 %_entryPointOutput_Color |
| OpExecutionMode %main OriginUpperLeft |
| OpSource HLSL 500 |
| OpName %main "main" |
| OpName %g_tTex1df4 "g_tTex1df4" |
| OpName %g_sSamp "g_sSamp" |
| OpName %cbuff "cbuff" |
| OpMemberName %cbuff 0 "c" |
| OpName %_ "" |
| OpName %i_Tex0 "i.Tex0" |
| OpName %_entryPointOutput_Color "@entryPointOutput.Color" |
| OpDecorate %g_tTex1df4 DescriptorSet 0 |
| OpDecorate %g_tTex1df4 Binding 0 |
| OpDecorate %g_sSamp DescriptorSet 0 |
| OpDecorate %g_sSamp Binding 0 |
| OpMemberDecorate %cbuff 0 Offset 0 |
| OpDecorate %cbuff Block |
| OpDecorate %_ DescriptorSet 0 |
| OpDecorate %_ Binding 1 |
| OpDecorate %i_Tex0 Location 0 |
| OpDecorate %_entryPointOutput_Color Location 0 |
| OpDecorate %48 RelaxedPrecision |
| OpDecorate %63 RelaxedPrecision |
| OpDecorate %65 RelaxedPrecision |
| OpDecorate %66 RelaxedPrecision |
| %void = OpTypeVoid |
| %3 = OpTypeFunction %void |
| %float = OpTypeFloat 32 |
| %v4float = OpTypeVector %float 4 |
| %int = OpTypeInt 32 1 |
| %int_0 = OpConstant %int 0 |
| %19 = OpTypeImage %float 1D 0 0 0 1 Unknown |
| %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19 |
| %g_tTex1df4 = OpVariable %_ptr_UniformConstant_19 UniformConstant |
| %23 = OpTypeSampler |
| %_ptr_UniformConstant_23 = OpTypePointer UniformConstant %23 |
| %g_sSamp = OpVariable %_ptr_UniformConstant_23 UniformConstant |
| %27 = OpTypeSampledImage %19 |
| %cbuff = OpTypeStruct %float |
| %_ptr_Uniform_cbuff = OpTypePointer Uniform %cbuff |
| %_ = OpVariable %_ptr_Uniform_cbuff Uniform |
| %_ptr_Uniform_float = OpTypePointer Uniform %float |
| %_ptr_Input_float = OpTypePointer Input %float |
| %i_Tex0 = OpVariable %_ptr_Input_float Input |
| %_ptr_Output_v4float = OpTypePointer Output %v4float |
| %_entryPointOutput_Color = OpVariable %_ptr_Output_v4float Output |
| )"; |
| |
| const std::string defs_after = |
| R"(OpCapability Shader |
| OpCapability Sampled1D |
| OpCapability Float16 |
| %1 = OpExtInstImport "GLSL.std.450" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Fragment %main "main" %i_Tex0 %_entryPointOutput_Color |
| OpExecutionMode %main OriginUpperLeft |
| OpSource HLSL 500 |
| OpName %main "main" |
| OpName %g_tTex1df4 "g_tTex1df4" |
| OpName %g_sSamp "g_sSamp" |
| OpName %cbuff "cbuff" |
| OpMemberName %cbuff 0 "c" |
| OpName %_ "" |
| OpName %i_Tex0 "i.Tex0" |
| OpName %_entryPointOutput_Color "@entryPointOutput.Color" |
| OpDecorate %g_tTex1df4 DescriptorSet 0 |
| OpDecorate %g_tTex1df4 Binding 0 |
| OpDecorate %g_sSamp DescriptorSet 0 |
| OpDecorate %g_sSamp Binding 0 |
| OpMemberDecorate %cbuff 0 Offset 0 |
| OpDecorate %cbuff Block |
| OpDecorate %_ DescriptorSet 0 |
| OpDecorate %_ Binding 1 |
| OpDecorate %i_Tex0 Location 0 |
| OpDecorate %_entryPointOutput_Color Location 0 |
| %void = OpTypeVoid |
| %3 = OpTypeFunction %void |
| %float = OpTypeFloat 32 |
| %v4float = OpTypeVector %float 4 |
| %int = OpTypeInt 32 1 |
| %int_0 = OpConstant %int 0 |
| %19 = OpTypeImage %float 1D 0 0 0 1 Unknown |
| %_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19 |
| %g_tTex1df4 = OpVariable %_ptr_UniformConstant_19 UniformConstant |
| %23 = OpTypeSampler |
| %_ptr_UniformConstant_23 = OpTypePointer UniformConstant %23 |
| %g_sSamp = OpVariable %_ptr_UniformConstant_23 UniformConstant |
| %27 = OpTypeSampledImage %19 |
| %cbuff = OpTypeStruct %float |
| %_ptr_Uniform_cbuff = OpTypePointer Uniform %cbuff |
| %_ = OpVariable %_ptr_Uniform_cbuff Uniform |
| %_ptr_Uniform_float = OpTypePointer Uniform %float |
| %_ptr_Input_float = OpTypePointer Input %float |
| %i_Tex0 = OpVariable %_ptr_Input_float Input |
| %_ptr_Output_v4float = OpTypePointer Output %v4float |
| %_entryPointOutput_Color = OpVariable %_ptr_Output_v4float Output |
| %half = OpTypeFloat 16 |
| %v4half = OpTypeVector %half 4 |
| )"; |
| |
| const std::string func_before = |
| R"(%main = OpFunction %void None %3 |
| %5 = OpLabel |
| %48 = OpLoad %float %i_Tex0 |
| %58 = OpLoad %19 %g_tTex1df4 |
| %59 = OpLoad %23 %g_sSamp |
| %60 = OpSampledImage %27 %58 %59 |
| %63 = OpImageSampleImplicitLod %v4float %60 %48 |
| %64 = OpAccessChain %_ptr_Uniform_float %_ %int_0 |
| %65 = OpLoad %float %64 |
| %66 = OpVectorTimesScalar %v4float %63 %65 |
| OpStore %_entryPointOutput_Color %66 |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| const std::string func_after = |
| R"(%main = OpFunction %void None %3 |
| %5 = OpLabel |
| %48 = OpLoad %float %i_Tex0 |
| %58 = OpLoad %19 %g_tTex1df4 |
| %59 = OpLoad %23 %g_sSamp |
| %60 = OpSampledImage %27 %58 %59 |
| %63 = OpImageSampleImplicitLod %v4float %60 %48 |
| %64 = OpAccessChain %_ptr_Uniform_float %_ %int_0 |
| %65 = OpLoad %float %64 |
| %69 = OpFConvert %v4half %63 |
| %70 = OpFConvert %half %65 |
| %66 = OpVectorTimesScalar %v4half %69 %70 |
| %71 = OpFConvert %v4float %66 |
| OpStore %_entryPointOutput_Color %71 |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); |
| SinglePassRunAndCheck<ConvertToHalfPass>(defs_before + func_before, |
| defs_after + func_after, true, true); |
| } |
| |
| TEST_F(ConvertToHalfTest, ConvertToHalfForLinkage) { |
| const std::string before = |
| R"(OpCapability Shader |
| OpCapability Linkage |
| OpMemoryModel Logical GLSL450 |
| OpSource HLSL 630 |
| OpName %type_cbuff "type.cbuff" |
| OpMemberName %type_cbuff 0 "c" |
| OpName %cbuff "cbuff" |
| OpName %main "main" |
| OpName %BaseColor "BaseColor" |
| OpName %bb_entry "bb.entry" |
| OpName %v "v" |
| OpDecorate %main LinkageAttributes "main" Export |
| OpDecorate %cbuff DescriptorSet 0 |
| OpDecorate %cbuff Binding 0 |
| OpMemberDecorate %type_cbuff 0 Offset 0 |
| OpDecorate %type_cbuff Block |
| OpDecorate %18 RelaxedPrecision |
| %int = OpTypeInt 32 1 |
| %int_0 = OpConstant %int 0 |
| %float = OpTypeFloat 32 |
| %type_cbuff = OpTypeStruct %float |
| %_ptr_Uniform_type_cbuff = OpTypePointer Uniform %type_cbuff |
| %v4float = OpTypeVector %float 4 |
| %_ptr_Function_v4float = OpTypePointer Function %v4float |
| %9 = OpTypeFunction %v4float %_ptr_Function_v4float |
| %_ptr_Uniform_float = OpTypePointer Uniform %float |
| %cbuff = OpVariable %_ptr_Uniform_type_cbuff Uniform |
| %main = OpFunction %v4float None %9 |
| %BaseColor = OpFunctionParameter %_ptr_Function_v4float |
| %bb_entry = OpLabel |
| %v = OpVariable %_ptr_Function_v4float Function |
| %14 = OpLoad %v4float %BaseColor |
| %16 = OpAccessChain %_ptr_Uniform_float %cbuff %int_0 |
| %17 = OpLoad %float %16 |
| %18 = OpVectorTimesScalar %v4float %14 %17 |
| OpStore %v %18 |
| %19 = OpLoad %v4float %v |
| OpReturnValue %19 |
| OpFunctionEnd |
| )"; |
| |
| const std::string after = |
| R"(OpCapability Shader |
| OpCapability Linkage |
| OpCapability Float16 |
| OpMemoryModel Logical GLSL450 |
| OpSource HLSL 630 |
| OpName %type_cbuff "type.cbuff" |
| OpMemberName %type_cbuff 0 "c" |
| OpName %cbuff "cbuff" |
| OpName %main "main" |
| OpName %BaseColor "BaseColor" |
| OpName %bb_entry "bb.entry" |
| OpName %v "v" |
| OpDecorate %main LinkageAttributes "main" Export |
| OpDecorate %cbuff DescriptorSet 0 |
| OpDecorate %cbuff Binding 0 |
| OpMemberDecorate %type_cbuff 0 Offset 0 |
| OpDecorate %type_cbuff Block |
| %int = OpTypeInt 32 1 |
| %int_0 = OpConstant %int 0 |
| %float = OpTypeFloat 32 |
| %type_cbuff = OpTypeStruct %float |
| %_ptr_Uniform_type_cbuff = OpTypePointer Uniform %type_cbuff |
| %v4float = OpTypeVector %float 4 |
| %_ptr_Function_v4float = OpTypePointer Function %v4float |
| %14 = OpTypeFunction %v4float %_ptr_Function_v4float |
| %_ptr_Uniform_float = OpTypePointer Uniform %float |
| %cbuff = OpVariable %_ptr_Uniform_type_cbuff Uniform |
| %half = OpTypeFloat 16 |
| %v4half = OpTypeVector %half 4 |
| %main = OpFunction %v4float None %14 |
| %BaseColor = OpFunctionParameter %_ptr_Function_v4float |
| %bb_entry = OpLabel |
| %v = OpVariable %_ptr_Function_v4float Function |
| %16 = OpLoad %v4float %BaseColor |
| %17 = OpAccessChain %_ptr_Uniform_float %cbuff %int_0 |
| %18 = OpLoad %float %17 |
| %22 = OpFConvert %v4half %16 |
| %23 = OpFConvert %half %18 |
| %7 = OpVectorTimesScalar %v4half %22 %23 |
| %24 = OpFConvert %v4float %7 |
| OpStore %v %24 |
| %19 = OpLoad %v4float %v |
| OpReturnValue %19 |
| OpFunctionEnd |
| )"; |
| |
| SinglePassRunAndCheck<ConvertToHalfPass>(before, after, true, true); |
| } |
| TEST_F(ConvertToHalfTest, ConvertToHalfWithDrefSample) { |
| // The resulting SPIR-V was processed with --relax-float-ops. |
| // |
| // clang-format off |
| // |
| // SamplerComparisonState g_sSamp : register(s0); |
| // uniform Texture1D <float4> g_tTex1df4 : register(t0); |
| // |
| // cbuffer cbuff{ |
| // float c1; |
| // float c2; |
| // }; |
| // |
| // struct PS_INPUT |
| // { |
| // float Tex0 : TEXCOORD0; |
| // float Tex1 : TEXCOORD1; |
| // }; |
| // |
| // struct PS_OUTPUT |
| // { |
| // float Color : SV_Target0; |
| // }; |
| // |
| // PS_OUTPUT main(PS_INPUT i) |
| // { |
| // PS_OUTPUT psout; |
| // float txval10 = g_tTex1df4.SampleCmp(g_sSamp, i.Tex0 * 0.1, c1 + 0.1); |
| // float txval11 = g_tTex1df4.SampleCmp(g_sSamp, i.Tex1 * 0.2, c2 + 0.2); |
| // float t = txval10 + txval11; |
| // float t2 = t / 2.0; |
| // psout.Color = t2; |
| // return psout; |
| // } |
| // |
| // clang-format on |
| |
| const std::string defs_before = |
| R"(OpCapability Shader |
| OpCapability Sampled1D |
| %1 = OpExtInstImport "GLSL.std.450" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Fragment %main "main" %i_Tex0 %i_Tex1 %_entryPointOutput_Color |
| OpExecutionMode %main OriginUpperLeft |
| OpSource HLSL 500 |
| OpName %main "main" |
| OpName %g_tTex1df4 "g_tTex1df4" |
| OpName %g_sSamp "g_sSamp" |
| OpName %cbuff "cbuff" |
| OpMemberName %cbuff 0 "c1" |
| OpMemberName %cbuff 1 "c2" |
| OpName %_ "" |
| OpName %i_Tex0 "i.Tex0" |
| OpName %i_Tex1 "i.Tex1" |
| OpName %_entryPointOutput_Color "@entryPointOutput.Color" |
| OpDecorate %g_tTex1df4 DescriptorSet 0 |
| OpDecorate %g_tTex1df4 Binding 0 |
| OpDecorate %g_sSamp DescriptorSet 0 |
| OpDecorate %g_sSamp Binding 0 |
| OpMemberDecorate %cbuff 0 Offset 0 |
| OpMemberDecorate %cbuff 1 Offset 4 |
| OpDecorate %cbuff Block |
| OpDecorate %_ DescriptorSet 0 |
| OpDecorate %_ Binding 1 |
| OpDecorate %i_Tex0 Location 0 |
| OpDecorate %i_Tex1 Location 1 |
| OpDecorate %_entryPointOutput_Color Location 0 |
| OpDecorate %100 RelaxedPrecision |
| OpDecorate %76 RelaxedPrecision |
| OpDecorate %79 RelaxedPrecision |
| OpDecorate %98 RelaxedPrecision |
| OpDecorate %101 RelaxedPrecision |
| OpDecorate %110 RelaxedPrecision |
| OpDecorate %102 RelaxedPrecision |
| OpDecorate %112 RelaxedPrecision |
| OpDecorate %104 RelaxedPrecision |
| OpDecorate %113 RelaxedPrecision |
| OpDecorate %114 RelaxedPrecision |
| OpDecorate %116 RelaxedPrecision |
| OpDecorate %119 RelaxedPrecision |
| OpDecorate %121 RelaxedPrecision |
| %void = OpTypeVoid |
| %3 = OpTypeFunction %void |
| %float = OpTypeFloat 32 |
| %16 = OpTypeImage %float 1D 1 0 0 1 Unknown |
| %_ptr_UniformConstant_16 = OpTypePointer UniformConstant %16 |
| %g_tTex1df4 = OpVariable %_ptr_UniformConstant_16 UniformConstant |
| %20 = OpTypeSampler |
| %_ptr_UniformConstant_20 = OpTypePointer UniformConstant %20 |
| %g_sSamp = OpVariable %_ptr_UniformConstant_20 UniformConstant |
| %24 = OpTypeSampledImage %16 |
| %int = OpTypeInt 32 1 |
| %int_0 = OpConstant %int 0 |
| %float_0_100000001 = OpConstant %float 0.100000001 |
| %cbuff = OpTypeStruct %float %float |
| %_ptr_Uniform_cbuff = OpTypePointer Uniform %cbuff |
| %_ = OpVariable %_ptr_Uniform_cbuff Uniform |
| %_ptr_Uniform_float = OpTypePointer Uniform %float |
| %v2float = OpTypeVector %float 2 |
| %int_1 = OpConstant %int 1 |
| %float_0_200000003 = OpConstant %float 0.200000003 |
| %_ptr_Input_float = OpTypePointer Input %float |
| %i_Tex0 = OpVariable %_ptr_Input_float Input |
| %i_Tex1 = OpVariable %_ptr_Input_float Input |
| %_ptr_Output_float = OpTypePointer Output %float |
| %_entryPointOutput_Color = OpVariable %_ptr_Output_float Output |
| %float_0_5 = OpConstant %float 0.5 |
| )"; |
| |
| const std::string defs_after = |
| R"(OpCapability Shader |
| OpCapability Sampled1D |
| OpCapability Float16 |
| %1 = OpExtInstImport "GLSL.std.450" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Fragment %main "main" %i_Tex0 %i_Tex1 %_entryPointOutput_Color |
| OpExecutionMode %main OriginUpperLeft |
| OpSource HLSL 500 |
| OpName %main "main" |
| OpName %g_tTex1df4 "g_tTex1df4" |
| OpName %g_sSamp "g_sSamp" |
| OpName %cbuff "cbuff" |
| OpMemberName %cbuff 0 "c1" |
| OpMemberName %cbuff 1 "c2" |
| OpName %_ "" |
| OpName %i_Tex0 "i.Tex0" |
| OpName %i_Tex1 "i.Tex1" |
| OpName %_entryPointOutput_Color "@entryPointOutput.Color" |
| OpDecorate %g_tTex1df4 DescriptorSet 0 |
| OpDecorate %g_tTex1df4 Binding 0 |
| OpDecorate %g_sSamp DescriptorSet 0 |
| OpDecorate %g_sSamp Binding 0 |
| OpMemberDecorate %cbuff 0 Offset 0 |
| OpMemberDecorate %cbuff 1 Offset 4 |
| OpDecorate %cbuff Block |
| OpDecorate %_ DescriptorSet 0 |
| OpDecorate %_ Binding 1 |
| OpDecorate %i_Tex0 Location 0 |
| OpDecorate %i_Tex1 Location 1 |
| OpDecorate %_entryPointOutput_Color Location 0 |
| %void = OpTypeVoid |
| %25 = OpTypeFunction %void |
| %float = OpTypeFloat 32 |
| %27 = OpTypeImage %float 1D 1 0 0 1 Unknown |
| %_ptr_UniformConstant_27 = OpTypePointer UniformConstant %27 |
| %g_tTex1df4 = OpVariable %_ptr_UniformConstant_27 UniformConstant |
| %29 = OpTypeSampler |
| %_ptr_UniformConstant_29 = OpTypePointer UniformConstant %29 |
| %g_sSamp = OpVariable %_ptr_UniformConstant_29 UniformConstant |
| %31 = OpTypeSampledImage %27 |
| %int = OpTypeInt 32 1 |
| %int_0 = OpConstant %int 0 |
| %float_0_100000001 = OpConstant %float 0.100000001 |
| %cbuff = OpTypeStruct %float %float |
| %_ptr_Uniform_cbuff = OpTypePointer Uniform %cbuff |
| %_ = OpVariable %_ptr_Uniform_cbuff Uniform |
| %_ptr_Uniform_float = OpTypePointer Uniform %float |
| %v2float = OpTypeVector %float 2 |
| %int_1 = OpConstant %int 1 |
| %float_0_200000003 = OpConstant %float 0.200000003 |
| %_ptr_Input_float = OpTypePointer Input %float |
| %i_Tex0 = OpVariable %_ptr_Input_float Input |
| %i_Tex1 = OpVariable %_ptr_Input_float Input |
| %_ptr_Output_float = OpTypePointer Output %float |
| %_entryPointOutput_Color = OpVariable %_ptr_Output_float Output |
| %float_0_5 = OpConstant %float 0.5 |
| %half = OpTypeFloat 16 |
| %v2half = OpTypeVector %half 2 |
| )"; |
| |
| const std::string func_before = |
| R"(%main = OpFunction %void None %3 |
| %5 = OpLabel |
| %76 = OpLoad %float %i_Tex0 |
| %79 = OpLoad %float %i_Tex1 |
| %93 = OpLoad %16 %g_tTex1df4 |
| %94 = OpLoad %20 %g_sSamp |
| %95 = OpSampledImage %24 %93 %94 |
| %98 = OpFMul %float %76 %float_0_100000001 |
| %99 = OpAccessChain %_ptr_Uniform_float %_ %int_0 |
| %100 = OpLoad %float %99 |
| %101 = OpFAdd %float %100 %float_0_100000001 |
| %102 = OpCompositeConstruct %v2float %98 %101 |
| %104 = OpImageSampleDrefImplicitLod %float %95 %102 %101 |
| %105 = OpLoad %16 %g_tTex1df4 |
| %106 = OpLoad %20 %g_sSamp |
| %107 = OpSampledImage %24 %105 %106 |
| %110 = OpFMul %float %79 %float_0_200000003 |
| %111 = OpAccessChain %_ptr_Uniform_float %_ %int_1 |
| %112 = OpLoad %float %111 |
| %113 = OpFAdd %float %112 %float_0_200000003 |
| %114 = OpCompositeConstruct %v2float %110 %113 |
| %116 = OpImageSampleDrefImplicitLod %float %107 %114 %113 |
| %119 = OpFAdd %float %104 %116 |
| %121 = OpFMul %float %119 %float_0_5 |
| OpStore %_entryPointOutput_Color %121 |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| const std::string func_after = |
| R"(%main = OpFunction %void None %25 |
| %43 = OpLabel |
| %11 = OpLoad %float %i_Tex0 |
| %12 = OpLoad %float %i_Tex1 |
| %44 = OpLoad %27 %g_tTex1df4 |
| %45 = OpLoad %29 %g_sSamp |
| %46 = OpSampledImage %31 %44 %45 |
| %53 = OpFConvert %half %11 |
| %54 = OpFConvert %half %float_0_100000001 |
| %13 = OpFMul %half %53 %54 |
| %47 = OpAccessChain %_ptr_Uniform_float %_ %int_0 |
| %10 = OpLoad %float %47 |
| %55 = OpFConvert %half %10 |
| %56 = OpFConvert %half %float_0_100000001 |
| %14 = OpFAdd %half %55 %56 |
| %16 = OpCompositeConstruct %v2half %13 %14 |
| %58 = OpFConvert %float %14 |
| %18 = OpImageSampleDrefImplicitLod %float %46 %16 %58 |
| %48 = OpLoad %27 %g_tTex1df4 |
| %49 = OpLoad %29 %g_sSamp |
| %50 = OpSampledImage %31 %48 %49 |
| %59 = OpFConvert %half %12 |
| %60 = OpFConvert %half %float_0_200000003 |
| %15 = OpFMul %half %59 %60 |
| %51 = OpAccessChain %_ptr_Uniform_float %_ %int_1 |
| %17 = OpLoad %float %51 |
| %61 = OpFConvert %half %17 |
| %62 = OpFConvert %half %float_0_200000003 |
| %19 = OpFAdd %half %61 %62 |
| %20 = OpCompositeConstruct %v2half %15 %19 |
| %63 = OpFConvert %float %19 |
| %21 = OpImageSampleDrefImplicitLod %float %50 %20 %63 |
| %64 = OpFConvert %half %18 |
| %65 = OpFConvert %half %21 |
| %22 = OpFAdd %half %64 %65 |
| %66 = OpFConvert %half %float_0_5 |
| %23 = OpFMul %half %22 %66 |
| %67 = OpFConvert %float %23 |
| OpStore %_entryPointOutput_Color %67 |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| SinglePassRunAndCheck<ConvertToHalfPass>(defs_before + func_before, |
| defs_after + func_after, true, true); |
| } |
| |
| TEST_F(ConvertToHalfTest, ConvertToHalfWithVectorMatrixMult) { |
| // The resulting SPIR-V was processed with --relax-float-ops. |
| // |
| // clang-format off |
| // |
| // SamplerState g_sSamp : register(s0); |
| // uniform Texture1D <float4> g_tTex1df4 : register(t0); |
| // |
| // struct PS_OUTPUT |
| // { |
| // float4 Color : SV_Target0; |
| // }; |
| // |
| // cbuffer cbuff{ |
| // float4x4 M; |
| // } |
| // |
| // PS_OUTPUT main() |
| // { |
| // PS_OUTPUT psout; |
| // float4 txval10 = g_tTex1df4.Sample(g_sSamp, 0.1); |
| // float4 t = mul(txval10, M); |
| // psout.Color = t; |
| // return psout; |
| //} |
| // |
| // clang-format on |
| |
| const std::string defs_before = |
| R"(OpCapability Shader |
| OpCapability Sampled1D |
| %1 = OpExtInstImport "GLSL.std.450" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Fragment %main "main" %_entryPointOutput_Color |
| OpExecutionMode %main OriginUpperLeft |
| OpSource HLSL 500 |
| OpName %main "main" |
| OpName %g_tTex1df4 "g_tTex1df4" |
| OpName %g_sSamp "g_sSamp" |
| OpName %cbuff "cbuff" |
| OpMemberName %cbuff 0 "M" |
| OpName %_ "" |
| OpName %_entryPointOutput_Color "@entryPointOutput.Color" |
| OpDecorate %g_tTex1df4 DescriptorSet 0 |
| OpDecorate %g_tTex1df4 Binding 0 |
| OpDecorate %g_sSamp DescriptorSet 0 |
| OpDecorate %g_sSamp Binding 0 |
| OpMemberDecorate %cbuff 0 RowMajor |
| OpMemberDecorate %cbuff 0 Offset 0 |
| OpMemberDecorate %cbuff 0 MatrixStride 16 |
| OpDecorate %cbuff Block |
| OpDecorate %_ DescriptorSet 0 |
| OpDecorate %_ Binding 1 |
| OpDecorate %_entryPointOutput_Color Location 0 |
| OpDecorate %56 RelaxedPrecision |
| OpDecorate %58 RelaxedPrecision |
| OpDecorate %60 RelaxedPrecision |
| %void = OpTypeVoid |
| %3 = OpTypeFunction %void |
| %float = OpTypeFloat 32 |
| %v4float = OpTypeVector %float 4 |
| %14 = OpTypeImage %float 1D 0 0 0 1 Unknown |
| %_ptr_UniformConstant_14 = OpTypePointer UniformConstant %14 |
| %g_tTex1df4 = OpVariable %_ptr_UniformConstant_14 UniformConstant |
| %18 = OpTypeSampler |
| %_ptr_UniformConstant_18 = OpTypePointer UniformConstant %18 |
| %g_sSamp = OpVariable %_ptr_UniformConstant_18 UniformConstant |
| %22 = OpTypeSampledImage %14 |
| %float_0_100000001 = OpConstant %float 0.100000001 |
| %mat4v4float = OpTypeMatrix %v4float 4 |
| %cbuff = OpTypeStruct %mat4v4float |
| %_ptr_Uniform_cbuff = OpTypePointer Uniform %cbuff |
| %_ = OpVariable %_ptr_Uniform_cbuff Uniform |
| %int = OpTypeInt 32 1 |
| %int_0 = OpConstant %int 0 |
| %_ptr_Uniform_mat4v4float = OpTypePointer Uniform %mat4v4float |
| %_ptr_Output_v4float = OpTypePointer Output %v4float |
| %_entryPointOutput_Color = OpVariable %_ptr_Output_v4float Output |
| )"; |
| |
| const std::string defs_after = |
| R"(OpCapability Shader |
| OpCapability Sampled1D |
| OpCapability Float16 |
| %1 = OpExtInstImport "GLSL.std.450" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Fragment %main "main" %_entryPointOutput_Color |
| OpExecutionMode %main OriginUpperLeft |
| OpSource HLSL 500 |
| OpName %main "main" |
| OpName %g_tTex1df4 "g_tTex1df4" |
| OpName %g_sSamp "g_sSamp" |
| OpName %cbuff "cbuff" |
| OpMemberName %cbuff 0 "M" |
| OpName %_ "" |
| OpName %_entryPointOutput_Color "@entryPointOutput.Color" |
| OpDecorate %g_tTex1df4 DescriptorSet 0 |
| OpDecorate %g_tTex1df4 Binding 0 |
| OpDecorate %g_sSamp DescriptorSet 0 |
| OpDecorate %g_sSamp Binding 0 |
| OpMemberDecorate %cbuff 0 RowMajor |
| OpMemberDecorate %cbuff 0 Offset 0 |
| OpMemberDecorate %cbuff 0 MatrixStride 16 |
| OpDecorate %cbuff Block |
| OpDecorate %_ DescriptorSet 0 |
| OpDecorate %_ Binding 1 |
| OpDecorate %_entryPointOutput_Color Location 0 |
| %void = OpTypeVoid |
| %3 = OpTypeFunction %void |
| %float = OpTypeFloat 32 |
| %v4float = OpTypeVector %float 4 |
| %14 = OpTypeImage %float 1D 0 0 0 1 Unknown |
| %_ptr_UniformConstant_14 = OpTypePointer UniformConstant %14 |
| %g_tTex1df4 = OpVariable %_ptr_UniformConstant_14 UniformConstant |
| %18 = OpTypeSampler |
| %_ptr_UniformConstant_18 = OpTypePointer UniformConstant %18 |
| %g_sSamp = OpVariable %_ptr_UniformConstant_18 UniformConstant |
| %22 = OpTypeSampledImage %14 |
| %float_0_100000001 = OpConstant %float 0.100000001 |
| %mat4v4float = OpTypeMatrix %v4float 4 |
| %cbuff = OpTypeStruct %mat4v4float |
| %_ptr_Uniform_cbuff = OpTypePointer Uniform %cbuff |
| %_ = OpVariable %_ptr_Uniform_cbuff Uniform |
| %int = OpTypeInt 32 1 |
| %int_0 = OpConstant %int 0 |
| %_ptr_Uniform_mat4v4float = OpTypePointer Uniform %mat4v4float |
| %_ptr_Output_v4float = OpTypePointer Output %v4float |
| %_entryPointOutput_Color = OpVariable %_ptr_Output_v4float Output |
| %half = OpTypeFloat 16 |
| %v4half = OpTypeVector %half 4 |
| %mat4v4half = OpTypeMatrix %v4half 4 |
| )"; |
| |
| const std::string func_before = |
| R"(%main = OpFunction %void None %3 |
| %5 = OpLabel |
| %53 = OpLoad %14 %g_tTex1df4 |
| %54 = OpLoad %18 %g_sSamp |
| %55 = OpSampledImage %22 %53 %54 |
| %56 = OpImageSampleImplicitLod %v4float %55 %float_0_100000001 |
| %57 = OpAccessChain %_ptr_Uniform_mat4v4float %_ %int_0 |
| %58 = OpLoad %mat4v4float %57 |
| %60 = OpMatrixTimesVector %v4float %58 %56 |
| OpStore %_entryPointOutput_Color %60 |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| const std::string func_after = |
| R"(%main = OpFunction %void None %3 |
| %5 = OpLabel |
| %53 = OpLoad %14 %g_tTex1df4 |
| %54 = OpLoad %18 %g_sSamp |
| %55 = OpSampledImage %22 %53 %54 |
| %56 = OpImageSampleImplicitLod %v4float %55 %float_0_100000001 |
| %57 = OpAccessChain %_ptr_Uniform_mat4v4float %_ %int_0 |
| %58 = OpLoad %mat4v4float %57 |
| %67 = OpCompositeExtract %v4float %58 0 |
| %68 = OpFConvert %v4half %67 |
| %69 = OpCompositeExtract %v4float %58 1 |
| %70 = OpFConvert %v4half %69 |
| %71 = OpCompositeExtract %v4float %58 2 |
| %72 = OpFConvert %v4half %71 |
| %73 = OpCompositeExtract %v4float %58 3 |
| %74 = OpFConvert %v4half %73 |
| %75 = OpCompositeConstruct %mat4v4half %68 %70 %72 %74 |
| %64 = OpCopyObject %mat4v4float %58 |
| %65 = OpFConvert %v4half %56 |
| %60 = OpMatrixTimesVector %v4half %75 %65 |
| %66 = OpFConvert %v4float %60 |
| OpStore %_entryPointOutput_Color %66 |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); |
| SinglePassRunAndCheck<ConvertToHalfPass>(defs_before + func_before, |
| defs_after + func_after, true, true); |
| } |
| |
| TEST_F(ConvertToHalfTest, ConvertToHalfWithPhi) { |
| // The resulting SPIR-V was processed with --relax-float-ops. |
| // |
| // clang-format off |
| // |
| // SamplerState g_sSamp : register(s0); |
| // uniform Texture1D <float4> g_tTex1df4 : register(t0); |
| // |
| // struct PS_OUTPUT |
| // { |
| // float4 Color : SV_Target0; |
| // }; |
| // |
| // cbuffer cbuff{ |
| // bool b; |
| // float4x4 M; |
| // } |
| // |
| // PS_OUTPUT main() |
| // { |
| // PS_OUTPUT psout; |
| // float4 t; |
| // |
| // if (b) |
| // t = g_tTex1df4.Sample(g_sSamp, 0.1); |
| // else |
| // t = float4(0.0, 0.0, 0.0, 0.0); |
| // |
| // float4 t2 = t * 2.0; |
| // psout.Color = t2; |
| // return psout; |
| // } |
| // |
| // clang-format on |
| |
| const std::string defs_before = |
| R"(OpCapability Shader |
| OpCapability Sampled1D |
| %1 = OpExtInstImport "GLSL.std.450" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Fragment %main "main" %_entryPointOutput_Color |
| OpExecutionMode %main OriginUpperLeft |
| OpSource HLSL 500 |
| OpName %main "main" |
| OpName %cbuff "cbuff" |
| OpMemberName %cbuff 0 "b" |
| OpMemberName %cbuff 1 "M" |
| OpName %_ "" |
| OpName %g_tTex1df4 "g_tTex1df4" |
| OpName %g_sSamp "g_sSamp" |
| OpName %_entryPointOutput_Color "@entryPointOutput.Color" |
| OpMemberDecorate %cbuff 0 Offset 0 |
| OpMemberDecorate %cbuff 1 RowMajor |
| OpMemberDecorate %cbuff 1 Offset 16 |
| OpMemberDecorate %cbuff 1 MatrixStride 16 |
| OpDecorate %cbuff Block |
| OpDecorate %_ DescriptorSet 0 |
| OpDecorate %_ Binding 1 |
| OpDecorate %g_tTex1df4 DescriptorSet 0 |
| OpDecorate %g_tTex1df4 Binding 0 |
| OpDecorate %g_sSamp DescriptorSet 0 |
| OpDecorate %g_sSamp Binding 0 |
| OpDecorate %_entryPointOutput_Color Location 0 |
| OpDecorate %72 RelaxedPrecision |
| OpDecorate %85 RelaxedPrecision |
| OpDecorate %74 RelaxedPrecision |
| %void = OpTypeVoid |
| %3 = OpTypeFunction %void |
| %float = OpTypeFloat 32 |
| %v4float = OpTypeVector %float 4 |
| %uint = OpTypeInt 32 0 |
| %mat4v4float = OpTypeMatrix %v4float 4 |
| %cbuff = OpTypeStruct %uint %mat4v4float |
| %_ptr_Uniform_cbuff = OpTypePointer Uniform %cbuff |
| %_ = OpVariable %_ptr_Uniform_cbuff Uniform |
| %int = OpTypeInt 32 1 |
| %int_0 = OpConstant %int 0 |
| %_ptr_Uniform_uint = OpTypePointer Uniform %uint |
| %bool = OpTypeBool |
| %uint_0 = OpConstant %uint 0 |
| %29 = OpTypeImage %float 1D 0 0 0 1 Unknown |
| %_ptr_UniformConstant_29 = OpTypePointer UniformConstant %29 |
| %g_tTex1df4 = OpVariable %_ptr_UniformConstant_29 UniformConstant |
| %33 = OpTypeSampler |
| %_ptr_UniformConstant_33 = OpTypePointer UniformConstant %33 |
| %g_sSamp = OpVariable %_ptr_UniformConstant_33 UniformConstant |
| %37 = OpTypeSampledImage %29 |
| %float_0_100000001 = OpConstant %float 0.100000001 |
| %float_0 = OpConstant %float 0 |
| %43 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0 |
| %float_2 = OpConstant %float 2 |
| %_ptr_Output_v4float = OpTypePointer Output %v4float |
| %_entryPointOutput_Color = OpVariable %_ptr_Output_v4float Output |
| )"; |
| |
| const std::string defs_after = |
| R"(OpCapability Shader |
| OpCapability Sampled1D |
| OpCapability Float16 |
| %1 = OpExtInstImport "GLSL.std.450" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Fragment %main "main" %_entryPointOutput_Color |
| OpExecutionMode %main OriginUpperLeft |
| OpSource HLSL 500 |
| OpName %main "main" |
| OpName %cbuff "cbuff" |
| OpMemberName %cbuff 0 "b" |
| OpMemberName %cbuff 1 "M" |
| OpName %_ "" |
| OpName %g_tTex1df4 "g_tTex1df4" |
| OpName %g_sSamp "g_sSamp" |
| OpName %_entryPointOutput_Color "@entryPointOutput.Color" |
| OpMemberDecorate %cbuff 0 Offset 0 |
| OpMemberDecorate %cbuff 1 RowMajor |
| OpMemberDecorate %cbuff 1 Offset 16 |
| OpMemberDecorate %cbuff 1 MatrixStride 16 |
| OpDecorate %cbuff Block |
| OpDecorate %_ DescriptorSet 0 |
| OpDecorate %_ Binding 1 |
| OpDecorate %g_tTex1df4 DescriptorSet 0 |
| OpDecorate %g_tTex1df4 Binding 0 |
| OpDecorate %g_sSamp DescriptorSet 0 |
| OpDecorate %g_sSamp Binding 0 |
| OpDecorate %_entryPointOutput_Color Location 0 |
| %void = OpTypeVoid |
| %3 = OpTypeFunction %void |
| %float = OpTypeFloat 32 |
| %v4float = OpTypeVector %float 4 |
| %uint = OpTypeInt 32 0 |
| %mat4v4float = OpTypeMatrix %v4float 4 |
| %cbuff = OpTypeStruct %uint %mat4v4float |
| %_ptr_Uniform_cbuff = OpTypePointer Uniform %cbuff |
| %_ = OpVariable %_ptr_Uniform_cbuff Uniform |
| %int = OpTypeInt 32 1 |
| %int_0 = OpConstant %int 0 |
| %_ptr_Uniform_uint = OpTypePointer Uniform %uint |
| %bool = OpTypeBool |
| %uint_0 = OpConstant %uint 0 |
| %29 = OpTypeImage %float 1D 0 0 0 1 Unknown |
| %_ptr_UniformConstant_29 = OpTypePointer UniformConstant %29 |
| %g_tTex1df4 = OpVariable %_ptr_UniformConstant_29 UniformConstant |
| %33 = OpTypeSampler |
| %_ptr_UniformConstant_33 = OpTypePointer UniformConstant %33 |
| %g_sSamp = OpVariable %_ptr_UniformConstant_33 UniformConstant |
| %37 = OpTypeSampledImage %29 |
| %float_0_100000001 = OpConstant %float 0.100000001 |
| %float_0 = OpConstant %float 0 |
| %43 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0 |
| %float_2 = OpConstant %float 2 |
| %_ptr_Output_v4float = OpTypePointer Output %v4float |
| %_entryPointOutput_Color = OpVariable %_ptr_Output_v4float Output |
| %half = OpTypeFloat 16 |
| %v4half = OpTypeVector %half 4 |
| )"; |
| |
| const std::string func_before = |
| R"(%main = OpFunction %void None %3 |
| %5 = OpLabel |
| %63 = OpAccessChain %_ptr_Uniform_uint %_ %int_0 |
| %64 = OpLoad %uint %63 |
| %65 = OpINotEqual %bool %64 %uint_0 |
| OpSelectionMerge %66 None |
| OpBranchConditional %65 %67 %68 |
| %67 = OpLabel |
| %69 = OpLoad %29 %g_tTex1df4 |
| %70 = OpLoad %33 %g_sSamp |
| %71 = OpSampledImage %37 %69 %70 |
| %72 = OpImageSampleImplicitLod %v4float %71 %float_0_100000001 |
| OpBranch %66 |
| %68 = OpLabel |
| OpBranch %66 |
| %66 = OpLabel |
| %85 = OpPhi %v4float %72 %67 %43 %68 |
| %74 = OpVectorTimesScalar %v4float %85 %float_2 |
| OpStore %_entryPointOutput_Color %74 |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| const std::string func_after = |
| R"(%main = OpFunction %void None %3 |
| %5 = OpLabel |
| %63 = OpAccessChain %_ptr_Uniform_uint %_ %int_0 |
| %64 = OpLoad %uint %63 |
| %65 = OpINotEqual %bool %64 %uint_0 |
| OpSelectionMerge %66 None |
| OpBranchConditional %65 %67 %68 |
| %67 = OpLabel |
| %69 = OpLoad %29 %g_tTex1df4 |
| %70 = OpLoad %33 %g_sSamp |
| %71 = OpSampledImage %37 %69 %70 |
| %72 = OpImageSampleImplicitLod %v4float %71 %float_0_100000001 |
| %88 = OpFConvert %v4half %72 |
| OpBranch %66 |
| %68 = OpLabel |
| %89 = OpFConvert %v4half %43 |
| OpBranch %66 |
| %66 = OpLabel |
| %85 = OpPhi %v4half %88 %67 %89 %68 |
| %90 = OpFConvert %half %float_2 |
| %74 = OpVectorTimesScalar %v4half %85 %90 |
| %91 = OpFConvert %v4float %74 |
| OpStore %_entryPointOutput_Color %91 |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); |
| SinglePassRunAndCheck<ConvertToHalfPass>(defs_before + func_before, |
| defs_after + func_after, true, true); |
| } |
| |
| TEST_F(ConvertToHalfTest, ConvertToHalfWithLoopAndFConvert) { |
| // The resulting SPIR-V was processed with --relax-float-ops. |
| // |
| // The loop causes an FConvert to be generated at the bottom of the loop |
| // for the Phi. The FConvert is later processed and turned into a (dead) |
| // copy. |
| // |
| // clang-format off |
| // |
| // struct PS_OUTPUT |
| // { |
| // float4 Color : SV_Target0; |
| // }; |
| // |
| // cbuffer cbuff{ |
| // float4 a[10]; |
| // } |
| // |
| // PS_OUTPUT main() |
| // { |
| // PS_OUTPUT psout; |
| // float4 t = 0.0;; |
| // |
| // for (int i = 0; i<10; ++i) |
| // t = t + a[i]; |
| // |
| // float4 t2 = t / 10.0; |
| // psout.Color = t2; |
| // return psout; |
| // } |
| // |
| // clang-format on |
| |
| const std::string defs_before = |
| R"(OpCapability Shader |
| %1 = OpExtInstImport "GLSL.std.450" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Fragment %main "main" %_entryPointOutput_Color |
| OpExecutionMode %main OriginUpperLeft |
| OpSource HLSL 500 |
| OpName %main "main" |
| OpName %cbuff "cbuff" |
| OpMemberName %cbuff 0 "a" |
| OpName %_ "" |
| OpName %_entryPointOutput_Color "@entryPointOutput.Color" |
| OpDecorate %_arr_v4float_uint_10 ArrayStride 16 |
| OpMemberDecorate %cbuff 0 Offset 0 |
| OpDecorate %cbuff Block |
| OpDecorate %_ DescriptorSet 0 |
| OpDecorate %_ Binding 0 |
| OpDecorate %_entryPointOutput_Color Location 0 |
| OpDecorate %96 RelaxedPrecision |
| OpDecorate %81 RelaxedPrecision |
| OpDecorate %75 RelaxedPrecision |
| OpDecorate %76 RelaxedPrecision |
| %void = OpTypeVoid |
| %3 = OpTypeFunction %void |
| %float = OpTypeFloat 32 |
| %v4float = OpTypeVector %float 4 |
| %float_0 = OpConstant %float 0 |
| %15 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0 |
| %int = OpTypeInt 32 1 |
| %int_0 = OpConstant %int 0 |
| %int_10 = OpConstant %int 10 |
| %bool = OpTypeBool |
| %uint = OpTypeInt 32 0 |
| %uint_10 = OpConstant %uint 10 |
| %_arr_v4float_uint_10 = OpTypeArray %v4float %uint_10 |
| %cbuff = OpTypeStruct %_arr_v4float_uint_10 |
| %_ptr_Uniform_cbuff = OpTypePointer Uniform %cbuff |
| %_ = OpVariable %_ptr_Uniform_cbuff Uniform |
| %_ptr_Uniform_v4float = OpTypePointer Uniform %v4float |
| %int_1 = OpConstant %int 1 |
| %_ptr_Output_v4float = OpTypePointer Output %v4float |
| %_entryPointOutput_Color = OpVariable %_ptr_Output_v4float Output |
| %float_0_100000001 = OpConstant %float 0.100000001 |
| %94 = OpConstantComposite %v4float %float_0_100000001 %float_0_100000001 %float_0_100000001 %float_0_100000001 |
| )"; |
| |
| const std::string defs_after = |
| R"(OpCapability Shader |
| OpCapability Float16 |
| %1 = OpExtInstImport "GLSL.std.450" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Fragment %main "main" %_entryPointOutput_Color |
| OpExecutionMode %main OriginUpperLeft |
| OpSource HLSL 500 |
| OpName %main "main" |
| OpName %cbuff "cbuff" |
| OpMemberName %cbuff 0 "a" |
| OpName %_ "" |
| OpName %_entryPointOutput_Color "@entryPointOutput.Color" |
| OpDecorate %_arr_v4float_uint_10 ArrayStride 16 |
| OpMemberDecorate %cbuff 0 Offset 0 |
| OpDecorate %cbuff Block |
| OpDecorate %_ DescriptorSet 0 |
| OpDecorate %_ Binding 0 |
| OpDecorate %_entryPointOutput_Color Location 0 |
| %void = OpTypeVoid |
| %3 = OpTypeFunction %void |
| %float = OpTypeFloat 32 |
| %v4float = OpTypeVector %float 4 |
| %float_0 = OpConstant %float 0 |
| %15 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0 |
| %int = OpTypeInt 32 1 |
| %int_0 = OpConstant %int 0 |
| %int_10 = OpConstant %int 10 |
| %bool = OpTypeBool |
| %uint = OpTypeInt 32 0 |
| %uint_10 = OpConstant %uint 10 |
| %_arr_v4float_uint_10 = OpTypeArray %v4float %uint_10 |
| %cbuff = OpTypeStruct %_arr_v4float_uint_10 |
| %_ptr_Uniform_cbuff = OpTypePointer Uniform %cbuff |
| %_ = OpVariable %_ptr_Uniform_cbuff Uniform |
| %_ptr_Uniform_v4float = OpTypePointer Uniform %v4float |
| %int_1 = OpConstant %int 1 |
| %_ptr_Output_v4float = OpTypePointer Output %v4float |
| %_entryPointOutput_Color = OpVariable %_ptr_Output_v4float Output |
| %float_0_100000001 = OpConstant %float 0.100000001 |
| %94 = OpConstantComposite %v4float %float_0_100000001 %float_0_100000001 %float_0_100000001 %float_0_100000001 |
| %half = OpTypeFloat 16 |
| %v4half = OpTypeVector %half 4 |
| )"; |
| |
| const std::string func_before = |
| R"(%main = OpFunction %void None %3 |
| %5 = OpLabel |
| OpBranch %65 |
| %65 = OpLabel |
| %96 = OpPhi %v4float %15 %5 %76 %71 |
| %95 = OpPhi %int %int_0 %5 %78 %71 |
| %70 = OpSLessThan %bool %95 %int_10 |
| OpLoopMerge %66 %71 None |
| OpBranchConditional %70 %71 %66 |
| %71 = OpLabel |
| %74 = OpAccessChain %_ptr_Uniform_v4float %_ %int_0 %95 |
| %75 = OpLoad %v4float %74 |
| %76 = OpFAdd %v4float %96 %75 |
| %78 = OpIAdd %int %95 %int_1 |
| OpBranch %65 |
| %66 = OpLabel |
| %81 = OpFMul %v4float %96 %94 |
| OpStore %_entryPointOutput_Color %81 |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| const std::string func_after = |
| R"(%main = OpFunction %void None %3 |
| %5 = OpLabel |
| %99 = OpFConvert %v4half %15 |
| OpBranch %65 |
| %65 = OpLabel |
| %96 = OpPhi %v4half %99 %5 %100 %71 |
| %95 = OpPhi %int %int_0 %5 %78 %71 |
| %70 = OpSLessThan %bool %95 %int_10 |
| OpLoopMerge %66 %71 None |
| OpBranchConditional %70 %71 %66 |
| %71 = OpLabel |
| %74 = OpAccessChain %_ptr_Uniform_v4float %_ %int_0 %95 |
| %75 = OpLoad %v4float %74 |
| %103 = OpFConvert %v4half %75 |
| %76 = OpFAdd %v4half %96 %103 |
| %78 = OpIAdd %int %95 %int_1 |
| %100 = OpCopyObject %v4half %76 |
| OpBranch %65 |
| %66 = OpLabel |
| %101 = OpFConvert %v4half %94 |
| %81 = OpFMul %v4half %96 %101 |
| %102 = OpFConvert %v4float %81 |
| OpStore %_entryPointOutput_Color %102 |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); |
| SinglePassRunAndCheck<ConvertToHalfPass>(defs_before + func_before, |
| defs_after + func_after, true, true); |
| } |
| |
| TEST_F(ConvertToHalfTest, ConvertToHalfWithExtracts) { |
| // The resulting SPIR-V was processed with --relax-float-ops. |
| // |
| // The extra converts in the func_after can be DCE'd. |
| // |
| // clang-format off |
| // |
| // SamplerState g_sSamp : register(s0); |
| // uniform Texture1D <float4> g_tTex1df4 : register(t0); |
| // |
| // struct PS_INPUT |
| // { |
| // float Tex0 : TEXCOORD0; |
| // }; |
| // |
| // struct PS_OUTPUT |
| // { |
| // float4 Color : SV_Target0; |
| // }; |
| // |
| // cbuffer cbuff{ |
| // float c; |
| // } |
| // |
| // PS_OUTPUT main(PS_INPUT i) |
| // { |
| // PS_OUTPUT psout; |
| // float4 tx = g_tTex1df4.Sample(g_sSamp, i.Tex0); |
| // float4 t = float4(tx.y, tx.z, tx.x, tx.w) * c; |
| // psout.Color = t; |
| // return psout; |
| // } |
| // |
| // clang-format on |
| |
| const std::string defs_before = |
| R"(OpCapability Shader |
| OpCapability Sampled1D |
| %1 = OpExtInstImport "GLSL.std.450" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Fragment %main "main" %i_Tex0 %_entryPointOutput_Color |
| OpExecutionMode %main OriginUpperLeft |
| OpSource HLSL 500 |
| OpName %main "main" |
| OpName %g_tTex1df4 "g_tTex1df4" |
| OpName %g_sSamp "g_sSamp" |
| OpName %cbuff "cbuff" |
| OpMemberName %cbuff 0 "c" |
| OpName %_ "" |
| OpName %i_Tex0 "i.Tex0" |
| OpName %_entryPointOutput_Color "@entryPointOutput.Color" |
| OpDecorate %g_tTex1df4 DescriptorSet 0 |
| OpDecorate %g_tTex1df4 Binding 0 |
| OpDecorate %g_sSamp DescriptorSet 0 |
| OpDecorate %g_sSamp Binding 0 |
| OpMemberDecorate %cbuff 0 Offset 0 |
| OpDecorate %cbuff Block |
| OpDecorate %_ DescriptorSet 0 |
| OpDecorate %_ Binding 1 |
| OpDecorate %i_Tex0 Location 0 |
| OpDecorate %_entryPointOutput_Color Location 0 |
| OpDecorate %65 RelaxedPrecision |
| OpDecorate %82 RelaxedPrecision |
| OpDecorate %84 RelaxedPrecision |
| OpDecorate %86 RelaxedPrecision |
| OpDecorate %88 RelaxedPrecision |
| OpDecorate %90 RelaxedPrecision |
| OpDecorate %91 RelaxedPrecision |
| OpDecorate %93 RelaxedPrecision |
| OpDecorate %94 RelaxedPrecision |
| %void = OpTypeVoid |
| %3 = OpTypeFunction %void |
| %float = OpTypeFloat 32 |
| %v4float = OpTypeVector %float 4 |
| %17 = OpTypeImage %float 1D 0 0 0 1 Unknown |
| %_ptr_UniformConstant_17 = OpTypePointer UniformConstant %17 |
| %g_tTex1df4 = OpVariable %_ptr_UniformConstant_17 UniformConstant |
| %21 = OpTypeSampler |
| %_ptr_UniformConstant_21 = OpTypePointer UniformConstant %21 |
| %g_sSamp = OpVariable %_ptr_UniformConstant_21 UniformConstant |
| %25 = OpTypeSampledImage %17 |
| %int = OpTypeInt 32 1 |
| %int_0 = OpConstant %int 0 |
| %cbuff = OpTypeStruct %float |
| %_ptr_Uniform_cbuff = OpTypePointer Uniform %cbuff |
| %_ = OpVariable %_ptr_Uniform_cbuff Uniform |
| %_ptr_Uniform_float = OpTypePointer Uniform %float |
| %_ptr_Input_float = OpTypePointer Input %float |
| %i_Tex0 = OpVariable %_ptr_Input_float Input |
| %_ptr_Output_v4float = OpTypePointer Output %v4float |
| %_entryPointOutput_Color = OpVariable %_ptr_Output_v4float Output |
| )"; |
| |
| const std::string defs_after = |
| R"(OpCapability Shader |
| OpCapability Sampled1D |
| OpCapability Float16 |
| %1 = OpExtInstImport "GLSL.std.450" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Fragment %main "main" %i_Tex0 %_entryPointOutput_Color |
| OpExecutionMode %main OriginUpperLeft |
| OpSource HLSL 500 |
| OpName %main "main" |
| OpName %g_tTex1df4 "g_tTex1df4" |
| OpName %g_sSamp "g_sSamp" |
| OpName %cbuff "cbuff" |
| OpMemberName %cbuff 0 "c" |
| OpName %_ "" |
| OpName %i_Tex0 "i.Tex0" |
| OpName %_entryPointOutput_Color "@entryPointOutput.Color" |
| OpDecorate %g_tTex1df4 DescriptorSet 0 |
| OpDecorate %g_tTex1df4 Binding 0 |
| OpDecorate %g_sSamp DescriptorSet 0 |
| OpDecorate %g_sSamp Binding 0 |
| OpMemberDecorate %cbuff 0 Offset 0 |
| OpDecorate %cbuff Block |
| OpDecorate %_ DescriptorSet 0 |
| OpDecorate %_ Binding 1 |
| OpDecorate %i_Tex0 Location 0 |
| OpDecorate %_entryPointOutput_Color Location 0 |
| %void = OpTypeVoid |
| %3 = OpTypeFunction %void |
| %float = OpTypeFloat 32 |
| %v4float = OpTypeVector %float 4 |
| %17 = OpTypeImage %float 1D 0 0 0 1 Unknown |
| %_ptr_UniformConstant_17 = OpTypePointer UniformConstant %17 |
| %g_tTex1df4 = OpVariable %_ptr_UniformConstant_17 UniformConstant |
| %21 = OpTypeSampler |
| %_ptr_UniformConstant_21 = OpTypePointer UniformConstant %21 |
| %g_sSamp = OpVariable %_ptr_UniformConstant_21 UniformConstant |
| %25 = OpTypeSampledImage %17 |
| %int = OpTypeInt 32 1 |
| %int_0 = OpConstant %int 0 |
| %cbuff = OpTypeStruct %float |
| %_ptr_Uniform_cbuff = OpTypePointer Uniform %cbuff |
| %_ = OpVariable %_ptr_Uniform_cbuff Uniform |
| %_ptr_Uniform_float = OpTypePointer Uniform %float |
| %_ptr_Input_float = OpTypePointer Input %float |
| %i_Tex0 = OpVariable %_ptr_Input_float Input |
| %_ptr_Output_v4float = OpTypePointer Output %v4float |
| %_entryPointOutput_Color = OpVariable %_ptr_Output_v4float Output |
| %half = OpTypeFloat 16 |
| %v4half = OpTypeVector %half 4 |
| )"; |
| |
| const std::string func_before = |
| R"(%main = OpFunction %void None %3 |
| %5 = OpLabel |
| %65 = OpLoad %float %i_Tex0 |
| %77 = OpLoad %17 %g_tTex1df4 |
| %78 = OpLoad %21 %g_sSamp |
| %79 = OpSampledImage %25 %77 %78 |
| %82 = OpImageSampleImplicitLod %v4float %79 %65 |
| %84 = OpCompositeExtract %float %82 1 |
| %86 = OpCompositeExtract %float %82 2 |
| %88 = OpCompositeExtract %float %82 0 |
| %90 = OpCompositeExtract %float %82 3 |
| %91 = OpCompositeConstruct %v4float %84 %86 %88 %90 |
| %92 = OpAccessChain %_ptr_Uniform_float %_ %int_0 |
| %93 = OpLoad %float %92 |
| %94 = OpVectorTimesScalar %v4float %91 %93 |
| OpStore %_entryPointOutput_Color %94 |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| const std::string func_after = |
| R"(%main = OpFunction %void None %3 |
| %5 = OpLabel |
| %65 = OpLoad %float %i_Tex0 |
| %77 = OpLoad %17 %g_tTex1df4 |
| %78 = OpLoad %21 %g_sSamp |
| %79 = OpSampledImage %25 %77 %78 |
| %82 = OpImageSampleImplicitLod %v4float %79 %65 |
| %97 = OpFConvert %v4half %82 |
| %84 = OpCompositeExtract %half %97 1 |
| %98 = OpFConvert %v4half %82 |
| %86 = OpCompositeExtract %half %98 2 |
| %99 = OpFConvert %v4half %82 |
| %88 = OpCompositeExtract %half %99 0 |
| %100 = OpFConvert %v4half %82 |
| %90 = OpCompositeExtract %half %100 3 |
| %91 = OpCompositeConstruct %v4half %84 %86 %88 %90 |
| %92 = OpAccessChain %_ptr_Uniform_float %_ %int_0 |
| %93 = OpLoad %float %92 |
| %101 = OpFConvert %half %93 |
| %94 = OpVectorTimesScalar %v4half %91 %101 |
| %102 = OpFConvert %v4float %94 |
| OpStore %_entryPointOutput_Color %102 |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); |
| SinglePassRunAndCheck<ConvertToHalfPass>(defs_before + func_before, |
| defs_after + func_after, true, true); |
| } |
| |
| TEST_F(ConvertToHalfTest, ConvertToHalfWithClosure) { |
| // Include as many contiguous composite instructions as possible into |
| // half-precision computations |
| // |
| // Compiled with glslang -V -Os |
| // |
| // clang-format off |
| // |
| // #version 410 core |
| // |
| // precision mediump float; |
| // |
| // layout(location = 1) in vec3 foo; |
| // layout(location = 2) in mat2 bar; |
| // layout(location = 1) out vec3 res; |
| // |
| // vec3 func(vec3 tap, mat2 M) { |
| // return vec3(M * tap.xy, 1.0); |
| // } |
| // |
| // void main() { |
| // res = func(foo, bar); |
| // } |
| // |
| // clang-format on |
| |
| const std::string defs = |
| R"(OpCapability Shader |
| ; CHECK: OpCapability Float16 |
| %1 = OpExtInstImport "GLSL.std.450" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Fragment %main "main" %res %foo %bar |
| OpExecutionMode %main OriginUpperLeft |
| OpSource GLSL 410 |
| OpName %main "main" |
| OpName %res "res" |
| OpName %foo "foo" |
| OpName %bar "bar" |
| OpDecorate %res RelaxedPrecision |
| ; CHECK-NOT: OpDecorate %res RelaxedPrecision |
| OpDecorate %res Location 1 |
| OpDecorate %foo RelaxedPrecision |
| ; CHECK-NOT: OpDecorate %foo RelaxedPrecision |
| OpDecorate %foo Location 1 |
| OpDecorate %bar RelaxedPrecision |
| ; CHECK-NOT: OpDecorate %bar RelaxedPrecision |
| OpDecorate %bar Location 2 |
| OpDecorate %34 RelaxedPrecision |
| OpDecorate %36 RelaxedPrecision |
| OpDecorate %41 RelaxedPrecision |
| OpDecorate %42 RelaxedPrecision |
| ; CHECK-NOT: OpDecorate %34 RelaxedPrecision |
| ; CHECK-NOT: OpDecorate %36 RelaxedPrecision |
| ; CHECK-NOT: OpDecorate %41 RelaxedPrecision |
| ; CHECK-NOT: OpDecorate %42 RelaxedPrecision |
| %void = OpTypeVoid |
| %3 = OpTypeFunction %void |
| %float = OpTypeFloat 32 |
| %v3float = OpTypeVector %float 3 |
| %v2float = OpTypeVector %float 2 |
| %mat2v2float = OpTypeMatrix %v2float 2 |
| %float_1 = OpConstant %float 1 |
| %_ptr_Output_v3float = OpTypePointer Output %v3float |
| %res = OpVariable %_ptr_Output_v3float Output |
| %_ptr_Input_v3float = OpTypePointer Input %v3float |
| %foo = OpVariable %_ptr_Input_v3float Input |
| %_ptr_Input_mat2v2float = OpTypePointer Input %mat2v2float |
| %bar = OpVariable %_ptr_Input_mat2v2float Input |
| )"; |
| |
| const std::string func = |
| R"(%main = OpFunction %void None %3 |
| %5 = OpLabel |
| %34 = OpLoad %v3float %foo |
| %36 = OpLoad %mat2v2float %bar |
| ; CHECK: %48 = OpFConvert %v3half %34 |
| ; CHECK: %49 = OpFConvert %v3half %34 |
| %41 = OpVectorShuffle %v2float %34 %34 0 1 |
| ; CHECK-NOT: %41 = OpVectorShuffle %v2float %34 %34 0 1 |
| ; CHECK: %41 = OpVectorShuffle %v2half %48 %49 0 1 |
| %42 = OpMatrixTimesVector %v2float %36 %41 |
| ; CHECK-NOT: %42 = OpMatrixTimesVector %v2float %36 %41 |
| ; CHECK: %55 = OpCompositeExtract %v2float %36 0 |
| ; CHECK: %56 = OpFConvert %v2half %55 |
| ; CHECK: %57 = OpCompositeExtract %v2float %36 1 |
| ; CHECK: %58 = OpFConvert %v2half %57 |
| ; CHECK: %59 = OpCompositeConstruct %mat2v2half %56 %58 |
| ; CHECK: %52 = OpCopyObject %mat2v2float %36 |
| ; CHECK: %42 = OpMatrixTimesVector %v2half %59 %41 |
| %43 = OpCompositeExtract %float %42 0 |
| %44 = OpCompositeExtract %float %42 1 |
| ; CHECK-NOT: %43 = OpCompositeExtract %float %42 0 |
| ; CHECK-NOT: %44 = OpCompositeExtract %float %42 1 |
| ; CHECK: %43 = OpCompositeExtract %half %42 0 |
| ; CHECK: %44 = OpCompositeExtract %half %42 1 |
| %45 = OpCompositeConstruct %v3float %43 %44 %float_1 |
| ; CHECK-NOT: %45 = OpCompositeConstruct %v3float %43 %44 %float_1 |
| ; CHECK: %53 = OpFConvert %float %43 |
| ; CHECK: %54 = OpFConvert %float %44 |
| ; CHECK: %45 = OpCompositeConstruct %v3float %53 %54 %float_1 |
| OpStore %res %45 |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); |
| SinglePassRunAndMatch<ConvertToHalfPass>(defs + func, true); |
| } |
| |
| TEST_F(ConvertToHalfTest, RemoveRelaxDec) { |
| // See https://github.com/KhronosGroup/SPIRV-Tools/issues/4117 |
| |
| // This test is a case where the relax precision decorations need to be |
| // removed, but the body of the function does not change because there are not |
| // arithmetic operations. So, there is not need for the Float16 capability. |
| const std::string test = |
| R"( |
| ; CHECK-NOT: OpCapability Float16 |
| ; GLSL seems to generate this decoration on the load of a texture, which seems odd to me. |
| ; This pass does not currently remove it, and I'm not sure what we should do with it, so I will leave it. |
| ; CHECK: OpDecorate [[tex:%\w+]] RelaxedPrecision |
| ; CHECK-NOT: OpDecorate {{%\w+}} RelaxedPrecision |
| ; CHECK: OpLabel |
| ; CHECK: [[tex]] = OpLoad {{%\w+}} %sTexture |
| ; CHECK: [[coord:%\w+]] = OpLoad %v2float |
| ; CHECK: [[retval:%\w+]] = OpImageSampleImplicitLod %v4float {{%\w+}} [[coord]] |
| ; CHECK: OpStore %outFragColor [[retval]] |
| OpCapability Shader |
| %1 = OpExtInstImport "GLSL.std.450" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Fragment %main "main" %outFragColor %v_texcoord |
| OpExecutionMode %main OriginUpperLeft |
| OpSource ESSL 310 |
| OpName %main "main" |
| OpName %outFragColor "outFragColor" |
| OpName %sTexture "sTexture" |
| OpName %v_texcoord "v_texcoord" |
| OpDecorate %outFragColor RelaxedPrecision |
| OpDecorate %outFragColor Location 0 |
| OpDecorate %sTexture RelaxedPrecision |
| OpDecorate %sTexture DescriptorSet 0 |
| OpDecorate %sTexture Binding 0 |
| OpDecorate %14 RelaxedPrecision |
| OpDecorate %v_texcoord RelaxedPrecision |
| OpDecorate %v_texcoord Location 0 |
| OpDecorate %18 RelaxedPrecision |
| OpDecorate %19 RelaxedPrecision |
| %void = OpTypeVoid |
| %3 = OpTypeFunction %void |
| %float = OpTypeFloat 32 |
| %v4float = OpTypeVector %float 4 |
| %_ptr_Output_v4float = OpTypePointer Output %v4float |
| %outFragColor = OpVariable %_ptr_Output_v4float Output |
| %10 = OpTypeImage %float 2D 0 0 0 1 Unknown |
| %11 = OpTypeSampledImage %10 |
| %_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11 |
| %sTexture = OpVariable %_ptr_UniformConstant_11 UniformConstant |
| %v2float = OpTypeVector %float 2 |
| %_ptr_Input_v2float = OpTypePointer Input %v2float |
| %v_texcoord = OpVariable %_ptr_Input_v2float Input |
| %main = OpFunction %void None %3 |
| %5 = OpLabel |
| %14 = OpLoad %11 %sTexture |
| %18 = OpLoad %v2float %v_texcoord |
| %19 = OpImageSampleImplicitLod %v4float %14 %18 |
| OpStore %outFragColor %19 |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); |
| auto result = SinglePassRunAndMatch<ConvertToHalfPass>(test, true); |
| EXPECT_EQ(Pass::Status::SuccessWithChange, std::get<1>(result)); |
| } |
| |
| TEST_F(ConvertToHalfTest, HandleNonRelaxedPhi) { |
| // See https://github.com/KhronosGroup/SPIRV-Tools/issues/4452 |
| |
| // This test is a case with a non-relaxed phi with a relaxed operand. |
| // A convert must be inserted at the end of the block associated with |
| // the operand. |
| const std::string test = |
| R"( |
| ; CHECK: [[fcvt:%\w+]] = OpFConvert %v3float {{%\w+}} |
| ; CHECK-NEXT: OpSelectionMerge {{%\w+}} None |
| ; CHECK: {{%\w+}} = OpPhi %v3float [[fcvt]] {{%\w+}} {{%\w+}} {{%\w+}} |
| OpCapability Shader |
| %1 = OpExtInstImport "GLSL.std.450" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Fragment %main "main" %output_color |
| OpExecutionMode %main OriginUpperLeft |
| OpSource GLSL 450 |
| OpName %main "main" |
| OpName %MaterialParams "MaterialParams" |
| OpMemberName %MaterialParams 0 "foo" |
| OpName %materialParams "materialParams" |
| OpName %output_color "output_color" |
| OpMemberDecorate %MaterialParams 0 Offset 0 |
| OpDecorate %MaterialParams Block |
| OpDecorate %materialParams DescriptorSet 0 |
| OpDecorate %materialParams Binding 5 |
| OpDecorate %output_color Location 0 |
| OpDecorate %57 RelaxedPrecision |
| %void = OpTypeVoid |
| %3 = OpTypeFunction %void |
| %float = OpTypeFloat 32 |
| %v3float = OpTypeVector %float 3 |
| %MaterialParams = OpTypeStruct %float |
| %_ptr_Uniform_MaterialParams = OpTypePointer Uniform %MaterialParams |
| %materialParams = OpVariable %_ptr_Uniform_MaterialParams Uniform |
| %int = OpTypeInt 32 1 |
| %int_0 = OpConstant %int 0 |
| %_ptr_Uniform_float = OpTypePointer Uniform %float |
| %float_0 = OpConstant %float 0 |
| %bool = OpTypeBool |
| %v4float = OpTypeVector %float 4 |
| %_ptr_Output_v4float = OpTypePointer Output %v4float |
| %output_color = OpVariable %_ptr_Output_v4float Output |
| %uint = OpTypeInt 32 0 |
| %uint_0 = OpConstant %uint 0 |
| %_ptr_Output_float = OpTypePointer Output %float |
| %uint_1 = OpConstant %uint 1 |
| %uint_2 = OpConstant %uint 2 |
| %float_0_5 = OpConstant %float 0.5 |
| %61 = OpConstantComposite %v3float %float_0_5 %float_0_5 %float_0_5 |
| %main = OpFunction %void None %3 |
| %5 = OpLabel |
| %55 = OpAccessChain %_ptr_Uniform_float %materialParams %int_0 |
| %56 = OpLoad %float %55 |
| %57 = OpCompositeConstruct %v3float %56 %56 %56 |
| %31 = OpFOrdGreaterThan %bool %56 %float_0 |
| OpSelectionMerge %33 None |
| OpBranchConditional %31 %32 %33 |
| %32 = OpLabel |
| %37 = OpFMul %v3float %57 %61 |
| OpBranch %33 |
| %33 = OpLabel |
| %58 = OpPhi %v3float %57 %5 %37 %32 |
| %45 = OpAccessChain %_ptr_Output_float %output_color %uint_0 |
| %46 = OpCompositeExtract %float %58 0 |
| OpStore %45 %46 |
| %48 = OpAccessChain %_ptr_Output_float %output_color %uint_1 |
| %49 = OpCompositeExtract %float %58 1 |
| OpStore %48 %49 |
| %51 = OpAccessChain %_ptr_Output_float %output_color %uint_2 |
| %52 = OpCompositeExtract %float %58 2 |
| OpStore %51 %52 |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); |
| auto result = SinglePassRunAndMatch<ConvertToHalfPass>(test, true); |
| EXPECT_EQ(Pass::Status::SuccessWithChange, std::get<1>(result)); |
| } |
| |
| TEST_F(ConvertToHalfTest, DoNotReplaceStructMember) { |
| // See https://github.com/KhronosGroup/SPIRV-Tools/issues/4814 |
| |
| // This test is a case with a non-relaxed phi with a relaxed operand. |
| // A convert must be inserted at the end of the block associated with |
| // the operand. |
| const std::string test = |
| R"(OpCapability Shader |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Fragment %PSMain "PSMain" %out_var_SV_TARGET %MyConstants |
| OpExecutionMode %PSMain OriginUpperLeft |
| OpSource HLSL 600 |
| OpName %type_ConstantBuffer_myStruct "type.ConstantBuffer.myStruct" |
| OpMemberName %type_ConstantBuffer_myStruct 0 "f" |
| OpName %MyConstants "MyConstants" |
| OpName %out_var_SV_TARGET "out.var.SV_TARGET" |
| OpName %PSMain "PSMain" |
| OpDecorate %out_var_SV_TARGET Location 0 |
| OpDecorate %MyConstants DescriptorSet 1 |
| OpDecorate %MyConstants Binding 2 |
| OpMemberDecorate %type_ConstantBuffer_myStruct 0 Offset 0 |
| OpDecorate %type_ConstantBuffer_myStruct Block |
| %float = OpTypeFloat 32 |
| %type_ConstantBuffer_myStruct = OpTypeStruct %float |
| %_ptr_Uniform_type_ConstantBuffer_myStruct = OpTypePointer Uniform %type_ConstantBuffer_myStruct |
| %_ptr_Output_float = OpTypePointer Output %float |
| %void = OpTypeVoid |
| %9 = OpTypeFunction %void |
| %MyConstants = OpVariable %_ptr_Uniform_type_ConstantBuffer_myStruct Uniform |
| %out_var_SV_TARGET = OpVariable %_ptr_Output_float Output |
| %PSMain = OpFunction %void None %9 |
| %10 = OpLabel |
| %11 = OpLoad %type_ConstantBuffer_myStruct %MyConstants |
| %12 = OpCompositeExtract %float %11 0 |
| OpStore %out_var_SV_TARGET %12 |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); |
| SinglePassRunAndCheck<ConvertToHalfPass>(test, test, true); |
| } |
| |
| TEST_F(ConvertToHalfTest, PreserveImageOperandPrecision) { |
| // Ensure that a non-relaxed texture coordinate does not get relaxed nor |
| // converted to half precision if the image instruction is marked relaxed. |
| |
| // Also ensure that a relaxed local variable does get converted to half |
| // precision before being passed to an image opeartor. |
| |
| // #version 310 es |
| // |
| // precision mediump float; |
| // |
| // layout(location = 10) in highp vec4 vertex_uv01; |
| // layout(binding = 0, set = 3) uniform sampler2D materialParams_baseColorMap; |
| // |
| // layout(location = 0) out vec4 fragColor; |
| // |
| // void main() { |
| // vec4 uv = vec4(2.0); |
| // fragColor = texture(materialParams_baseColorMap, uv.xy); |
| // fragColor = texture(materialParams_baseColorMap, vertex_uv01.xy); |
| // } |
| const std::string test = R"( |
| OpCapability Shader |
| OpCapability Float16 |
| %1 = OpExtInstImport "GLSL.std.450" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Fragment %4 "main" %13 %25 |
| OpExecutionMode %4 OriginUpperLeft |
| OpSource ESSL 310 |
| OpDecorate %9 RelaxedPrecision |
| ;CHECK: OpDecorate [[uv:%\w+]] RelaxedPrecision |
| OpDecorate %13 Location 0 |
| OpDecorate %17 DescriptorSet 3 |
| OpDecorate %17 Binding 0 |
| OpDecorate %18 RelaxedPrecision |
| OpDecorate %23 RelaxedPrecision |
| OpDecorate %25 Location 10 |
| %2 = OpTypeVoid |
| %3 = OpTypeFunction %2 |
| %6 = OpTypeFloat 32 |
| ;CHECK: [[float32_t:%\w+]] = OpTypeFloat 32 |
| %7 = OpTypeVector %6 4 |
| ;CHECK: [[vec4_t:%\w+]] = OpTypeVector [[float32_t]] 4 |
| %8 = OpTypePointer Function %7 |
| %10 = OpConstant %6 2 |
| %11 = OpConstantComposite %7 %10 %10 %10 %10 |
| %12 = OpTypePointer Output %7 |
| ;CHECK: [[output_ptr_t:%\w+]] = OpTypePointer Output [[vec4_t]] |
| %13 = OpVariable %12 Output |
| ;CHECK: [[output:%\w+]] = OpVariable [[output_ptr_t]] Output |
| %14 = OpTypeImage %6 2D 0 0 0 1 Unknown |
| %15 = OpTypeSampledImage %14 |
| %16 = OpTypePointer UniformConstant %15 |
| %17 = OpVariable %16 UniformConstant |
| %19 = OpTypeVector %6 2 |
| ;CHECK: [[vec2_t:%\w+]] = OpTypeVector [[float32_t]] 2 |
| %24 = OpTypePointer Input %7 |
| ;CHECK: [[input_ptr_t:%\w+]] = OpTypePointer Input [[vec4_t]] |
| %25 = OpVariable %24 Input |
| %29 = OpTypeFloat 16 |
| ;CHECK: [[float16_t:%\w+]] = OpTypeFloat 16 |
| %30 = OpTypeVector %29 4 |
| %33 = OpTypeVector %29 2 |
| ;CHECK: [[vec2_16b_t:%\w+]] = OpTypeVector [[float16_t]] 2 |
| %4 = OpFunction %2 None %3 |
| %5 = OpLabel |
| |
| ; The only Function storage variable is marked as relaxed |
| %9 = OpVariable %8 Function |
| ;CHECK: [[uv]] = OpVariable {{%\w+}} Function |
| OpStore %9 %11 |
| %18 = OpLoad %15 %17 |
| %20 = OpLoad %7 %9 |
| %31 = OpFConvert %30 %20 |
| %32 = OpFConvert %30 %20 |
| |
| ; The first sample op should get a 16b coordinate |
| %21 = OpVectorShuffle %33 %31 %32 0 1 |
| ;CHECK: [[uv_16b:%\w+]] = OpVectorShuffle [[vec2_16b_t]] |
| %22 = OpImageSampleImplicitLod %7 %18 %21 |
| ;CHECK: OpImageSampleImplicitLod [[vec4_t]] {{%\w+}} [[uv_16b]] |
| |
| OpStore %13 %22 |
| %23 = OpLoad %15 %17 |
| %26 = OpLoad %7 %25 |
| |
| ; The second sample op should get a 32b coordinate |
| %27 = OpVectorShuffle %19 %26 %26 0 1 |
| ;CHECK: [[uv_32b:%\w+]] = OpVectorShuffle [[vec2_t]] |
| %28 = OpImageSampleImplicitLod %7 %23 %27 |
| ;CHECK: OpImageSampleImplicitLod [[vec4_t]] {{%\w+}} [[uv_32b]] |
| |
| OpStore %13 %28 |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| SinglePassRunAndMatch<ConvertToHalfPass>(test, true); |
| } |
| |
| TEST_F(ConvertToHalfTest, DontRelaxDecoratedOpCompositeExtract) { |
| // This test checks that a OpCompositeExtract with a Struct operand won't be |
| // relaxed, even if it is explicitly decorated with RelaxedPrecision. |
| const std::string test = |
| R"(OpCapability Shader |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Fragment %1 "main" |
| OpExecutionMode %1 OriginUpperLeft |
| OpDecorate %9 RelaxedPrecision |
| %void = OpTypeVoid |
| %3 = OpTypeFunction %void |
| %float = OpTypeFloat 32 |
| %v4float = OpTypeVector %float 4 |
| %_struct_6 = OpTypeStruct %v4float |
| %7 = OpUndef %_struct_6 |
| %1 = OpFunction %void None %3 |
| %8 = OpLabel |
| %9 = OpCompositeExtract %float %7 0 3 |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| const std::string expected = |
| R"(OpCapability Shader |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Fragment %1 "main" |
| OpExecutionMode %1 OriginUpperLeft |
| %void = OpTypeVoid |
| %3 = OpTypeFunction %void |
| %float = OpTypeFloat 32 |
| %v4float = OpTypeVector %float 4 |
| %_struct_6 = OpTypeStruct %v4float |
| %7 = OpUndef %_struct_6 |
| %1 = OpFunction %void None %3 |
| %8 = OpLabel |
| %9 = OpCompositeExtract %float %7 0 3 |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); |
| SinglePassRunAndCheck<ConvertToHalfPass>(test, expected, true); |
| } |
| |
| TEST_F(ConvertToHalfTest, DontRelaxOpCompositeExtract) { |
| // This test checks that a OpCompositeExtract with a Struct operand won't be |
| // relaxed, even if its result has no uses. |
| const std::string test = |
| R"(OpCapability Shader |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Fragment %1 "main" |
| OpExecutionMode %1 OriginUpperLeft |
| %void = OpTypeVoid |
| %3 = OpTypeFunction %void |
| %float = OpTypeFloat 32 |
| %v4float = OpTypeVector %float 4 |
| %_struct_6 = OpTypeStruct %v4float |
| %7 = OpUndef %_struct_6 |
| %1 = OpFunction %void None %3 |
| %8 = OpLabel |
| %9 = OpCompositeExtract %float %7 0 3 |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); |
| SinglePassRunAndCheck<ConvertToHalfPass>(test, test, true); |
| } |
| |
| } // namespace |
| } // namespace opt |
| } // namespace spvtools |