DirectXShaderCompiler
DirectXShaderCompiler copied to clipboard
GetAttributeAtVertex() doesn't work on function parameters
Description
When using an array member of a VS interpolant structure, GetAttributeAtVertex
fails to compile.
Steps to Reproduce
// dxc.exe repro.hlsl /Tps_6_1 /EMainPS
cbuffer Globals : register (b0)
{
int GIndex;
};
struct Interpolants
{
float3 BaryWeights : SV_Barycentrics;
nointerpolation float4 PackedTexCoords[1] : COLOR0;
nointerpolation uint PrimitiveId : PRIMITIVE_ID;
};
float4 GetUV(Interpolants vs, int index)
{
float4 a1 = GetAttributeAtVertex(vs.PackedTexCoords[index], 0);
float4 a2 = GetAttributeAtVertex(vs.PackedTexCoords[index], 1);
float4 a3 = GetAttributeAtVertex(vs.PackedTexCoords[index], 2);
return a1 * vs.BaryWeights.x + a2 * vs.BaryWeights.y + a3 * vs.BaryWeights.z;
}
[RootSignature("CBV(b0)")]
float4 MainPS(Interpolants vs) : SV_Target0
{
float4 x = GetUV(vs, 0); // FAIL
return x;
}
Actual Behavior
gaav-repro.hlsl:19:14: error: attribute evaluation can only be done on values taken directly from inputs.
float4 a3 = GetAttributeAtVertex(vs.PackedTexCoords[index], 2);
^
gaav-repro.hlsl:18:14: error: attribute evaluation can only be done on values taken directly from inputs.
float4 a2 = GetAttributeAtVertex(vs.PackedTexCoords[index], 1);
^
gaav-repro.hlsl:17:14: error: attribute evaluation can only be done on values taken directly from inputs.
float4 a1 = GetAttributeAtVertex(vs.PackedTexCoords[index], 0);
^
Note that moving the GetAttributeAtVertex calls to be inside MainPS
can compile successfully.
Environment
- DXC version dxcompiler.dll: 1.7 - 1.7.2308.7 (69e54e290); dxil.dll: 1.7(101.7.2308.12)
- Host Operating System Windows 11
Unfortunately, this one is not sound language-wise, and tricky to support. It's likely going to be considered by-design.
The language semantics are such that you could not use GetAttributeAtVertex anywhere but inside the main entry point function. This intrinsic doesn’t operate on the value read from the interpolant, but does something special to point the intrinsic at the right input interpolant location. I think making this work language-wise would require reference support for your called function.
That said, it wouldn't be impossible for the compiler to make this work as long as inlining and optimizations performed at some early stage ensured that the intrinsic could tunnel directly to the input interpolant before we processed the function inputs. However, this is not something DXC does, and it's not something DXC is likely to do.
Here is the godbolt link: https://godbolt.org/z/z9bYK4sb9
Note that using shader model 6.6 resolves the issue and may be an acceptable workaround