3
\$\begingroup\$

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?

\$\endgroup\$
2
  • 1
    \$\begingroup\$ 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.. \$\endgroup\$
    – Tordin
    Commented Jan 30, 2013 at 14:23
  • \$\begingroup\$ 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. \$\endgroup\$ Commented Jan 30, 2013 at 14:42

1 Answer 1

3
\$\begingroup\$

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.

\$\endgroup\$
8
  • \$\begingroup\$ Yes, g_fSplitPlane wasn't used in the VS and GS. \$\endgroup\$ Commented Feb 1, 2013 at 16:04
  • \$\begingroup\$ So doesn't float g_fSplitPlane[4] just get packed neatly into 16 consecutive bytes? But float4 myVect does? That's ridiculous! \$\endgroup\$
    – NPS
    Commented Aug 12, 2013 at 23:07
  • \$\begingroup\$ @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. \$\endgroup\$ Commented Aug 12, 2013 at 23:10
  • \$\begingroup\$ @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]? \$\endgroup\$
    – NPS
    Commented Aug 12, 2013 at 23:14
  • \$\begingroup\$ @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. \$\endgroup\$ Commented Aug 12, 2013 at 23:20

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .