Skip to content

Commit 0b4e463

Browse files
authored
Add raypayload decoration to ray payload structs (shader-slang#6164)
* Add raypayload decoration to ray payload structs Closes shader-slang#6104 * Disable PAQs when compiling with DXC See shader-slang#3448
1 parent 0bc18d2 commit 0b4e463

10 files changed

+131
-27
lines changed

source/compiler-core/slang-dxc-compiler.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,13 @@ SlangResult DXCDownstreamCompiler::compile(const CompileOptions& inOptions, IArt
479479
args.add(compilerSpecific[i]);
480480
}
481481

482+
// This can be re-enabled when we add PAQs: https://github.com/shader-slang/slang/issues/3448
483+
const bool enablePAQs = false;
484+
if (!enablePAQs)
485+
args.add(L"-disable-payload-qualifiers");
486+
else
487+
args.add(L"-enable-payload-qualifiers");
488+
482489
// TODO: deal with
483490
bool treatWarningsAsErrors = false;
484491
if (treatWarningsAsErrors)

source/slang/hlsl.meta.slang

+12-5
Original file line numberDiff line numberDiff line change
@@ -16464,6 +16464,13 @@ __generic<T>
1646416464
__intrinsic_op($(kIROp_ForceVarIntoStructTemporarily))
1646516465
Ref<T> __forceVarIntoStructTemporarily(inout T maybeStruct);
1646616466

16467+
// Some functions require a struct type which is decorated with a [raypayload]
16468+
// attribute. This will do the same as __forceVarIntoStructTemporarily and also
16469+
// ensure that the struct type in question is decorated appropriately.
16470+
__generic<T>
16471+
__intrinsic_op($(kIROp_ForceVarIntoRayPayloadStructTemporarily))
16472+
Ref<T> __forceVarIntoRayPayloadStructTemporarily(inout T maybeStruct);
16473+
1646716474
__generic<payload_t>
1646816475
[require(hlsl, raytracing)]
1646916476
void __traceRayHLSL(
@@ -16548,7 +16555,7 @@ void TraceRay(
1654816555
MultiplierForGeometryContributionToHitGroupIndex,
1654916556
MissShaderIndex,
1655016557
Ray,
16551-
__forceVarIntoStructTemporarily(Payload));
16558+
__forceVarIntoRayPayloadStructTemporarily(Payload));
1655216559
return;
1655316560
case cuda: __intrinsic_asm "traceOptiXRay";
1655416561
case glsl:
@@ -16686,7 +16693,7 @@ void TraceMotionRay(
1668616693
MissShaderIndex,
1668716694
Ray,
1668816695
CurrentTime,
16689-
__forceVarIntoStructTemporarily(Payload));
16696+
__forceVarIntoRayPayloadStructTemporarily(Payload));
1669016697
return;
1669116698
case glsl:
1669216699
{
@@ -18830,7 +18837,7 @@ struct HitObject
1883018837
MultiplierForGeometryContributionToHitGroupIndex,
1883118838
MissShaderIndex,
1883218839
Ray,
18833-
__forceVarIntoStructTemporarily(Payload),
18840+
__forceVarIntoRayPayloadStructTemporarily(Payload),
1883418841
hitObj);
1883518842
return hitObj;
1883618843
}
@@ -18923,7 +18930,7 @@ struct HitObject
1892318930
MissShaderIndex,
1892418931
Ray,
1892518932
CurrentTime,
18926-
__forceVarIntoStructTemporarily(Payload));
18933+
__forceVarIntoRayPayloadStructTemporarily(Payload));
1892718934
case glsl:
1892818935
{
1892918936
[__vulkanRayPayload]
@@ -19441,7 +19448,7 @@ struct HitObject
1944119448
__InvokeHLSL(
1944219449
AccelerationStructure,
1944319450
HitOrMiss,
19444-
__forceVarIntoStructTemporarily(Payload));
19451+
__forceVarIntoRayPayloadStructTemporarily(Payload));
1944519452
case glsl:
1944619453
{
1944719454
[__vulkanRayPayload]

source/slang/slang-emit-hlsl.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -1669,6 +1669,15 @@ void HLSLSourceEmitter::emitPostKeywordTypeAttributesImpl(IRInst* inst)
16691669
{
16701670
m_writer->emit("[payload] ");
16711671
}
1672+
// This can be re-enabled when we add PAQs: https://github.com/shader-slang/slang/issues/3448
1673+
const bool enablePAQs = false;
1674+
if (enablePAQs)
1675+
{
1676+
if (const auto payloadDecoration = inst->findDecoration<IRRayPayloadDecoration>())
1677+
{
1678+
m_writer->emit("[raypayload] ");
1679+
}
1680+
}
16721681
}
16731682

