Skip to content

Commit 5deaea9

Browse files
Fix crash when HitObject::TraceRay payload is an empty struct (#10634)
Extend legalizeEmptyRayPayloadsForHLSL to also handle global variables with IRVulkanRayPayloadDecoration whose element struct type is empty. Previously only struct types with the decoration were handled; the [__vulkanRayPayload] static variable in __spirvTraceRayHitObjectEXT places the decoration on the variable, not the struct type, causing the type legalization pass to crash with "non-simple operand(s)\!". Fixes #9757 --------- Co-authored-by: Ellie Hermaszewska <ellieh@nvidia.com>
1 parent ef3d763 commit 5deaea9

2 files changed

Lines changed: 51 additions & 1 deletion

File tree

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

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,13 +126,34 @@ void legalizeEmptyRayPayloadsForHLSL(IRModule* module)
126126
// First, collect all empty ray payload structs to process.
127127
// We must collect first because the processing phase inserts new global
128128
// instructions (struct keys, string values) which would invalidate the iterator.
129-
List<IRStructType*> emptyRayPayloadStructs;
129+
HashSet<IRStructType*> emptyRayPayloadStructs;
130130

131131
for (auto globalInst : module->getGlobalInsts())
132132
{
133133
auto structType = as<IRStructType>(globalInst);
134134
if (!structType)
135+
{
136+
// Also check global variables with IRVulkanRayPayloadDecoration.
137+
// These arise from [__vulkanRayPayload] parameters in built-in functions
138+
// (e.g. __spirvTraceRayHitObjectEXT) where the decoration is on the
139+
// variable rather than the struct type itself.
140+
auto globalVar = as<IRGlobalVar>(globalInst);
141+
if (!globalVar)
142+
continue;
143+
if (!globalVar->findDecoration<IRVulkanRayPayloadDecoration>())
144+
continue;
145+
auto ptrType = as<IRPtrTypeBase>(globalVar->getDataType());
146+
if (!ptrType)
147+
continue;
148+
structType = as<IRStructType>(ptrType->getValueType());
149+
if (!structType)
150+
continue;
151+
// Check if the struct is empty
152+
if (structType->getFields().begin() != structType->getFields().end())
153+
continue;
154+
emptyRayPayloadStructs.add(structType);
135155
continue;
156+
}
136157

137158
// Check if this struct has ray payload decoration
138159
auto rayPayloadDec = structType->findDecoration<IRRayPayloadDecoration>();

tests/bugs/gh-9757.slang

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Test for issue #9757: InternalError when HitObject::TraceRay payload is an empty struct.
2+
// Empty ray payload structs should compile without crashing.
3+
4+
//TEST:SIMPLE(filecheck=CHECK): -target spirv-asm -emit-spirv-directly -capability spvShaderInvocationReorderNV -entry main -stage raygeneration
5+
6+
struct Payload{};
7+
8+
RaytracingAccelerationStructure tlas;
9+
RWTexture2D<float> outImage;
10+
11+
[shader("raygeneration")]
12+
void main()
13+
{
14+
RayDesc ray;
15+
ray.Origin = float3(0.0);
16+
ray.Direction = float3(0.0, 0.0, 1.0);
17+
ray.TMin = 0.0;
18+
ray.TMax = 1e30;
19+
20+
Payload payload;
21+
HitObject hitObj = HitObject::TraceRay(tlas, 0, 0xFF, 0, 0, 0, ray, payload);
22+
if (hitObj.IsHit())
23+
{
24+
outImage[DispatchRaysIndex().xy] = 1.0f;
25+
}
26+
27+
// CHECK: OpMemberName %Payload 0 "_slang_dummy"
28+
// CHECK: OpHitObjectTraceRayNV
29+
}

0 commit comments

Comments
 (0)