Skip to content

Commit 98956e7

Browse files
MarijnS95claude
andcommitted
Wire AABB/procedural geometry through the Pipeline-level AS builder
Routes BLASDesc.AABBs through the Pipeline → API conversion in buildPipelineAccelerationStructures, picking createAABBBLAS- BuildRequest vs createTriangleBLASBuildRequest based on which geometry list is populated (mixed and empty cases now error explicitly). The DX/VK/MTL AABB build paths were already in place. The covering test defines a single AABB, fires a ray through it, and in the candidate loop calls CommitProceduralPrimitiveHit(); CommittedStatus() must return COMMITTED_PROCEDURAL_PRIMITIVE_HIT. Part of the inline-RT test coverage epic (#1258). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 9147302 commit 98956e7

2 files changed

Lines changed: 150 additions & 34 deletions

File tree

lib/API/Device.cpp

Lines changed: 64 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -116,42 +116,72 @@ llvm::Error offloadtest::buildPipelineAccelerationStructures(
116116
llvm::StringMap<size_t> BLASIndex;
117117

118118
for (const auto &BD : P.AccelStructs.BLAS) {
119-
llvm::SmallVector<TriangleGeometryDesc> Triangles;
120-
Triangles.reserve(BD.Triangles.size());
121-
for (const auto &T : BD.Triangles) {
122-
assert(T.VertexBufferPtr && "VertexBufferPtr not resolved");
123-
auto VBOrErr = createBufferWithData(
124-
Dev, "AS-Vertices", UploadDesc, T.VertexBufferPtr->Data[0].get(),
125-
T.VertexBufferPtr->size(), nullptr, nullptr);
126-
if (!VBOrErr)
127-
return VBOrErr.takeError();
128-
129-
TriangleGeometryDesc TGD;
130-
TGD.VertexBuffer = VBOrErr->get();
131-
TGD.VertexCount = T.VertexCount;
132-
TGD.VertexStride = T.VertexStride;
133-
TGD.VertexFormat = T.VertexFormat;
134-
TGD.Opaque = T.Opaque;
135-
136-
OutInputBuffers.push_back(std::move(*VBOrErr));
137-
138-
if (T.IndexBufferPtr) {
139-
auto IBOrErr = createBufferWithData(
140-
Dev, "AS-Indices", UploadDesc, T.IndexBufferPtr->Data[0].get(),
141-
T.IndexBufferPtr->size(), nullptr, nullptr);
142-
if (!IBOrErr)
143-
return IBOrErr.takeError();
144-
TGD.IndexBuffer = IBOrErr->get();
145-
TGD.IndexCount = T.IndexCount;
146-
TGD.IdxFormat = T.IdxFormat;
147-
OutInputBuffers.push_back(std::move(*IBOrErr));
119+
if (!BD.Triangles.empty() && !BD.AABBs.empty())
120+
return llvm::createStringError(
121+
std::errc::invalid_argument,
122+
"BLAS '%s' mixes triangle and AABB geometry; pick one.",
123+
BD.Name.c_str());
124+
if (BD.Triangles.empty() && BD.AABBs.empty())
125+
return llvm::createStringError(std::errc::invalid_argument,
126+
"BLAS '%s' has no geometry.",
127+
BD.Name.c_str());
128+
129+
auto ReqOrErr = [&]() -> llvm::Expected<BLASBuildRequest> {
130+
if (!BD.Triangles.empty()) {
131+
llvm::SmallVector<TriangleGeometryDesc> Triangles;
132+
Triangles.reserve(BD.Triangles.size());
133+
for (const auto &T : BD.Triangles) {
134+
assert(T.VertexBufferPtr && "VertexBufferPtr not resolved");
135+
auto VBOrErr = createBufferWithData(
136+
Dev, "AS-Vertices", UploadDesc, T.VertexBufferPtr->Data[0].get(),
137+
T.VertexBufferPtr->size(), nullptr, nullptr);
138+
if (!VBOrErr)
139+
return VBOrErr.takeError();
140+
141+
TriangleGeometryDesc TGD;
142+
TGD.VertexBuffer = VBOrErr->get();
143+
TGD.VertexCount = T.VertexCount;
144+
TGD.VertexStride = T.VertexStride;
145+
TGD.VertexFormat = T.VertexFormat;
146+
TGD.Opaque = T.Opaque;
147+
148+
OutInputBuffers.push_back(std::move(*VBOrErr));
149+
150+
if (T.IndexBufferPtr) {
151+
auto IBOrErr = createBufferWithData(
152+
Dev, "AS-Indices", UploadDesc, T.IndexBufferPtr->Data[0].get(),
153+
T.IndexBufferPtr->size(), nullptr, nullptr);
154+
if (!IBOrErr)
155+
return IBOrErr.takeError();
156+
TGD.IndexBuffer = IBOrErr->get();
157+
TGD.IndexCount = T.IndexCount;
158+
TGD.IdxFormat = T.IdxFormat;
159+
OutInputBuffers.push_back(std::move(*IBOrErr));
160+
}
161+
Triangles.push_back(TGD);
162+
}
163+
return Dev.createTriangleBLASBuildRequest(Triangles, BuildFlagNone);
148164
}
149-
Triangles.push_back(TGD);
150-
}
151-
// TODO: AABB geometry support (would mirror the triangle path).
165+
llvm::SmallVector<AABBGeometryDesc> AABBs;
166+
AABBs.reserve(BD.AABBs.size());
167+
for (const auto &A : BD.AABBs) {
168+
assert(A.AABBBufferPtr && "AABBBufferPtr not resolved");
169+
auto ABOrErr = createBufferWithData(
170+
Dev, "AS-AABBs", UploadDesc, A.AABBBufferPtr->Data[0].get(),
171+
A.AABBBufferPtr->size(), nullptr, nullptr);
172+
if (!ABOrErr)
173+
return ABOrErr.takeError();
174+
AABBGeometryDesc AGD;
175+
AGD.AABBBuffer = ABOrErr->get();
176+
AGD.AABBCount = A.AABBCount;
177+
AGD.AABBStride = A.AABBStride;
178+
AGD.Opaque = A.Opaque;
179+
OutInputBuffers.push_back(std::move(*ABOrErr));
180+
AABBs.push_back(AGD);
181+
}
182+
return Dev.createAABBBLASBuildRequest(AABBs, BuildFlagNone);
183+
}();
152184

153-
auto ReqOrErr =
154-
Dev.createTriangleBLASBuildRequest(Triangles, BuildFlagNone);
155185
if (!ReqOrErr)
156186
return ReqOrErr.takeError();
157187
auto ASOrErr = Dev.createAccelerationStructure(*ReqOrErr);
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
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(1,1,1)]
7+
void main() {
8+
// A single AABB at [-1, 1]^3. The candidate path fires once per AABB
9+
// hit; the shader supplies a fixed hit-t of 1.5 (inside the box on the
10+
// -z ray below). After the loop CommittedStatus() must report
11+
// COMMITTED_PROCEDURAL_PRIMITIVE_HIT (2).
12+
RayDesc Ray;
13+
Ray.Origin = float3(0, 0, 2);
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+
while (Q.Proceed()) {
20+
if (Q.CandidateType() == CANDIDATE_PROCEDURAL_PRIMITIVE)
21+
Q.CommitProceduralPrimitiveHit(1.5);
22+
}
23+
Output[0] = (uint)Q.CommittedStatus();
24+
}
25+
//--- pipeline.yaml
26+
---
27+
Shaders:
28+
- Stage: Compute
29+
Entry: main
30+
Buffers:
31+
- Name: AABBs
32+
Format: Float32
33+
Stride: 24
34+
# D3D12_RAYTRACING_AABB / VkAabbPositionsKHR layout:
35+
# { MinX, MinY, MinZ, MaxX, MaxY, MaxZ }, one box per stride.
36+
Data: [ -1.0, -1.0, -1.0, 1.0, 1.0, 1.0 ]
37+
- Name: Output
38+
Format: UInt32
39+
Stride: 4
40+
FillSize: 4
41+
- Name: Expected
42+
Format: UInt32
43+
Stride: 4
44+
# COMMITTED_PROCEDURAL_PRIMITIVE_HIT = 2
45+
Data: [ 2 ]
46+
AccelerationStructures:
47+
BLAS:
48+
- Name: AABBBLAS
49+
AABBs:
50+
- AABBBuffer: AABBs
51+
AABBCount: 1
52+
AABBStride: 24
53+
TLAS:
54+
- Name: Scene
55+
Instances:
56+
- BLAS: AABBBLAS
57+
DescriptorSets:
58+
- Resources:
59+
- Name: Scene
60+
Kind: AccelerationStructure
61+
DirectXBinding:
62+
Register: 0
63+
Space: 0
64+
VulkanBinding:
65+
Binding: 0
66+
- Name: Output
67+
Kind: RWStructuredBuffer
68+
DirectXBinding:
69+
Register: 0
70+
Space: 0
71+
VulkanBinding:
72+
Binding: 1
73+
Results:
74+
- Result: AABBProcedural
75+
Rule: BufferExact
76+
Actual: Output
77+
Expected: Expected
78+
...
79+
#--- end
80+
81+
# REQUIRES: acceleration-structure
82+
# XFAIL: Clang
83+
84+
# RUN: split-file %s %t
85+
# RUN: %dxc_target -T cs_6_5 -Fo %t.o %t/source.hlsl
86+
# RUN: %offloader %t/pipeline.yaml %t.o

0 commit comments

Comments
 (0)