Sign in to follow this  
Dave Eberly

ID3D11ShaderReflection question

Recommended Posts

Dave Eberly    1173
I am trying this approach to querying the ID3DBlob* that is returned from compiling a shader. I have a cbuffer that contains several native-data-type members and a struct definition with various members of type 'matrix', 'float2', and 'float[]' where the last item (in my special case) is an array of 5 numbers.

I grab an ID3DShaderReflectionBuffer pointer from GetConstantBufferByName(...), iterate over the variables (using GetVariableByIndex and GetType), finding out that the struct information has Class = D3D_SVC_STRUCT. For this item, I iterate over the members (GetMemberTypeName and GetMemberTypeByIndex).

The information I get from this approach appears not to have everything I need to know about the memory layout of the cbuffer. My struct has two 'matrix' elements, two 'float2' elements, and an array 'float[5]'. The 'matrix' elements report correct offsets relative to the parent struct (64 and 128), the two 'float2' elements appear to be packed into a single 4-float register, but each array element from the 'float[5]' is mapped to a single register (.x component, but the .yzw components are ignored). I do not believe the shader reflection interface allows me to deduce the packing of the struct. Is this a known deficiency? Or am I missing something about the query process?

If need be, I can post a link to a simple MSVS project that shows what I am doing, what my experiments are, and what information I get from those experiments.

Thanks.

Share this post


Link to post
Share on other sites
MJP    19755
When you say that you cannot obtain the packing of the struct, are you referring specifically to the packing of elements within the array? Arrays are [url="http://msdn.microsoft.com/en-us/library/windows/desktop/bb509632%28v=vs.85%29.aspx"]always packed[/url] such that elements start on a float4 boundary, and there's no way to override that so you should be able to infer the offset of an element within that array by calculating roundUpTo16(sizeof(ArrayType)) * elementIndex.

Share this post


Link to post
Share on other sites
Dave Eberly    1173
I found another post of yours that mentions the assignment of each element of a float[] to a single register. That was helpful. When I query for the array member, I saw Rows=1, Columns=1, and Elements=5, which seemed strange (a 1x1 array with 5 elements?). Because the query does not tell me I have an "array", I suppose that I can infer it from Rows==1 and Columns==1 and Elements > 1. The other information that seemed strange: cbuffer Whatever { struct Something {...}; Something A; Something B[2]}. The number of bytes reported for A is different from the number of bytes reported for B. Of course, for B the number of bytes is for both array items, but it was not [b]twice[/b] the size of A. And it appears I'd have to [b]assume[/b] that both array items of B use the same number of bytes. Reverse engineering (by compiling some shaders that access the .x components of various struct members) made it clear that there was some set of rules the compiler was using. So I think that knowing how arrays are mapped to registers and knowing to trap the rows/columns/elements case I mentioned, I can infer the packing of the struct (which I want so I know how to typecast the mapped cbuffer data properly). Thanks.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this