From 0bedb69b02d9bca63f52211f8881fe276147822b Mon Sep 17 00:00:00 2001 From: Hans-Kristian Arntzen Date: Mon, 23 Oct 2023 12:04:19 +0200 Subject: [PATCH] HLSL: Declare sample mask array with proper module type. GLSL uses int[] and HLSL emits uint[], and to deal properly with array copies where we lose ability to rewrite arithmetic types, we need to declare with proper type. --- .../frag/sample-mask-in-and-out.frag | 6 +-- .../opt/shaders-hlsl/frag/sample-mask-in.frag | 2 +- .../shaders-hlsl/frag/sample-mask-out.frag | 4 +- .../frag/sample-mask-in-and-out.frag | 6 +-- .../shaders-hlsl/frag/sample-mask-in.frag | 2 +- .../shaders-hlsl/frag/sample-mask-out.frag | 4 +- spirv_hlsl.cpp | 54 +++++++++++++------ 7 files changed, 51 insertions(+), 27 deletions(-) diff --git a/reference/opt/shaders-hlsl/frag/sample-mask-in-and-out.frag b/reference/opt/shaders-hlsl/frag/sample-mask-in-and-out.frag index e8c1c8698..e2238828b 100644 --- a/reference/opt/shaders-hlsl/frag/sample-mask-in-and-out.frag +++ b/reference/opt/shaders-hlsl/frag/sample-mask-in-and-out.frag @@ -1,5 +1,5 @@ -static uint gl_SampleMaskIn[1]; -static uint gl_SampleMask[1]; +static int gl_SampleMaskIn[1]; +static int gl_SampleMask[1]; static float4 FragColor; struct SPIRV_Cross_Input @@ -16,7 +16,7 @@ struct SPIRV_Cross_Output void frag_main() { FragColor = 1.0f.xxxx; - gl_SampleMask[0] = uint(gl_SampleMaskIn[0]); + gl_SampleMask[0] = gl_SampleMaskIn[0]; } SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input) diff --git a/reference/opt/shaders-hlsl/frag/sample-mask-in.frag b/reference/opt/shaders-hlsl/frag/sample-mask-in.frag index 1750e945a..dfbe29b9c 100644 --- a/reference/opt/shaders-hlsl/frag/sample-mask-in.frag +++ b/reference/opt/shaders-hlsl/frag/sample-mask-in.frag @@ -1,5 +1,5 @@ static int gl_SampleID; -static uint gl_SampleMaskIn[1]; +static int gl_SampleMaskIn[1]; static float4 FragColor; struct SPIRV_Cross_Input diff --git a/reference/opt/shaders-hlsl/frag/sample-mask-out.frag b/reference/opt/shaders-hlsl/frag/sample-mask-out.frag index b649e8a62..14de570df 100644 --- a/reference/opt/shaders-hlsl/frag/sample-mask-out.frag +++ b/reference/opt/shaders-hlsl/frag/sample-mask-out.frag @@ -1,4 +1,4 @@ -static uint gl_SampleMask[1]; +static int gl_SampleMask[1]; static float4 FragColor; struct SPIRV_Cross_Output @@ -10,7 +10,7 @@ struct SPIRV_Cross_Output void frag_main() { FragColor = 1.0f.xxxx; - gl_SampleMask[0] = uint(0); + gl_SampleMask[0] = 0; } SPIRV_Cross_Output main() diff --git a/reference/shaders-hlsl/frag/sample-mask-in-and-out.frag b/reference/shaders-hlsl/frag/sample-mask-in-and-out.frag index e8c1c8698..e2238828b 100644 --- a/reference/shaders-hlsl/frag/sample-mask-in-and-out.frag +++ b/reference/shaders-hlsl/frag/sample-mask-in-and-out.frag @@ -1,5 +1,5 @@ -static uint gl_SampleMaskIn[1]; -static uint gl_SampleMask[1]; +static int gl_SampleMaskIn[1]; +static int gl_SampleMask[1]; static float4 FragColor; struct SPIRV_Cross_Input @@ -16,7 +16,7 @@ struct SPIRV_Cross_Output void frag_main() { FragColor = 1.0f.xxxx; - gl_SampleMask[0] = uint(gl_SampleMaskIn[0]); + gl_SampleMask[0] = gl_SampleMaskIn[0]; } SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input) diff --git a/reference/shaders-hlsl/frag/sample-mask-in.frag b/reference/shaders-hlsl/frag/sample-mask-in.frag index 1750e945a..dfbe29b9c 100644 --- a/reference/shaders-hlsl/frag/sample-mask-in.frag +++ b/reference/shaders-hlsl/frag/sample-mask-in.frag @@ -1,5 +1,5 @@ static int gl_SampleID; -static uint gl_SampleMaskIn[1]; +static int gl_SampleMaskIn[1]; static float4 FragColor; struct SPIRV_Cross_Input diff --git a/reference/shaders-hlsl/frag/sample-mask-out.frag b/reference/shaders-hlsl/frag/sample-mask-out.frag index b649e8a62..14de570df 100644 --- a/reference/shaders-hlsl/frag/sample-mask-out.frag +++ b/reference/shaders-hlsl/frag/sample-mask-out.frag @@ -1,4 +1,4 @@ -static uint gl_SampleMask[1]; +static int gl_SampleMask[1]; static float4 FragColor; struct SPIRV_Cross_Output @@ -10,7 +10,7 @@ struct SPIRV_Cross_Output void frag_main() { FragColor = 1.0f.xxxx; - gl_SampleMask[0] = uint(0); + gl_SampleMask[0] = 0; } SPIRV_Cross_Output main() diff --git a/spirv_hlsl.cpp b/spirv_hlsl.cpp index 32ca72e94..c0706e413 100644 --- a/spirv_hlsl.cpp +++ b/spirv_hlsl.cpp @@ -1149,29 +1149,48 @@ void CompilerHLSL::emit_builtin_variables() builtins.merge_or(active_output_builtins); std::unordered_map builtin_to_initializer; - ir.for_each_typed_id([&](uint32_t, SPIRVariable &var) { - if (!is_builtin_variable(var) || var.storage != StorageClassOutput || !var.initializer) - return; - auto *c = this->maybe_get(var.initializer); - if (!c) + // We need to declare sample mask with the same type that module declares it. + // Sample mask is somewhat special in that SPIR-V has an array, and we can copy that array, so we need to + // match sign. + SPIRType::BaseType sample_mask_in_basetype = SPIRType::Void; + SPIRType::BaseType sample_mask_out_basetype = SPIRType::Void; + + ir.for_each_typed_id([&](uint32_t, SPIRVariable &var) { + if (!is_builtin_variable(var)) return; auto &type = this->get(var.basetype); - if (type.basetype == SPIRType::Struct) + auto builtin = BuiltIn(get_decoration(var.self, DecorationBuiltIn)); + + if (var.storage == StorageClassInput && builtin == BuiltInSampleMask) + sample_mask_in_basetype = type.basetype; + else if (var.storage == StorageClassOutput && builtin == BuiltInSampleMask) + sample_mask_out_basetype = type.basetype; + + if (var.initializer && var.storage == StorageClassOutput) { - uint32_t member_count = uint32_t(type.member_types.size()); - for (uint32_t i = 0; i < member_count; i++) + auto *c = this->maybe_get(var.initializer); + if (!c) + return; + + if (type.basetype == SPIRType::Struct) { - if (has_member_decoration(type.self, i, DecorationBuiltIn)) + uint32_t member_count = uint32_t(type.member_types.size()); + for (uint32_t i = 0; i < member_count; i++) { - builtin_to_initializer[get_member_decoration(type.self, i, DecorationBuiltIn)] = - c->subconstants[i]; + if (has_member_decoration(type.self, i, DecorationBuiltIn)) + { + builtin_to_initializer[get_member_decoration(type.self, i, DecorationBuiltIn)] = + c->subconstants[i]; + } } } + else if (has_decoration(var.self, DecorationBuiltIn)) + { + builtin_to_initializer[builtin] = var.initializer; + } } - else if (has_decoration(var.self, DecorationBuiltIn)) - builtin_to_initializer[get_decoration(var.self, DecorationBuiltIn)] = var.initializer; }); // Emit global variables for the interface variables which are statically used by the shader. @@ -1288,7 +1307,10 @@ void CompilerHLSL::emit_builtin_variables() break; case BuiltInSampleMask: - type = "uint"; + if (active_input_builtins.get(BuiltInSampleMask)) + type = sample_mask_in_basetype == SPIRType::UInt ? "uint" : "int"; + else + type = sample_mask_out_basetype == SPIRType::UInt ? "uint" : "int"; array_size = 1; break; @@ -1323,6 +1345,7 @@ void CompilerHLSL::emit_builtin_variables() // declared the input variable and we need to add the output one now. if (builtin == BuiltInSampleMask && storage == StorageClassInput && this->active_output_builtins.get(i)) { + type = sample_mask_out_basetype == SPIRType::UInt ? "uint" : "int"; if (array_size) statement("static ", type, " ", this->builtin_to_glsl(builtin, StorageClassOutput), "[", array_size, "]", init_expr, ";"); else @@ -1545,7 +1568,8 @@ SPIRType::BaseType CompilerHLSL::get_builtin_basetype(BuiltIn builtin, SPIRType: switch (builtin) { case BuiltInSampleMask: - return SPIRType::UInt; + // We declare sample mask array with module type, so always use default_type here. + return default_type; default: return CompilerGLSL::get_builtin_basetype(builtin, default_type); }