0
votes

Calling CreateInputLayout creates an Input Layout that works only for a shader with the exact same Semantic locations using a single buffer for vertex data.

For example:

VSInput1
{
    float3 Position  : POSITION;
    float2 TexCoord0 : TEXCOORD0;
    float3 Normal    : NORMAL;
};

does not translate over correctly to:

VSInput2
{
    float3 Position  : POSITION;
    float3 Normal    : NORMAL;
};

i.e., while using the shader attached to VSInput2 and Input Layout from VSInput1, TEXCOORD0 from VSInput1 will be used in the place of NORMAL from VSInput2 despite using the Input Layout from VSInput1 stating that NORMAL is after TEXCOORD0.

This behavior indicates that CreateInputLayout only uses Semantics to determine if a shader possesses them, and otherwise disregards variable location in memory.

This is horrible because it would require one of these two options:

1) Create a new Input Layout using the compiled shader code of the VSInput2 shader.

This would take more memory to create a new Input Layout for each buffer requiring the use of multiple shaders (taking into consideration shadows). OpenGL handles the noncontiguous memory locations with ease by determining the location where in the buffer the data should reside. Apparently, DX11 does not.

2) Break the vertex data down into separate buffers.

This would be slower than having the memory in order, i.e. jumping to a location just to return to the next location in the previous buffer.

From MS website:

the data may be reinterpreted when read from a register

Is there a way to ensure the register is interpreted in the manner required above without having to write the shader in asm?

If asm is required, then how would the Input Layout be created?

1
DX10 and DX11 use that mechanism to prepare everything at initialization and prevent unwanted complex and costly process while rendering frames. Modern GPU do not have hardware anymore to fetch from buffers easily. It means that a vertex shader need a new compilation for each different buffer layout. OpenGL continue to stick to the DX9 lazy way of things were at each draw, things triggers without controls because of an unanticipated rendering context.galop1n
Your proposed solution 1 and 2 are the same because of the need of different shaders anyway in the lower level layer next to the GPU. OpenGL just hide more stuff from you and miss opportunity to prepare stuff in advance as the API care more on legacy compatibility and is not as near to the GPU hardware as it was in the past.galop1n

1 Answers

2
votes

Hand-crafting the input layout is not possible. If you want a more generic input assembly mechanism, you always have the option to read vertex data from a ShaderResourceView, interpreting it using whatever logic you like. Keep in mind, however, that if you want the layout to be flexible at run-time within a single shader, you will require significant branching or pre-load arithmetic which will degrade performance.

A better approach would in fact be your option (1) above. While it's true that creating multiple input layouts does increase memory requirements, it's significantly faster at run-time; to have any shader's input layout "just work" would require run-time patching of some sort; noticeable framerate difference versus a few hundred Bytes of overhead? I'll take perf please. I also suspect the same thing is going on behind the scenes in OpenGL for the same performance reasons, though it may not be exposed directly through the API.

Ultimately, switching input layout is costly in general, and should be avoided. Really, the best approach is to try to stick to only a handful of them and switch only when necessary. You may end up wasting a bit of memory, but you'll almost certainly get better performance by reusing VSInput1 as the input for the shader associated with VSInput2, even if you're not using the float2 TexCoord0 : TEXCOORD0; input.

Really the best approach would be to implement what you think is best, profile, and see where you can make performance improvements. Unless this is just about programming simplicity in which case you might be out of luck.