-
Notifications
You must be signed in to change notification settings - Fork 805
Description
Title
Array in cbuffer reported as unused by reflection when optimization is turned on and there are other members in the cbuffer
Functional impact
This causes our compute shader (form Unity Scriptable Render Pipeline) to read garbage values for light probe data during a lighting loop since the array being read is reported by reflection to be unused and is thus left uninitialized in the cbuffer.
Minimal repro steps
- Compile repro_shader.txt with the IDxcCompiler3 interface and
-O2 -T cs_6_3 -E CSMainoptions (same shader shown below)
float4 g_Float4Array[3]; //Any array type or array size will do
float g_NeedAtLeastOneOtherVariableInTheCBuffer; //Need another member in the cbuffer to reproduce the issue
RWStructuredBuffer<uint> OptimizationPreventionBuffer;
RWTexture2D<float4> OutTexture;
[numthreads(1,1,1)]
void CSMain ()
{
int index = OptimizationPreventionBuffer[2]; // index must not be known at compile time
index -= 2; // issue disappears without this line
float3 outColor = g_Float4Array[index].xyz; // Reads garbage value
OutTexture[uint2(0,0)] = float4(outColor, 1);
}
- After compilation get the reflection part out of the result blob similar to:
ComPtr<IDxcBlob> reflectionPart;
if (pResult->HasOutput(DXC_OUT_REFLECTION))
pResult->GetOutput(DXC_OUT_REFLECTION, __uuidof(IDxcBlob), &reflectionPart, NULL);
- Get the D3D12_SHADER_DESC structure:
ComPtr<ID3D12ShaderReflection> shaderReflection;
DxcBuffer buffer = { reflectionPart->GetBufferPointer(), reflectionPart->GetBufferSize(), 0 };
g_pDxcUtils->CreateReflection(&buffer, __uuidof(ID3D12ShaderReflection), &shaderReflection)
D3D12_SHADER_DESC shaderDesc;
shaderReflection->GetDesc(&shaderDesc);
- Loop over cbuffers and their elements:
for (UINT i = 0; i < shaderDesc.ConstantBuffers; ++i)
{
ID3D12ShaderReflectionConstantBuffer* cb = shaderReflection->GetConstantBufferByIndex(i);
D3D12_SHADER_BUFFER_DESC desc;
cb->GetDesc(&desc);
if (desc.Type == D3D11_CT_CBUFFER)
{
for (UINT j = 0; j < desc.Variables; ++j)
{
ID3D12ShaderReflectionVariable* var = cb->GetVariableByIndex(j);
D3D12_SHADER_VARIABLE_DESC vdesc;
var->GetDesc(&vdesc);
if (!(vdesc.uFlags & D3D_SVF_USED)) // g_Float4Array's vdesc.uFlags == 0
continue;
//... Perform further reflection for used members
}
}
}
Expected result
The cbuffer member g_Float4Array has the flag D3D_SVF_USED(2) set and the member g_NeedAtLeastOneOtherVariableInTheCBuffer has uFlags == 0
Actual result
The cbuffer member g_Float4Array has uFlags == 0 and g_NeedAtLeastOneOtherVariableInTheCBuffer has the flag D3D_SVF_USED(2) set
Further technical details
Looking at the DXIL this might not be a codegen issue but an issue with the reflection information generation. If only the array g_Float4Array is present in the cbuffer the issue will not reproduce, it will also fail to reproduce with compiler optimization turned off or when the index variable is not modified after declaring it
DXC used was built from most recent source f26d32c
Metadata
Metadata
Assignees
Labels
Type
Projects
Status