2
\$\begingroup\$

I'm having some problems when passing multiple light structures to a shader stage. I'm using an array of point lights that is updated each frame.

This is my code for creating the buffer

D3D11_BUFFER_DESC lbDesc;
lbDesc.ByteWidth            = sizeof( PointLightData ) * NUM_LIGHTS;
lbDesc.Usage                = D3D11_USAGE_DYNAMIC;
lbDesc.BindFlags            = D3D11_BIND_CONSTANT_BUFFER;
lbDesc.CPUAccessFlags       = D3D11_CPU_ACCESS_WRITE;
lbDesc.MiscFlags            = 0;
lbDesc.StructureByteStride  = 0;

hr = mDevice->CreateBuffer( &lbDesc, nullptr, &mLightBuffer );

And this is how I update it

D3D11_MAPPED_SUBRESOURCE mappedResource;
hr = mDeviceContext->Map( mLightBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource );

if( SUCCEEDED( hr ) )
{
    memcpy( mappedResource.pData, &mPointLightData[0], sizeof(PointLightData) * NUM_LIGHTS );
    mDeviceContext->Unmap( mLightBuffer, 0 ); 
}

mPointLightData is declared like this

mPointLightData = new PointLightData[NUM_LIGHTS];

In my shader I declare the light

struct PointLight
{
    float4  positionAndRadius;
    float4  ambient;
    float4  diffuse;
    float4  specular;
    float3  attenuation;
};

cbuffer CB_LIGHT : register(b1)
{
    PointLight  pointLight[2];
};

I can only access the first light object in the buffer successfully. Rendering the second light results in a pitch black scene.

However, if I change the starting address at the mapping stage from &mPointLightData[0] to &mPointLightData[1] the second light works but obviously not the first.

So my guess is that I'm doing simething wrong at either the mapping stage or at the creation of the buffer..

Any suggestions? Thank you!

\$\endgroup\$
3
\$\begingroup\$

There are additional alignment and layout rules for constant buffers. The float3 probably needs padding on the CPU side to get the right stride.

Roughly paraphrased, things need to be on 16-byte boundaries.

\$\endgroup\$
  • \$\begingroup\$ This totally fixed it! I've always thought that the size of the structure had to be a multiple of 16. Not that each element within a structure had to be 16-byte alligned. I thank you for adding knowledge to my brain! \$\endgroup\$ – SvinSimpe Aug 7 '15 at 14:19
  • \$\begingroup\$ Use Debug Layer to diagnose those issues; in your case, DX runtime will print that your buffers are not aligned properly. msdn.microsoft.com/en-us/library/windows/desktop/… \$\endgroup\$ – Hernán Mar 15 '16 at 21:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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