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.
Version:
dxcompiler.dll 1.9(5402-0d3ee6b5)(1.9.0.5402) - 1.9.0.5402 (0d3ee6b55-dirty)Repro files: payload_traceray.zip
Actual
RayGenhas a%struct.MyPayloadalloca that is the payload's canonicallocation. It is what is handed to
dx.op.traceRayand what the hit shaderswrite through. It never gets a
llvm.dbg.declare:After
TraceRayreturns, the debug info still claimspayload.hitT == -1.0andpayload.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:
Expected
payloadinRayGenshould be described by allvm.dbg.declareon the allocafor its whole live range.