• Create Account

## C++ Directx 11 CBuffers and HLSL.

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

16 replies to this topic

### #1Migi0027 (肉コーダ)  Members

Posted 02 July 2012 - 08:54 AM

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:

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/

### #2L. Spiro  Members

Posted 02 July 2012 - 09:16 AM

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[I], 0UL, D3D11_MAP_WRITE_DISCARD, 0UL, &msMapped );
pvConstData = msMapped.pData;
CStd::MemCpy( pvConstData, &m_vConstBufferRawData[I].vRaw[0], m_vConstBufferRawData[I].vRaw.Length() );
CDirectX11::GetDirectX11Context()->Unmap( m_vConstantBuffers[I], 0 );

L. Spiro

### #3mhagain  Members

Posted 02 July 2012 - 09:53 AM

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

It appears that the gentleman thought C++ was extremely difficult and he was overjoyed that the machine was absorbing it; he understood that good C++ is difficult but the best C++ is well-nigh unintelligible.

### #4CryZe  Members

Posted 03 July 2012 - 03:28 AM

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, 03 July 2012 - 03:28 AM.

### #5iedoc  Members

Posted 03 July 2012 - 05:42 AM

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.
Braynzar Soft - DirectX Lessons & Game Programming Resources!

### #6L. Spiro  Members

Posted 03 July 2012 - 06:42 AM

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, 03 July 2012 - 07:14 AM.

### #7iedoc  Members

Posted 03 July 2012 - 07:05 AM

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, 03 July 2012 - 07:08 AM.

Braynzar Soft - DirectX Lessons & Game Programming Resources!

### #8mhagain  Members

Posted 03 July 2012 - 08:39 AM

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.

It appears that the gentleman thought C++ was extremely difficult and he was overjoyed that the machine was absorbing it; he understood that good C++ is difficult but the best C++ is well-nigh unintelligible.

### #9Migi0027 (肉コーダ)  Members

Posted 03 July 2012 - 10:30 AM

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/

### #10Jason Z  Members

Posted 03 July 2012 - 05:38 PM

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

Jason Zink :: DirectX MVP

Direct3D 11 engine on CodePlex: Hieroglyph 3

Games: Lunar Rift

### #11iYossi  Members

Posted 05 July 2012 - 02:21 AM

In the C++ code, do
__declspec( align( 16 ) ) struct ConstantBuffer
{
/*...*/
};

### #12Migi0027 (肉コーダ)  Members

Posted 05 July 2012 - 06:14 AM

In the C++ code, do
__declspec( align( 16 ) ) struct ConstantBuffer
{
/*...*/
};

Ok, i never saw that function, but ill research it... thanks!

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/

### #13sss_abaker  Members

Posted 05 July 2012 - 04:27 PM

__declspec(align(16)) seems like a simpler option, but will that translate over to video memory? You're aligning it in system memory just fine, but I'm not sure if it is treated the same way when you map it.

Edited by sss_abaker, 05 July 2012 - 04:33 PM.

### #14mhagain  Members

Posted 05 July 2012 - 04:48 PM

It's not going to matter because when you map it you're getting a pointer to a different chunk of memory that has already been properly aligned/sized/etc when the cbuffer was created.

It appears that the gentleman thought C++ was extremely difficult and he was overjoyed that the machine was absorbing it; he understood that good C++ is difficult but the best C++ is well-nigh unintelligible.

### #15sss_abaker  Members

Posted 05 July 2012 - 04:57 PM

I figured. Thanks for the confirmation. I was nodding my head throughout this thread until I came across that claim and was pretty sure that's not how it worked.

### #16QPig  Members

Posted 05 July 2012 - 08:31 PM

in my opinion
first. make your data full with 4 float every unit both in hlsl and c++, forget your c++ ruler and habit, what you contact with is gpu not cpu, and also hlsl is just like c but not c, naturally there are big differents at asm level. if ok, forget order of readableness just align it.
second. Updatesubresource sounds great, i agree, but map and unmap is handy, obviously. next time, try map, you will like it
third. i do not know why i still find d3dx*** at directx11, is it pure one, if it is, en, d3dx*** is history.

### #17MJP  Moderators

Posted 05 July 2012 - 11:40 PM

Aligning a struct to 16-bytes will affect the alignment and size of that structure, but not the members within it. The reason it's useful this case is because it will round up your structure size to the next multiple of 16-bytes (which is a requirement for constant buffers), but you could also do that just by rounding it up yourself. What you really need to be careful about with constant buffers is the alignment of the individual variables within the constant buffer. HLSL has its own particular rules for this that differ from the defaults for 32-bit and 64-bit C++, which means if you want to use a C++ struct to fill a constant buffer then you need to pay attention to member alignment. One way to do this will be to use __declspec(align(16)) to align individual members to the next 16-byte boundary. Here's a simple example:

struct ConstantBuffer
{
float3 position;
__declspec(align(16)) float3 color;
};


Without the alignment on the "color" member, it will be placed 12-bytes from the start of the constant buffer while HLSL requires it to be placed at the next 16-byte boundary.

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.