Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I have the following C/C++ struct:

struct ShadowMapCB {
        Math::Matrix4 cropMatrix[4];
        Math::Matrix4 textureMatrix[4];
        float splitPlane[4];
    };

and my HLSL constant buffer:

cbuffer CBShadowMap : register(b4)
{
    matrix g_CropMatrix[4];
    matrix g_TextureMatrix[4];
    float g_fSplitPlane[4];
};

When i bind it to pixel shader i get an error:

D3D11: WARNING: ID3D11DeviceContext::DrawIndexed: The size of the Constant Buffer at slot 4 of the Pixel Shader unit is too small (528 bytes provided, 576 bytes, at least, expected). This is OK, as out-of-bounds reads are defined to return 0. It is also possible the developer knows the missing data will not be used anyway. This is only a problem if the developer actually intended to bind a sufficiently large Constant Buffer for what the shader expects. [ EXECUTION WARNING #351: DEVICE_DRAW_CONSTANT_BUFFER_TOO_SMALL ]

and infact the last 4 floats (array[4]) are messed up, the weird thing is that on the VS and GS it works fine..., and yes i did bind them with PSSetConstantBuffers and update it ofcourse.

What could be causing this?

share|improve this question
1  
Only thing i cant think of out of the box is that the gpu might be padding them up to another 64 boundry... so you simply missingout 48 bytes... but i have gotten the same issues latley. But some how just solved them.. –  Tordin Jan 30 '13 at 14:23
    
actually you're right, i just set the g_fSplitPlane variable to a float4 type (float4 g_fSplitPlane) and then i cast it as an array and it works nicely. –  Jeremy Rodriguez Jan 30 '13 at 14:42

1 Answer 1

up vote 2 down vote accepted

IIRC, in a constant buffer, each element of an array must start on a 4-float boundary. That didn't affect the matrices since each matrix already starts on a 4-float boundary, but it caused the float g_fSplitPlane[4] to get an extra 3 floats of padding between array elements.

The constant buffer layout rules are the same for all kinds of shaders, so if it doesn't work in the PS, it shouldn't work in the VS and GS either. Was the g_fSplitPlane member not used in the VS and GS, perhaps? If so, the shader compiler might have stripped it out of those, preventing the error from firing.

share|improve this answer
    
Yes, g_fSplitPlane wasn't used in the VS and GS. –  Jeremy Rodriguez Feb 1 '13 at 16:04
    
So doesn't float g_fSplitPlane[4] just get packed neatly into 16 consecutive bytes? But float4 myVect does? That's ridiculous! –  NPS Aug 12 '13 at 23:07
    
@NPS It has to do with dynamic constant indexing on older architectures. The constant buffer was made of 16-byte registers so if you wanted to get g_fSplitPlane[i], where i is calculated dynamically, it would be a lot cheaper if elements of the array were in consecutive registers, rather than packed tightly together. –  Nathan Reed Aug 12 '13 at 23:10
    
@NathanReed So if I don't want to waste 48 bytes (padding) of memory I should use float4 instead? What if I need to use char array[32]? –  NPS Aug 12 '13 at 23:14
    
@NPS I'm not sure if HLSL even has a char type, but if it does, then yeah, an array of char would waste 15 bytes for each element. That's how it works for constant buffers. On D3D11 you could use structured buffers instead, which are packed tighter. –  Nathan Reed Aug 12 '13 at 23:20

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.