Jump to content
  • Advertisement
Sign in to follow this  
Migi0027

C++ Directx 11 CBuffers and HLSL.

This topic is 2208 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites

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).

Share this post


Link to post
Share on other sites
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. Edited by CryZe

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites

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 Edited by L. Spiro

Share this post


Link to post
Share on other sites
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 Edited by iedoc

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites

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 :)

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!