DirectXShaderCompiler
DirectXShaderCompiler copied to clipboard
Accessing "aggressively packed" array elements in a constant buffer via static cast results in ICE
As per https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-packing-rules#more-aggressive-packing
#define MAX_TEXTURES 4
#define MAX_BUFFERS 4
cbuffer CResourceIndexRootConstants : register(b2)
{
uint4 iTexs[MAX_TEXTURES / 4];
uint4 iBufs[MAX_BUFFERS / 4];
}
float4 main(CPSInLighting pin) : SV_Target0
{
static const uint iTexsArray[MAX_TEXTURES] = (uint[MAX_TEXTURES])iTexs;
static const uint iBufsArray[MAX_BUFFERS] = (uint[MAX_BUFFERS])iBufs;
uint iAlbedoTexture = iTexsArray[0];
uint iNormalTexture = iTexsArray[1];
This results in:
Internal compiler error: access violation. Attempted to read from address 0x0000000000000048
CResourceIndexRootConstants is mapped via root constants.
Version: dxcompiler.dll: 1.8 - 1.8.0.14496 (main, 37c0487e9); dxil.dll: 1.8(101.8.2403.21)
Godbolt link reproduces: https://godbolt.org/z/KnKbeKdWf
The problem is rooted in the use of static for the local variables. This is unnecessary, and it sets up a flag to track first entry into function predicating the initializers. We have fragile special-case code to replace uses of the scalar array with users of the vector array when used in a pattern where you initialize one array from the other. Unfortunately, we can't tell if it's legal to replace uses in our pass, because at that point, the initializers don't appear to dominate the uses.
While it should be technically possible to make this case work, because semantically, it's well-defined. However, we don't have any clear easy path to do so in DXC at this time.
The current recommendation is to drop static from the variable declarations, and this should work as expected. See here for the version with this workaround: https://godbolt.org/z/Gv4e5c8dT.
@tex3d - has a fix nearly ready for this, so we'll see about picking this up.