diff --git a/reference/opt/shaders-hlsl/frag/dual-source-blending.frag b/reference/opt/shaders-hlsl/frag/dual-source-blending.frag new file mode 100644 index 00000000..961e8000 --- /dev/null +++ b/reference/opt/shaders-hlsl/frag/dual-source-blending.frag @@ -0,0 +1,23 @@ +static float4 FragColor0; +static float4 FragColor1; + +struct SPIRV_Cross_Output +{ + float4 FragColor0 : SV_Target0; + float4 FragColor1 : SV_Target1; +}; + +void frag_main() +{ + FragColor0 = 1.0f.xxxx; + FragColor1 = 2.0f.xxxx; +} + +SPIRV_Cross_Output main() +{ + frag_main(); + SPIRV_Cross_Output stage_output; + stage_output.FragColor0 = FragColor0; + stage_output.FragColor1 = FragColor1; + return stage_output; +} diff --git a/reference/shaders-hlsl/frag/dual-source-blending.frag b/reference/shaders-hlsl/frag/dual-source-blending.frag new file mode 100644 index 00000000..961e8000 --- /dev/null +++ b/reference/shaders-hlsl/frag/dual-source-blending.frag @@ -0,0 +1,23 @@ +static float4 FragColor0; +static float4 FragColor1; + +struct SPIRV_Cross_Output +{ + float4 FragColor0 : SV_Target0; + float4 FragColor1 : SV_Target1; +}; + +void frag_main() +{ + FragColor0 = 1.0f.xxxx; + FragColor1 = 2.0f.xxxx; +} + +SPIRV_Cross_Output main() +{ + frag_main(); + SPIRV_Cross_Output stage_output; + stage_output.FragColor0 = FragColor0; + stage_output.FragColor1 = FragColor1; + return stage_output; +} diff --git a/shaders-hlsl/frag/dual-source-blending.frag b/shaders-hlsl/frag/dual-source-blending.frag new file mode 100644 index 00000000..f322cf4c --- /dev/null +++ b/shaders-hlsl/frag/dual-source-blending.frag @@ -0,0 +1,10 @@ +#version 450 + +layout(location = 0, index = 0) out vec4 FragColor0; +layout(location = 0, index = 1) out vec4 FragColor1; + +void main() +{ + FragColor0 = vec4(1.0); + FragColor1 = vec4(2.0); +} diff --git a/spirv_hlsl.cpp b/spirv_hlsl.cpp index 486fec54..404a8292 100644 --- a/spirv_hlsl.cpp +++ b/spirv_hlsl.cpp @@ -805,7 +805,14 @@ void CompilerHLSL::emit_interface_block_in_struct(const SPIRVariable &var, unord bool legacy = hlsl_options.shader_model <= 30; if (execution.model == ExecutionModelFragment && var.storage == StorageClassOutput) { - binding = join(legacy ? "COLOR" : "SV_Target", get_decoration(var.self, DecorationLocation)); + // Dual-source blending is achieved in HLSL by emitting to SV_Target0 and 1. + uint32_t index = get_decoration(var.self, DecorationIndex); + uint32_t location = get_decoration(var.self, DecorationLocation); + + if (index != 0 && location != 0) + SPIRV_CROSS_THROW("Dual-source blending is only supported on MRT #0 in HLSL."); + + binding = join(legacy ? "COLOR" : "SV_Target", location + index); use_location_number = false; if (legacy) // COLOR must be a four-component vector on legacy shader model targets (HLSL ERR_COLOR_4COMP) type.vecsize = 4;