16741683
void HLSLSourceEmitter::_emitPrefixTypeAttr(IRAttr* attr)

source/slang/slang-ir-hlsl-legalize.cpp

+17-8
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,20 @@ void searchChildrenForForceVarIntoStructTemporarily(IRModule* module, IRInst* in
2929
for (UInt i = 0; i < call->getArgCount(); i++)
3030
{
3131
auto arg = call->getArg(i);
32-
if (arg->getOp() != kIROp_ForceVarIntoStructTemporarily)
32+
const bool isForcedStruct = arg->getOp() == kIROp_ForceVarIntoStructTemporarily;
33+
const bool isForcedRayPayloadStruct =
34+
arg->getOp() == kIROp_ForceVarIntoRayPayloadStructTemporarily;
35+
if (!(isForcedStruct || isForcedRayPayloadStruct))
3336
continue;
3437
auto forceStructArg = arg->getOperand(0);
3538
auto forceStructBaseType =
3639
as<IRType>(forceStructArg->getDataType()->getOperand(0));
40+
IRBuilder builder(call);
3741
if (forceStructBaseType->getOp() == kIROp_StructType)
3842
{
3943
call->setArg(i, arg->getOperand(0));
44+
if (isForcedRayPayloadStruct)
45+
builder.addRayPayloadDecoration(forceStructBaseType);
4046
continue;
4147
}
4248

@@ -47,14 +53,19 @@ void searchChildrenForForceVarIntoStructTemporarily(IRModule* module, IRInst* in
4753
// `__forceVarIntoStructTemporarily` is a parameter to a side effect type
4854
// (`ref`, `out`, `inout`) we copy the struct back into our original non-struct
4955
// parameter.
50-
IRBuilder builder(call);
56+
57+
const auto typeNameHint = isForcedRayPayloadStruct
58+
? "RayPayload_t"
59+
: "ForceVarIntoStructTemporarily_t";
60+
const auto varNameHint =
61+
isForcedRayPayloadStruct ? "rayPayload" : "forceVarIntoStructTemporarily";
5162

5263
builder.setInsertBefore(call->getCallee());
5364
auto structType = builder.createStructType();
5465
StringBuilder structName;
55-
builder.addNameHintDecoration(
56-
structType,
57-
UnownedStringSlice("ForceVarIntoStructTemporarily_t"));
66+
builder.addNameHintDecoration(structType, UnownedStringSlice(typeNameHint));
67+
if (isForcedRayPayloadStruct)
68+
builder.addRayPayloadDecoration(structType);
5869

5970
auto elementBufferKey = builder.createStructKey();
6071
builder.addNameHintDecoration(elementBufferKey, UnownedStringSlice("data"));
@@ -65,9 +76,7 @@ void searchChildrenForForceVarIntoStructTemporarily(IRModule* module, IRInst* in
6576

6677
builder.setInsertBefore(call);
6778
auto structVar = builder.emitVar(structType);
68-
builder.addNameHintDecoration(
69-
structVar,
70-
UnownedStringSlice("forceVarIntoStructTemporarily"));
79+
builder.addNameHintDecoration(structVar, UnownedStringSlice(varNameHint));
7180
builder.emitStore(
7281
builder.emitFieldAddress(
7382
builder.getPtrType(_dataField->getFieldType()),

source/slang/slang-ir-inst-defs.h

+4
Original file line numberDiff line numberDiff line change
@@ -759,6 +759,9 @@ INST(GetPerVertexInputArray, GetPerVertexInputArray, 1, HOISTABLE)
759759
INST(ResolveVaryingInputRef, ResolveVaryingInputRef, 1, HOISTABLE)
760760

761761
INST(ForceVarIntoStructTemporarily, ForceVarIntoStructTemporarily, 1, 0)
762+
INST(ForceVarIntoRayPayloadStructTemporarily, ForceVarIntoRayPayloadStructTemporarily, 1, 0)
763+
INST_RANGE(ForceVarIntoStructTemporarily, ForceVarIntoStructTemporarily, ForceVarIntoRayPayloadStructTemporarily)
764+
762765
INST(MetalAtomicCast, MetalAtomicCast, 1, 0)
763766

764767
INST(IsTextureAccess, IsTextureAccess, 1, 0)
@@ -992,6 +995,7 @@ INST_RANGE(BindingQuery, GetRegisterIndex, GetRegisterSpace)
992995
INST(GLSLLocationDecoration, glslLocation, 1, 0)
993996
INST(GLSLOffsetDecoration, glslOffset, 1, 0)
994997
INST(PayloadDecoration, payload, 0, 0)
998+
INST(RayPayloadDecoration, raypayload, 0, 0)
995999

9961000
/* Mesh Shader outputs */
9971001
INST(VerticesDecoration, vertices, 1, 0)

source/slang/slang-ir-insts.h

+7
Original file line numberDiff line numberDiff line change
@@ -1605,6 +1605,11 @@ struct IRPayloadDecoration : public IRDecoration
16051605
IR_LEAF_ISA(PayloadDecoration)
16061606
};
16071607

1608+
struct IRRayPayloadDecoration : public IRDecoration
1609+
{
1610+
IR_LEAF_ISA(RayPayloadDecoration)
1611+
};
1612+
16081613
// Mesh shader decorations
16091614

16101615
struct IRMeshOutputDecoration : public IRDecoration
@@ -5289,6 +5294,8 @@ struct IRBuilder
52895294
{
52905295
addDecoration(inst, kIROp_EntryPointParamDecoration, entryPointFunc);
52915296
}
5297+
5298+
void addRayPayloadDecoration(IRType* inst) { addDecoration(inst, kIROp_RayPayloadDecoration); }
52925299
};
52935300

52945301
// Helper to establish the source location that will be used

tests/expected-failure-github.txt

-2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,4 @@ tests/bugs/buffer-swizzle-store.slang.3 syn (wgpu)
1313
tests/compute/interface-shader-param-in-struct.slang.4 syn (wgpu)
1414
tests/compute/interface-shader-param.slang.5 syn (wgpu)
1515
tests/language-feature/shader-params/interface-shader-param-ordinary.slang.4 syn (wgpu)
16-
gfx-unit-test-tool/RayTracingTestAD3D12.internal
17-
gfx-unit-test-tool/RayTracingTestBD3D12.internal
1816
gfx-unit-test-tool/precompiledTargetModule2Vulkan.internal
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//enable when https://github.com/shader-slang/slang/issues/3448 is implemented
2+
//DISABLE_TEST:SIMPLE(filecheck=CHECK): -target hlsl -stage raygeneration -entry rayGenShaderA
3+
4+
// CHECK: struct [raypayload]
5+
6+
uniform RWTexture2D resultTexture;
7+
uniform RaytracingAccelerationStructure sceneBVH;
8+
9+
[shader("raygeneration")]
10+
void rayGenShaderA()
11+
{
12+
int2 threadIdx = DispatchRaysIndex().xy;
13+
14+
float3 rayDir = float3(0, 0, 1);
15+
float3 rayOrigin = 0;
16+
rayOrigin.x = (threadIdx.x * 2) - 1;
17+
rayOrigin.y = (threadIdx.y * 2) - 1;
18+
19+
// Trace the ray.
20+
RayDesc ray;
21+
ray.Origin = rayOrigin;
22+
ray.Direction = rayDir;
23+
ray.TMin = 0.001;
24+
ray.TMax = 10000.0;
25+
float4 payload = float4(0, 0, 0, 0);
26+
TraceRay(sceneBVH, RAY_FLAG_NONE, ~0, 0, 0, 0, ray, payload);
27+
28+
resultTexture[threadIdx.xy] = payload;
29+
}

tests/hlsl/raypayload-attribute.slang

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//enable when https://github.com/shader-slang/slang/issues/3448 is implemented
2+
//DISABLE_TEST:SIMPLE(filecheck=CHECK): -target hlsl -stage raygeneration -entry rayGenShaderA
3+
4+
// CHECK: struct [raypayload]
5+
6+
struct RayPayload
7+
{
8+
float4 color;
9+
};
10+
11+
uniform RWTexture2D resultTexture;
12+
uniform RaytracingAccelerationStructure sceneBVH;
13+
14+
[shader("raygeneration")]
15+
void rayGenShaderA()
16+
{
17+
int2 threadIdx = DispatchRaysIndex().xy;
18+
19+
float3 rayDir = float3(0, 0, 1);
20+
float3 rayOrigin = 0;
21+
rayOrigin.x = (threadIdx.x * 2) - 1;
22+
rayOrigin.y = (threadIdx.y * 2) - 1;
23+
24+
// Trace the ray.
25+
RayDesc ray;
26+
ray.Origin = rayOrigin;
27+
ray.Direction = rayDir;
28+
ray.TMin = 0.001;
29+
ray.TMax = 10000.0;
30+
RayPayload payload = { float4(0, 0, 0, 0) };
31+
TraceRay(sceneBVH, RAY_FLAG_NONE, ~0, 0, 0, 0, ray, payload);
32+
33+
resultTexture[threadIdx.xy] = payload.color;
34+
}

tests/vkray/raygen-trace-ray-param-non-struct.slang

+12-12
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,13 @@ void main()
2222
ray.Direction = float3(0,0,1);
2323
ray.TMax = 100.0f;
2424

25-
// CHECK: ForceVarIntoStructTemporarily_t{{_[0-9]}} forceVarIntoStructTemporarily{{_[0-9]}};
25+
// CHECK: RayPayload_t{{_[0-9]}} rayPayload{{_[0-9]}};
2626
float someInData1 = 5.0f;
2727
addComplexity1(someInData1);
2828

29-
// CHECK: forceVarIntoStructTemporarily{{_[0-9]}}.data{{_[0-9]}} = {{.*}}
29+
// CHECK: rayPayload{{_[0-9]}}.data{{_[0-9]}} = {{.*}}
3030
// CHECK: TraceRay(
31-
// CHECK: {{.*}} = forceVarIntoStructTemporarily{{.*}}.data{{.*}};
31+
// CHECK: {{.*}} = rayPayload{{.*}}.data{{.*}};
3232
TraceRay(as,
3333
1,
3434
0xff,
@@ -39,9 +39,9 @@ void main()
3939
someInData1);
4040
outputBuffer1[0] = outputBuffer1[0]+someInData1;
4141

42-
// CHECK: forceVarIntoStructTemporarily{{_[0-9]}}.data{{_[0-9]}} = {{.*}}
42+
// CHECK: rayPayload{{_[0-9]}}.data{{_[0-9]}} = {{.*}}
4343
// CHECK: TraceMotionRay(
44-
// CHECK: {{.*}} = forceVarIntoStructTemporarily{{.*}}.data{{.*}};
44+
// CHECK: {{.*}} = rayPayload{{.*}}.data{{.*}};
4545
TraceMotionRay(as,
4646
1,
4747
0xff,
@@ -53,9 +53,9 @@ void main()
5353
someInData1);
5454
outputBuffer1[0] = outputBuffer1[0]+someInData1;
5555

56-
// CHECK: forceVarIntoStructTemporarily{{_[0-9]}}.data{{_[0-9]}} = {{.*}}
56+
// CHECK: rayPayload{{_[0-9]}}.data{{_[0-9]}} = {{.*}}
5757
// CHECK: NvTraceRayHitObject(
58-
// CHECK: {{.*}} = forceVarIntoStructTemporarily{{.*}}.data{{.*}};
58+
// CHECK: {{.*}} = rayPayload{{.*}}.data{{.*}};
5959
HitObject::TraceRay(as,
6060
1,
6161
0xff,
@@ -66,9 +66,9 @@ void main()
6666
someInData1);
6767
outputBuffer1[0] = outputBuffer1[0]+someInData1;
6868

69-
// CHECK: forceVarIntoStructTemporarily{{_[0-9]}}.data{{_[0-9]}} = {{.*}}
69+
// CHECK: rayPayload{{_[0-9]}}.data{{_[0-9]}} = {{.*}}
7070
// CHECK: TraceMotionRay(
71-
// CHECK: {{.*}} = forceVarIntoStructTemporarily{{.*}}.data{{.*}};
71+
// CHECK: {{.*}} = rayPayload{{.*}}.data{{.*}};
7272
HitObject::TraceMotionRay(as,
7373
1,
7474
0xff,
@@ -80,9 +80,9 @@ void main()
8080
someInData1);
8181
outputBuffer1[0] = outputBuffer1[0]+someInData1;
8282

83-
// CHECK: forceVarIntoStructTemporarily{{_[0-9]}}.data{{_[0-9]}} = {{.*}}
83+
// CHECK: rayPayload{{_[0-9]}}.data{{_[0-9]}} = {{.*}}
8484
// CHECK: NvInvokeHitObject(
85-
// CHECK: {{.*}} = forceVarIntoStructTemporarily{{.*}}.data{{.*}};
85+
// CHECK: {{.*}} = rayPayload{{.*}}.data{{.*}};
8686
HitObject hitObject_HitOrMiss;
8787
HitObject::Invoke(
8888
as,
@@ -91,4 +91,4 @@ void main()
9191
outputBuffer1[0] = outputBuffer1[0]+someInData1;
9292

9393
addComplexity2(someInData1);
94-
}
94+
}

0 commit comments

Comments
 (0)