Open tex3d opened 9 months ago
The rules as stated in the first section on that page in the DXC Wiki stipulate that a struct must have a type alignment corresponding to its largest member alignment, which is true for Structured Buffers (and C). The sticking point, which is something I've tried (and possibly failed) to elaborate on in the article is that type alignment always requires the size of the type to be a multiple of its alignment. So a struct { double d; float a; }
has a size of 16 and the 4 bytes of padding are actually part of the type itself, it doesn't matter what type follows this struct of whether there is even anything at all, it's completely context-independent and applies directly to the type.
The Wiki page then says that the constant buffer layout rules apply on top of those basic alignment rules. In my interpretation, this is not true in this particular case, because the aforementioned struct actually has a real size of 12 in a constant buffer and if you followed it up with e.g. a float
, there would be no padding at all in between that and the struct before it, nor would there be padding within the struct itself.
Essentially, my interpretation is that structs and arrays in constant buffers do not inherently have any type alignment at all. Of course, you could turn this around and say that "type alignment" within constant buffers just works differently than it does everywhere else in that it does not require adjusting the size to a multiple of the alignment, but I chose to say it just isn't really type alignment at all.
I should have perhaps not used the word "error", it's just a bit unclear and I had to actually test these rules to figure it out. Now that I read it again, I think the following part of the cbuffer rules actually does cover what I'm talking about, I may have just not been careful enough when reading:
If the aggregate ends in an element that does not completely fill a row, the remaining space on the last row may be used by the next value.
I may remove the footnote entirely in a future update, thanks for double checking with me.
Ok, I think I understand now.
Although the prior section doesn't say that the size follows the alignment of the type, it is needed for the basic layout and StructuredBuffer, and therefore could be seen as implied. If you make that (reasonable) assumption, it's inconsistent with the size for use in constant buffers.
my interpretation is that structs and arrays in constant buffers do not inherently have any type alignment at all.
That sounds like a valid interpretation. I think you could say the same for matrix types and even vectors. The only alignment being imposed is a scalar element alignment, plus additional rules around the placement of variable declaration fields in a structure or in the constant buffer.
I might be able to clarify the Wiki page a bit given this feedback, thanks!
I also think it might be useful to call out that the C size alignment rule you refer to simply does not apply at all to constant buffers. The following statement says that the extra rules "effectively make this detail irrelevant", but I don't think that's strong enough.
In C-like struct packing, the size of a type must always be an integer multiple of its alignment. Otherwise, an array of that type would misalign its elements and a struct containing an overaligned type would have its layout depend on its starting address. Note that HLSL has extra rules for arrays and structs which we will see later and effectively make this detail irrelevant in constant buffers.
There are subtle, but important differences in interpreting things in the following two ways:
That, along with an update to the Wiki page, might help.
I also think it might be useful to call out that the C size alignment rule you refer to simply does not apply at all to constant buffers. The following statement says that the extra rules "effectively make this detail irrelevant", but I don't think that's strong enough.
Right, that paragraph used to be in a footnote in the first draft, before I realized that it's kind of central point to my model of alignment and how it applies to constant buffers. I agree it needs stronger wording, I was hedging a bit too hard there (what if HLSL introduced a type with alignment > size in the future? a bit silly). I've actually been slightly afraid that a compiler dev was going to come in and tell me that my entire model is wrong and not at all how it's implemented 😅. Thank you for the useful discussion. I'll update that sentence and the footnote probably later today.
First, I have to say, stellar work on this! 🤯
I noticed this footnote, and would like to correct any error on the Wiki page this refers to, but I couldn't identify the error: https://github.com/Maraneshi/HLSL-ConstantBufferLayoutVisualizer/blob/3675f1837049f433f5654f591d243143ca82e634/index.html#L808-L809
This seems to imply a lack of basis for forcing alignment to 16 for structures in the document for Rule 4.
Under
"Legacy" Constant Buffer Basics
it says:This point appears to be the basis for Rule 4, and it supersedes the basic type alignment rule when a struct appears in a cbuffer.
I think the basic point about alignment for the structure is that the structure itself does not force alignment of 16. The alignment to 16 is required when the struct is included inside a constant buffer.
Perhaps your interpretation of what's written is different than mine. If so, can you more clearly identify the error you're referring to?