diff --git a/reference/opt/shaders-hlsl/asm/frag/single-function-private-lut.asm.frag b/reference/opt/shaders-hlsl/asm/frag/single-function-private-lut.asm.frag new file mode 100644 index 00000000..507bbe1d --- /dev/null +++ b/reference/opt/shaders-hlsl/asm/frag/single-function-private-lut.asm.frag @@ -0,0 +1,62 @@ +struct myType +{ + float data; +}; + +static const myType _18 = { 0.0f }; +static const myType _20 = { 1.0f }; +static const myType _21[5] = { { 0.0f }, { 1.0f }, { 0.0f }, { 1.0f }, { 0.0f } }; + +static float4 gl_FragCoord; +static float4 o_color; + +struct SPIRV_Cross_Input +{ + float4 gl_FragCoord : SV_Position; +}; + +struct SPIRV_Cross_Output +{ + float4 o_color : SV_Target0; +}; + +float mod(float x, float y) +{ + return x - y * floor(x / y); +} + +float2 mod(float2 x, float2 y) +{ + return x - y * floor(x / y); +} + +float3 mod(float3 x, float3 y) +{ + return x - y * floor(x / y); +} + +float4 mod(float4 x, float4 y) +{ + return x - y * floor(x / y); +} + +void frag_main() +{ + if (_21[int(mod(gl_FragCoord.x, 4.0f))].data > 0.0f) + { + o_color = float4(0.0f, 1.0f, 0.0f, 1.0f); + } + else + { + o_color = float4(1.0f, 0.0f, 0.0f, 1.0f); + } +} + +SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input) +{ + gl_FragCoord = stage_input.gl_FragCoord; + frag_main(); + SPIRV_Cross_Output stage_output; + stage_output.o_color = o_color; + return stage_output; +} diff --git a/reference/opt/shaders-msl/asm/frag/single-function-private-lut.asm.frag b/reference/opt/shaders-msl/asm/frag/single-function-private-lut.asm.frag new file mode 100644 index 00000000..4081c3d8 --- /dev/null +++ b/reference/opt/shaders-msl/asm/frag/single-function-private-lut.asm.frag @@ -0,0 +1,40 @@ +#pragma clang diagnostic ignored "-Wmissing-prototypes" + +#include +#include + +using namespace metal; + +struct myType +{ + float data; +}; + +constant myType _21[5] = { myType{ 0.0 }, myType{ 1.0 }, myType{ 0.0 }, myType{ 1.0 }, myType{ 0.0 } }; + +struct main0_out +{ + float4 o_color [[color(0)]]; +}; + +// Implementation of the GLSL mod() function, which is slightly different than Metal fmod() +template +Tx mod(Tx x, Ty y) +{ + return x - y * floor(x / y); +} + +fragment main0_out main0(float4 gl_FragCoord [[position]]) +{ + main0_out out = {}; + if (_21[int(mod(gl_FragCoord.x, 4.0))].data > 0.0) + { + out.o_color = float4(0.0, 1.0, 0.0, 1.0); + } + else + { + out.o_color = float4(1.0, 0.0, 0.0, 1.0); + } + return out; +} + diff --git a/reference/opt/shaders/asm/frag/single-function-private-lut.asm.frag b/reference/opt/shaders/asm/frag/single-function-private-lut.asm.frag new file mode 100644 index 00000000..45fc4b1c --- /dev/null +++ b/reference/opt/shaders/asm/frag/single-function-private-lut.asm.frag @@ -0,0 +1,23 @@ +#version 460 + +struct myType +{ + float data; +}; + +const myType _21[5] = myType[](myType(0.0), myType(1.0), myType(0.0), myType(1.0), myType(0.0)); + +layout(location = 0) out vec4 o_color; + +void main() +{ + if (_21[int(mod(gl_FragCoord.x, 4.0))].data > 0.0) + { + o_color = vec4(0.0, 1.0, 0.0, 1.0); + } + else + { + o_color = vec4(1.0, 0.0, 0.0, 1.0); + } +} + diff --git a/reference/shaders-hlsl/asm/frag/single-function-private-lut.asm.frag b/reference/shaders-hlsl/asm/frag/single-function-private-lut.asm.frag new file mode 100644 index 00000000..281c3976 --- /dev/null +++ b/reference/shaders-hlsl/asm/frag/single-function-private-lut.asm.frag @@ -0,0 +1,65 @@ +struct myType +{ + float data; +}; + +static const myType _18 = { 0.0f }; +static const myType _20 = { 1.0f }; +static const myType _21[5] = { { 0.0f }, { 1.0f }, { 0.0f }, { 1.0f }, { 0.0f } }; + +static float4 gl_FragCoord; +static float4 o_color; + +struct SPIRV_Cross_Input +{ + float4 gl_FragCoord : SV_Position; +}; + +struct SPIRV_Cross_Output +{ + float4 o_color : SV_Target0; +}; + +float mod(float x, float y) +{ + return x - y * floor(x / y); +} + +float2 mod(float2 x, float2 y) +{ + return x - y * floor(x / y); +} + +float3 mod(float3 x, float3 y) +{ + return x - y * floor(x / y); +} + +float4 mod(float4 x, float4 y) +{ + return x - y * floor(x / y); +} + +void frag_main() +{ + float2 uv = gl_FragCoord.xy; + int index = int(mod(uv.x, 4.0f)); + myType elt = _21[index]; + if (elt.data > 0.0f) + { + o_color = float4(0.0f, 1.0f, 0.0f, 1.0f); + } + else + { + o_color = float4(1.0f, 0.0f, 0.0f, 1.0f); + } +} + +SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input) +{ + gl_FragCoord = stage_input.gl_FragCoord; + frag_main(); + SPIRV_Cross_Output stage_output; + stage_output.o_color = o_color; + return stage_output; +} diff --git a/reference/shaders-hlsl/frag/constant-composites.frag b/reference/shaders-hlsl/frag/constant-composites.frag index 2613e1c2..306ca5ca 100644 --- a/reference/shaders-hlsl/frag/constant-composites.frag +++ b/reference/shaders-hlsl/frag/constant-composites.frag @@ -22,15 +22,10 @@ struct SPIRV_Cross_Output float4 FragColor : SV_Target0; }; -static float lut[4]; -static Foo foos[2]; - void frag_main() { - lut = _16; - foos = _28; - FragColor = lut[_line].xxxx; - FragColor += (foos[_line].a * foos[1 - _line].a).xxxx; + FragColor = _16[_line].xxxx; + FragColor += (_28[_line].a * _28[1 - _line].a).xxxx; } SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input) diff --git a/reference/shaders-msl/asm/frag/single-function-private-lut.asm.frag b/reference/shaders-msl/asm/frag/single-function-private-lut.asm.frag new file mode 100644 index 00000000..628d5c7c --- /dev/null +++ b/reference/shaders-msl/asm/frag/single-function-private-lut.asm.frag @@ -0,0 +1,56 @@ +#pragma clang diagnostic ignored "-Wmissing-prototypes" + +#include +#include + +using namespace metal; + +struct myType +{ + float data; +}; + +constant myType _21[5] = { myType{ 0.0 }, myType{ 1.0 }, myType{ 0.0 }, myType{ 1.0 }, myType{ 0.0 } }; + +struct main0_out +{ + float4 o_color [[color(0)]]; +}; + +// Implementation of the GLSL mod() function, which is slightly different than Metal fmod() +template +Tx mod(Tx x, Ty y) +{ + return x - y * floor(x / y); +} + +// Implementation of an array copy function to cover GLSL's ability to copy an array via assignment. +template +void spvArrayCopyFromStack1(thread T (&dst)[N], thread const T (&src)[N]) +{ + for (uint i = 0; i < N; dst[i] = src[i], i++); +} + +template +void spvArrayCopyFromConstant1(thread T (&dst)[N], constant T (&src)[N]) +{ + for (uint i = 0; i < N; dst[i] = src[i], i++); +} + +fragment main0_out main0(float4 gl_FragCoord [[position]]) +{ + main0_out out = {}; + float2 uv = gl_FragCoord.xy; + int index = int(mod(uv.x, 4.0)); + myType elt = _21[index]; + if (elt.data > 0.0) + { + out.o_color = float4(0.0, 1.0, 0.0, 1.0); + } + else + { + out.o_color = float4(1.0, 0.0, 0.0, 1.0); + } + return out; +} + diff --git a/reference/shaders-msl/frag/constant-composites.frag b/reference/shaders-msl/frag/constant-composites.frag index 2c91b111..504beaa0 100644 --- a/reference/shaders-msl/frag/constant-composites.frag +++ b/reference/shaders-msl/frag/constant-composites.frag @@ -40,10 +40,8 @@ void spvArrayCopyFromConstant1(thread T (&dst)[N], constant T (&src)[N]) fragment main0_out main0(main0_in in [[stage_in]]) { main0_out out = {}; - float lut[4] = { 1.0, 4.0, 3.0, 2.0 }; - Foo foos[2] = { Foo{ 10.0, 20.0 }, Foo{ 30.0, 40.0 } }; - out.FragColor = float4(lut[in.line]); - out.FragColor += float4(foos[in.line].a * foos[1 - in.line].a); + out.FragColor = float4(_16[in.line]); + out.FragColor += float4(_28[in.line].a * _28[1 - in.line].a); return out; } diff --git a/reference/shaders/asm/frag/single-function-private-lut.asm.frag b/reference/shaders/asm/frag/single-function-private-lut.asm.frag new file mode 100644 index 00000000..9c45d854 --- /dev/null +++ b/reference/shaders/asm/frag/single-function-private-lut.asm.frag @@ -0,0 +1,26 @@ +#version 460 + +struct myType +{ + float data; +}; + +const myType _21[5] = myType[](myType(0.0), myType(1.0), myType(0.0), myType(1.0), myType(0.0)); + +layout(location = 0) out vec4 o_color; + +void main() +{ + vec2 uv = gl_FragCoord.xy; + int index = int(mod(uv.x, 4.0)); + myType elt = _21[index]; + if (elt.data > 0.0) + { + o_color = vec4(0.0, 1.0, 0.0, 1.0); + } + else + { + o_color = vec4(1.0, 0.0, 0.0, 1.0); + } +} + diff --git a/reference/shaders/frag/constant-composites.frag b/reference/shaders/frag/constant-composites.frag index c65c6061..7813b98d 100644 --- a/reference/shaders/frag/constant-composites.frag +++ b/reference/shaders/frag/constant-composites.frag @@ -2,22 +2,22 @@ precision mediump float; precision highp int; +const float _16[4] = float[](1.0, 4.0, 3.0, 2.0); + struct Foo { float a; float b; }; +const Foo _28[2] = Foo[](Foo(10.0, 20.0), Foo(30.0, 40.0)); + layout(location = 0) out vec4 FragColor; layout(location = 0) flat in mediump int line; -float lut[4]; -Foo foos[2]; void main() { - lut = float[](1.0, 4.0, 3.0, 2.0); - foos = Foo[](Foo(10.0, 20.0), Foo(30.0, 40.0)); - FragColor = vec4(lut[line]); - FragColor += vec4(foos[line].a * foos[1 - line].a); + FragColor = vec4(_16[line]); + FragColor += vec4(_28[line].a * _28[1 - line].a); } diff --git a/shaders-hlsl/asm/frag/single-function-private-lut.asm.frag b/shaders-hlsl/asm/frag/single-function-private-lut.asm.frag new file mode 100644 index 00000000..0d5b29c6 --- /dev/null +++ b/shaders-hlsl/asm/frag/single-function-private-lut.asm.frag @@ -0,0 +1,86 @@ +; SPIR-V +; Version: 1.3 +; Generator: Khronos SPIR-V Tools Assembler; 0 +; Bound: 54 +; Schema: 0 + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %main "main" %gl_FragCoord %o_color + OpExecutionMode %main OriginUpperLeft + OpSource GLSL 460 + OpName %main "main" + OpName %myType "myType" + OpMemberName %myType 0 "data" + OpName %myData "myData" + OpName %uv "uv" + OpName %gl_FragCoord "gl_FragCoord" + OpName %index "index" + OpName %elt "elt" + OpName %o_color "o_color" + OpDecorate %gl_FragCoord BuiltIn FragCoord + OpDecorate %o_color Location 0 + %void = OpTypeVoid + %11 = OpTypeFunction %void + %float = OpTypeFloat 32 + %myType = OpTypeStruct %float + %uint = OpTypeInt 32 0 + %uint_5 = OpConstant %uint 5 +%_arr_myType_uint_5 = OpTypeArray %myType %uint_5 +%_ptr_Private__arr_myType_uint_5 = OpTypePointer Private %_arr_myType_uint_5 + %myData = OpVariable %_ptr_Private__arr_myType_uint_5 Private + %float_0 = OpConstant %float 0 + %18 = OpConstantComposite %myType %float_0 + %float_1 = OpConstant %float 1 + %20 = OpConstantComposite %myType %float_1 + %21 = OpConstantComposite %_arr_myType_uint_5 %18 %20 %18 %20 %18 + %v2float = OpTypeVector %float 2 +%_ptr_Function_v2float = OpTypePointer Function %v2float + %v4float = OpTypeVector %float 4 +%_ptr_Input_v4float = OpTypePointer Input %v4float +%gl_FragCoord = OpVariable %_ptr_Input_v4float Input + %int = OpTypeInt 32 1 +%_ptr_Function_int = OpTypePointer Function %int + %uint_0 = OpConstant %uint 0 +%_ptr_Function_float = OpTypePointer Function %float + %float_4 = OpConstant %float 4 +%_ptr_Function_myType = OpTypePointer Function %myType +%_ptr_Private_myType = OpTypePointer Private %myType + %int_0 = OpConstant %int 0 + %bool = OpTypeBool +%_ptr_Output_v4float = OpTypePointer Output %v4float + %o_color = OpVariable %_ptr_Output_v4float Output + %36 = OpConstantComposite %v4float %float_0 %float_1 %float_0 %float_1 + %37 = OpConstantComposite %v4float %float_1 %float_0 %float_0 %float_1 + %main = OpFunction %void None %11 + %38 = OpLabel + %uv = OpVariable %_ptr_Function_v2float Function + %index = OpVariable %_ptr_Function_int Function + %elt = OpVariable %_ptr_Function_myType Function + OpStore %myData %21 + %39 = OpLoad %v4float %gl_FragCoord + %40 = OpVectorShuffle %v2float %39 %39 0 1 + OpStore %uv %40 + %41 = OpAccessChain %_ptr_Function_float %uv %uint_0 + %42 = OpLoad %float %41 + %43 = OpFMod %float %42 %float_4 + %44 = OpConvertFToS %int %43 + OpStore %index %44 + %45 = OpLoad %int %index + %46 = OpAccessChain %_ptr_Private_myType %myData %45 + %47 = OpLoad %myType %46 + OpStore %elt %47 + %48 = OpAccessChain %_ptr_Function_float %elt %int_0 + %49 = OpLoad %float %48 + %50 = OpFOrdGreaterThan %bool %49 %float_0 + OpSelectionMerge %51 None + OpBranchConditional %50 %52 %53 + %52 = OpLabel + OpStore %o_color %36 + OpBranch %51 + %53 = OpLabel + OpStore %o_color %37 + OpBranch %51 + %51 = OpLabel + OpReturn + OpFunctionEnd diff --git a/shaders-msl/asm/frag/single-function-private-lut.asm.frag b/shaders-msl/asm/frag/single-function-private-lut.asm.frag new file mode 100644 index 00000000..0d5b29c6 --- /dev/null +++ b/shaders-msl/asm/frag/single-function-private-lut.asm.frag @@ -0,0 +1,86 @@ +; SPIR-V +; Version: 1.3 +; Generator: Khronos SPIR-V Tools Assembler; 0 +; Bound: 54 +; Schema: 0 + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %main "main" %gl_FragCoord %o_color + OpExecutionMode %main OriginUpperLeft + OpSource GLSL 460 + OpName %main "main" + OpName %myType "myType" + OpMemberName %myType 0 "data" + OpName %myData "myData" + OpName %uv "uv" + OpName %gl_FragCoord "gl_FragCoord" + OpName %index "index" + OpName %elt "elt" + OpName %o_color "o_color" + OpDecorate %gl_FragCoord BuiltIn FragCoord + OpDecorate %o_color Location 0 + %void = OpTypeVoid + %11 = OpTypeFunction %void + %float = OpTypeFloat 32 + %myType = OpTypeStruct %float + %uint = OpTypeInt 32 0 + %uint_5 = OpConstant %uint 5 +%_arr_myType_uint_5 = OpTypeArray %myType %uint_5 +%_ptr_Private__arr_myType_uint_5 = OpTypePointer Private %_arr_myType_uint_5 + %myData = OpVariable %_ptr_Private__arr_myType_uint_5 Private + %float_0 = OpConstant %float 0 + %18 = OpConstantComposite %myType %float_0 + %float_1 = OpConstant %float 1 + %20 = OpConstantComposite %myType %float_1 + %21 = OpConstantComposite %_arr_myType_uint_5 %18 %20 %18 %20 %18 + %v2float = OpTypeVector %float 2 +%_ptr_Function_v2float = OpTypePointer Function %v2float + %v4float = OpTypeVector %float 4 +%_ptr_Input_v4float = OpTypePointer Input %v4float +%gl_FragCoord = OpVariable %_ptr_Input_v4float Input + %int = OpTypeInt 32 1 +%_ptr_Function_int = OpTypePointer Function %int + %uint_0 = OpConstant %uint 0 +%_ptr_Function_float = OpTypePointer Function %float + %float_4 = OpConstant %float 4 +%_ptr_Function_myType = OpTypePointer Function %myType +%_ptr_Private_myType = OpTypePointer Private %myType + %int_0 = OpConstant %int 0 + %bool = OpTypeBool +%_ptr_Output_v4float = OpTypePointer Output %v4float + %o_color = OpVariable %_ptr_Output_v4float Output + %36 = OpConstantComposite %v4float %float_0 %float_1 %float_0 %float_1 + %37 = OpConstantComposite %v4float %float_1 %float_0 %float_0 %float_1 + %main = OpFunction %void None %11 + %38 = OpLabel + %uv = OpVariable %_ptr_Function_v2float Function + %index = OpVariable %_ptr_Function_int Function + %elt = OpVariable %_ptr_Function_myType Function + OpStore %myData %21 + %39 = OpLoad %v4float %gl_FragCoord + %40 = OpVectorShuffle %v2float %39 %39 0 1 + OpStore %uv %40 + %41 = OpAccessChain %_ptr_Function_float %uv %uint_0 + %42 = OpLoad %float %41 + %43 = OpFMod %float %42 %float_4 + %44 = OpConvertFToS %int %43 + OpStore %index %44 + %45 = OpLoad %int %index + %46 = OpAccessChain %_ptr_Private_myType %myData %45 + %47 = OpLoad %myType %46 + OpStore %elt %47 + %48 = OpAccessChain %_ptr_Function_float %elt %int_0 + %49 = OpLoad %float %48 + %50 = OpFOrdGreaterThan %bool %49 %float_0 + OpSelectionMerge %51 None + OpBranchConditional %50 %52 %53 + %52 = OpLabel + OpStore %o_color %36 + OpBranch %51 + %53 = OpLabel + OpStore %o_color %37 + OpBranch %51 + %51 = OpLabel + OpReturn + OpFunctionEnd diff --git a/shaders/asm/frag/single-function-private-lut.asm.frag b/shaders/asm/frag/single-function-private-lut.asm.frag new file mode 100644 index 00000000..0d5b29c6 --- /dev/null +++ b/shaders/asm/frag/single-function-private-lut.asm.frag @@ -0,0 +1,86 @@ +; SPIR-V +; Version: 1.3 +; Generator: Khronos SPIR-V Tools Assembler; 0 +; Bound: 54 +; Schema: 0 + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %main "main" %gl_FragCoord %o_color + OpExecutionMode %main OriginUpperLeft + OpSource GLSL 460 + OpName %main "main" + OpName %myType "myType" + OpMemberName %myType 0 "data" + OpName %myData "myData" + OpName %uv "uv" + OpName %gl_FragCoord "gl_FragCoord" + OpName %index "index" + OpName %elt "elt" + OpName %o_color "o_color" + OpDecorate %gl_FragCoord BuiltIn FragCoord + OpDecorate %o_color Location 0 + %void = OpTypeVoid + %11 = OpTypeFunction %void + %float = OpTypeFloat 32 + %myType = OpTypeStruct %float + %uint = OpTypeInt 32 0 + %uint_5 = OpConstant %uint 5 +%_arr_myType_uint_5 = OpTypeArray %myType %uint_5 +%_ptr_Private__arr_myType_uint_5 = OpTypePointer Private %_arr_myType_uint_5 + %myData = OpVariable %_ptr_Private__arr_myType_uint_5 Private + %float_0 = OpConstant %float 0 + %18 = OpConstantComposite %myType %float_0 + %float_1 = OpConstant %float 1 + %20 = OpConstantComposite %myType %float_1 + %21 = OpConstantComposite %_arr_myType_uint_5 %18 %20 %18 %20 %18 + %v2float = OpTypeVector %float 2 +%_ptr_Function_v2float = OpTypePointer Function %v2float + %v4float = OpTypeVector %float 4 +%_ptr_Input_v4float = OpTypePointer Input %v4float +%gl_FragCoord = OpVariable %_ptr_Input_v4float Input + %int = OpTypeInt 32 1 +%_ptr_Function_int = OpTypePointer Function %int + %uint_0 = OpConstant %uint 0 +%_ptr_Function_float = OpTypePointer Function %float + %float_4 = OpConstant %float 4 +%_ptr_Function_myType = OpTypePointer Function %myType +%_ptr_Private_myType = OpTypePointer Private %myType + %int_0 = OpConstant %int 0 + %bool = OpTypeBool +%_ptr_Output_v4float = OpTypePointer Output %v4float + %o_color = OpVariable %_ptr_Output_v4float Output + %36 = OpConstantComposite %v4float %float_0 %float_1 %float_0 %float_1 + %37 = OpConstantComposite %v4float %float_1 %float_0 %float_0 %float_1 + %main = OpFunction %void None %11 + %38 = OpLabel + %uv = OpVariable %_ptr_Function_v2float Function + %index = OpVariable %_ptr_Function_int Function + %elt = OpVariable %_ptr_Function_myType Function + OpStore %myData %21 + %39 = OpLoad %v4float %gl_FragCoord + %40 = OpVectorShuffle %v2float %39 %39 0 1 + OpStore %uv %40 + %41 = OpAccessChain %_ptr_Function_float %uv %uint_0 + %42 = OpLoad %float %41 + %43 = OpFMod %float %42 %float_4 + %44 = OpConvertFToS %int %43 + OpStore %index %44 + %45 = OpLoad %int %index + %46 = OpAccessChain %_ptr_Private_myType %myData %45 + %47 = OpLoad %myType %46 + OpStore %elt %47 + %48 = OpAccessChain %_ptr_Function_float %elt %int_0 + %49 = OpLoad %float %48 + %50 = OpFOrdGreaterThan %bool %49 %float_0 + OpSelectionMerge %51 None + OpBranchConditional %50 %52 %53 + %52 = OpLabel + OpStore %o_color %36 + OpBranch %51 + %53 = OpLabel + OpStore %o_color %37 + OpBranch %51 + %51 = OpLabel + OpReturn + OpFunctionEnd diff --git a/spirv_cross.cpp b/spirv_cross.cpp index 19bac301..676fb277 100644 --- a/spirv_cross.cpp +++ b/spirv_cross.cpp @@ -3054,7 +3054,8 @@ bool Compiler::StaticExpressionAccessHandler::handle(spv::Op op, const uint32_t return true; } -void Compiler::find_function_local_luts(SPIRFunction &entry, const AnalyzeVariableScopeAccessHandler &handler) +void Compiler::find_function_local_luts(SPIRFunction &entry, const AnalyzeVariableScopeAccessHandler &handler, + bool single_function) { auto &cfg = *function_cfgs.find(entry.self)->second; @@ -3066,7 +3067,10 @@ void Compiler::find_function_local_luts(SPIRFunction &entry, const AnalyzeVariab auto &type = expression_type(accessed_var.first); // Only consider function local variables here. - if (var.storage != StorageClassFunction) + // If we only have a single function in our CFG, private storage is also fine, + // since it behaves like a function local variable. + bool allow_lut = var.storage == StorageClassFunction || (single_function && var.storage == StorageClassPrivate); + if (!allow_lut) continue; // We cannot be a phi variable. @@ -3651,13 +3655,14 @@ void Compiler::build_function_control_flow_graphs_and_analyze() handler.function_cfgs[ir.default_entry_point].reset(new CFG(*this, get(ir.default_entry_point))); traverse_all_reachable_opcodes(get(ir.default_entry_point), handler); function_cfgs = move(handler.function_cfgs); + bool single_function = function_cfgs.size() <= 1; for (auto &f : function_cfgs) { auto &func = get(f.first); AnalyzeVariableScopeAccessHandler scope_handler(*this, func); analyze_variable_scope(func, scope_handler); - find_function_local_luts(func, scope_handler); + find_function_local_luts(func, scope_handler, single_function); // Check if we can actually use the loop variables we found in analyze_variable_scope. // To use multiple initializers, we need the same type and qualifiers. diff --git a/spirv_cross.hpp b/spirv_cross.hpp index d587e509..377f48ea 100644 --- a/spirv_cross.hpp +++ b/spirv_cross.hpp @@ -938,7 +938,8 @@ protected: }; void analyze_variable_scope(SPIRFunction &function, AnalyzeVariableScopeAccessHandler &handler); - void find_function_local_luts(SPIRFunction &function, const AnalyzeVariableScopeAccessHandler &handler); + void find_function_local_luts(SPIRFunction &function, const AnalyzeVariableScopeAccessHandler &handler, + bool single_function); void make_constant_null(uint32_t id, uint32_t type); diff --git a/spirv_glsl.cpp b/spirv_glsl.cpp index a8855987..6666933f 100644 --- a/spirv_glsl.cpp +++ b/spirv_glsl.cpp @@ -2137,6 +2137,20 @@ void CompilerGLSL::declare_undefined_values() statement(""); } +bool CompilerGLSL::variable_is_lut(const SPIRVariable &var) const +{ + bool statically_assigned = var.statically_assigned && var.static_expression != 0 && var.remapped_variable; + + if (statically_assigned) + { + auto *constant = maybe_get(var.static_expression); + if (constant && constant->is_used_as_lut) + return true; + } + + return false; +} + void CompilerGLSL::emit_resources() { auto &execution = get_entry_point(); @@ -2347,9 +2361,12 @@ void CompilerGLSL::emit_resources() auto &var = get(global); if (var.storage != StorageClassOutput) { - add_resource_name(var.self); - statement(variable_decl(var), ";"); - emitted = true; + if (!variable_is_lut(var)) + { + add_resource_name(var.self); + statement(variable_decl(var), ";"); + emitted = true; + } } } diff --git a/spirv_glsl.hpp b/spirv_glsl.hpp index caf0ad3b..4c9f5e98 100644 --- a/spirv_glsl.hpp +++ b/spirv_glsl.hpp @@ -638,6 +638,8 @@ protected: uint32_t get_integer_width_for_instruction(const Instruction &instr) const; + bool variable_is_lut(const SPIRVariable &var) const; + private: void init() { diff --git a/spirv_hlsl.cpp b/spirv_hlsl.cpp index a5b6d2dc..4ba264b7 100644 --- a/spirv_hlsl.cpp +++ b/spirv_hlsl.cpp @@ -1327,21 +1327,24 @@ void CompilerHLSL::emit_resources() auto &var = get(global); if (var.storage != StorageClassOutput) { - add_resource_name(var.self); - - const char *storage = nullptr; - switch (var.storage) + if (!variable_is_lut(var)) { - case StorageClassWorkgroup: - storage = "groupshared"; - break; + add_resource_name(var.self); - default: - storage = "static"; - break; + const char *storage = nullptr; + switch (var.storage) + { + case StorageClassWorkgroup: + storage = "groupshared"; + break; + + default: + storage = "static"; + break; + } + statement(storage, " ", variable_decl(var), ";"); + emitted = true; } - statement(storage, " ", variable_decl(var), ";"); - emitted = true; } } diff --git a/spirv_msl.cpp b/spirv_msl.cpp index 0e1e733d..61b45acb 100644 --- a/spirv_msl.cpp +++ b/spirv_msl.cpp @@ -534,7 +534,8 @@ void CompilerMSL::localize_global_variables() auto &var = get(v_id); if (var.storage == StorageClassPrivate || var.storage == StorageClassWorkgroup) { - entry_func.add_local_variable(v_id); + if (!variable_is_lut(var)) + entry_func.add_local_variable(v_id); iter = global_variables.erase(iter); } else