InputLayout Build-O-Matic – FXO Edition

I'm lacking inspiration for a title picture. Have a platypus.
I’m lacking inspiration for a title picture. Have a platypus.

Or, “How to access the bytecode of a vertex shader in a compiled DirectX Effect file?”

Earlier in the year, looking into symplifying the use of my DirectX library, I have been pointed to a tutorial by Bobby Anguelov, which described in detail how to load your own InputLayout for a shader by using reflection. InputLayouts are usually difficult to implement coherently, without having to hard code them to match each individual shader in the application.

But what this code allows you to do is, in a nutshell, to read the compiled shader bytecode to obtain the input information of the vertex shader. Based on this information, you can automatically set up a suitable InputLayout to bind to the shader.

You can find this tutorial on Bobby’s blog.

This tutorial is indeed very useful, except that my library uses the Effects framework (which Microsoft had the grace of deprecating – FABULOUS!). The Effects framework provides its own implementation of reflection, but nonetheless the process of accessing the shader input is the same as in the tutorial above, using an instance of ID3D11ShaderReflection.

However, what changes is how we obtain the shader bytecode, to create said instance. We need to access it through the framework’s own reflection, by obtaining the description of the pass within the technique we want to build the layout for. From the pass description, we can then obtain the Vertex Shader description, which will provide us with the desired ShaderEffectVariable. Using the ShaderEffectVariable, we create the shader’s description, which contains the shader’s bytecode! 

Here is a snippet which creates an ID3D11ShaderReflection instance from Pass 0 of Technique 0 of an effect. It is probably a lot more demonstrative.

ID3DX11EffectTechnique* currentEffectTechnique = 0;

currentEffectTechnique = m_effect->GetTechniqueByIndex(0);
 passDesc.pShaderVariable->GetShaderDesc(passDesc.ShaderIndex, &shaderDesc);
 ID3D11ShaderReflection* shaderReflection = 0;

if( FAILED(D3DReflect(shaderDesc.pBytecode, shaderDesc.BytecodeLength, IID_ID3D11ShaderReflection, (void**)&shaderReflection)))
 return S_FALSE;

[Although it builds, I haven’t had the chance to test it properly. It should work, but handle with care!]


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s