Please help me understand D3D12 cbuffer alignment

Started by
9 comments, last by JGP 1 year, 2 months ago

Hi,

According to MS, float1 aligns to 4 bytes like this:

//  1 x 16byte elements
cbuffer IE
{
    float1 Val1;
    float1 Val2;
    float2 Val3;
};

However, according to PIX, the float1 member variables of my cbuffer seem to be aligned to 16 bytes (as if they were float4 each):

// cbuffer EnvironmentVariables (672 bytes)
...
[[offset(160)]]
float varN;
[[offset(176)]]
float varN1;
[[offset(192)]]
float2 varN2;
[[offset(208)]]
float2 varN3;
[[offset(224)]]
...

Seems like the compiler (fxc.exe) has decided to align every single member variable in the cbuffer to 16 bytes.

Isn't this contradicting MS packagind rules? (https://learn.microsoft.com/en-gb/windows/win32/direct3dhlsl/dx-graphics-hlsl-packing-rules?redirectedfrom=MSDN)

Any ideas?

Advertisement

According to the Microsoft documentation

Each structure forces the next variable to start on the next four-component vector.

cbuffer IE
{
    float Val1;

    struct     {
        float SVal1;    // starts a new vector
    } Val2;
};

Therefore, make sure that every float is not wrapped in a structure. Then, check if RenderDoc (or NSight graphics) gives you the same alignment (to ensure it's not a PIX bug).

@undefined Im not at home now, so I can't really check , but I recall there was some related bug in PIX that gives you bad info like this. I'm pretty sure that I pack data into 16 byte chunks. You only can't cross the 16 byte boundary with data. Is there an actual bug, or is it just what PIX is telling you?

@pam79 there are no structs surrounding the cbuffer members.

@gnollrunner i don’t think it’s a pix issue because I had some real flickering in my demo (remember last post from me?), and this was the problem. So after realizing this in pix I aligned my data in the cpp side like this and the flickering was gone.

JGP said:

@gnollrunner i don’t think it’s a pix issue because I had some real flickering in my demo (remember last post from me?), and this was the problem. So after realizing this in pix I aligned my data in the cpp side like this and the flickering was gone.

My question is, does your code run correctly now, and this is just what you are seeing in PIX? Or are you trying to debug some new problem? Because if it's running OK, it's likely a PIX issue. I even reported this to MS at one point.

@undefined The code works fine after aligning my cpp structure the way pix says it’s aligned. This means it’s not a pix issue. in any case, it should be a fxc.exe issue.

I will probably switch to dxil and see if it aligns the right way

At this point, try compiling the shader code at runtime and see what PIX tells you.
If PIX shows you the CB aligned correctly, then the problem is with fxc.

@undefined Yeah but I’d have expected that fxc by default would use MS rules on aligning.

I just looked at my code and do this kind of stuff all the times and it's not a problem. I can't imagine the compiler would fail on something so basic. Sure, if you space out your data it will still work and possibly PIX will give you what you expect. But that's a huge waste of space, and I'm sure you don't need to do it.

So just to make sure I'm understanding you, your program (not PIX) failed until you aligned everything at 16-byte boundaries? Just as an example the code below works fine.

//################################################################
//## SDLSLight
//################################################################

struct SDLSLight
{
   uint   uLightType;		// Vector4 0
   float3 f3Attenuation;

   float3 f3Position;      // Vector4 1
   float  fRange;

   float4 f4Ambient;       // Vector4 2
   float4 f4Diffuse;       // Vector4 3
   float4 f4Specular;      // Vector4 4

   float3 f3Face;          // Vector4 5
   float  fSpot;
};

//################################################################
//## CBPerFrameData
//################################################################

struct CBPerFrameData
{
	// f4P is our special projection vector. It is constructed as follows:
	// 
	// f4P = [tan(HeightViewAng/2) * AspectRatio, tan(HeightViewAng/2), PowerOfTwoZDiv, NearPlane]
	// 
	// AspectRatio = Viewing aspect ratio width over height
	// HeightViewAng = vertical viewing angle of the window
	// PowerOfTwoZDiv = Tested with ldexp(1,96) which should be OK up to a galaxy 
	// NearPlane = Near clipping plane (near Z)
	//
	float4		f4P;

	int         iLightCount;
	int         iLightWireframe;
	int         iLightReserved2;
	int         iLightReserved3;
	SDLSLight   sLightArray[MDLDX_MAX_LIGHTS];
};

And then the constant buffer declaration:

ConstantBuffer<CBPerFrameData> cbPFD : register(b0,space0);

Yes exactly my program was failing until I changed the alignment on the cpp side to match the one indicated by pix.

This topic is closed to new replies.

Advertisement