microsoft / microsoft/DirectXShaderCompiler
Constant register declarations have diverging behavior between FXC and DXC
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 3.7k
- Forks
- 900
- Avg merge
- 2d 11h
- Merged PRs (30d)
- 44
Description
Description
Constant register declarations are legacy syntax, but still accepted by DXC and packed into the implicit $Globals constant buffer. However, the packing behavior differs to FXC.
Steps to Reproduce
uint u1 : register(b2);
uint u2 : register(c2);
uint u3 : register(i2);
If the above declarations are compiled with DXC, it interprets all three register declarations as packoffsets within the $Globals constant buffer, thus overlapping all three variables at offset 32. The reflection output is:
cbuffer $Globals
{
struct $Globals
{
uint u1; ; Offset: 32
uint u2; ; Offset: 32
uint u3; ; Offset: 32
} $Globals; ; Offset: 0 Size: 36
}
https://hlsl.godbolt.org/z/9fbE5svEx
FXC with shader models >= 4.0 instead ignores the first and third register declaration and only interprets the second one as a packoffset equivalent, leading to the following layout:
cbuffer $Globals
{
uint u2; // Offset: 32 Size: 4
uint u1; // Offset: 36 Size: 4
uint u3; // Offset: 40 Size: 4
}
https://shader-playground.timjones.io/536347a8d3b1b75f6ec00229afd283cf
Interestingly enough, clang seems to agree with FXC when the errors about the syntax are downgraded to warnings (see first link, it doesn't output the struct reflection, but the actual loads/extractvalues in DXIL confirm the layout).
This is all very much legacy (and I'm not even technically using it fully correctly for SM3 or older), but still accepted syntax and maybe someone still wants to port really old shaders and will run into weird issues.
Possible courses of action include aligning the behavior and/or deprecating those declarations altogether. In any case there should be at least warnings, since it either breaks potential existing shaders using that syntax with DXC (if its behavior will be aligned to FXC) or breaks shaders being ported from FXC to DXC (if its packing behavior will not be changed). Clang made b# and i# declarations on globals errors by default, see also the HLSL Register Types and Diagnostics Proposal.
Environment
- DXC version: 1.6+
- Host Operating System: All
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
No source file or test is named. Start by reproducing the three HLSL declarations with DXC and compare the reflection layout against FXC and the linked examples. Done means the compiler behavior is aligned or the legacy declarations receive diagnostics, with regression coverage for the reported packing difference.
Written by the indexing model from the issue text.
Assessment
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100