Merge pull request #1299 from KhronosGroup/fix-1298
Add support for forcefully zero-initialized variables.
This commit is contained in:
commit
9b3c5e12be
@ -323,7 +323,7 @@ if (SPIRV_CROSS_STATIC)
|
||||
endif()
|
||||
|
||||
set(spirv-cross-abi-major 0)
|
||||
set(spirv-cross-abi-minor 27)
|
||||
set(spirv-cross-abi-minor 28)
|
||||
set(spirv-cross-abi-patch 0)
|
||||
|
||||
if (SPIRV_CROSS_SHARED)
|
||||
|
5
main.cpp
5
main.cpp
@ -529,6 +529,7 @@ struct CLIArguments
|
||||
bool vulkan_glsl_disable_ext_samplerless_texture_functions = false;
|
||||
bool emit_line_directives = false;
|
||||
bool enable_storage_image_qualifier_deduction = true;
|
||||
bool force_zero_initialized_variables = false;
|
||||
SmallVector<uint32_t> msl_discrete_descriptor_sets;
|
||||
SmallVector<uint32_t> msl_device_argument_buffers;
|
||||
SmallVector<pair<uint32_t, uint32_t>> msl_dynamic_buffers;
|
||||
@ -598,6 +599,7 @@ static void print_help()
|
||||
"\t[--cpp]\n"
|
||||
"\t[--cpp-interface-name <name>]\n"
|
||||
"\t[--disable-storage-image-qualifier-deduction]\n"
|
||||
"\t[--force-zero-initialized-variables]\n"
|
||||
"\t[--glsl-emit-push-constant-as-ubo]\n"
|
||||
"\t[--glsl-emit-ubo-as-plain-uniforms]\n"
|
||||
"\t[--glsl-remap-ext-framebuffer-fetch input-attachment color-location]\n"
|
||||
@ -949,6 +951,7 @@ static string compile_iteration(const CLIArguments &args, std::vector<uint32_t>
|
||||
opts.emit_uniform_buffer_as_plain_uniforms = args.glsl_emit_ubo_as_plain_uniforms;
|
||||
opts.emit_line_directives = args.emit_line_directives;
|
||||
opts.enable_storage_image_qualifier_deduction = args.enable_storage_image_qualifier_deduction;
|
||||
opts.force_zero_initialized_variables = args.force_zero_initialized_variables;
|
||||
compiler->set_common_options(opts);
|
||||
|
||||
for (auto &fetch : args.glsl_ext_framebuffer_fetch)
|
||||
@ -1139,6 +1142,8 @@ static int main_inner(int argc, char *argv[])
|
||||
[&args](CLIParser &) { args.vulkan_glsl_disable_ext_samplerless_texture_functions = true; });
|
||||
cbs.add("--disable-storage-image-qualifier-deduction",
|
||||
[&args](CLIParser &) { args.enable_storage_image_qualifier_deduction = false; });
|
||||
cbs.add("--force-zero-initialized-variables",
|
||||
[&args](CLIParser &) { args.force_zero_initialized_variables = true; });
|
||||
cbs.add("--msl", [&args](CLIParser &) { args.msl = true; });
|
||||
cbs.add("--hlsl", [&args](CLIParser &) { args.hlsl = true; });
|
||||
cbs.add("--hlsl-enable-compat", [&args](CLIParser &) { args.hlsl_compat = true; });
|
||||
|
@ -0,0 +1,45 @@
|
||||
struct Foo
|
||||
{
|
||||
int a;
|
||||
};
|
||||
|
||||
static float4 vColor;
|
||||
static float4 FragColor;
|
||||
|
||||
struct SPIRV_Cross_Input
|
||||
{
|
||||
float4 vColor : TEXCOORD0;
|
||||
};
|
||||
|
||||
struct SPIRV_Cross_Output
|
||||
{
|
||||
float4 FragColor : SV_Target0;
|
||||
};
|
||||
|
||||
static int uninit_int = 0;
|
||||
static int4 uninit_vector = int4(0, 0, 0, 0);
|
||||
static float4x4 uninit_matrix = float4x4(0.0f.xxxx, 0.0f.xxxx, 0.0f.xxxx, 0.0f.xxxx);
|
||||
static Foo uninit_foo = { 0 };
|
||||
|
||||
void frag_main()
|
||||
{
|
||||
int _39 = 0;
|
||||
if (vColor.x > 10.0f)
|
||||
{
|
||||
_39 = 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
_39 = 20;
|
||||
}
|
||||
FragColor = vColor;
|
||||
}
|
||||
|
||||
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
|
||||
{
|
||||
vColor = stage_input.vColor;
|
||||
frag_main();
|
||||
SPIRV_Cross_Output stage_output;
|
||||
stage_output.FragColor = FragColor;
|
||||
return stage_output;
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
static float4 FragColor;
|
||||
static int vA;
|
||||
static int vB;
|
||||
|
||||
struct SPIRV_Cross_Input
|
||||
{
|
||||
nointerpolation int vA : TEXCOORD0;
|
||||
nointerpolation int vB : TEXCOORD1;
|
||||
};
|
||||
|
||||
struct SPIRV_Cross_Output
|
||||
{
|
||||
float4 FragColor : SV_Target0;
|
||||
};
|
||||
|
||||
void frag_main()
|
||||
{
|
||||
FragColor = 0.0f.xxxx;
|
||||
int _10 = 0;
|
||||
int _15 = 0;
|
||||
for (int _16 = 0, _17 = 0; _16 < vA; _17 = _15, _16 += _10)
|
||||
{
|
||||
if ((vA + _16) == 20)
|
||||
{
|
||||
_15 = 50;
|
||||
}
|
||||
else
|
||||
{
|
||||
_15 = ((vB + _16) == 40) ? 60 : _17;
|
||||
}
|
||||
_10 = _15 + 10;
|
||||
FragColor += 1.0f.xxxx;
|
||||
}
|
||||
}
|
||||
|
||||
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
|
||||
{
|
||||
vA = stage_input.vA;
|
||||
vB = stage_input.vB;
|
||||
frag_main();
|
||||
SPIRV_Cross_Output stage_output;
|
||||
stage_output.FragColor = FragColor;
|
||||
return stage_output;
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
struct Foo
|
||||
{
|
||||
int a;
|
||||
};
|
||||
|
||||
static float4 vColor;
|
||||
static float4 FragColor;
|
||||
|
||||
struct SPIRV_Cross_Input
|
||||
{
|
||||
float4 vColor : TEXCOORD0;
|
||||
};
|
||||
|
||||
struct SPIRV_Cross_Output
|
||||
{
|
||||
float4 FragColor : SV_Target0;
|
||||
};
|
||||
|
||||
static int uninit_int = 0;
|
||||
static int4 uninit_vector = int4(0, 0, 0, 0);
|
||||
static float4x4 uninit_matrix = float4x4(0.0f.xxxx, 0.0f.xxxx, 0.0f.xxxx, 0.0f.xxxx);
|
||||
static Foo uninit_foo = { 0 };
|
||||
|
||||
void frag_main()
|
||||
{
|
||||
int uninit_function_int = 0;
|
||||
if (vColor.x > 10.0f)
|
||||
{
|
||||
uninit_function_int = 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
uninit_function_int = 20;
|
||||
}
|
||||
FragColor = vColor;
|
||||
}
|
||||
|
||||
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
|
||||
{
|
||||
vColor = stage_input.vColor;
|
||||
frag_main();
|
||||
SPIRV_Cross_Output stage_output;
|
||||
stage_output.FragColor = FragColor;
|
||||
return stage_output;
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct Foo
|
||||
{
|
||||
int a;
|
||||
};
|
||||
|
||||
constant int uninit_int = {};
|
||||
constant int4 uninit_vector = {};
|
||||
constant float4x4 uninit_matrix = {};
|
||||
constant Foo uninit_foo = {};
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float4 FragColor [[color(0)]];
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
float4 vColor [[user(locn0)]];
|
||||
};
|
||||
|
||||
fragment main0_out main0(main0_in in [[stage_in]])
|
||||
{
|
||||
main0_out out = {};
|
||||
int _39 = {};
|
||||
if (in.vColor.x > 10.0)
|
||||
{
|
||||
_39 = 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
_39 = 20;
|
||||
}
|
||||
out.FragColor = in.vColor;
|
||||
return out;
|
||||
}
|
||||
|
@ -0,0 +1,38 @@
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float4 FragColor [[color(0)]];
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
int vA [[user(locn0)]];
|
||||
int vB [[user(locn1)]];
|
||||
};
|
||||
|
||||
fragment main0_out main0(main0_in in [[stage_in]])
|
||||
{
|
||||
main0_out out = {};
|
||||
out.FragColor = float4(0.0);
|
||||
int _10 = {};
|
||||
int _15 = {};
|
||||
for (int _16 = 0, _17 = 0; _16 < in.vA; _17 = _15, _16 += _10)
|
||||
{
|
||||
if ((in.vA + _16) == 20)
|
||||
{
|
||||
_15 = 50;
|
||||
}
|
||||
else
|
||||
{
|
||||
_15 = ((in.vB + _16) == 40) ? 60 : _17;
|
||||
}
|
||||
_10 = _15 + 10;
|
||||
out.FragColor += float4(1.0);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
@ -0,0 +1,40 @@
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct Foo
|
||||
{
|
||||
int a;
|
||||
};
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float4 FragColor [[color(0)]];
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
float4 vColor [[user(locn0)]];
|
||||
};
|
||||
|
||||
fragment main0_out main0(main0_in in [[stage_in]])
|
||||
{
|
||||
main0_out out = {};
|
||||
int uninit_function_int = {};
|
||||
int uninit_int = {};
|
||||
int4 uninit_vector = {};
|
||||
float4x4 uninit_matrix = {};
|
||||
Foo uninit_foo = {};
|
||||
if (in.vColor.x > 10.0)
|
||||
{
|
||||
uninit_function_int = 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
uninit_function_int = 20;
|
||||
}
|
||||
out.FragColor = in.vColor;
|
||||
return out;
|
||||
}
|
||||
|
@ -0,0 +1,29 @@
|
||||
#version 450
|
||||
|
||||
struct Foo
|
||||
{
|
||||
int a;
|
||||
};
|
||||
|
||||
layout(location = 0) in vec4 vColor;
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
|
||||
int uninit_int = 0;
|
||||
ivec4 uninit_vector = ivec4(0);
|
||||
mat4 uninit_matrix = mat4(vec4(0.0), vec4(0.0), vec4(0.0), vec4(0.0));
|
||||
Foo uninit_foo = Foo(0);
|
||||
|
||||
void main()
|
||||
{
|
||||
int _39 = 0;
|
||||
if (vColor.x > 10.0)
|
||||
{
|
||||
_39 = 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
_39 = 20;
|
||||
}
|
||||
FragColor = vColor;
|
||||
}
|
||||
|
@ -0,0 +1,28 @@
|
||||
#version 310 es
|
||||
precision mediump float;
|
||||
precision highp int;
|
||||
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
layout(location = 0) flat in mediump int vA;
|
||||
layout(location = 1) flat in mediump int vB;
|
||||
|
||||
void main()
|
||||
{
|
||||
FragColor = vec4(0.0);
|
||||
mediump int _10 = 0;
|
||||
mediump int _15 = 0;
|
||||
for (mediump int _16 = 0, _17 = 0; _16 < vA; _17 = _15, _16 += _10)
|
||||
{
|
||||
if ((vA + _16) == 20)
|
||||
{
|
||||
_15 = 50;
|
||||
}
|
||||
else
|
||||
{
|
||||
_15 = ((vB + _16) == 40) ? 60 : _17;
|
||||
}
|
||||
_10 = _15 + 10;
|
||||
FragColor += vec4(1.0);
|
||||
}
|
||||
}
|
||||
|
28
reference/shaders-no-opt/frag/variables.zero-initialize.frag
Normal file
28
reference/shaders-no-opt/frag/variables.zero-initialize.frag
Normal file
@ -0,0 +1,28 @@
|
||||
#version 450
|
||||
|
||||
struct Foo
|
||||
{
|
||||
int a;
|
||||
};
|
||||
|
||||
layout(location = 0) in vec4 vColor;
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
int uninit_int = 0;
|
||||
ivec4 uninit_vector = ivec4(0);
|
||||
mat4 uninit_matrix = mat4(vec4(0.0), vec4(0.0), vec4(0.0), vec4(0.0));
|
||||
Foo uninit_foo = Foo(0);
|
||||
|
||||
void main()
|
||||
{
|
||||
int uninit_function_int = 0;
|
||||
if (vColor.x > 10.0)
|
||||
{
|
||||
uninit_function_int = 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
uninit_function_int = 20;
|
||||
}
|
||||
FragColor = vColor;
|
||||
}
|
||||
|
69
shaders-hlsl-no-opt/asm/frag/phi.zero-initialize.asm.frag
Normal file
69
shaders-hlsl-no-opt/asm/frag/phi.zero-initialize.asm.frag
Normal file
@ -0,0 +1,69 @@
|
||||
; SPIR-V
|
||||
; Version: 1.0
|
||||
; Generator: Khronos Glslang Reference Front End; 8
|
||||
; Bound: 40
|
||||
; Schema: 0
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main" %vColor %FragColor
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
OpSource GLSL 450
|
||||
OpName %main "main"
|
||||
OpName %vColor "vColor"
|
||||
OpName %uninit_function_int "uninit_function_int"
|
||||
OpName %FragColor "FragColor"
|
||||
OpName %uninit_int "uninit_int"
|
||||
OpName %uninit_vector "uninit_vector"
|
||||
OpName %uninit_matrix "uninit_matrix"
|
||||
OpName %Foo "Foo"
|
||||
OpMemberName %Foo 0 "a"
|
||||
OpName %uninit_foo "uninit_foo"
|
||||
OpDecorate %vColor Location 0
|
||||
OpDecorate %FragColor Location 0
|
||||
%void = OpTypeVoid
|
||||
%3 = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%v4float = OpTypeVector %float 4
|
||||
%_ptr_Input_v4float = OpTypePointer Input %v4float
|
||||
%vColor = OpVariable %_ptr_Input_v4float Input
|
||||
%uint = OpTypeInt 32 0
|
||||
%uint_0 = OpConstant %uint 0
|
||||
%_ptr_Input_float = OpTypePointer Input %float
|
||||
%float_10 = OpConstant %float 10
|
||||
%bool = OpTypeBool
|
||||
%int = OpTypeInt 32 1
|
||||
%_ptr_Function_int = OpTypePointer Function %int
|
||||
%int_10 = OpConstant %int 10
|
||||
%int_20 = OpConstant %int 20
|
||||
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
||||
%FragColor = OpVariable %_ptr_Output_v4float Output
|
||||
%_ptr_Private_int = OpTypePointer Private %int
|
||||
%uninit_int = OpUndef %int
|
||||
%v4int = OpTypeVector %int 4
|
||||
%_ptr_Private_v4int = OpTypePointer Private %v4int
|
||||
%uninit_vector = OpUndef %v4int
|
||||
%mat4v4float = OpTypeMatrix %v4float 4
|
||||
%_ptr_Private_mat4v4float = OpTypePointer Private %mat4v4float
|
||||
%uninit_matrix = OpUndef %mat4v4float
|
||||
%Foo = OpTypeStruct %int
|
||||
%_ptr_Private_Foo = OpTypePointer Private %Foo
|
||||
%uninit_foo = OpUndef %Foo
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
%uninit_function_int = OpVariable %_ptr_Function_int Function
|
||||
%13 = OpAccessChain %_ptr_Input_float %vColor %uint_0
|
||||
%14 = OpLoad %float %13
|
||||
%17 = OpFOrdGreaterThan %bool %14 %float_10
|
||||
OpSelectionMerge %19 None
|
||||
OpBranchConditional %17 %18 %24
|
||||
%18 = OpLabel
|
||||
OpBranch %19
|
||||
%24 = OpLabel
|
||||
OpBranch %19
|
||||
%19 = OpLabel
|
||||
%27 = OpPhi %int %int_10 %18 %int_20 %24
|
||||
%28 = OpLoad %v4float %vColor
|
||||
OpStore %FragColor %28
|
||||
OpReturn
|
||||
OpFunctionEnd
|
93
shaders-hlsl-no-opt/asm/temporary.zero-initialize.asm.frag
Normal file
93
shaders-hlsl-no-opt/asm/temporary.zero-initialize.asm.frag
Normal file
@ -0,0 +1,93 @@
|
||||
; SPIR-V
|
||||
; Version: 1.0
|
||||
; Generator: Khronos Glslang Reference Front End; 8
|
||||
; Bound: 65
|
||||
; Schema: 0
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main" %FragColor %vA %vB
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
OpSource ESSL 310
|
||||
OpName %main "main"
|
||||
OpName %FragColor "FragColor"
|
||||
OpName %vA "vA"
|
||||
OpName %vB "vB"
|
||||
OpDecorate %FragColor RelaxedPrecision
|
||||
OpDecorate %FragColor Location 0
|
||||
OpDecorate %vA RelaxedPrecision
|
||||
OpDecorate %vA Flat
|
||||
OpDecorate %vA Location 0
|
||||
OpDecorate %25 RelaxedPrecision
|
||||
OpDecorate %30 RelaxedPrecision
|
||||
OpDecorate %vB RelaxedPrecision
|
||||
OpDecorate %vB Flat
|
||||
OpDecorate %vB Location 1
|
||||
OpDecorate %38 RelaxedPrecision
|
||||
OpDecorate %40 RelaxedPrecision
|
||||
OpDecorate %49 RelaxedPrecision
|
||||
OpDecorate %51 RelaxedPrecision
|
||||
OpDecorate %53 RelaxedPrecision
|
||||
OpDecorate %56 RelaxedPrecision
|
||||
OpDecorate %64 RelaxedPrecision
|
||||
OpDecorate %58 RelaxedPrecision
|
||||
OpDecorate %57 RelaxedPrecision
|
||||
OpDecorate %60 RelaxedPrecision
|
||||
%void = OpTypeVoid
|
||||
%3 = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%v4float = OpTypeVector %float 4
|
||||
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
||||
%FragColor = OpVariable %_ptr_Output_v4float Output
|
||||
%float_0 = OpConstant %float 0
|
||||
%11 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
|
||||
%int = OpTypeInt 32 1
|
||||
%int_0 = OpConstant %int 0
|
||||
%_ptr_Input_int = OpTypePointer Input %int
|
||||
%vA = OpVariable %_ptr_Input_int Input
|
||||
%bool = OpTypeBool
|
||||
%int_20 = OpConstant %int 20
|
||||
%int_50 = OpConstant %int 50
|
||||
%vB = OpVariable %_ptr_Input_int Input
|
||||
%int_40 = OpConstant %int 40
|
||||
%int_60 = OpConstant %int 60
|
||||
%int_10 = OpConstant %int 10
|
||||
%float_1 = OpConstant %float 1
|
||||
%63 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
OpStore %FragColor %11
|
||||
OpBranch %17
|
||||
%17 = OpLabel
|
||||
%60 = OpPhi %int %int_0 %5 %58 %20
|
||||
%57 = OpPhi %int %int_0 %5 %56 %20
|
||||
%25 = OpLoad %int %vA
|
||||
%27 = OpSLessThan %bool %57 %25
|
||||
OpLoopMerge %19 %20 None
|
||||
OpBranchConditional %27 %18 %19
|
||||
%18 = OpLabel
|
||||
%30 = OpIAdd %int %25 %57
|
||||
%32 = OpIEqual %bool %30 %int_20
|
||||
OpSelectionMerge %34 None
|
||||
OpBranchConditional %32 %33 %36
|
||||
%33 = OpLabel
|
||||
OpBranch %34
|
||||
%36 = OpLabel
|
||||
%38 = OpLoad %int %vB
|
||||
%40 = OpIAdd %int %38 %57
|
||||
%42 = OpIEqual %bool %40 %int_40
|
||||
%64 = OpSelect %int %42 %int_60 %60
|
||||
OpBranch %34
|
||||
%34 = OpLabel
|
||||
%58 = OpPhi %int %int_50 %33 %64 %36
|
||||
%49 = OpIAdd %int %58 %int_10
|
||||
%51 = OpLoad %v4float %FragColor
|
||||
%53 = OpFAdd %v4float %51 %63
|
||||
OpStore %FragColor %53
|
||||
OpBranch %20
|
||||
%20 = OpLabel
|
||||
%56 = OpIAdd %int %57 %49
|
||||
OpBranch %17
|
||||
%19 = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
21
shaders-hlsl-no-opt/frag/variables.zero-initialize.frag
Normal file
21
shaders-hlsl-no-opt/frag/variables.zero-initialize.frag
Normal file
@ -0,0 +1,21 @@
|
||||
#version 450
|
||||
|
||||
layout(location = 0) in vec4 vColor;
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
|
||||
int uninit_int;
|
||||
ivec4 uninit_vector;
|
||||
mat4 uninit_matrix;
|
||||
|
||||
struct Foo { int a; };
|
||||
Foo uninit_foo;
|
||||
|
||||
void main()
|
||||
{
|
||||
int uninit_function_int;
|
||||
if (vColor.x > 10.0)
|
||||
uninit_function_int = 10;
|
||||
else
|
||||
uninit_function_int = 20;
|
||||
FragColor = vColor;
|
||||
}
|
69
shaders-msl-no-opt/asm/frag/phi.zero-initialize.asm.frag
Normal file
69
shaders-msl-no-opt/asm/frag/phi.zero-initialize.asm.frag
Normal file
@ -0,0 +1,69 @@
|
||||
; SPIR-V
|
||||
; Version: 1.0
|
||||
; Generator: Khronos Glslang Reference Front End; 8
|
||||
; Bound: 40
|
||||
; Schema: 0
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main" %vColor %FragColor
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
OpSource GLSL 450
|
||||
OpName %main "main"
|
||||
OpName %vColor "vColor"
|
||||
OpName %uninit_function_int "uninit_function_int"
|
||||
OpName %FragColor "FragColor"
|
||||
OpName %uninit_int "uninit_int"
|
||||
OpName %uninit_vector "uninit_vector"
|
||||
OpName %uninit_matrix "uninit_matrix"
|
||||
OpName %Foo "Foo"
|
||||
OpMemberName %Foo 0 "a"
|
||||
OpName %uninit_foo "uninit_foo"
|
||||
OpDecorate %vColor Location 0
|
||||
OpDecorate %FragColor Location 0
|
||||
%void = OpTypeVoid
|
||||
%3 = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%v4float = OpTypeVector %float 4
|
||||
%_ptr_Input_v4float = OpTypePointer Input %v4float
|
||||
%vColor = OpVariable %_ptr_Input_v4float Input
|
||||
%uint = OpTypeInt 32 0
|
||||
%uint_0 = OpConstant %uint 0
|
||||
%_ptr_Input_float = OpTypePointer Input %float
|
||||
%float_10 = OpConstant %float 10
|
||||
%bool = OpTypeBool
|
||||
%int = OpTypeInt 32 1
|
||||
%_ptr_Function_int = OpTypePointer Function %int
|
||||
%int_10 = OpConstant %int 10
|
||||
%int_20 = OpConstant %int 20
|
||||
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
||||
%FragColor = OpVariable %_ptr_Output_v4float Output
|
||||
%_ptr_Private_int = OpTypePointer Private %int
|
||||
%uninit_int = OpUndef %int
|
||||
%v4int = OpTypeVector %int 4
|
||||
%_ptr_Private_v4int = OpTypePointer Private %v4int
|
||||
%uninit_vector = OpUndef %v4int
|
||||
%mat4v4float = OpTypeMatrix %v4float 4
|
||||
%_ptr_Private_mat4v4float = OpTypePointer Private %mat4v4float
|
||||
%uninit_matrix = OpUndef %mat4v4float
|
||||
%Foo = OpTypeStruct %int
|
||||
%_ptr_Private_Foo = OpTypePointer Private %Foo
|
||||
%uninit_foo = OpUndef %Foo
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
%uninit_function_int = OpVariable %_ptr_Function_int Function
|
||||
%13 = OpAccessChain %_ptr_Input_float %vColor %uint_0
|
||||
%14 = OpLoad %float %13
|
||||
%17 = OpFOrdGreaterThan %bool %14 %float_10
|
||||
OpSelectionMerge %19 None
|
||||
OpBranchConditional %17 %18 %24
|
||||
%18 = OpLabel
|
||||
OpBranch %19
|
||||
%24 = OpLabel
|
||||
OpBranch %19
|
||||
%19 = OpLabel
|
||||
%27 = OpPhi %int %int_10 %18 %int_20 %24
|
||||
%28 = OpLoad %v4float %vColor
|
||||
OpStore %FragColor %28
|
||||
OpReturn
|
||||
OpFunctionEnd
|
93
shaders-msl-no-opt/asm/temporary.zero-initialize.asm.frag
Normal file
93
shaders-msl-no-opt/asm/temporary.zero-initialize.asm.frag
Normal file
@ -0,0 +1,93 @@
|
||||
; SPIR-V
|
||||
; Version: 1.0
|
||||
; Generator: Khronos Glslang Reference Front End; 8
|
||||
; Bound: 65
|
||||
; Schema: 0
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main" %FragColor %vA %vB
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
OpSource ESSL 310
|
||||
OpName %main "main"
|
||||
OpName %FragColor "FragColor"
|
||||
OpName %vA "vA"
|
||||
OpName %vB "vB"
|
||||
OpDecorate %FragColor RelaxedPrecision
|
||||
OpDecorate %FragColor Location 0
|
||||
OpDecorate %vA RelaxedPrecision
|
||||
OpDecorate %vA Flat
|
||||
OpDecorate %vA Location 0
|
||||
OpDecorate %25 RelaxedPrecision
|
||||
OpDecorate %30 RelaxedPrecision
|
||||
OpDecorate %vB RelaxedPrecision
|
||||
OpDecorate %vB Flat
|
||||
OpDecorate %vB Location 1
|
||||
OpDecorate %38 RelaxedPrecision
|
||||
OpDecorate %40 RelaxedPrecision
|
||||
OpDecorate %49 RelaxedPrecision
|
||||
OpDecorate %51 RelaxedPrecision
|
||||
OpDecorate %53 RelaxedPrecision
|
||||
OpDecorate %56 RelaxedPrecision
|
||||
OpDecorate %64 RelaxedPrecision
|
||||
OpDecorate %58 RelaxedPrecision
|
||||
OpDecorate %57 RelaxedPrecision
|
||||
OpDecorate %60 RelaxedPrecision
|
||||
%void = OpTypeVoid
|
||||
%3 = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%v4float = OpTypeVector %float 4
|
||||
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
||||
%FragColor = OpVariable %_ptr_Output_v4float Output
|
||||
%float_0 = OpConstant %float 0
|
||||
%11 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
|
||||
%int = OpTypeInt 32 1
|
||||
%int_0 = OpConstant %int 0
|
||||
%_ptr_Input_int = OpTypePointer Input %int
|
||||
%vA = OpVariable %_ptr_Input_int Input
|
||||
%bool = OpTypeBool
|
||||
%int_20 = OpConstant %int 20
|
||||
%int_50 = OpConstant %int 50
|
||||
%vB = OpVariable %_ptr_Input_int Input
|
||||
%int_40 = OpConstant %int 40
|
||||
%int_60 = OpConstant %int 60
|
||||
%int_10 = OpConstant %int 10
|
||||
%float_1 = OpConstant %float 1
|
||||
%63 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
OpStore %FragColor %11
|
||||
OpBranch %17
|
||||
%17 = OpLabel
|
||||
%60 = OpPhi %int %int_0 %5 %58 %20
|
||||
%57 = OpPhi %int %int_0 %5 %56 %20
|
||||
%25 = OpLoad %int %vA
|
||||
%27 = OpSLessThan %bool %57 %25
|
||||
OpLoopMerge %19 %20 None
|
||||
OpBranchConditional %27 %18 %19
|
||||
%18 = OpLabel
|
||||
%30 = OpIAdd %int %25 %57
|
||||
%32 = OpIEqual %bool %30 %int_20
|
||||
OpSelectionMerge %34 None
|
||||
OpBranchConditional %32 %33 %36
|
||||
%33 = OpLabel
|
||||
OpBranch %34
|
||||
%36 = OpLabel
|
||||
%38 = OpLoad %int %vB
|
||||
%40 = OpIAdd %int %38 %57
|
||||
%42 = OpIEqual %bool %40 %int_40
|
||||
%64 = OpSelect %int %42 %int_60 %60
|
||||
OpBranch %34
|
||||
%34 = OpLabel
|
||||
%58 = OpPhi %int %int_50 %33 %64 %36
|
||||
%49 = OpIAdd %int %58 %int_10
|
||||
%51 = OpLoad %v4float %FragColor
|
||||
%53 = OpFAdd %v4float %51 %63
|
||||
OpStore %FragColor %53
|
||||
OpBranch %20
|
||||
%20 = OpLabel
|
||||
%56 = OpIAdd %int %57 %49
|
||||
OpBranch %17
|
||||
%19 = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
21
shaders-msl-no-opt/frag/variables.zero-initialize.frag
Normal file
21
shaders-msl-no-opt/frag/variables.zero-initialize.frag
Normal file
@ -0,0 +1,21 @@
|
||||
#version 450
|
||||
|
||||
layout(location = 0) in vec4 vColor;
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
|
||||
int uninit_int;
|
||||
ivec4 uninit_vector;
|
||||
mat4 uninit_matrix;
|
||||
|
||||
struct Foo { int a; };
|
||||
Foo uninit_foo;
|
||||
|
||||
void main()
|
||||
{
|
||||
int uninit_function_int;
|
||||
if (vColor.x > 10.0)
|
||||
uninit_function_int = 10;
|
||||
else
|
||||
uninit_function_int = 20;
|
||||
FragColor = vColor;
|
||||
}
|
69
shaders-no-opt/asm/frag/phi.zero-initialize.asm.frag
Normal file
69
shaders-no-opt/asm/frag/phi.zero-initialize.asm.frag
Normal file
@ -0,0 +1,69 @@
|
||||
; SPIR-V
|
||||
; Version: 1.0
|
||||
; Generator: Khronos Glslang Reference Front End; 8
|
||||
; Bound: 40
|
||||
; Schema: 0
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main" %vColor %FragColor
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
OpSource GLSL 450
|
||||
OpName %main "main"
|
||||
OpName %vColor "vColor"
|
||||
OpName %uninit_function_int "uninit_function_int"
|
||||
OpName %FragColor "FragColor"
|
||||
OpName %uninit_int "uninit_int"
|
||||
OpName %uninit_vector "uninit_vector"
|
||||
OpName %uninit_matrix "uninit_matrix"
|
||||
OpName %Foo "Foo"
|
||||
OpMemberName %Foo 0 "a"
|
||||
OpName %uninit_foo "uninit_foo"
|
||||
OpDecorate %vColor Location 0
|
||||
OpDecorate %FragColor Location 0
|
||||
%void = OpTypeVoid
|
||||
%3 = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%v4float = OpTypeVector %float 4
|
||||
%_ptr_Input_v4float = OpTypePointer Input %v4float
|
||||
%vColor = OpVariable %_ptr_Input_v4float Input
|
||||
%uint = OpTypeInt 32 0
|
||||
%uint_0 = OpConstant %uint 0
|
||||
%_ptr_Input_float = OpTypePointer Input %float
|
||||
%float_10 = OpConstant %float 10
|
||||
%bool = OpTypeBool
|
||||
%int = OpTypeInt 32 1
|
||||
%_ptr_Function_int = OpTypePointer Function %int
|
||||
%int_10 = OpConstant %int 10
|
||||
%int_20 = OpConstant %int 20
|
||||
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
||||
%FragColor = OpVariable %_ptr_Output_v4float Output
|
||||
%_ptr_Private_int = OpTypePointer Private %int
|
||||
%uninit_int = OpUndef %int
|
||||
%v4int = OpTypeVector %int 4
|
||||
%_ptr_Private_v4int = OpTypePointer Private %v4int
|
||||
%uninit_vector = OpUndef %v4int
|
||||
%mat4v4float = OpTypeMatrix %v4float 4
|
||||
%_ptr_Private_mat4v4float = OpTypePointer Private %mat4v4float
|
||||
%uninit_matrix = OpUndef %mat4v4float
|
||||
%Foo = OpTypeStruct %int
|
||||
%_ptr_Private_Foo = OpTypePointer Private %Foo
|
||||
%uninit_foo = OpUndef %Foo
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
%uninit_function_int = OpVariable %_ptr_Function_int Function
|
||||
%13 = OpAccessChain %_ptr_Input_float %vColor %uint_0
|
||||
%14 = OpLoad %float %13
|
||||
%17 = OpFOrdGreaterThan %bool %14 %float_10
|
||||
OpSelectionMerge %19 None
|
||||
OpBranchConditional %17 %18 %24
|
||||
%18 = OpLabel
|
||||
OpBranch %19
|
||||
%24 = OpLabel
|
||||
OpBranch %19
|
||||
%19 = OpLabel
|
||||
%27 = OpPhi %int %int_10 %18 %int_20 %24
|
||||
%28 = OpLoad %v4float %vColor
|
||||
OpStore %FragColor %28
|
||||
OpReturn
|
||||
OpFunctionEnd
|
93
shaders-no-opt/asm/temporary.zero-initialize.asm.frag
Normal file
93
shaders-no-opt/asm/temporary.zero-initialize.asm.frag
Normal file
@ -0,0 +1,93 @@
|
||||
; SPIR-V
|
||||
; Version: 1.0
|
||||
; Generator: Khronos Glslang Reference Front End; 8
|
||||
; Bound: 65
|
||||
; Schema: 0
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main" %FragColor %vA %vB
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
OpSource ESSL 310
|
||||
OpName %main "main"
|
||||
OpName %FragColor "FragColor"
|
||||
OpName %vA "vA"
|
||||
OpName %vB "vB"
|
||||
OpDecorate %FragColor RelaxedPrecision
|
||||
OpDecorate %FragColor Location 0
|
||||
OpDecorate %vA RelaxedPrecision
|
||||
OpDecorate %vA Flat
|
||||
OpDecorate %vA Location 0
|
||||
OpDecorate %25 RelaxedPrecision
|
||||
OpDecorate %30 RelaxedPrecision
|
||||
OpDecorate %vB RelaxedPrecision
|
||||
OpDecorate %vB Flat
|
||||
OpDecorate %vB Location 1
|
||||
OpDecorate %38 RelaxedPrecision
|
||||
OpDecorate %40 RelaxedPrecision
|
||||
OpDecorate %49 RelaxedPrecision
|
||||
OpDecorate %51 RelaxedPrecision
|
||||
OpDecorate %53 RelaxedPrecision
|
||||
OpDecorate %56 RelaxedPrecision
|
||||
OpDecorate %64 RelaxedPrecision
|
||||
OpDecorate %58 RelaxedPrecision
|
||||
OpDecorate %57 RelaxedPrecision
|
||||
OpDecorate %60 RelaxedPrecision
|
||||
%void = OpTypeVoid
|
||||
%3 = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%v4float = OpTypeVector %float 4
|
||||
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
||||
%FragColor = OpVariable %_ptr_Output_v4float Output
|
||||
%float_0 = OpConstant %float 0
|
||||
%11 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
|
||||
%int = OpTypeInt 32 1
|
||||
%int_0 = OpConstant %int 0
|
||||
%_ptr_Input_int = OpTypePointer Input %int
|
||||
%vA = OpVariable %_ptr_Input_int Input
|
||||
%bool = OpTypeBool
|
||||
%int_20 = OpConstant %int 20
|
||||
%int_50 = OpConstant %int 50
|
||||
%vB = OpVariable %_ptr_Input_int Input
|
||||
%int_40 = OpConstant %int 40
|
||||
%int_60 = OpConstant %int 60
|
||||
%int_10 = OpConstant %int 10
|
||||
%float_1 = OpConstant %float 1
|
||||
%63 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
OpStore %FragColor %11
|
||||
OpBranch %17
|
||||
%17 = OpLabel
|
||||
%60 = OpPhi %int %int_0 %5 %58 %20
|
||||
%57 = OpPhi %int %int_0 %5 %56 %20
|
||||
%25 = OpLoad %int %vA
|
||||
%27 = OpSLessThan %bool %57 %25
|
||||
OpLoopMerge %19 %20 None
|
||||
OpBranchConditional %27 %18 %19
|
||||
%18 = OpLabel
|
||||
%30 = OpIAdd %int %25 %57
|
||||
%32 = OpIEqual %bool %30 %int_20
|
||||
OpSelectionMerge %34 None
|
||||
OpBranchConditional %32 %33 %36
|
||||
%33 = OpLabel
|
||||
OpBranch %34
|
||||
%36 = OpLabel
|
||||
%38 = OpLoad %int %vB
|
||||
%40 = OpIAdd %int %38 %57
|
||||
%42 = OpIEqual %bool %40 %int_40
|
||||
%64 = OpSelect %int %42 %int_60 %60
|
||||
OpBranch %34
|
||||
%34 = OpLabel
|
||||
%58 = OpPhi %int %int_50 %33 %64 %36
|
||||
%49 = OpIAdd %int %58 %int_10
|
||||
%51 = OpLoad %v4float %FragColor
|
||||
%53 = OpFAdd %v4float %51 %63
|
||||
OpStore %FragColor %53
|
||||
OpBranch %20
|
||||
%20 = OpLabel
|
||||
%56 = OpIAdd %int %57 %49
|
||||
OpBranch %17
|
||||
%19 = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
21
shaders-no-opt/frag/variables.zero-initialize.frag
Normal file
21
shaders-no-opt/frag/variables.zero-initialize.frag
Normal file
@ -0,0 +1,21 @@
|
||||
#version 450
|
||||
|
||||
layout(location = 0) in vec4 vColor;
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
|
||||
int uninit_int;
|
||||
ivec4 uninit_vector;
|
||||
mat4 uninit_matrix;
|
||||
|
||||
struct Foo { int a; };
|
||||
Foo uninit_foo;
|
||||
|
||||
void main()
|
||||
{
|
||||
int uninit_function_int;
|
||||
if (vColor.x > 10.0)
|
||||
uninit_function_int = 10;
|
||||
else
|
||||
uninit_function_int = 20;
|
||||
FragColor = vColor;
|
||||
}
|
@ -423,6 +423,9 @@ spvc_result spvc_compiler_options_set_uint(spvc_compiler_options options, spvc_c
|
||||
case SPVC_COMPILER_OPTION_ENABLE_STORAGE_IMAGE_QUALIFIER_DEDUCTION:
|
||||
options->glsl.enable_storage_image_qualifier_deduction = value != 0;
|
||||
break;
|
||||
case SPVC_COMPILER_OPTION_FORCE_ZERO_INITIALIZED_VARIABLES:
|
||||
options->glsl.force_zero_initialized_variables = value != 0;
|
||||
break;
|
||||
|
||||
case SPVC_COMPILER_OPTION_GLSL_SUPPORT_NONZERO_BASE_INSTANCE:
|
||||
options->glsl.vertex.support_nonzero_base_instance = value != 0;
|
||||
|
@ -33,7 +33,7 @@ extern "C" {
|
||||
/* Bumped if ABI or API breaks backwards compatibility. */
|
||||
#define SPVC_C_API_VERSION_MAJOR 0
|
||||
/* Bumped if APIs or enumerations are added in a backwards compatible way. */
|
||||
#define SPVC_C_API_VERSION_MINOR 27
|
||||
#define SPVC_C_API_VERSION_MINOR 28
|
||||
/* Bumped if internal implementation details change. */
|
||||
#define SPVC_C_API_VERSION_PATCH 0
|
||||
|
||||
@ -578,6 +578,8 @@ typedef enum spvc_compiler_option
|
||||
|
||||
SPVC_COMPILER_OPTION_HLSL_FORCE_STORAGE_BUFFER_AS_UAV = 53 | SPVC_COMPILER_OPTION_HLSL_BIT,
|
||||
|
||||
SPVC_COMPILER_OPTION_FORCE_ZERO_INITIALIZED_VARIABLES = 54 | SPVC_COMPILER_OPTION_COMMON_BIT,
|
||||
|
||||
SPVC_COMPILER_OPTION_INT_MAX = 0x7fffffff
|
||||
} spvc_compiler_option;
|
||||
|
||||
|
@ -854,4 +854,57 @@ ParsedIR::LoopLock &ParsedIR::LoopLock::operator=(LoopLock &&other) SPIRV_CROSS_
|
||||
return *this;
|
||||
}
|
||||
|
||||
void ParsedIR::make_constant_null(uint32_t id, uint32_t type, bool add_to_typed_id_set)
|
||||
{
|
||||
auto &constant_type = get<SPIRType>(type);
|
||||
|
||||
if (constant_type.pointer)
|
||||
{
|
||||
if (add_to_typed_id_set)
|
||||
add_typed_id(TypeConstant, id);
|
||||
auto &constant = variant_set<SPIRConstant>(ids[id], type);
|
||||
constant.self = id;
|
||||
constant.make_null(constant_type);
|
||||
}
|
||||
else if (!constant_type.array.empty())
|
||||
{
|
||||
assert(constant_type.parent_type);
|
||||
uint32_t parent_id = increase_bound_by(1);
|
||||
make_constant_null(parent_id, constant_type.parent_type, add_to_typed_id_set);
|
||||
|
||||
if (!constant_type.array_size_literal.back())
|
||||
SPIRV_CROSS_THROW("Array size of OpConstantNull must be a literal.");
|
||||
|
||||
SmallVector<uint32_t> elements(constant_type.array.back());
|
||||
for (uint32_t i = 0; i < constant_type.array.back(); i++)
|
||||
elements[i] = parent_id;
|
||||
|
||||
if (add_to_typed_id_set)
|
||||
add_typed_id(TypeConstant, id);
|
||||
variant_set<SPIRConstant>(ids[id], type, elements.data(), uint32_t(elements.size()), false).self = id;
|
||||
}
|
||||
else if (!constant_type.member_types.empty())
|
||||
{
|
||||
uint32_t member_ids = increase_bound_by(uint32_t(constant_type.member_types.size()));
|
||||
SmallVector<uint32_t> elements(constant_type.member_types.size());
|
||||
for (uint32_t i = 0; i < constant_type.member_types.size(); i++)
|
||||
{
|
||||
make_constant_null(member_ids + i, constant_type.member_types[i], add_to_typed_id_set);
|
||||
elements[i] = member_ids + i;
|
||||
}
|
||||
|
||||
if (add_to_typed_id_set)
|
||||
add_typed_id(TypeConstant, id);
|
||||
variant_set<SPIRConstant>(ids[id], type, elements.data(), uint32_t(elements.size()), false).self = id;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (add_to_typed_id_set)
|
||||
add_typed_id(TypeConstant, id);
|
||||
auto &constant = variant_set<SPIRConstant>(ids[id], type);
|
||||
constant.self = id;
|
||||
constant.make_null(constant_type);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace SPIRV_CROSS_NAMESPACE
|
||||
|
@ -206,6 +206,8 @@ public:
|
||||
return empty_string;
|
||||
}
|
||||
|
||||
void make_constant_null(uint32_t id, uint32_t type, bool add_to_typed_id_set);
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
T &get(uint32_t id)
|
||||
|
@ -2806,7 +2806,12 @@ void CompilerGLSL::declare_undefined_values()
|
||||
{
|
||||
bool emitted = false;
|
||||
ir.for_each_typed_id<SPIRUndef>([&](uint32_t, const SPIRUndef &undef) {
|
||||
statement(variable_decl(this->get<SPIRType>(undef.basetype), to_name(undef.self), undef.self), ";");
|
||||
string initializer;
|
||||
if (options.force_zero_initialized_variables && type_can_zero_initialize(this->get<SPIRType>(undef.basetype)))
|
||||
initializer = join(" = ", to_zero_initialized_expression(undef.basetype));
|
||||
|
||||
statement(variable_decl(this->get<SPIRType>(undef.basetype), to_name(undef.self), undef.self), initializer,
|
||||
";");
|
||||
emitted = true;
|
||||
});
|
||||
|
||||
@ -3097,7 +3102,15 @@ void CompilerGLSL::emit_resources()
|
||||
if (!variable_is_lut(var))
|
||||
{
|
||||
add_resource_name(var.self);
|
||||
statement(variable_decl(var), ";");
|
||||
|
||||
string initializer;
|
||||
if (options.force_zero_initialized_variables && var.storage == StorageClassPrivate &&
|
||||
!var.initializer && !var.static_expression && type_can_zero_initialize(get_variable_data_type(var)))
|
||||
{
|
||||
initializer = join(" = ", to_zero_initialized_expression(get_variable_data_type_id(var)));
|
||||
}
|
||||
|
||||
statement(variable_decl(var), initializer, ";");
|
||||
emitted = true;
|
||||
}
|
||||
}
|
||||
@ -4415,7 +4428,12 @@ void CompilerGLSL::emit_uninitialized_temporary(uint32_t result_type, uint32_t r
|
||||
|
||||
// The result_id has not been made into an expression yet, so use flags interface.
|
||||
add_local_variable_name(result_id);
|
||||
statement(flags_to_qualifiers_glsl(type, flags), variable_decl(type, to_name(result_id)), ";");
|
||||
|
||||
string initializer;
|
||||
if (options.force_zero_initialized_variables && type_can_zero_initialize(type))
|
||||
initializer = join(" = ", to_zero_initialized_expression(result_type));
|
||||
|
||||
statement(flags_to_qualifiers_glsl(type, flags), variable_decl(type, to_name(result_id)), initializer, ";");
|
||||
}
|
||||
}
|
||||
|
||||
@ -7947,7 +7965,16 @@ void CompilerGLSL::flush_variable_declaration(uint32_t id)
|
||||
auto *var = maybe_get<SPIRVariable>(id);
|
||||
if (var && var->deferred_declaration)
|
||||
{
|
||||
statement(variable_decl_function_local(*var), ";");
|
||||
string initializer;
|
||||
if (options.force_zero_initialized_variables &&
|
||||
(var->storage == StorageClassFunction || var->storage == StorageClassGeneric ||
|
||||
var->storage == StorageClassPrivate) &&
|
||||
!var->initializer && type_can_zero_initialize(get_variable_data_type(*var)))
|
||||
{
|
||||
initializer = join(" = ", to_zero_initialized_expression(get_variable_data_type_id(*var)));
|
||||
}
|
||||
|
||||
statement(variable_decl_function_local(*var), initializer, ";");
|
||||
var->deferred_declaration = false;
|
||||
}
|
||||
if (var)
|
||||
@ -11113,6 +11140,37 @@ string CompilerGLSL::to_initializer_expression(const SPIRVariable &var)
|
||||
return to_expression(var.initializer);
|
||||
}
|
||||
|
||||
string CompilerGLSL::to_zero_initialized_expression(uint32_t type_id)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
auto &type = get<SPIRType>(type_id);
|
||||
assert(type.storage == StorageClassPrivate || type.storage == StorageClassFunction ||
|
||||
type.storage == StorageClassGeneric);
|
||||
#endif
|
||||
uint32_t id = ir.increase_bound_by(1);
|
||||
ir.make_constant_null(id, type_id, false);
|
||||
return constant_expression(get<SPIRConstant>(id));
|
||||
}
|
||||
|
||||
bool CompilerGLSL::type_can_zero_initialize(const SPIRType &type) const
|
||||
{
|
||||
if (type.pointer)
|
||||
return false;
|
||||
|
||||
if (!type.array.empty() && options.flatten_multidimensional_arrays)
|
||||
return false;
|
||||
|
||||
for (auto &literal : type.array_size_literal)
|
||||
if (!literal)
|
||||
return false;
|
||||
|
||||
for (auto &memb : type.member_types)
|
||||
if (!type_can_zero_initialize(get<SPIRType>(memb)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
string CompilerGLSL::variable_decl(const SPIRVariable &variable)
|
||||
{
|
||||
// Ignore the pointer type since GLSL doesn't have pointers.
|
||||
@ -11128,13 +11186,18 @@ string CompilerGLSL::variable_decl(const SPIRVariable &variable)
|
||||
uint32_t expr = variable.static_expression;
|
||||
if (ir.ids[expr].get_type() != TypeUndef)
|
||||
res += join(" = ", to_expression(variable.static_expression));
|
||||
else if (options.force_zero_initialized_variables && type_can_zero_initialize(type))
|
||||
res += join(" = ", to_zero_initialized_expression(get_variable_data_type_id(variable)));
|
||||
}
|
||||
else if (variable.initializer)
|
||||
{
|
||||
uint32_t expr = variable.initializer;
|
||||
if (ir.ids[expr].get_type() != TypeUndef)
|
||||
res += join(" = ", to_initializer_expression(variable));
|
||||
else if (options.force_zero_initialized_variables && type_can_zero_initialize(type))
|
||||
res += join(" = ", to_zero_initialized_expression(get_variable_data_type_id(variable)));
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -12523,7 +12586,13 @@ void CompilerGLSL::emit_hoisted_temporaries(SmallVector<pair<TypeID, ID>> &tempo
|
||||
add_local_variable_name(tmp.second);
|
||||
auto &flags = ir.meta[tmp.second].decoration.decoration_flags;
|
||||
auto &type = get<SPIRType>(tmp.first);
|
||||
statement(flags_to_qualifiers_glsl(type, flags), variable_decl(type, to_name(tmp.second)), ";");
|
||||
|
||||
// Not all targets support pointer literals, so don't bother with that case.
|
||||
string initializer;
|
||||
if (options.force_zero_initialized_variables && type_can_zero_initialize(type))
|
||||
initializer = join(" = ", to_zero_initialized_expression(tmp.first));
|
||||
|
||||
statement(flags_to_qualifiers_glsl(type, flags), variable_decl(type, to_name(tmp.second)), initializer, ";");
|
||||
|
||||
hoisted_temporaries.insert(tmp.second);
|
||||
forced_temporaries.insert(tmp.second);
|
||||
|
@ -115,6 +115,11 @@ public:
|
||||
// by the SPIR-V, it's recommended to set this to false.
|
||||
bool enable_storage_image_qualifier_deduction = true;
|
||||
|
||||
// On some targets (WebGPU), uninitialized variables are banned.
|
||||
// If this is enabled, all variables (temporaries, Private, Function)
|
||||
// which would otherwise be uninitialized will now be initialized to 0 instead.
|
||||
bool force_zero_initialized_variables = false;
|
||||
|
||||
enum Precision
|
||||
{
|
||||
DontCare,
|
||||
@ -576,6 +581,8 @@ protected:
|
||||
spv::StorageClass rhs_storage);
|
||||
virtual void emit_block_hints(const SPIRBlock &block);
|
||||
virtual std::string to_initializer_expression(const SPIRVariable &var);
|
||||
virtual std::string to_zero_initialized_expression(uint32_t type_id);
|
||||
bool type_can_zero_initialize(const SPIRType &type) const;
|
||||
|
||||
bool buffer_is_packing_standard(const SPIRType &type, BufferPackingStandard packing,
|
||||
uint32_t *failed_index = nullptr, uint32_t start_offset = 0,
|
||||
|
@ -1121,7 +1121,12 @@ void CompilerHLSL::declare_undefined_values()
|
||||
{
|
||||
bool emitted = false;
|
||||
ir.for_each_typed_id<SPIRUndef>([&](uint32_t, const SPIRUndef &undef) {
|
||||
statement("static ", variable_decl(this->get<SPIRType>(undef.basetype), to_name(undef.self), undef.self), ";");
|
||||
string initializer;
|
||||
if (options.force_zero_initialized_variables && type_can_zero_initialize(this->get<SPIRType>(undef.basetype)))
|
||||
initializer = join(" = ", to_zero_initialized_expression(undef.basetype));
|
||||
|
||||
statement("static ", variable_decl(this->get<SPIRType>(undef.basetype), to_name(undef.self), undef.self),
|
||||
initializer, ";");
|
||||
emitted = true;
|
||||
});
|
||||
|
||||
@ -1362,7 +1367,15 @@ void CompilerHLSL::emit_resources()
|
||||
storage = "static";
|
||||
break;
|
||||
}
|
||||
statement(storage, " ", variable_decl(var), ";");
|
||||
|
||||
string initializer;
|
||||
if (options.force_zero_initialized_variables && var.storage == StorageClassPrivate &&
|
||||
!var.initializer && !var.static_expression && type_can_zero_initialize(get_variable_data_type(var)))
|
||||
{
|
||||
initializer = join(" = ", to_zero_initialized_expression(get_variable_data_type_id(var)));
|
||||
}
|
||||
statement(storage, " ", variable_decl(var), initializer, ";");
|
||||
|
||||
emitted = true;
|
||||
}
|
||||
}
|
||||
|
@ -12450,7 +12450,7 @@ void CompilerMSL::bitcast_to_builtin_store(uint32_t target_id, std::string &expr
|
||||
}
|
||||
}
|
||||
|
||||
std::string CompilerMSL::to_initializer_expression(const SPIRVariable &var)
|
||||
string CompilerMSL::to_initializer_expression(const SPIRVariable &var)
|
||||
{
|
||||
// We risk getting an array initializer here with MSL. If we have an array.
|
||||
// FIXME: We cannot handle non-constant arrays being initialized.
|
||||
@ -12463,6 +12463,11 @@ std::string CompilerMSL::to_initializer_expression(const SPIRVariable &var)
|
||||
return CompilerGLSL::to_initializer_expression(var);
|
||||
}
|
||||
|
||||
string CompilerMSL::to_zero_initialized_expression(uint32_t)
|
||||
{
|
||||
return "{}";
|
||||
}
|
||||
|
||||
bool CompilerMSL::descriptor_set_is_argument_buffer(uint32_t desc_set) const
|
||||
{
|
||||
if (!msl_options.argument_buffers)
|
||||
|
@ -619,6 +619,7 @@ protected:
|
||||
uint32_t grad_y, uint32_t lod, uint32_t coffset, uint32_t offset, uint32_t bias,
|
||||
uint32_t comp, uint32_t sample, uint32_t minlod, bool *p_forward) override;
|
||||
std::string to_initializer_expression(const SPIRVariable &var) override;
|
||||
std::string to_zero_initialized_expression(uint32_t type_id) override;
|
||||
|
||||
std::string unpack_expression_type(std::string expr_str, const SPIRType &type, uint32_t physical_type_id,
|
||||
bool is_packed, bool row_major) override;
|
||||
|
@ -771,7 +771,7 @@ void Parser::parse(const Instruction &instruction)
|
||||
{
|
||||
uint32_t id = ops[1];
|
||||
uint32_t type = ops[0];
|
||||
make_constant_null(id, type);
|
||||
ir.make_constant_null(id, type, true);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1136,46 +1136,4 @@ bool Parser::variable_storage_is_aliased(const SPIRVariable &v) const
|
||||
|
||||
return !is_restrict && (ssbo || image || counter);
|
||||
}
|
||||
|
||||
void Parser::make_constant_null(uint32_t id, uint32_t type)
|
||||
{
|
||||
auto &constant_type = get<SPIRType>(type);
|
||||
|
||||
if (constant_type.pointer)
|
||||
{
|
||||
auto &constant = set<SPIRConstant>(id, type);
|
||||
constant.make_null(constant_type);
|
||||
}
|
||||
else if (!constant_type.array.empty())
|
||||
{
|
||||
assert(constant_type.parent_type);
|
||||
uint32_t parent_id = ir.increase_bound_by(1);
|
||||
make_constant_null(parent_id, constant_type.parent_type);
|
||||
|
||||
if (!constant_type.array_size_literal.back())
|
||||
SPIRV_CROSS_THROW("Array size of OpConstantNull must be a literal.");
|
||||
|
||||
SmallVector<uint32_t> elements(constant_type.array.back());
|
||||
for (uint32_t i = 0; i < constant_type.array.back(); i++)
|
||||
elements[i] = parent_id;
|
||||
set<SPIRConstant>(id, type, elements.data(), uint32_t(elements.size()), false);
|
||||
}
|
||||
else if (!constant_type.member_types.empty())
|
||||
{
|
||||
uint32_t member_ids = ir.increase_bound_by(uint32_t(constant_type.member_types.size()));
|
||||
SmallVector<uint32_t> elements(constant_type.member_types.size());
|
||||
for (uint32_t i = 0; i < constant_type.member_types.size(); i++)
|
||||
{
|
||||
make_constant_null(member_ids + i, constant_type.member_types[i]);
|
||||
elements[i] = member_ids + i;
|
||||
}
|
||||
set<SPIRConstant>(id, type, elements.data(), uint32_t(elements.size()), false);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto &constant = set<SPIRConstant>(id, type);
|
||||
constant.make_null(constant_type);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace SPIRV_CROSS_NAMESPACE
|
||||
|
@ -87,7 +87,6 @@ private:
|
||||
|
||||
bool types_are_logically_equivalent(const SPIRType &a, const SPIRType &b) const;
|
||||
bool variable_storage_is_aliased(const SPIRVariable &v) const;
|
||||
void make_constant_null(uint32_t id, uint32_t type);
|
||||
};
|
||||
} // namespace SPIRV_CROSS_NAMESPACE
|
||||
|
||||
|
@ -256,6 +256,8 @@ def cross_compile_msl(shader, spirv, opt, iterations, paths):
|
||||
msl_args.append('1')
|
||||
if '.force-native-array.' in shader:
|
||||
msl_args.append('--msl-force-native-arrays')
|
||||
if '.zero-initialize.' in shader:
|
||||
msl_args.append('--force-zero-initialized-variables')
|
||||
|
||||
subprocess.check_call(msl_args)
|
||||
|
||||
@ -360,6 +362,9 @@ def cross_compile_hlsl(shader, spirv, opt, force_no_external_validation, iterati
|
||||
hlsl_args.append('--emit-line-directives')
|
||||
if '.force-uav.' in shader:
|
||||
hlsl_args.append('--hlsl-force-storage-buffer-as-uav')
|
||||
if '.zero-initialize.' in shader:
|
||||
hlsl_args.append('--force-zero-initialized-variables')
|
||||
|
||||
subprocess.check_call(hlsl_args)
|
||||
|
||||
if not shader_is_invalid_spirv(hlsl_path):
|
||||
@ -445,6 +450,8 @@ def cross_compile(shader, vulkan, spirv, invalid_spirv, eliminate, is_legacy, fl
|
||||
extra_args += ['--glsl-remap-ext-framebuffer-fetch', '1', '1']
|
||||
extra_args += ['--glsl-remap-ext-framebuffer-fetch', '2', '2']
|
||||
extra_args += ['--glsl-remap-ext-framebuffer-fetch', '3', '3']
|
||||
if '.zero-initialize.' in shader:
|
||||
extra_args += ['--force-zero-initialized-variables']
|
||||
|
||||
spirv_cross_path = paths.spirv_cross
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user