diff --git a/reference/opt/shaders-hlsl/vert/legacy-int-attribute.sm30.vert b/reference/opt/shaders-hlsl/vert/legacy-int-attribute.sm30.vert new file mode 100644 index 00000000..84e28348 --- /dev/null +++ b/reference/opt/shaders-hlsl/vert/legacy-int-attribute.sm30.vert @@ -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; +} diff --git a/reference/opt/shaders/legacy/vert/int-attribute.legacy.vert b/reference/opt/shaders/legacy/vert/int-attribute.legacy.vert new file mode 100644 index 00000000..cc41c3fa --- /dev/null +++ b/reference/opt/shaders/legacy/vert/int-attribute.legacy.vert @@ -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; +} + diff --git a/reference/shaders-hlsl/vert/legacy-int-attribute.sm30.vert b/reference/shaders-hlsl/vert/legacy-int-attribute.sm30.vert new file mode 100644 index 00000000..84e28348 --- /dev/null +++ b/reference/shaders-hlsl/vert/legacy-int-attribute.sm30.vert @@ -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; +} diff --git a/reference/shaders/legacy/vert/int-attribute.legacy.vert b/reference/shaders/legacy/vert/int-attribute.legacy.vert new file mode 100644 index 00000000..cc41c3fa --- /dev/null +++ b/reference/shaders/legacy/vert/int-attribute.legacy.vert @@ -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; +} + diff --git a/shaders-hlsl/vert/legacy-int-attribute.sm30.vert b/shaders-hlsl/vert/legacy-int-attribute.sm30.vert new file mode 100644 index 00000000..6f88febf --- /dev/null +++ b/shaders-hlsl/vert/legacy-int-attribute.sm30.vert @@ -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); +} diff --git a/shaders/legacy/vert/int-attribute.legacy.vert b/shaders/legacy/vert/int-attribute.legacy.vert new file mode 100644 index 00000000..6f88febf --- /dev/null +++ b/shaders/legacy/vert/int-attribute.legacy.vert @@ -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); +} diff --git a/spirv_glsl.cpp b/spirv_glsl.cpp index 4b22d47e..c4597952 100644 --- a/spirv_glsl.cpp +++ b/spirv_glsl.cpp @@ -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(get_decoration(source_id, DecorationBuiltIn)); auto expected_type = expr_type.basetype; diff --git a/spirv_hlsl.cpp b/spirv_hlsl.cpp index b3ba5804..19990b80 100644 --- a/spirv_hlsl.cpp +++ b/spirv_hlsl.cpp @@ -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) {