WGSL target doesn't increase location id for attributes
Closed this issue · 5 comments
Simple rasterization pipeline shader doesn't increase the location id for the different inputs.
struct VertexOutput {
float4 position : SV_Position;
float4 color : F_COLOR;
}
struct VertexInput {
float2 position : V_POSITION;
float4 color : V_COLOR;
}
[shader("vertex")]
VertexOutput vert(VertexInput input) {
var output: VertexOutput;
output.position = float4(input.position, 0.0, 1.0);
output.color = input.color;
return output;
}
struct FragmentInput {
float4 color : F_COLOR;
}
[shader("fragment")]
float4 frag(FragmentInput input) : SV_Target
{
return input.color;
}
Output:
struct VertexOutput_0
{
@builtin(position) position_0 : vec4<f32>,
@location(0) color_0 : vec4<f32>,
};
struct VertexInput_0
{
@location(0) position_1 : vec2<f32>,
@location(0) color_1 : vec4<f32>,
};
@vertex
fn vert( input_0 : VertexInput_0) -> VertexOutput_0
{
var output_0 : VertexOutput_0;
output_0.position_0 = vec4<f32>(input_0.position_1, 0.0f, 1.0f);
output_0.color_0 = input_0.color_1;
return output_0;
}
struct pixelOutput_0
{
@location(0) output_0 : vec4<f32>,
};
struct FragmentInput_0
{
@location(0) color_0 : vec4<f32>,
};
@fragment
fn frag( input_0 : FragmentInput_0) -> pixelOutput_0
{
var _S1 : pixelOutput_0 = pixelOutput_0( input_0.color_0 );
return _S1;
}
I would expect the location ids inside VertexInput_0
to increase, so position_1
has @location(0)
while color_1
has @location(1)
.
Have already tried playing with the semantics defined, renaming them, but the output remains the same.
As per the documentation inside "WGSL specific functionalities":
Parameters without semantics are given automatic location indices. (See the @location attribute.)
I would believe they shouldn't even need a user defined semantics.
But if I remove the defined semantics I get the following result:
struct VertexOutput {
float4 position : SV_Position;
float4 color : F_COLOR;
}
struct VertexInput {
float2 position;
float4 color;
}
[shader("vertex")]
VertexOutput vert(VertexInput input) {
var output: VertexOutput;
output.position = float4(input.position, 0.0, 1.0);
output.color = input.color;
return output;
}
struct FragmentInput {
float4 color : F_COLOR;
}
[shader("fragment")]
float4 frag(FragmentInput input) : SV_Target
{
return input.color;
}
generated:
struct VertexOutput_0
{
@builtin(position) position_0 : vec4<f32>,
@location(0) color_0 : vec4<f32>,
};
struct VertexInput_0
{
position_1 : vec2<f32>,
color_1 : vec4<f32>,
};
@vertex
fn vert( input_0 : VertexInput_0) -> VertexOutput_0
{
var output_0 : VertexOutput_0;
output_0.position_0 = vec4<f32>(input_0.position_1, 0.0f, 1.0f);
output_0.color_0 = input_0.color_1;
return output_0;
}
struct pixelOutput_0
{
@location(0) output_0 : vec4<f32>,
};
struct FragmentInput_0
{
@location(0) color_0 : vec4<f32>,
};
@fragment
fn frag( input_0 : FragmentInput_0) -> pixelOutput_0
{
var _S1 : pixelOutput_0 = pixelOutput_0( input_0.color_0 );
return _S1;
}
Where the attributes inside VertexInput_0
no longer generate @location
.
First time diving into slang so I might be missing something.
Commit: fdf061e
OS: Linux
That seems to be a bug in Slang.
I expect that color in VertexInput to have 1 not 0.
Yes, this is a known problem and we are working to address this issue.
Interestingly, the issue of repeated locations seems to only happen to stage inputs.
For example, if I add localPosition
between vertex and fragment stages, then its location is numbered
correctly for the vertex output, but not for the fragment input.
struct VertexOutput {
float4 position : SV_Position;
float2 localPosition : V_LOCAL_POSITION;
float4 color : F_COLOR;
}
struct VertexInput {
float2 position : V_POSITION;
float4 color : V_COLOR;
}
VertexOutput vertexMain(VertexInput input) {
var output: VertexOutput;
output.position = float4(input.position, 0.0, 1.0);
output.localPosition = input.position;
output.color = input.color;
return output;
}
struct FragmentInput {
float4 localPosition : V_LOCAL_POSITION;
float4 color : F_COLOR;
}
float4 fragmentMain(FragmentInput input) : SV_Target
{
return input.color + input.localPosition;
}
Resulting WGSL vertex shader (notice repeated/incrementing location index in input/output):
struct VertexOutput_0
{
@builtin(position) position_0 : vec4<f32>,
@location(0) localPosition_0 : vec2<f32>,
@location(1) color_0 : vec4<f32>,
};
struct VertexInput_0
{
@location(0) position_1 : vec2<f32>,
@location(0) color_1 : vec4<f32>,
};
@vertex
fn vertexMain( input_0 : VertexInput_0) -> VertexOutput_0
{
var output_0 : VertexOutput_0;
output_0.position_0 = vec4<f32>(input_0.position_1, 0.0f, 1.0f);
output_0.localPosition_0 = input_0.position_1;
output_0.color_0 = input_0.color_1;
return output_0;
}
Resulting WGSL fragment shader (notice repeated location index in input):
struct pixelOutput_0
{
@location(0) output_0 : vec4<f32>,
};
struct FragmentInput_0
{
@location(0) localPosition_0 : vec4<f32>,
@location(0) color_0 : vec4<f32>,
};
@fragment
fn fragmentMain( input_0 : FragmentInput_0) -> pixelOutput_0
{
var _S1 : pixelOutput_0 = pixelOutput_0( input_0.color_0 + input_0.localPosition_0 );
return _S1;
}
I created a small fix that seems to fix the repeated input location issue: #5642
Input with explicit semantics:
struct VertexOutput {
float4 position : SV_Position;
float4 color : F_COLOR;
}
struct VertexInput {
float2 position : V_POSITION;
float4 color : V_COLOR;
}
[shader("vertex")]
VertexOutput vert(VertexInput input) {
var output: VertexOutput;
output.position = float4(input.position, 0.0, 1.0);
output.color = input.color;
return output;
}
struct FragmentInput {
float4 color : F_COLOR;
}
[shader("fragment")]
float4 frag(FragmentInput input) : SV_Target
{
return input.color;
}
Output vertex:
struct VertexOutput_0
{
@builtin(position) position_0 : vec4<f32>,
@location(0) color_0 : vec4<f32>,
};
struct VertexInput_0
{
@location(0) position_1 : vec2<f32>,
@location(1) color_1 : vec4<f32>,
};
@vertex
fn vertexMain( input_0 : VertexInput_0) -> VertexOutput_0
{
var output_0 : VertexOutput_0;
output_0.position_0 = vec4<f32>(input_0.position_1, 0.0f, 1.0f);
output_0.color_0 = input_0.color_1;
return output_0;
}
Output fragment:
struct pixelOutput_0
{
@location(0) output_0 : vec4<f32>,
};
struct FragmentInput_0
{
@location(0) color_0 : vec4<f32>,
};
@fragment
fn fragmentMain( input_0 : FragmentInput_0) -> pixelOutput_0
{
var _S1 : pixelOutput_0 = pixelOutput_0( input_0.color_0 );
return _S1;
}
That still doesn't fix the issue where there is no location attribute generated in case no semantics are specified... working on that now.
With PR #5670, the version without any semantics also seems to now also work:
Input Slang code:
struct VertexOutput {
float4 position : SV_Position;
float4 color;
}
struct VertexInput {
float2 position;
float4 color;
}
[shader("vertex")]
VertexOutput vert(VertexInput input) {
var output: VertexOutput;
output.position = float4(input.position, 0.0, 1.0);
output.color = input.color;
return output;
}
struct FragmentInput {
float4 color;
}
[shader("fragment")]
float4 frag(FragmentInput input) : SV_Target
{
return input.color;
}
Output vertex shader WGSL code:
struct VertexOutput_0
{
@builtin(position) position_0 : vec4<f32>,
@location(0) color_0 : vec4<f32>,
};
struct VertexInput_0
{
@location(0) position_1 : vec2<f32>,
@location(1) color_1 : vec4<f32>,
};
@vertex
fn vert( input_0 : VertexInput_0) -> VertexOutput_0
{
var output_0 : VertexOutput_0;
output_0.position_0 = vec4<f32>(input_0.position_1, 0.0f, 1.0f);
output_0.color_0 = input_0.color_1;
return output_0;
}
Output fragment shader WGSL code:
struct pixelOutput_0
{
@location(0) output_0 : vec4<f32>,
};
struct FragmentInput_0
{
@location(0) color_0 : vec4<f32>,
};
@fragment
fn frag( input_0 : FragmentInput_0) -> pixelOutput_0
{
var _S1 : pixelOutput_0 = pixelOutput_0( input_0.color_0 );
return _S1;
}