5

people.

I have a problem passing a float array to vertex shader (HLSL) through constant buffer. I know that each "float" in the array below gets a 16-byte slot all by itself (space equivalent to float4) due to HLSL packing rule:

// C++ struct
struct ForegroundConstants
{
    DirectX::XMMATRIX transform;
    float bounceCpp[64];
};


// Vertex shader constant buffer
cbuffer ForegroundConstantBuffer : register(b0)
{
    matrix transform;
    float bounceHlsl[64];
};

(Unfortunately, the simple solution here does not work, nothing is drawn after I made that change)

While the C++ data gets passed, due to the packing rule they get spaced out such that each "float" in the bounceCpp C++ array gets into a 16-byte space all by itself in bounceHlsl array. This resulted in an warning similar to the following:

ID3D11DeviceContext::DrawIndexed: The size of the Constant Buffer at slot 0 of the Vertex Shader unit is too small (320 bytes provided, 1088 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.

The recommendation, as being pointed out here and here, is to rewrite the HLSL constant buffer this way:

cbuffer ForegroundConstantBuffer : register(b0)
{
    matrix transform;
    float4 bounceHlsl[16]; // equivalent to 64 floats.
};

static float temp[64] = (float[64]) bounceHlsl;

main(pos : POSITION) : SV_POSITION
{
    int index = someValueRangeFrom0to63;
    float y = temp[index];

    // Bla bla bla...
}

But that didn't work (i.e. ID3D11Device1::CreateVertexShader never returns). I'm compiling things against Shader Model 4 Level 9_1, can you spot anything that I have done wrong here?

Thanks in advance! :)

Regards, Ben

Community
  • 1
  • 1
Ben Goh
  • 107
  • 1
  • 3
  • 11

1 Answers1

4

One solution, albeit non optimal, is to just declare your float array as

float4 bounceHlsl[16];

then process the index like

float x = ((float[4])(bounceHlsl[i/4]))[i%4];

where i is the index you require.

alanw
  • 645
  • 6
  • 10
  • Thanks Alanw, I guess this works (as I have seen it on other sites, too), but it does not work in my case. I'll proceed to mark yours as answer though, and debug further to find out what is failing for me :) – Ben Goh Feb 12 '13 at 16:08
  • 2
    But be careful, it can be inefficient: https://geidav.wordpress.com/2013/03/05/hidden-hlsl-performance-hit-accessing-unpadded-arrays-in-constant-buffers/ – vines Nov 03 '17 at 17:58