GLSL/HLSL: Add legacy handling for int vertex attributes

This commit is contained in:
rdb 2023-01-14 18:56:54 +01:00
parent 49e4117c5f
commit 4ba13e0c1a
8 changed files with 145 additions and 21 deletions

View File

@ -0,0 +1,36 @@
uniform float4 gl_HalfPixel;
static float4 gl_Position;
static int4 attr_int4;
static int attr_int1;
struct SPIRV_Cross_Input
{
float4 attr_int4 : TEXCOORD0;
float attr_int1 : TEXCOORD1;
};
struct SPIRV_Cross_Output
{
float4 gl_Position : POSITION;
};
void vert_main()
{
gl_Position.x = float(attr_int4[attr_int1]);
gl_Position.y = 0.0f;
gl_Position.z = 0.0f;
gl_Position.w = 0.0f;
gl_Position.x = gl_Position.x - gl_HalfPixel.x * gl_Position.w;
gl_Position.y = gl_Position.y + gl_HalfPixel.y * gl_Position.w;
}
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
{
attr_int4 = stage_input.attr_int4;
attr_int1 = stage_input.attr_int1;
vert_main();
SPIRV_Cross_Output stage_output;
stage_output.gl_Position = gl_Position;
return stage_output;
}

View File

@ -0,0 +1,13 @@
#version 100
attribute vec4 attr_int4;
attribute float attr_int1;
void main()
{
gl_Position.x = float(int(attr_int4[int(attr_int1)]));
gl_Position.y = 0.0;
gl_Position.z = 0.0;
gl_Position.w = 0.0;
}

View File

@ -0,0 +1,36 @@
uniform float4 gl_HalfPixel;
static float4 gl_Position;
static int4 attr_int4;
static int attr_int1;
struct SPIRV_Cross_Input
{
float4 attr_int4 : TEXCOORD0;
float attr_int1 : TEXCOORD1;
};
struct SPIRV_Cross_Output
{
float4 gl_Position : POSITION;
};
void vert_main()
{
gl_Position.x = float(attr_int4[attr_int1]);
gl_Position.y = 0.0f;
gl_Position.z = 0.0f;
gl_Position.w = 0.0f;
gl_Position.x = gl_Position.x - gl_HalfPixel.x * gl_Position.w;
gl_Position.y = gl_Position.y + gl_HalfPixel.y * gl_Position.w;
}
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
{
attr_int4 = stage_input.attr_int4;
attr_int1 = stage_input.attr_int1;
vert_main();
SPIRV_Cross_Output stage_output;
stage_output.gl_Position = gl_Position;
return stage_output;
}

View File

@ -0,0 +1,13 @@
#version 100
attribute vec4 attr_int4;
attribute float attr_int1;
void main()
{
gl_Position.x = float(int(attr_int4[int(attr_int1)]));
gl_Position.y = 0.0;
gl_Position.z = 0.0;
gl_Position.w = 0.0;
}

View File

@ -0,0 +1,10 @@
#version 310 es
layout(location=0) in ivec4 attr_int4;
layout(location=1) in int attr_int1;
void main()
{
gl_Position.x = float(attr_int4[attr_int1]);
gl_Position.yzw = vec3(0.0f, 0.0f, 0.0f);
}

View File

@ -0,0 +1,10 @@
#version 310 es
layout(location=0) in ivec4 attr_int4;
layout(location=1) in int attr_int1;
void main()
{
gl_Position.x = float(attr_int4[attr_int1]);
gl_Position.yzw = vec3(0.0f, 0.0f, 0.0f);
}

View File

@ -2713,30 +2713,26 @@ void CompilerGLSL::emit_interface_block(const SPIRVariable &var)
{
add_resource_name(var.self);
// Tessellation control and evaluation shaders must have either gl_MaxPatchVertices or unsized arrays for input arrays.
// Legacy GLSL did not support int attributes, we automatically
// declare them as float and cast them on load/store
SPIRType newtype = type;
if (is_legacy() && var.storage == StorageClassInput && type.basetype == SPIRType::Int)
newtype.basetype = SPIRType::Float;
// Tessellation control and evaluation shaders must have either
// gl_MaxPatchVertices or unsized arrays for input arrays.
// Opt for unsized as it's the more "correct" variant to use.
bool control_point_input_array = type.storage == StorageClassInput && !type.array.empty() &&
!has_decoration(var.self, DecorationPatch) &&
(get_entry_point().model == ExecutionModelTessellationControl ||
get_entry_point().model == ExecutionModelTessellationEvaluation);
uint32_t old_array_size = 0;
bool old_array_size_literal = true;
if (control_point_input_array)
if (type.storage == StorageClassInput && !type.array.empty() &&
!has_decoration(var.self, DecorationPatch) &&
(get_entry_point().model == ExecutionModelTessellationControl ||
get_entry_point().model == ExecutionModelTessellationEvaluation))
{
swap(type.array.back(), old_array_size);
swap(type.array_size_literal.back(), old_array_size_literal);
newtype.array.back() = 0;
newtype.array_size_literal.back() = true;
}
statement(layout_for_variable(var), to_qualifiers_glsl(var.self),
variable_decl(type, to_name(var.self), var.self), ";");
if (control_point_input_array)
{
swap(type.array.back(), old_array_size);
swap(type.array_size_literal.back(), old_array_size_literal);
}
variable_decl(newtype, to_name(var.self), var.self), ";");
}
}
}
@ -16654,7 +16650,12 @@ void CompilerGLSL::cast_from_variable_load(uint32_t source_id, std::string &expr
// Only interested in standalone builtin variables.
if (!has_decoration(source_id, DecorationBuiltIn))
{
// Except for int attributes in legacy GLSL, which are cast from float.
if (is_legacy() && expr_type.basetype == SPIRType::Int && var && var->storage == StorageClassInput)
expr = join(type_to_glsl(expr_type), "(", expr, ")");
return;
}
auto builtin = static_cast<BuiltIn>(get_decoration(source_id, DecorationBuiltIn));
auto expected_type = expr_type.basetype;

View File

@ -1016,6 +1016,7 @@ void CompilerHLSL::emit_interface_block_in_struct(const SPIRVariable &var, unord
string binding;
bool use_location_number = true;
bool need_matrix_unroll = false;
bool legacy = hlsl_options.shader_model <= 30;
if (execution.model == ExecutionModelFragment && var.storage == StorageClassOutput)
{
@ -1031,6 +1032,12 @@ void CompilerHLSL::emit_interface_block_in_struct(const SPIRVariable &var, unord
if (legacy) // COLOR must be a four-component vector on legacy shader model targets (HLSL ERR_COLOR_4COMP)
type.vecsize = 4;
}
else if (var.storage == StorageClassInput && execution.model == ExecutionModelVertex)
{
need_matrix_unroll = true;
if (legacy) // Inputs must be floating-point in legacy targets.
type.basetype = SPIRType::Float;
}
const auto get_vacant_location = [&]() -> uint32_t {
for (uint32_t i = 0; i < 64; i++)
@ -1039,8 +1046,6 @@ void CompilerHLSL::emit_interface_block_in_struct(const SPIRVariable &var, unord
SPIRV_CROSS_THROW("All locations from 0 to 63 are exhausted.");
};
bool need_matrix_unroll = var.storage == StorageClassInput && execution.model == ExecutionModelVertex;
auto name = to_name(var.self);
if (use_location_number)
{