Issues With Input Layout

Started by
12 comments, last by eppo 11 years, 5 months ago
Currently, i have two techniques setup for my skinned mesh, one using straight Diffuse texturing, and one using Normal Mapping. I want to be able to toggle between these techniques during runtime. My model contains the following attributes in the vertex buffer

float3 Position
float2 TexCoord
float3 Normal
float4 Tangent
float4 Weights
float4 Bones

Then i have my vertex shader input setup as such


struct GeometryVSIn {
float3 position : Position;
float2 texCoord : TexCoord;
float3 normal : Normal;
#ifdef NORMALMAP
float4 tangent : Tangent;
#endif
#ifdef SKINNED
float4 weights : Weights;
float4 bones : Bones;
#endif
};


now if i run the normal mapped technique, all works fine, and looks correct. However, if i run it without normal mapping ( I Don't define the preprocessor definition NORMALMAP), i get an error message as follows from Direct3D in the output window

D3D11: ERROR: ID3D11DeviceContext::DrawIndexed: Input Assembler - Vertex Shader linkage error: Signatures between stages are incompatible. Semantic 'Weights' is defined for mismatched hardware registers between the output stage and input stage. [ EXECUTION ERROR #343: DEVICE_SHADER_LINKAGE_REGISTERINDEX ]
D3D11: ERROR: ID3D11DeviceContext::DrawIndexed: Input Assembler - Vertex Shader linkage error: Signatures between stages are incompatible. Semantic 'Bones' is defined for mismatched hardware registers between the output stage and input stage. [ EXECUTION ERROR #343: DEVICE_SHADER_LINKAGE_REGISTERINDEX ]

Now when i view it in PIX, i see that the Tangent values are being passed thru to the vertex shader even though they are not supposed to be. I am under the impression that i can define my vertex buffer to have as many elements in it as i want, and inside the vertex shader using Semantics, i can tell the shader which ones to use, and which ones not to use (map to certain registers, etc...), although this doesn't seem to be the case that i am experiencing.

Would appreciate any help
Code makes the man
Advertisement
I assume you are using the same input layout for both cases?

Input signatures between the input assembler and the vertex shader stage aren't compatible when you're skipping the Tangent semantic in the VS input struct.

http://msdn.microsoft.com/en-us/library/windows/desktop/bb509650(v=vs.85).aspx
So, based on that, i shouldn't even worry about creating a vertex shader per model, instead i should just use reflection at shader creation, and retrieve the input layout from that, and set that based on the shader that is currently bound...
Code makes the man
and when i skip the tangent piece, why are the input assembler and the vertex shader stage incompatible... it is a subset of the input assembler, and the order is the same though... sorry i am not seeing it, it's one of those days.
Code makes the man
The input layout tells the input assembler what your giving it. When you don't define NORMALMAP, you will also have to not define it in your input assembler. you will also have to adjust each element's offset after the NORMALMAP element in the input layout, otherwise what will happen is your input assembler will still think you are giving it tangent data, but since you did not define NORMALMAP, it will actually be reading the next member in your structure, which looks like weights. by the time it gets to the bones data, it will have run out of data for that vertex, and either give you an error right there, or start reading into the next vertex, which then every vertex after will be off, and eventually you will run into an error anyway after there is no more vertex data.

if NORMALMAP is defined, everything will work just fine, but if NORMALMAP is not defined, but the input layout has not changed, the input assembler will still expect it.

struct Vertex // Vertex Structure
{
XMFLOAT3 pos;
XMFLOAT2 texCoord;
#ifdef NORMALMAP
XMFLOAT3 normal;
#endif
XMFLOAT3 tangent;
};

// input layout
D3D11_INPUT_ELEMENT_DESC layout[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 20, D3D11_INPUT_PER_VERTEX_DATA, 0},
{ "TANGENT", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 32, D3D11_INPUT_PER_VERTEX_DATA, 0}
};


even if you changed the code so that you took out NORMAL from the input layout when NORMALMAP is not defined, there would still be a problem because TANGENT offset is still 32. if NORMALMAP is not defined, you will need to remove NORMAL from the input layout and change TANGENT offset to 20.
So using the semantics Position, TexCoord, Normal, Tangent, etc... does not tell the shader which chunk to pull. It just pulls the vertex buffer in completely, and reads that data as is ? not sure i understand the point of the semantics then aside from readability on the developers side...
Code makes the man
sorry, your right, that was a mistake. you don't have to match the vertex shaders input exactly with the input layout.

you just have to match the input layout with your vertex structure so that the input assembler knows what its getting. more specifically you have to match the input layout with the structure of vertices in the buffer you will give to the input assembler, since this buffers vertices might differ from the vertex structure you use in your applications code
so if that is the case, then i should be able to use one input layout, that describes my vertex buffer, all elements in it. and then inside of my vertex shader, i should be able to extract the elements i need, as long as i keep them in the same order as the input layout.

example
vertexbuffer has the following elements
-Position (float3)
-TexCoord1(float2)
-TexCoord2(float2)
-Normal(float3)

inputlayout created to match that vertexbuffer

inside of my vertex shader i shoudl be able to pull
-Position
-TexCoord1
-Normal

and skip over the second set, as not all of my vertex shaders need the second set of tex coords. or do i need an input layout for every permutation, which doesn't seem right at all
Code makes the man
yes, you can do that. i made a mistake though, and you don't have to match the vertex shaders inputs with the input layout. you can just take whichever elements you want out of the vertex data, skipping the ones you don't need, as long as the data the vertex shader wants is in the vertex structure and input layout (although you will want to avoid sending extra data you don't use as much as possible for performance reasons)
So in my original issue at the beginning, I have tangent data in my vertex buffer, however on the low end technique I don't need it, so I reprocess it out. My input layout has tangent in it correctly. So why doesn't it skip over that portion of the vertex buffer and go to weights next?
Code makes the man

This topic is closed to new replies.

Advertisement