InputLayout Permutations

Started by
3 comments, last by Aqua Costa 10 years, 8 months ago

Hello,

I was checking Hieroglyph 3 source code and I think I found something really useful...

It looks like you can use the same array D3D11_INPUT_ELEMENT_DESC array to create multiple InputLayout permutations.


m_iPointLightIL = Renderer.CreateInputLayout( inputElements, m_PointLightEffect[0].GetVertexShader() );
m_iSpotLightIL = Renderer.CreateInputLayout( inputElements, m_SpotLightEffect[0].GetVertexShader() );
m_iDirectionalLightIL = Renderer.CreateInputLayout( inputElements, m_DirectionalLightEffect[0].GetVertexShader() );

As you can see the CreateInputLayout function is called 3 times using the same inputElements to create multiple (different) InputLayouts.

So the D3D Device goes through the inputElements and picks the ones that match the semantics (and format, etc) in the vertex shader input and ignores the rest?

Is this referred somewhere in the documentation and I simply missed it?

This will greatly simplify my tools and InputLayout management so thanks MJP smile.png .

Advertisement

Actually if that's from one of the deferred rendering samples, then I'm pretty sure that I wrote that code. tongue.png

The input elements array that you passed is meant to represent all of the possible elements that you will have in your vertex buffer when you render with that vertex shader. The input layout then represents a unique mapping of those elements to the input parameters of the vertex shader. There doesn't need to be a 1:1 relation between vertex elements and VS input parameters, the input elements just needs to contain at least the parameters expected by the vertex shader. All other elements will be ignored. So yes, you can certainly re-use a vertex element array if you're using the same vertex buffer with different vertex shaders. A good example would be if you had a mesh, and you had two sets of shaders: one for normal rendering, and one for shadow map rendering. The main vertex shader will probably require all of the vertex elements, but the shadow map vertex shader will probably require only the positions. Since the two shaders have different input parameters you'll need to 2 different input layouts, but if you use the same vetex buffer for both then you can re-use the same vertex element array.

You can also use the same input layout for different vertex shaders as long as the vertex shaders have the same input signature.

Actually if that's from one of the deferred rendering samples, then I'm pretty sure that I wrote code. tongue.png


Fixed happy.png

A good example would be if you had a mesh, and you had two sets of shaders: one for normal rendering, and one for shadow map rendering. The main vertex shader will probably require all of the vertex elements, but the shadow map vertex shader will probably require only the positions. Since the two shaders have different input parameters you'll need to 2 different input layouts, but if you use the same vetex buffer for both then you can re-use the same vertex element array.

Will this improve performance of the Input Assembler? The memory performance will be the same right? Because the IA will still have to read all data from the vertex buffer and select the vertex elements it needs.

How is the vertex data passed from the IA to the VS? Is it copied by "value" to a temporary buffer that the vertex shader reads from?

On all hardware that I'm familiar with, there's no dedicated functionality for fetching vertices. Instead there will be a small bit of auto-generated vertex shader code that's run before your actual vertex shader, and that code will be responsible for reading data from your vertex buffer(s) using normal shader buffer loads and storing loaded vertex data into registers. AMD refers to this as a "fetch shader" in their documentation, and I think you can find a bit about how it works in their architecture guides. An input layout essentially contains all data required to generate this bit of shader code, so is probably why the D3D10/D3D11 API requires you to create input layouts ahead of time instead of just binding a vertex declaration like you did in D3D9. In the old D3D9 model the driver couldn't fully generate a fetch shader until you bound the vertex declaration and vertex shader for rendering, which meant it might have to do expensive driver work the first time that you do it. In D3D10/D3D11 on the other hand the association is known ahead of time, the driver can do it during initialization/loading instead of mid-frame.

As far as performance goes, the fetch shader is only going to read the vertex elements required by the vertex shader and will ignore everything else. So if you have extra elements in the vertex buffer that goes unused, the main performance deficient will be that you will have some extra unused data polluting the cache while the shader is running. If you were to have a more optimal vertex buffer that only contained the elements required by the vertex shader, then it's more likely that you'll get a cache hit. In practice though vertex shader memory access isn't something that I find myself having to optimize very often.

Thanks for the explanation.

This topic is closed to new replies.

Advertisement