diff options
author | Hans-Kristian Arntzen <post@arntzen-software.no> | 2019-01-30 12:29:08 +0300 |
---|---|---|
committer | Hans-Kristian Arntzen <post@arntzen-software.no> | 2019-01-30 12:29:08 +0300 |
commit | 3e098791313ecc8c91cbfa9d29ab36346db0f355 (patch) | |
tree | d3d083a4d4d9025643b022b19e9700d1addd458f | |
parent | 5ff12d780b36d75c9a7c7c8886e18c54d7b8ec10 (diff) |
Support initializers on StorageClassOutput.fix-838
12 files changed, 268 insertions, 4 deletions
diff --git a/reference/opt/shaders-hlsl/asm/frag/storage-class-output-initializer.asm.frag b/reference/opt/shaders-hlsl/asm/frag/storage-class-output-initializer.asm.frag new file mode 100644 index 00000000..1905b5ea --- /dev/null +++ b/reference/opt/shaders-hlsl/asm/frag/storage-class-output-initializer.asm.frag @@ -0,0 +1,23 @@ +static const float4 _20[2] = { float4(1.0f, 2.0f, 3.0f, 4.0f), 10.0f.xxxx }; + +static float4 FragColors[2] = _20; +static float4 FragColor = 5.0f.xxxx; + +struct SPIRV_Cross_Output +{ + float4 FragColors[2] : SV_Target0; + float4 FragColor : SV_Target2; +}; + +void frag_main() +{ +} + +SPIRV_Cross_Output main() +{ + frag_main(); + SPIRV_Cross_Output stage_output; + stage_output.FragColors = FragColors; + stage_output.FragColor = FragColor; + return stage_output; +} diff --git a/reference/opt/shaders-msl/asm/frag/storage-class-output-initializer.asm.frag b/reference/opt/shaders-msl/asm/frag/storage-class-output-initializer.asm.frag new file mode 100644 index 00000000..1bafc695 --- /dev/null +++ b/reference/opt/shaders-msl/asm/frag/storage-class-output-initializer.asm.frag @@ -0,0 +1,24 @@ +#include <metal_stdlib> +#include <simd/simd.h> + +using namespace metal; + +constant float4 _20[2] = { float4(1.0, 2.0, 3.0, 4.0), float4(10.0) }; + +struct main0_out +{ + float4 FragColors_0 [[color(0)]]; + float4 FragColors_1 [[color(1)]]; + float4 FragColor [[color(2)]]; +}; + +fragment main0_out main0() +{ + main0_out out = {}; + float4 FragColors[2] = { float4(1.0, 2.0, 3.0, 4.0), float4(10.0) }; + out.FragColor = float4(5.0); + out.FragColors_0 = FragColors[0]; + out.FragColors_1 = FragColors[1]; + return out; +} + diff --git a/reference/opt/shaders/asm/frag/storage-class-output-initializer.asm.frag b/reference/opt/shaders/asm/frag/storage-class-output-initializer.asm.frag new file mode 100644 index 00000000..22935875 --- /dev/null +++ b/reference/opt/shaders/asm/frag/storage-class-output-initializer.asm.frag @@ -0,0 +1,11 @@ +#version 450 + +layout(location = 0) out vec4 FragColors[2]; +layout(location = 2) out vec4 FragColor; + +void main() +{ + FragColors = vec4[](vec4(1.0, 2.0, 3.0, 4.0), vec4(10.0)); + FragColor = vec4(5.0); +} + diff --git a/reference/shaders-hlsl/asm/frag/storage-class-output-initializer.asm.frag b/reference/shaders-hlsl/asm/frag/storage-class-output-initializer.asm.frag new file mode 100644 index 00000000..1905b5ea --- /dev/null +++ b/reference/shaders-hlsl/asm/frag/storage-class-output-initializer.asm.frag @@ -0,0 +1,23 @@ +static const float4 _20[2] = { float4(1.0f, 2.0f, 3.0f, 4.0f), 10.0f.xxxx }; + +static float4 FragColors[2] = _20; +static float4 FragColor = 5.0f.xxxx; + +struct SPIRV_Cross_Output +{ + float4 FragColors[2] : SV_Target0; + float4 FragColor : SV_Target2; +}; + +void frag_main() +{ +} + +SPIRV_Cross_Output main() +{ + frag_main(); + SPIRV_Cross_Output stage_output; + stage_output.FragColors = FragColors; + stage_output.FragColor = FragColor; + return stage_output; +} diff --git a/reference/shaders-msl/asm/frag/storage-class-output-initializer.asm.frag b/reference/shaders-msl/asm/frag/storage-class-output-initializer.asm.frag new file mode 100644 index 00000000..1bafc695 --- /dev/null +++ b/reference/shaders-msl/asm/frag/storage-class-output-initializer.asm.frag @@ -0,0 +1,24 @@ +#include <metal_stdlib> +#include <simd/simd.h> + +using namespace metal; + +constant float4 _20[2] = { float4(1.0, 2.0, 3.0, 4.0), float4(10.0) }; + +struct main0_out +{ + float4 FragColors_0 [[color(0)]]; + float4 FragColors_1 [[color(1)]]; + float4 FragColor [[color(2)]]; +}; + +fragment main0_out main0() +{ + main0_out out = {}; + float4 FragColors[2] = { float4(1.0, 2.0, 3.0, 4.0), float4(10.0) }; + out.FragColor = float4(5.0); + out.FragColors_0 = FragColors[0]; + out.FragColors_1 = FragColors[1]; + return out; +} + diff --git a/reference/shaders/asm/frag/storage-class-output-initializer.asm.frag b/reference/shaders/asm/frag/storage-class-output-initializer.asm.frag new file mode 100644 index 00000000..22935875 --- /dev/null +++ b/reference/shaders/asm/frag/storage-class-output-initializer.asm.frag @@ -0,0 +1,11 @@ +#version 450 + +layout(location = 0) out vec4 FragColors[2]; +layout(location = 2) out vec4 FragColor; + +void main() +{ + FragColors = vec4[](vec4(1.0, 2.0, 3.0, 4.0), vec4(10.0)); + FragColor = vec4(5.0); +} + diff --git a/shaders-hlsl/asm/frag/storage-class-output-initializer.asm.frag b/shaders-hlsl/asm/frag/storage-class-output-initializer.asm.frag new file mode 100644 index 00000000..7763b7c1 --- /dev/null +++ b/shaders-hlsl/asm/frag/storage-class-output-initializer.asm.frag @@ -0,0 +1,41 @@ +; SPIR-V +; Version: 1.0 +; Generator: Khronos Glslang Reference Front End; 7 +; Bound: 25 +; Schema: 0 + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %main "main" %FragColors %FragColor + OpExecutionMode %main OriginUpperLeft + OpSource GLSL 450 + OpName %main "main" + OpName %FragColors "FragColors" + OpName %FragColor "FragColor" + OpDecorate %FragColors Location 0 + OpDecorate %FragColor Location 2 + %void = OpTypeVoid + %3 = OpTypeFunction %void + %float = OpTypeFloat 32 + %v4float = OpTypeVector %float 4 + %uint = OpTypeInt 32 0 + %uint_2 = OpConstant %uint 2 +%_arr_v4float_uint_2 = OpTypeArray %v4float %uint_2 +%_ptr_Output__arr_v4float_uint_2 = OpTypePointer Output %_arr_v4float_uint_2 + %float_1 = OpConstant %float 1 + %float_2 = OpConstant %float 2 + %float_3 = OpConstant %float 3 + %float_4 = OpConstant %float 4 + %17 = OpConstantComposite %v4float %float_1 %float_2 %float_3 %float_4 + %float_10 = OpConstant %float 10 + %19 = OpConstantComposite %v4float %float_10 %float_10 %float_10 %float_10 + %20 = OpConstantComposite %_arr_v4float_uint_2 %17 %19 +%_ptr_Output_v4float = OpTypePointer Output %v4float + %float_5 = OpConstant %float 5 + %24 = OpConstantComposite %v4float %float_5 %float_5 %float_5 %float_5 + %FragColors = OpVariable %_ptr_Output__arr_v4float_uint_2 Output %20 + %FragColor = OpVariable %_ptr_Output_v4float Output %24 + %main = OpFunction %void None %3 + %5 = OpLabel + OpReturn + OpFunctionEnd diff --git a/shaders-msl/asm/frag/storage-class-output-initializer.asm.frag b/shaders-msl/asm/frag/storage-class-output-initializer.asm.frag new file mode 100644 index 00000000..7763b7c1 --- /dev/null +++ b/shaders-msl/asm/frag/storage-class-output-initializer.asm.frag @@ -0,0 +1,41 @@ +; SPIR-V +; Version: 1.0 +; Generator: Khronos Glslang Reference Front End; 7 +; Bound: 25 +; Schema: 0 + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %main "main" %FragColors %FragColor + OpExecutionMode %main OriginUpperLeft + OpSource GLSL 450 + OpName %main "main" + OpName %FragColors "FragColors" + OpName %FragColor "FragColor" + OpDecorate %FragColors Location 0 + OpDecorate %FragColor Location 2 + %void = OpTypeVoid + %3 = OpTypeFunction %void + %float = OpTypeFloat 32 + %v4float = OpTypeVector %float 4 + %uint = OpTypeInt 32 0 + %uint_2 = OpConstant %uint 2 +%_arr_v4float_uint_2 = OpTypeArray %v4float %uint_2 +%_ptr_Output__arr_v4float_uint_2 = OpTypePointer Output %_arr_v4float_uint_2 + %float_1 = OpConstant %float 1 + %float_2 = OpConstant %float 2 + %float_3 = OpConstant %float 3 + %float_4 = OpConstant %float 4 + %17 = OpConstantComposite %v4float %float_1 %float_2 %float_3 %float_4 + %float_10 = OpConstant %float 10 + %19 = OpConstantComposite %v4float %float_10 %float_10 %float_10 %float_10 + %20 = OpConstantComposite %_arr_v4float_uint_2 %17 %19 +%_ptr_Output_v4float = OpTypePointer Output %v4float + %float_5 = OpConstant %float 5 + %24 = OpConstantComposite %v4float %float_5 %float_5 %float_5 %float_5 + %FragColors = OpVariable %_ptr_Output__arr_v4float_uint_2 Output %20 + %FragColor = OpVariable %_ptr_Output_v4float Output %24 + %main = OpFunction %void None %3 + %5 = OpLabel + OpReturn + OpFunctionEnd diff --git a/shaders/asm/frag/storage-class-output-initializer.asm.frag b/shaders/asm/frag/storage-class-output-initializer.asm.frag new file mode 100644 index 00000000..7763b7c1 --- /dev/null +++ b/shaders/asm/frag/storage-class-output-initializer.asm.frag @@ -0,0 +1,41 @@ +; SPIR-V +; Version: 1.0 +; Generator: Khronos Glslang Reference Front End; 7 +; Bound: 25 +; Schema: 0 + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %main "main" %FragColors %FragColor + OpExecutionMode %main OriginUpperLeft + OpSource GLSL 450 + OpName %main "main" + OpName %FragColors "FragColors" + OpName %FragColor "FragColor" + OpDecorate %FragColors Location 0 + OpDecorate %FragColor Location 2 + %void = OpTypeVoid + %3 = OpTypeFunction %void + %float = OpTypeFloat 32 + %v4float = OpTypeVector %float 4 + %uint = OpTypeInt 32 0 + %uint_2 = OpConstant %uint 2 +%_arr_v4float_uint_2 = OpTypeArray %v4float %uint_2 +%_ptr_Output__arr_v4float_uint_2 = OpTypePointer Output %_arr_v4float_uint_2 + %float_1 = OpConstant %float 1 + %float_2 = OpConstant %float 2 + %float_3 = OpConstant %float 3 + %float_4 = OpConstant %float 4 + %17 = OpConstantComposite %v4float %float_1 %float_2 %float_3 %float_4 + %float_10 = OpConstant %float 10 + %19 = OpConstantComposite %v4float %float_10 %float_10 %float_10 %float_10 + %20 = OpConstantComposite %_arr_v4float_uint_2 %17 %19 +%_ptr_Output_v4float = OpTypePointer Output %v4float + %float_5 = OpConstant %float 5 + %24 = OpConstantComposite %v4float %float_5 %float_5 %float_5 %float_5 + %FragColors = OpVariable %_ptr_Output__arr_v4float_uint_2 Output %20 + %FragColor = OpVariable %_ptr_Output_v4float Output %24 + %main = OpFunction %void None %3 + %5 = OpLabel + OpReturn + OpFunctionEnd diff --git a/spirv_cross.cpp b/spirv_cross.cpp index ef3ec249..19bac301 100644 --- a/spirv_cross.cpp +++ b/spirv_cross.cpp @@ -701,6 +701,12 @@ unordered_set<uint32_t> Compiler::get_active_interface_variables() const InterfaceVariableAccessHandler handler(*this, variables); traverse_all_reachable_opcodes(get<SPIRFunction>(ir.default_entry_point), handler); + // Make sure we preserve output variables which are only initialized, but never accessed by any code. + ir.for_each_typed_id<SPIRVariable>([&](uint32_t, const SPIRVariable &var) { + if (var.storage == StorageClassOutput && var.initializer != 0) + variables.insert(var.self); + }); + // If we needed to create one, we'll need it. if (dummy_sampler_id) variables.insert(dummy_sampler_id); diff --git a/spirv_glsl.cpp b/spirv_glsl.cpp index e4d54e0d..a0b826d7 100644 --- a/spirv_glsl.cpp +++ b/spirv_glsl.cpp @@ -1743,6 +1743,15 @@ void CompilerGLSL::emit_interface_block(const SPIRVariable &var) add_resource_name(var.self); statement(layout_for_variable(var), to_qualifiers_glsl(var.self), variable_decl(type, to_name(var.self), var.self), ";"); + + // If a StorageClassOutput variable has an initializer, we need to initialize it in main(). + if (var.storage == StorageClassOutput && var.initializer) + { + auto &entry_func = this->get<SPIRFunction>(ir.default_entry_point); + entry_func.fixup_hooks_in.push_back([&]() { + statement(to_name(var.self), " = ", to_expression(var.initializer), ";"); + }); + } } } } diff --git a/spirv_msl.cpp b/spirv_msl.cpp index 7f2d3c6f..fd90160f 100644 --- a/spirv_msl.cpp +++ b/spirv_msl.cpp @@ -851,10 +851,10 @@ void CompilerMSL::add_plain_variable_to_interface_block(StorageClass storage, co // Update the original variable reference to include the structure reference string qual_var_name = ib_var_ref + "." + mbr_name; + auto &entry_func = get<SPIRFunction>(ir.default_entry_point); if (padded_output) { - auto &entry_func = get<SPIRFunction>(ir.default_entry_point); entry_func.add_local_variable(var.self); vars_needing_early_declaration.push_back(var.self); @@ -866,6 +866,13 @@ void CompilerMSL::add_plain_variable_to_interface_block(StorageClass storage, co else ir.meta[var.self].decoration.qualified_alias = qual_var_name; + if (var.storage == StorageClassOutput && var.initializer != 0) + { + entry_func.fixup_hooks_in.push_back([=, &var]() { + statement(qual_var_name, " = ", to_expression(var.initializer), ";"); + }); + } + // Copy the variable location from the original variable to the member if (get_decoration_bitset(var.self).get(DecorationLocation)) { @@ -3383,10 +3390,13 @@ void CompilerMSL::emit_function_prototype(SPIRFunction &func, const Bitset &) for (auto var_id : vars_needing_early_declaration) { auto &ed_var = get<SPIRVariable>(var_id); - if (!ed_var.initializer) - ed_var.initializer = ir.increase_bound_by(1); + uint32_t &initializer = ed_var.initializer; + if (!initializer) + initializer = ir.increase_bound_by(1); - set<SPIRExpression>(ed_var.initializer, "{}", ed_var.basetype, true); + // Do not override proper initializers. + if (ir.ids[initializer].get_type() == TypeNone || ir.ids[initializer].get_type() == TypeExpression) + set<SPIRExpression>(ed_var.initializer, "{}", ed_var.basetype, true); } } |