Skip to content

Commit b7fb53e

Browse files
MarijnS95claude
andcommitted
Add InstanceContributionToHitGroupIndex YAML field and shader query
Adds a 24-bit per-instance InstanceContributionToHitGroupIndex slot on AccelerationStructureInstance / InstanceDesc, plumbed through DX (D3D12_RAYTRACING_INSTANCE_DESC), VK (instanceShaderBindingTableRecord- Offset), and the Metal IR converter's addressOfInstanceContributions sidecar. The covering test verifies CommittedInstanceContributionToHit- GroupIndex() returns the per-instance value across distinct instances, including the top-of-range 0xFFFFFF. Part of the inline-RT test coverage epic (#1258). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent c822105 commit b7fb53e

8 files changed

Lines changed: 109 additions & 3 deletions

File tree

include/API/AccelerationStructure.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ struct AccelerationStructureInstance {
5555
float Transform[3][4] = {{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}};
5656
uint32_t InstanceID = 0;
5757
uint8_t InstanceMask = 0xFF;
58+
// 24-bit; high bits are truncated by the backend to match DXR's bitfield.
59+
uint32_t InstanceContributionToHitGroupIndex = 0;
5860
AccelerationStructure *BLAS = nullptr;
5961
};
6062

include/Support/Pipeline.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,7 @@ struct InstanceDesc {
515515
float Transform[12] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0};
516516
uint32_t InstanceID = 0;
517517
uint8_t InstanceMask = 0xFF;
518+
uint32_t InstanceContributionToHitGroupIndex = 0;
518519
};
519520

