Skip to content

Commit

Permalink
HLSL: Declare sample mask array with proper module type.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
HansKristian-Work committed Oct 23, 2023
1 parent f12ee5e commit 0bedb69
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 27 deletions.
6 changes: 3 additions & 3 deletions reference/opt/shaders-hlsl/frag/sample-mask-in-and-out.frag
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion reference/opt/shaders-hlsl/frag/sample-mask-in.frag
Original file line number Diff line number Diff line change
@@ -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
Expand Down
4 changes: 2 additions & 2 deletions reference/opt/shaders-hlsl/frag/sample-mask-out.frag
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
static uint gl_SampleMask[1];
static int gl_SampleMask[1];
static float4 FragColor;

struct SPIRV_Cross_Output
Expand All @@ -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()
Expand Down
6 changes: 3 additions & 3 deletions reference/shaders-hlsl/frag/sample-mask-in-and-out.frag
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion reference/shaders-hlsl/frag/sample-mask-in.frag
Original file line number Diff line number Diff line change
@@ -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
Expand Down
4 changes: 2 additions & 2 deletions reference/shaders-hlsl/frag/sample-mask-out.frag
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
static uint gl_SampleMask[1];
static int gl_SampleMask[1];
static float4 FragColor;

struct SPIRV_Cross_Output
Expand All @@ -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()
Expand Down
54 changes: 39 additions & 15 deletions spirv_hlsl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1149,29 +1149,48 @@ void CompilerHLSL::emit_builtin_variables()
builtins.merge_or(active_output_builtins);

std::unordered_map<uint32_t, ID> builtin_to_initializer;
ir.for_each_typed_id<SPIRVariable>([&](uint32_t, SPIRVariable &var) {
if (!is_builtin_variable(var) || var.storage != StorageClassOutput || !var.initializer)
return;

auto *c = this->maybe_get<SPIRConstant>(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<SPIRVariable>([&](uint32_t, SPIRVariable &var) {
if (!is_builtin_variable(var))
return;

auto &type = this->get<SPIRType>(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<SPIRConstant>(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.
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
}
Expand Down

0 comments on commit 0bedb69

Please sign in to comment.