6
\$\begingroup\$

I had been debugging a problem I was having in a single shader file with 2 functions in it. I'm using DirectX 11, vs_5_0 and ps_5_0. I have stripped it down to its basic components to understand what was going wrong with the shaders, because the different named components of the Pixel and Vertex shaders were swapping the data being input:

void QuadVertex ( inout float4 position : SV_Position,
            inout float4 color : COLOR0,
            inout float2 tex : TEXCOORD0 ) {
    // ViewProject is a 4x4 matrix,
    // just included here to show the simple passthrough of the data
    position = mul(position, ViewProjection);
}

And a Pixel Shader:

float4 QuadPixel (  float4 color : COLOR0,
            float2 tex : TEXCOORD0 ) : SV_Target0 {
    // Color is filled with position data and tex is
        // filled with color values from the Vertex Shader
    return color;
}

The ID3D11InputLayout and associated C++ code correctly compiles the shaders and sets them up with some simple primitive data:

        data[0].Position.x = 0.0f * 210;
        data[0].Position.y = 1.0f * 160;
        data[0].Position.z = 0.0f;
        data[1].Position.x = 0.0f * 210;
        data[1].Position.y = 0.0f * 160;
        data[1].Position.z = 0.0f;
        data[2].Position.x = 1.0f * 210;
        data[2].Position.y = 1.0f * 160;
        data[2].Position.z = 0.0f;
        data[0].Colour = Colors::Red;
        data[1].Colour = Colors::Red;
        data[2].Colour = Colors::Red;
        data[0].Texture = Vector2::Zero;
        data[1].Texture = Vector2::Zero;
        data[2].Texture = Vector2::Zero;

When used with the shader, the float4 color always ended up with the position data, and the float2 tex always ended up with the color data. After a moment, I figured out that the shader's input and output signatures needed to be in the correct order and the correct format and be laid out in the exact order of the output from the Vertex Shader, regardless of the semantics:

float4 QuadPixel (  float4 pos : SV_Position,
            float4 color : COLOR0,
            float2 tex : TEXCOORD0 ) : SV_Target0 {

    return color;
}

After finding this out, My question is: Why don't the semantics map the appropriate components when going from Vertex Shader to Pixel Shader? Is there any way that I can make it so certain semantics are always mapped to other semantics, or do I always have to follow the rigid Shader Signature (in this case, Position, Color, and Texture) ?

As a side note for why I'm asking: I know that when using XNA, my shader signatures for functions could differ in position and even drop items from Vertex Shader to Pixel Shader function parameters, having only the COLOR0 and TEXCOORD0 components being used (and it would still match up correctly). However, I also know that XNA relied on DX9 (and maybe a little DX10) implementation, and that maybe this kind of flexibility no longer exists in DX11?

\$\endgroup\$

2 Answers 2

4
\$\begingroup\$

Yes, this behavior changed from DX9 to DX10+, don't know much about the real story behind it, but I suspect that DX9 had to remap registers between VS and PS at runtime anyway (when linking shaders) which is inefficient.

In DX10+, when you compile a VertexShader and a PixelShader, you can see which register will be affected to a particular semantic (see output of fx.exe compiler), and these registers (which will almost map to an hardware register) should match between the output of a stage to the input of the next stage. Note that the input of a stage could have less semantics mapped, as long as the order is the same and there is no gap in the mapping.

If you are using some legacy FX file (techniques/passes) with DX10+, the compiler will check input/output signatures for you. But if you are compiling separately VS and PS, you will have to double check any signature mismatch (or you can use D3DCompiler API to verify this yourself).

There is one exception for the input of the VertexShader that is coming from the VertexBuffer and the InputLayout. The InputLayout is able to specify the byte offsets of each vertex elements and how it maps to the semantic in the VS shader, so you can have a "sparsed" mapping, the input layout can have more vertex elements/semantic bindings than the VS input, as long as all semantics from the VS are covered by the InputLayout declaration. This is handy when you have a model that has several vertex elements, and want to use the same vertex buffers for several vertex shaders that are expecting different input layouts: you can map the layout of the vertex buffer to the layout of the vertex shaders (as long as the mapping is covering all the input of the VS shader).

\$\endgroup\$
3
  • 1
    \$\begingroup\$ BTW: in DX10+, the semantics are completely user-defined. Only the semantics starting with SV, like SV_Position, correspond to specific hardware registers. There is no meaning to COLOR0 or TEXCOORD0 anymore; you could just as well call them BACON and EGGS. So of course when VS and PS are compiled separately it will not necessarily map the same semantics to the same registers. But if you use the Effects 11 API and compile everything together as a technique, it will ensure matching semantics have matching registers. \$\endgroup\$ Oct 22, 2012 at 4:19
  • \$\begingroup\$ Oh, yes, I forgot to mention the distinction between user-defined semantics and system semantics... but still, an input/output variable will be effectively affected to a register, no matter it is system or user-defined, and this register should match (same type/size) between the VS and PS. \$\endgroup\$
    – xoofx
    Oct 22, 2012 at 4:46
  • \$\begingroup\$ Thanks for your help. I was really trying to figure out if there was a way to make it 'just map', but it probably is grossly inefficient on the shader-writing side. I'll just have to be conformant between VShader and PShader: the Vertex stuff I already know how to do, but thank you for writing out the idea here! I'm sure someone besides from me could benefit a ton from it. \$\endgroup\$
    – user22071
    Oct 22, 2012 at 5:58
1
\$\begingroup\$

thanks to @xoofx 's good answer, and I found this MSDN doc:

https://msdn.microsoft.com/en-us/library/windows/desktop/bb509650(v=vs.85).aspx

\$\endgroup\$

You must log in to answer this question.