Blender V4.5
nanovdb.h
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2020-2021 Contributors to the OpenVDB Project
2 * SPDX-FileCopyrightText: 2023-2025 Blender Authors
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * This is an extract from NanoVDB.h, with minimal code needed for kernel side access to grids. The
7 * original headers are not compatible with Metal due to missing address space qualifiers. */
8
9#pragma once
10
11#include "util/defines.h"
12#include "util/types_base.h"
13
14#ifndef __KERNEL_GPU__
15# include <climits>
16#endif
17
19
20#define NANOVDB_USE_SINGLE_ROOT_KEY
21#define NANOVDB_DATA_ALIGNMENT 32 // NOLINT
22
23namespace nanovdb {
24
25/* Utilities */
26
27template<typename DstT, typename SrcT>
28const ccl_device ccl_global DstT *PtrAdd(const ccl_global SrcT *p, int64_t offset)
29{
30 return reinterpret_cast<const ccl_global DstT *>(reinterpret_cast<const ccl_global char *>(p) +
31 offset);
32}
33
34/* Coord */
35
36struct Coord {
37 int x, y, z;
38
39 ccl_device_inline_method explicit Coord(int32_t n) : x(n), y(n), z(n) {}
41
43 {
44 return Coord(x & n, y & n, z & n);
45 }
46};
47
48/* Mask */
49
50template<uint32_t LOG2DIM> struct Mask {
51 ccl_static_constexpr uint32_t SIZE = 1U << (3 * LOG2DIM);
54
56 {
57 return 0 == (mWords[n >> 6] & (uint64_t(1) << (n & 63)));
58 }
59};
60
61/* Grid */
62
63template<typename TreeT> struct alignas(NANOVDB_DATA_ALIGNMENT) Grid {
64 ccl_static_constexpr int MaxNameSize = 256;
72 char mGridName[MaxNameSize];
73 uint8_t mMap[264];
74 uint8_t mWorldBBox[48]; // double[6], but no doubles in Metal
75 uint8_t mVoxelSize[24]; // double[3], but no doubles in Metal
80
81 using BuildType = typename TreeT::BuildType;
82
84 {
85 return *reinterpret_cast<const ccl_global TreeT *>(this + 1);
86 }
87};
88
89/* Tree */
90
91template<typename RootT> struct alignas(NANOVDB_DATA_ALIGNMENT) Tree {
92 int64_t mNodeOffset[4];
93 uint32_t mNodeCount[3];
94 uint32_t mTileCount[3];
96
97 using ValueType = typename RootT::ValueType;
98 using BuildType = typename RootT::BuildType;
99
101 {
102 return *reinterpret_cast<const ccl_global RootT *>(
103 mNodeOffset[3] ? PtrAdd<uint8_t>(this, mNodeOffset[3]) : nullptr);
104 }
105};
106
107/* RootNode */
108
109template<typename ChildT> struct alignas(NANOVDB_DATA_ALIGNMENT) RootNode {
110 using ValueType = typename ChildT::ValueType;
111 using BuildType = typename ChildT::BuildType;
112
113#ifdef NANOVDB_USE_SINGLE_ROOT_KEY
114 using KeyT = uint64_t;
116 {
117 return (uint64_t(uint32_t(ijk.z) >> ChildT::TOTAL)) |
118 (uint64_t(uint32_t(ijk.y) >> ChildT::TOTAL) << 21) |
119 (uint64_t(uint32_t(ijk.x) >> ChildT::TOTAL) << 42);
120 }
121#else
122 using KeyT = Coord;
123 static ccl_device_inline_method Coord CoordToKey(const CoordT ijk)
124 {
125 return ijk & ~ChildT::MASK;
126 }
127#endif
128 Coord mBBox[2];
130
134 float mAverage;
135 float mStdDevi;
136
137 struct alignas(NANOVDB_DATA_ALIGNMENT) Tile {
142 };
143
145 {
146 const auto key = CoordToKey(ijk);
147 const ccl_global Tile *p = reinterpret_cast<const ccl_global Tile *>(this + 1);
148 const ccl_global Tile *q = p + mTableSize;
149 for (; p < q; ++p) {
150 if (p->key == key) {
151 return p;
152 }
153 }
154 return nullptr;
155 }
156
159 {
160 return PtrAdd<ChildT>(this, tile->child);
161 }
162
163 ccl_static_constexpr uint32_t LEVEL = 1 + ChildT::LEVEL;
164};
165
166/* InternalNode */
167
168template<typename ChildT, const uint32_t Log2Dim = ChildT::LOG2DIM + 1>
169struct alignas(NANOVDB_DATA_ALIGNMENT) InternalNode {
170 using ValueType = typename ChildT::ValueType;
171 using BuildType = typename ChildT::BuildType;
172
177
178 Coord mBBox[2];
182
185 float mAverage;
186 float mStdDevi;
187
188 alignas(32) Tile mTable[1u << (3 * Log2Dim)];
189
191 {
192 return PtrAdd<ChildT>(this, mTable[n].child);
193 }
194
196 ccl_static_constexpr uint32_t TOTAL = LOG2DIM + ChildT::TOTAL;
198 ccl_static_constexpr uint32_t SIZE = 1u << (3 * LOG2DIM);
199 ccl_static_constexpr uint32_t MASK = (1u << TOTAL) - 1u;
200 ccl_static_constexpr uint32_t LEVEL = 1 + ChildT::LEVEL;
201
203 {
204 return (((ijk.x & MASK) >> ChildT::TOTAL) << (2 * LOG2DIM)) |
205 (((ijk.y & MASK) >> ChildT::TOTAL) << (LOG2DIM)) | ((ijk.z & MASK) >> ChildT::TOTAL);
206 }
207};
208
209/* LeafData */
210
211template<typename ValueT, const uint32_t LOG2DIM> struct alignas(NANOVDB_DATA_ALIGNMENT) LeafData {
212 using ValueType = ValueT;
213 using BuildType = ValueT;
214
216 uint8_t mBBoxDif[3];
219
222 float mAverage;
223 float mStdDevi;
224 alignas(32) ValueType mValues[1u << 3 * LOG2DIM];
225
227 {
228 return mValues[i];
229 }
230};
231
232/* LeafFnBase */
233
234template<uint32_t LOG2DIM> struct alignas(NANOVDB_DATA_ALIGNMENT) LeafFnBase {
236 uint8_t mBBoxDif[3];
239
240 float mMinimum;
241 float mQuantum;
242 uint16_t mMin, mMax, mAvg, mDev;
243};
244
245/* LeafData<Fp16> */
246
247class Fp16 {};
248
249template<uint32_t LOG2DIM> struct alignas(NANOVDB_DATA_ALIGNMENT) LeafData<Fp16, LOG2DIM> {
250 using ValueType = float;
252
254 alignas(32) uint16_t mCode[1u << 3 * LOG2DIM];
255
257 {
258 return mCode[i] * base.mQuantum + base.mMinimum;
259 }
260};
261
262/* LeafData<FpN> */
263
264class FpN {};
265
266template<uint32_t LOG2DIM> struct alignas(NANOVDB_DATA_ALIGNMENT) LeafData<FpN, LOG2DIM> {
267 using ValueType = float;
268 using BuildType = FpN;
269
271
273 {
274 const int b = base.mFlags >> 5;
275 uint32_t code = reinterpret_cast<const ccl_global uint32_t *>(this + 1)[i >> (5 - b)];
276 code >>= (i & ((32 >> b) - 1)) << b;
277 code &= (1 << (1 << b)) - 1;
278 return float(code) * base.mQuantum + base.mMinimum;
279 }
280};
281
282/* LeafNode */
283
284template<typename BuildT, const uint32_t Log2Dim = 3>
285struct alignas(NANOVDB_DATA_ALIGNMENT) LeafNode {
289
291
295 ccl_static_constexpr uint32_t SIZE = 1u << 3 * LOG2DIM;
296 ccl_static_constexpr uint32_t MASK = (1u << LOG2DIM) - 1u;
298
300 {
301 return ((ijk.x & MASK) << (2 * LOG2DIM)) | ((ijk.y & MASK) << LOG2DIM) | (ijk.z & MASK);
302 }
303
305 {
306 return data.getValue(offset);
307 }
308
310 {
311 return getValue(CoordToOffset(ijk));
312 }
313};
314
315/* Template Specializations */
316
317template<typename BuildT> using NanoLeaf = LeafNode<BuildT, 3>;
318template<typename BuildT> using NanoLower = InternalNode<NanoLeaf<BuildT>, 4>;
319template<typename BuildT> using NanoUpper = InternalNode<NanoLower<BuildT>, 5>;
320template<typename BuildT> using NanoRoot = RootNode<NanoUpper<BuildT>>;
321template<typename BuildT> using NanoTree = Tree<NanoRoot<BuildT>>;
322template<typename BuildT> using NanoGrid = Grid<NanoTree<BuildT>>;
323
324/* ReadAccessor */
325
326template<typename BuildT> class ReadAccessor {
327 using RootT = NanoRoot<BuildT>;
328 using LeafT = NanoLeaf<BuildT>;
329
330 mutable const ccl_global RootT *mRoot;
331
332 public:
333 using ValueType = typename RootT::ValueType;
334
336
338 {
339 const ccl_global auto *tile = mRoot->probeTile(ijk);
340 if (tile == nullptr) {
341 return mRoot->mBackground;
342 }
343 if (tile->child == 0) {
344 return tile->value;
345 }
346
347 const ccl_global auto *upper = mRoot->getChild(tile);
348 const uint32_t upper_n = upper->CoordToOffset(ijk);
349 if (upper->mChildMask.isOff(upper_n)) {
350 return upper->mTable[upper_n].value;
351 }
352
353 const ccl_global auto *lower = upper->getChild(upper_n);
354 const uint32_t lower_n = lower->CoordToOffset(ijk);
355 if (lower->mChildMask.isOff(lower_n)) {
356 return lower->mTable[lower_n].value;
357 }
358
359 const ccl_global LeafT *leaf = lower->getChild(lower_n);
360 return leaf->getValue(ijk);
361 }
362};
363
364template<typename BuildT> class CachedReadAccessor {
365 using RootT = NanoRoot<BuildT>;
368 using LeafT = NanoLeaf<BuildT>;
369
370 mutable Coord mKeys[3] = {Coord(INT_MAX), Coord(INT_MAX), Coord(INT_MAX)};
371 mutable const ccl_global RootT *mRoot = nullptr;
372 mutable const ccl_global void *mNode[3] = {nullptr, nullptr, nullptr};
373
374 public:
375 using ValueType = typename RootT::ValueType;
376
378
379 template<typename NodeT> ccl_device_inline_method bool isCached(const Coord ijk) const
380 {
381 return (ijk.x & int32_t(~NodeT::MASK)) == mKeys[NodeT::LEVEL].x &&
382 (ijk.y & int32_t(~NodeT::MASK)) == mKeys[NodeT::LEVEL].y &&
383 (ijk.z & int32_t(~NodeT::MASK)) == mKeys[NodeT::LEVEL].z;
384 }
385
387 const Coord ijk) const
388 {
389 if (const ccl_global auto *tile = node.probeTile(ijk)) {
390 if (tile->child != 0) {
391 const ccl_global auto *child = node.getChild(tile);
392 insert(ijk, child);
393 return getValueAndCache(*child, ijk);
394 }
395 return tile->value;
396 }
397 return node.mBackground;
398 }
399
401 const Coord ijk) const
402 {
403 return node.getValue(ijk);
404 }
405
406 template<typename NodeT>
408 const Coord ijk) const
409 {
410 const uint32_t n = node.CoordToOffset(ijk);
411 if (node.mChildMask.isOff(n)) {
412 return node.mTable[n].value;
413 }
414 const ccl_global auto *child = node.getChild(n);
415 insert(ijk, child);
416 return getValueAndCache(*child, ijk);
417 }
418
420 {
421 if (isCached<LeafT>(ijk)) {
422 return getValueAndCache(*((const ccl_global LeafT *)mNode[0]), ijk);
423 }
424 if (isCached<LowerT>(ijk)) {
425 return getValueAndCache(*((const ccl_global LowerT *)mNode[1]), ijk);
426 }
427 if (isCached<UpperT>(ijk)) {
428 return getValueAndCache(*((const ccl_global UpperT *)mNode[2]), ijk);
429 }
430 return getValueAndCache(*mRoot, ijk);
431 }
432
433 template<typename NodeT>
434 ccl_device_inline_method void insert(const Coord ijk, const ccl_global NodeT *node) const
435 {
436 mKeys[NodeT::LEVEL] = ijk & ~NodeT::MASK;
437 mNode[NodeT::LEVEL] = node;
438 }
439};
440
441} // namespace nanovdb
442
#define SIZE
void BLI_kdtree_nd_ insert(KDTree *tree, int index, const float co[KD_DIMS]) ATTR_NONNULL(1
int key
std::string data
#define MASK
SIMD_FORCE_INLINE const btScalar & z() const
Return the z value.
Definition btQuadWord.h:117
typename RootT::ValueType ValueType
Definition nanovdb.h:375
ccl_device_inline_method ValueType getValueAndCache(const ccl_global RootT &node, const Coord ijk) const
Definition nanovdb.h:386
ccl_device_inline_method ValueType getValueAndCache(const ccl_global LeafT &node, const Coord ijk) const
Definition nanovdb.h:400
ccl_device_inline_method CachedReadAccessor(const ccl_global RootT &root)
Definition nanovdb.h:377
ccl_device_inline_method bool isCached(const Coord ijk) const
Definition nanovdb.h:379
ccl_device_inline_method void insert(const Coord ijk, const ccl_global NodeT *node) const
Definition nanovdb.h:434
ccl_device_inline_method ValueType getValue(const Coord ijk) const
Definition nanovdb.h:419
ccl_device_inline_method ValueType getValueAndCache(const ccl_global NodeT &node, const Coord ijk) const
Definition nanovdb.h:407
typename RootT::ValueType ValueType
Definition nanovdb.h:333
ccl_device_inline_method ValueType getValue(const Coord ijk) const
Definition nanovdb.h:337
ccl_device_inline_method ReadAccessor(const ccl_global RootT &root)
Definition nanovdb.h:335
OperationNode * node
#define ccl_device
#define ccl_global
#define CCL_NAMESPACE_END
#define ccl_static_constexpr
#define ccl_device_inline_method
unsigned int uint32_t
const ccl_global KernelWorkTile * tile
const ccl_device ccl_global DstT * PtrAdd(const ccl_global SrcT *p, int64_t offset)
Definition nanovdb.h:28
unsigned short uint16_t
Definition stdint.h:79
__int64 int64_t
Definition stdint.h:89
signed int int32_t
Definition stdint.h:77
unsigned char uint8_t
Definition stdint.h:78
unsigned __int64 uint64_t
Definition stdint.h:90
ccl_device_inline_method Coord operator&(int32_t n) const
Definition nanovdb.h:42
ccl_device_inline_method Coord(int32_t x, int32_t y, int32_t z)
Definition nanovdb.h:40
ccl_device_inline_method Coord(int32_t n)
Definition nanovdb.h:39
uint32_t mVersion
Definition nanovdb.h:67
const ccl_device_inline_method ccl_global TreeT & tree() const ccl_global
Definition nanovdb.h:83
uint32_t mFlags
Definition nanovdb.h:68
uint32_t mData0
Definition nanovdb.h:78
uint64_t mGridSize
Definition nanovdb.h:71
typename TreeT::BuildType BuildType
Definition nanovdb.h:81
uint64_t mChecksum
Definition nanovdb.h:66
uint32_t mGridType
Definition nanovdb.h:77
uint64_t mMagic
Definition nanovdb.h:65
uint32_t mGridClass
Definition nanovdb.h:76
uint32_t mGridIndex
Definition nanovdb.h:69
uint64_t mData1
Definition nanovdb.h:79
uint32_t mGridCount
Definition nanovdb.h:70
const ccl_device_inline_method ccl_global ChildT * getChild(const uint32_t n) const ccl_global
Definition nanovdb.h:190
Mask< Log2Dim > mValueMask
Definition nanovdb.h:180
typename ChildT::ValueType ValueType
Definition nanovdb.h:170
Mask< Log2Dim > mChildMask
Definition nanovdb.h:181
static ccl_device_inline_method uint32_t CoordToOffset(const Coord ijk)
Definition nanovdb.h:202
typename ChildT::BuildType BuildType
Definition nanovdb.h:171
ccl_device_inline_method float getValue(const uint32_t i) const ccl_global
Definition nanovdb.h:256
LeafFnBase< LOG2DIM > base
Definition nanovdb.h:253
ccl_device_inline_method float getValue(const uint32_t i) const ccl_global
Definition nanovdb.h:272
LeafFnBase< LOG2DIM > base
Definition nanovdb.h:270
ValueType mMaximum
Definition nanovdb.h:221
ValueType mMinimum
Definition nanovdb.h:220
ccl_device_inline_method ValueType getValue(const uint32_t i) const ccl_global
Definition nanovdb.h:226
Mask< LOG2DIM > mValueMask
Definition nanovdb.h:218
Mask< LOG2DIM > mValueMask
Definition nanovdb.h:238
DataType data
Definition nanovdb.h:290
typename DataType::BuildType BuildType
Definition nanovdb.h:288
typename DataType::ValueType ValueType
Definition nanovdb.h:287
static ccl_device_inline_method uint32_t CoordToOffset(const Coord ijk)
Definition nanovdb.h:299
ccl_device_inline_method ValueType getValue(const Coord ijk) const ccl_global
Definition nanovdb.h:309
ccl_device_inline_method ValueType getValue(const uint32_t offset) const ccl_global
Definition nanovdb.h:304
ccl_device_inline_method bool isOff(const uint32_t n) const ccl_global
Definition nanovdb.h:55
ccl_static_constexpr uint32_t SIZE
Definition nanovdb.h:51
ccl_static_constexpr uint32_t WORD_COUNT
Definition nanovdb.h:52
uint64_t mWords[WORD_COUNT]
Definition nanovdb.h:53
static ccl_device_inline_method uint64_t CoordToKey(const Coord ijk)
Definition nanovdb.h:115
typename ChildT::ValueType ValueType
Definition nanovdb.h:110
ValueType mBackground
Definition nanovdb.h:131
ValueType mMinimum
Definition nanovdb.h:132
typename ChildT::BuildType BuildType
Definition nanovdb.h:111
const ccl_device_inline_method ccl_global ChildT * getChild(const ccl_global Tile *tile) const ccl_global
Definition nanovdb.h:157
uint32_t mTableSize
Definition nanovdb.h:129
const ccl_device_inline_method ccl_global Tile * probeTile(const Coord ijk) const ccl_global
Definition nanovdb.h:144
ValueType mMaximum
Definition nanovdb.h:133
uint64_t KeyT
Definition nanovdb.h:114
uint64_t mVoxelCount
Definition nanovdb.h:95
const ccl_device_inline_method ccl_global RootT & root() const ccl_global
Definition nanovdb.h:100
typename RootT::ValueType ValueType
Definition nanovdb.h:97
typename RootT::BuildType BuildType
Definition nanovdb.h:98