microsoft / microsoft/DirectXShaderCompiler
[Debug info] TraceRay payload: no `dbg.declare` on the payload alloca, stale field values after the call
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 3.7k
- Forks
- 900
- Avg merge
- 2d 11h
- Merged PRs (30d)
- 44
Description
Version: dxcompiler.dll 1.9(5402-0d3ee6b5)(1.9.0.5402) - 1.9.0.5402 (0d3ee6b55-dirty)
Repro files: payload_traceray.zip
dxc -T lib_6_5 -Zi -Qembed_debug -Od -Fc payload_traceray.ll payload_traceray.hlsl
struct MyPayload
{
float4 color;
float hitT;
uint bounces;
};
[shader("raygeneration")]
void RayGen()
{
MyPayload payload;
payload.color = float4(0, 0, 0, 0);
payload.hitT = -1.0f;
payload.bounces = 0;
...
TraceRay(Scene, RAY_FLAG_NONE, 0xff, 0, 1, 0, ray, payload);
Result[0] = payload.color; // only .color is read afterwards
}
[shader("closesthit")]
void ClosestHit(inout MyPayload payload, in BuiltInTriangleIntersectionAttributes attr)
{
float4 incoming = payload.color;
payload.bounces = payload.bounces + 1; // writes .bounces
payload.hitT = RayTCurrent(); // writes .hitT
payload.color = incoming + float4(attr.barycentrics, 0, 1);
}
Actual
RayGen has a %struct.MyPayload alloca that is the payload's canonical
location. It is what is handed to dx.op.traceRay and what the hit shaders
write through. It never gets a llvm.dbg.declare:
%3 = alloca %struct.MyPayload
; no llvm.dbg.declare for %3 anywhere in RayGen
; payload is described purely by per-field dbg.values of the initialisers
call void @llvm.dbg.value(metadata <4 x float> zeroinitializer, ...) ; var:"payload" !DIExpression(DW_OP_bit_piece, 0, 128)
call void @llvm.dbg.value(metadata float -1.000000e+00, ...) ; var:"payload" !DIExpression(DW_OP_bit_piece, 128, 32)
call void @llvm.dbg.value(metadata i32 0, ...) ; var:"payload" !DIExpression(DW_OP_bit_piece, 160, 32)
; the struct is initialized into the alloca and TraceRay is called
%12 = getelementptr inbounds %struct.MyPayload, %struct.MyPayload* %3, i32 0, i32 0
store <4 x float> zeroinitializer, <4 x float>* %12
%13 = getelementptr inbounds %struct.MyPayload, %struct.MyPayload* %3, i32 0, i32 1
store float -1.000000e+00, float* %13
%14 = getelementptr inbounds %struct.MyPayload, %struct.MyPayload* %3, i32 0, i32 2
store i32 0, i32* %14
call void @dx.op.traceRay.struct.MyPayload(i32 157, ..., %struct.MyPayload* %3)
; after TraceRay only .color is re-described, because only .color is read
%15 = getelementptr inbounds %struct.MyPayload, %struct.MyPayload* %3, i32 0, i32 0
%16 = load <4 x float>, <4 x float>* %15
call void @llvm.dbg.value(metadata <4 x float> %16, ...) ; var:"payload" !DIExpression(DW_OP_bit_piece, 0, 128)
After TraceRay returns, the debug info still claims payload.hitT == -1.0 and
payload.bounces == 0, even though it could have been rewritten.
For contrast, the hit shader's payload parameter does get a declare, because it
stays a pointer:
define void @"\01?ClosestHit@@..."(%struct.MyPayload* noalias %payload, ...) {
call void @llvm.dbg.declare(metadata %struct.MyPayload* %payload, metadata !130, metadata !128) ; var:"payload" !DIExpression()
Expected
payload in RayGen should be described by a llvm.dbg.declare on the alloca
for its whole live range.
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
Start with payload_traceray.hlsl and payload_traceray.zip, run the provided dxc command, and inspect payload_traceray.ll around RayGen, the TraceRay call, and its debug intrinsics. Done means the payload alloca has a llvm.dbg.declare for its whole live range and the generated debug information no longer retains stale hitT or bounces values after the call.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100