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