520521
struct TLASDesc {

lib/API/DX/Device.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3001,7 +3001,8 @@ llvm::Error DXComputeEncoder::batchBuildAS(llvm::ArrayRef<ASBuildItem> Items) {
30013001
// silent narrowing.
30023002
NI.InstanceID = Inst.InstanceID & 0xFFFFFFu;
30033003
NI.InstanceMask = Inst.InstanceMask;
3004-
NI.InstanceContributionToHitGroupIndex = 0;
3004+
NI.InstanceContributionToHitGroupIndex =
3005+
Inst.InstanceContributionToHitGroupIndex & 0xFFFFFFu;
30053006
NI.Flags = D3D12_RAYTRACING_INSTANCE_FLAG_NONE;
30063007
auto *BLASPtr = llvm::cast<DXAccelerationStructure>(Inst.BLAS);
30073008
NI.AccelerationStructure = BLASPtr->getGPUVirtualAddress();

lib/API/Device.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,8 @@ llvm::Error offloadtest::buildPipelineAccelerationStructures(
195195
memcpy(Inst.Transform, I.Transform, sizeof(I.Transform));
196196
Inst.InstanceID = I.InstanceID;
197197
Inst.InstanceMask = I.InstanceMask;
198+
Inst.InstanceContributionToHitGroupIndex =
199+
I.InstanceContributionToHitGroupIndex;
198200
Inst.BLAS = OutAS[It->second].get();
199201
Instances.push_back(Inst);
200202
}

lib/API/MTL/MTLDevice.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1375,7 +1375,11 @@ class MTLDevice : public offloadtest::Device {
13751375
// header buffer's GPU address.
13761376
const uint32_t InstCount =
13771377
static_cast<uint32_t>(R.first->TLASPtr->Instances.size());
1378-
llvm::SmallVector<uint32_t> Contributions(InstCount, 0);
1378+
llvm::SmallVector<uint32_t> Contributions;
1379+
Contributions.reserve(InstCount);
1380+
for (const auto &Inst : R.first->TLASPtr->Instances)
1381+
Contributions.push_back(Inst.InstanceContributionToHitGroupIndex &
1382+
0xFFFFFFu);
13791383
MTL::Buffer *ContribBuf = Device->newBuffer(
13801384
Contributions.data(), InstCount * sizeof(uint32_t),
13811385
MTL::ResourceStorageModeShared);

lib/API/VK/Device.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4441,7 +4441,8 @@ llvm::Error VKComputeEncoder::batchBuildAS(llvm::ArrayRef<ASBuildItem> Items) {
44414441
memcpy(&NI.transform.matrix, Inst.Transform, sizeof(Inst.Transform));
44424442
NI.instanceCustomIndex = Inst.InstanceID & 0xFFFFFFu;
44434443
NI.mask = Inst.InstanceMask;
4444-
NI.instanceShaderBindingTableRecordOffset = 0;
4444+
NI.instanceShaderBindingTableRecordOffset =
4445+
Inst.InstanceContributionToHitGroupIndex & 0xFFFFFFu;
44454446
NI.flags = 0;
44464447
auto *BLASPtr = llvm::cast<VulkanAccelerationStructure>(Inst.BLAS);
44474448
NI.accelerationStructureReference = BLASPtr->getDeviceAddress();

lib/Support/Pipeline.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -668,6 +668,8 @@ void MappingTraits<offloadtest::InstanceDesc>::mapping(
668668
uint32_t Mask = D.InstanceMask;
669669
I.mapOptional("InstanceMask", Mask, 255u);
670670
D.InstanceMask = static_cast<uint8_t>(Mask);
671+
I.mapOptional("InstanceContributionToHitGroupIndex",
672+
D.InstanceContributionToHitGroupIndex, 0u);
671673
}
672674

673675
void MappingTraits<offloadtest::TLASDesc>::mapping(IO &I,
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
#--- source.hlsl
2+
3+
[[vk::binding(0, 0)]] RaytracingAccelerationStructure Scene : register(t0);
4+
[[vk::binding(1, 0)]] RWStructuredBuffer<uint> Output : register(u0);
5+
6+
[numthreads(3,1,1)]
7+
void main(uint3 tid : SV_DispatchThreadID) {
8+
// Three instances of the same triangle BLAS tiled along x at x = -4, 0, +4
9+
// with distinct InstanceContributionToHitGroupIndex values. Each lane fires
10+
// straight down at its own instance, so CommittedInstanceContributionToHit-
11+
// GroupIndex() must equal the per-instance value.
12+
RayDesc Ray;
13+
Ray.Origin = float3((float(tid.x) - 1.0) * 4.0, 0, 1);
14+
Ray.Direction = float3(0, 0, -1);
15+
Ray.TMin = 0.0;
16+
Ray.TMax = 100.0;
17+
RayQuery<RAY_FLAG_NONE> Q;
18+
Q.TraceRayInline(Scene, RAY_FLAG_NONE, 0xFF, Ray);
19+
Q.Proceed();
20+
Output[tid.x] = Q.CommittedStatus() == COMMITTED_TRIANGLE_HIT
21+
? Q.CommittedInstanceContributionToHitGroupIndex()
22+
: 0xFFFFFFFF;
23+
}
24+
//--- pipeline.yaml
25+
---
26+
Shaders:
27+
- Stage: Compute
28+
Entry: main
29+
Buffers:
30+
- Name: Vertices
31+
Format: Float32
32+
Stride: 12
33+
Data: [ 0.0, 1.0, 0.0, -1.0, -1.0, 0.0, 1.0, -1.0, 0.0 ]
34+
- Name: Output
35+
Format: UInt32
36+
Stride: 4
37+
FillSize: 12
38+
- Name: Expected
39+
Format: UInt32
40+
Stride: 4
41+
# 24-bit field: highest legal value is 0xFFFFFF. Pick three distinct
42+
# values across the range, including one that exercises the top bits.
43+
Data: [ 7, 99, 16777215 ]
44+
AccelerationStructures:
45+
BLAS:
46+
- Name: TriangleBLAS
47+
Triangles:
48+
- VertexBuffer: Vertices
49+
VertexFormat: RGB32Float
50+
VertexStride: 12
51+
VertexCount: 3
52+
TLAS:
53+
- Name: Scene
54+
Instances:
55+
- BLAS: TriangleBLAS
56+
Transform: [1, 0, 0, -4, 0, 1, 0, 0, 0, 0, 1, 0]
57+
InstanceContributionToHitGroupIndex: 7
58+
- BLAS: TriangleBLAS
59+
Transform: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0]
60+
InstanceContributionToHitGroupIndex: 99
61+
- BLAS: TriangleBLAS
62+
Transform: [1, 0, 0, 4, 0, 1, 0, 0, 0, 0, 1, 0]
63+
InstanceContributionToHitGroupIndex: 16777215
64+
DescriptorSets:
65+
- Resources:
66+
- Name: Scene
67+
Kind: AccelerationStructure
68+
DirectXBinding:
69+
Register: 0
70+
Space: 0
71+
VulkanBinding:
72+
Binding: 0
73+
- Name: Output
74+
Kind: RWStructuredBuffer
75+
DirectXBinding:
76+
Register: 0
77+
Space: 0
78+
VulkanBinding:
79+
Binding: 1
80+
Results:
81+
- Result: InstanceContribution
82+
Rule: BufferExact
83+
Actual: Output
84+
Expected: Expected
85+
...
86+
#--- end
87+
88+
# REQUIRES: acceleration-structure
89+
# XFAIL: Clang
90+
91+
# RUN: split-file %s %t
92+
# RUN: %dxc_target -T cs_6_5 -Fo %t.o %t/source.hlsl
93+
# RUN: %offloader %t/pipeline.yaml %t.o

0 commit comments

Comments
 (0)