C++ Directx 11 CBuffers and HLSL.

Started by
15 comments, last by MJP 11 years, 9 months ago
Hello, im new to Game Dev, and i have a problem with c++ sending a value to the hlsl code:
These are snippets of my code:

My Shader file:


cbuffer ConstantBuffer
{
float4x4 final;
float4x4 rotation; // the rotation matrix
float4 lightvec; // the light's vector
float4 lightcol; // the light's color
float4 ambientcol; // the ambient light's color
float mp;
}


Here I just defined my constant buffer in my hlsl file.

Declaration in c++:

struct CBUFFER
{
public:D3DXMATRIX Final;
public:D3DXMATRIX Rotation;
public:D3DXVECTOR4 LightVector;
public:D3DXCOLOR LightColor;
public:D3DXCOLOR AmbientColor;
public:float MP;
};


Then later on:

cBuffer.Final = UmatRotate * UmatPosition * UmatScaling * matView * matProjection;
cBuffer.Rotation = UmatRotate;
cBuffer.MP = 2.0f;


And:

devcon->UpdateSubresource(pCBuffer, 0, 0, &cBuffer, 0, 0);


And also some other code, but which is irrelevant.

So all the values other than the mp works, the mp in my shader is not given a value, and I would like to ask why? What did I do wrong?

Best Regards
Miguel Petersen

FastCall22: "I want to make the distinction that my laptop is a whore-box that connects to different network"

Blog about... stuff (GDNet, WordPress): www.gamedev.net/blog/1882-the-cuboid-zone/, cuboidzone.wordpress.com/

Advertisement
Firstly, switch to debug mode for your DirectX application. This prints any suspicious activity in your code.
Secondly use PIX to determine what value “mp” actually has inside the shader. When my CPU-side cbuffer’s are created I initialize every 4 bytes with float value 62.0f to make it clear what has not been properly updated when I view the buffers in PIX.

The buffer needs to be created with a size that is a multiple of 16.

Also, I use Map() and Unmap() to update buffers.


LSVOID * pvConstData;
D3D11_MAPPED_SUBRESOURCE msMapped;
CDirectX11::GetDirectX11Context()->Map( m_vConstantBuffers, 0UL, D3D11_MAP_WRITE_DISCARD, 0UL, &msMapped );
pvConstData = msMapped.pData;
CStd::MemCpy( pvConstData, &m_vConstBufferRawData.vRaw[0], m_vConstBufferRawData.vRaw.Length() );
CDirectX11::GetDirectX11Context()->Unmap( m_vConstantBuffers, 0 );



L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid


The buffer needs to be created with a size that is a multiple of 16.


This will be the cause - just add 3 extra floats at the end to pad it out (in both your .cpp and your HLSL).

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.

The best advice when working with constant buffers is to always take a look at the listing which can be generated while compiling the shader (/Fc <output> when using fxc). Inside the listing you can see all the compiled constant buffers (and everything else that got compiled), and even more important, the offsets of your constants which helps you understand the alignment of your constants.
I'm pretty sure directx adds padding to the end of constant buffers when they do not add up to a multiple of 4 bytes.

This will be the cause - just add 3 extra floats at the end to pad it out (in both your .cpp and your HLSL).


I'm pretty sure directx adds padding to the end of constant buffers when they do not add up to a multiple of 4 bytes.

In my experience, creation of the cbuffer simply fails when you do not pass an initial size that is a multiple of 16 bytes.
That would indicate that he has passed a multiple of 16 bytes if he is able to get any result at all.

But the reason I mentioned it is because I am also open to the possibility that I do not know about some quirks or such regarding DirectX 11, and maybe there are some circumstances that allow creating buffers of other sizes.

For now I am sitting on the fence. Since he is able to get any result at all, I am generally going to assume he passed a multiple of 16 when creating the buffer, but am waiting for evidence that this is not the case and that there is some other way to create a buffer that is not a multiple of 16 in size.


L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

I forgot to mention that it is of course a bad habit to assume directx will pad the buffer for you. but although i made that comment above, I do think the buffer packaging is probably his problem considering his post
What I've seen happen is: declare a struct in C++ that's larger than the intended corresponding cbuffer declaration in HLSL (e.g. by padding to 16), create a ID3D11Buffer from it - works, assign it to a cbuffer slot - works, Map for writing - works, write stuff to it - works, Unmap - BOOM.

In theory because you can have any ID3D11Buffer assigned to any buffer slot, problems won't happen until such a time as you actually try to do something where the declaration difference(s) become(s) significant, and when that happens you'll likely get either a CRT crash, a crash somewhere deep in driver or kernel code, or weird behaviour.

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.

Alright, thanks guys for your help, i finally understood what to do. As my float needed more bytes, i increased the amount of allocated memory. Thanks guys.

FastCall22: "I want to make the distinction that my laptop is a whore-box that connects to different network"

Blog about... stuff (GDNet, WordPress): www.gamedev.net/blog/1882-the-cuboid-zone/, cuboidzone.wordpress.com/


Alright, thanks guys for your help, i finally understood what to do. As my float needed more bytes, i increased the amount of allocated memory. Thanks guys.

The issue is not that your float needed more bytes - it is that you have to declare data on 16-byte boundaries. This makes it easier for the driver and hardware to make certain assumptions about copying data around (i.e. 4xfloat = 16 bytes) and allows the use of registers more easily. I typically just declare float4, and if I use a sub-portion of a float4 then so be it. There is just room for expansion later on :)

This topic is closed to new replies.

Advertisement