forked from llvm/offload-test-suite
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAccelerationStructure.h
More file actions
200 lines (176 loc) · 7 KB
/
Copy pathAccelerationStructure.h
File metadata and controls
200 lines (176 loc) · 7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
//===- AccelerationStructure.h - RT Acceleration Structure Types ----------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef OFFLOADTEST_API_ACCELERATIONSTRUCTURE_H
#define OFFLOADTEST_API_ACCELERATIONSTRUCTURE_H
#include "API/API.h"
#include "API/Buffer.h"
#include "API/Resources.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/BitmaskEnum.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Error.h"
#include <cstdint>
#include <variant>
namespace offloadtest {
LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
// Bit values match D3D12_RAYTRACING_INSTANCE_FLAGS, VkGeometryInstanceFlagBits-
// KHR, and MTLAccelerationStructureInstanceOptions so backends can pass the
// value through unchanged.
enum AccelerationStructureInstanceFlags : uint32_t {
InstanceFlagNone = 0,
TriangleCullDisable = 1 << 0,
TriangleFrontCounterclockwise = 1 << 1,
ForceOpaque = 1 << 2,
ForceNonOpaque = 1 << 3,
};
struct AccelerationStructureSizes {
uint64_t ResultDataMaxSizeInBytes = 0;
uint64_t ScratchDataSizeInBytes = 0;
uint64_t UpdateScratchDataSizeInBytes = 0;
};
struct TriangleGeometryDesc {
Buffer *VertexBuffer = nullptr;
uint64_t VertexBufferOffset = 0;
uint32_t VertexCount = 0;
uint32_t VertexStride = 0;
Format VertexFormat = Format::RGB32Float;
Buffer *IndexBuffer = nullptr;
uint64_t IndexBufferOffset = 0;
uint32_t IndexCount = 0;
IndexFormat IdxFormat = IndexFormat::Uint32;
bool Opaque = true;
};
struct AABBGeometryDesc {
Buffer *AABBBuffer = nullptr;
uint64_t AABBBufferOffset = 0;
uint32_t AABBCount = 0;
uint32_t AABBStride = 24;
bool Opaque = true;
};
class AccelerationStructure;
struct AccelerationStructureInstance {
float Transform[3][4] = {{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}};
uint32_t InstanceID = 0;
uint8_t InstanceMask = 0xFF;
// 24-bit; high bits are truncated by the backend to match DXR's bitfield.
uint32_t InstanceContributionToHitGroupIndex = 0;
AccelerationStructureInstanceFlags Flags = InstanceFlagNone;
AccelerationStructure *BLAS = nullptr;
};
struct BLASBuildRequest {
// Target AS this build writes into.
AccelerationStructure *AS = nullptr;
// DXR / Vulkan / Metal all forbid mixing triangle and AABB geometry in a
// single BLAS, so the geometry list is held as a variant — the invalid
// mixed-geometry state is unrepresentable.
std::variant<llvm::SmallVector<TriangleGeometryDesc>,
llvm::SmallVector<AABBGeometryDesc>>
Geometry;
};
struct TLASBuildRequest {
// Target AS this build writes into.
AccelerationStructure *AS = nullptr;
llvm::SmallVector<AccelerationStructureInstance> Instances;
};
inline llvm::Error validateGeometryDesc(const TriangleGeometryDesc &D) {
if (!D.VertexBuffer)
return llvm::createStringError(
std::errc::invalid_argument,
"TriangleGeometryDesc: VertexBuffer is null.");
if (!isPositionCompatible(D.VertexFormat))
return llvm::createStringError(
std::errc::invalid_argument,
"TriangleGeometryDesc: VertexFormat '%s' is not position-compatible.",
getFormatName(D.VertexFormat).data());
if (D.VertexStride < getFormatSizeInBytes(D.VertexFormat))
return llvm::createStringError(
std::errc::invalid_argument,
"TriangleGeometryDesc: VertexStride (%u) must be >= format size (%u).",
D.VertexStride, getFormatSizeInBytes(D.VertexFormat));
if (D.VertexCount == 0)
return llvm::createStringError(std::errc::invalid_argument,
"TriangleGeometryDesc: VertexCount is 0.");
if (D.IndexBuffer && D.IndexCount == 0)
return llvm::createStringError(
std::errc::invalid_argument,
"TriangleGeometryDesc: IndexBuffer is set but IndexCount is 0.");
if (!D.IndexBuffer && D.IndexCount != 0)
return llvm::createStringError(
std::errc::invalid_argument,
"TriangleGeometryDesc: IndexCount is set but IndexBuffer is null.");
if (D.IndexBuffer && D.IndexCount % 3 != 0)
return llvm::createStringError(
std::errc::invalid_argument,
"TriangleGeometryDesc: IndexCount (%u) must be a multiple of 3.",
D.IndexCount);
if (!D.IndexBuffer && D.VertexCount % 3 != 0)
return llvm::createStringError(
std::errc::invalid_argument,
"TriangleGeometryDesc: VertexCount (%u) must be a multiple of 3 when "
"no index buffer is provided.",
D.VertexCount);
return llvm::Error::success();
}
inline llvm::Error validateGeometryDesc(const AABBGeometryDesc &D) {
if (!D.AABBBuffer)
return llvm::createStringError(std::errc::invalid_argument,
"AABBGeometryDesc: AABBBuffer is null.");
if (D.AABBCount == 0)
return llvm::createStringError(std::errc::invalid_argument,
"AABBGeometryDesc: AABBCount is 0.");
if (D.AABBStride < 24)
return llvm::createStringError(
std::errc::invalid_argument,
"AABBGeometryDesc: AABBStride (%u) must be >= 24.", D.AABBStride);
return llvm::Error::success();
}
template <typename T>
inline llvm::Error validateBLASGeometry(llvm::ArrayRef<T> Geoms) {
if (Geoms.empty())
return llvm::createStringError(
std::errc::invalid_argument,
"BLASBuildRequest must have at least one geometry descriptor.");
for (const auto &G : Geoms)
if (auto Err = validateGeometryDesc(G))
return Err;
return llvm::Error::success();
}
inline llvm::Error validateTLASBuildRequest(const TLASBuildRequest &Req) {
if (Req.Instances.empty())
return llvm::createStringError(
std::errc::invalid_argument,
"TLASBuildRequest: Must have at least one instance.");
for (size_t I = 0; I < Req.Instances.size(); ++I)
if (!Req.Instances[I].BLAS)
return llvm::createStringError(
std::errc::invalid_argument,
"TLASBuildRequest: Instance %zu has a null BLAS pointer.", I);
return llvm::Error::success();
}
class AccelerationStructure {
GPUAPI API;
AccelerationStructureSizes Sizes;
public:
virtual ~AccelerationStructure();
AccelerationStructure(const AccelerationStructure &) = delete;
AccelerationStructure &operator=(const AccelerationStructure &) = delete;
GPUAPI getAPI() const { return API; }
// Result/scratch sizes the AS was allocated for. Available for the GPU
// build path so it can size the scratch buffer without re-querying.
const AccelerationStructureSizes &getSizes() const { return Sizes; }
protected:
explicit AccelerationStructure(GPUAPI API,
const AccelerationStructureSizes &Sizes)
: API(API), Sizes(Sizes) {}
};
} // namespace offloadtest
namespace llvm {
LLVM_DECLARE_ENUM_AS_BITMASK(::offloadtest::AccelerationStructureInstanceFlags,
::offloadtest::ForceNonOpaque);
} // namespace llvm
#endif // OFFLOADTEST_API_ACCELERATIONSTRUCTURE_H