Skip to content

Commit ab718cf

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 ab718cf

2 files changed

Lines changed: 150 additions & 33 deletions

File tree

lib/API/Device.cpp

Lines changed: 64 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -116,42 +116,73 @@ 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+
llvm::Expected<BLASBuildRequest> ReqOrErr =
130+
llvm::createStringError(std::errc::invalid_argument, "uninitialized");
131+
if (!BD.Triangles.empty()) {
132+
llvm::SmallVector<TriangleGeometryDesc> Triangles;
133+
Triangles.reserve(BD.Triangles.size());
134+
for (const auto &T : BD.Triangles) {
135+
assert(T.VertexBufferPtr && "VertexBufferPtr not resolved");
136+
auto VBOrErr = createBufferWithData(
137+
Dev, "AS-Vertices", UploadDesc, T.VertexBufferPtr->Data[0].get(),
138+
T.VertexBufferPtr->size(), nullptr, nullptr);
139+
if (!VBOrErr)
140+
return VBOrErr.takeError();
141+
142+
TriangleGeometryDesc TGD;
143+
TGD.VertexBuffer = VBOrErr->get();
144+
TGD.VertexCount = T.VertexCount;
145+
TGD.VertexStride = T.VertexStride;
146+
TGD.VertexFormat = T.VertexFormat;
147+
TGD.Opaque = T.Opaque;
148+
149+
OutInputBuffers.push_back(std::move(*VBOrErr));
150+
151+
if (T.IndexBufferPtr) {
152+
auto IBOrErr = createBufferWithData(
153+
Dev, "AS-Indices", UploadDesc, T.IndexBufferPtr->Data[0].get(),
154+
T.IndexBufferPtr->size(), nullptr, nullptr);
155+
if (!IBOrErr)
156+
return IBOrErr.takeError();
157+
TGD.IndexBuffer = IBOrErr->get();
158+
TGD.IndexCount = T.IndexCount;
159+
TGD.IdxFormat = T.IdxFormat;
160+
OutInputBuffers.push_back(std::move(*IBOrErr));
161+
}
162+
Triangles.push_back(TGD);
163+
}
164+
ReqOrErr = Dev.createTriangleBLASBuildRequest(Triangles, BuildFlagNone);
165+
} else {
166+
llvm::SmallVector<AABBGeometryDesc> AABBs;
167+
AABBs.reserve(BD.AABBs.size());
168+
for (const auto &A : BD.AABBs) {
169+
assert(A.AABBBufferPtr && "AABBBufferPtr not resolved");
170+
auto ABOrErr = createBufferWithData(
171+
Dev, "AS-AABBs", UploadDesc, A.AABBBufferPtr->Data[0].get(),
172+
A.AABBBufferPtr->size(), nullptr, nullptr);
173+
if (!ABOrErr)
174+
return ABOrErr.takeError();
175+
AABBGeometryDesc AGD;
176+
AGD.AABBBuffer = ABOrErr->get();
177+
AGD.AABBCount = A.AABBCount;
178+
AGD.AABBStride = A.AABBStride;
179+
AGD.Opaque = A.Opaque;
180+
OutInputBuffers.push_back(std::move(*ABOrErr));
181+
AABBs.push_back(AGD);
148182
}
149-
Triangles.push_back(TGD);
183+
ReqOrErr = Dev.createAABBBLASBuildRequest(AABBs, BuildFlagNone);
150184
}
151-
// TODO: AABB geometry support (would mirror the triangle path).
152185

153-
auto ReqOrErr =
154-
Dev.createTriangleBLASBuildRequest(Triangles, BuildFlagNone);
155186
if (!ReqOrErr)
156187
return ReqOrErr.takeError();
157188
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)