Skip to content

Commit 76b32d3

Browse files
committed
NanoVDB CUDA: spell out the abbreviated locals in the cached stencil resolvers
Rename the terse identifiers introduced with the cached resolvers to read as plain English, matching the naming used elsewhere in this file: c/slot/n -> entry/leafSlot/neighborID, nSpanned -> spannedLeafCount, firstSpanned -> firstLeaf, nl -> neighborLeaf, cached -> isCached, vi/vj/vk -> voxelX/Y/Z, li/lj/lk -> leafX/Y/Z, and sSpannedCount -> sSpannedLeafCount. Also note why the cross lookup tests (voxelOnAxis + dir) & ~7, i.e. whether the tap steps off the leaf on that axis. Comments and identifiers only. Registers, stack and shared memory are unchanged (38/16/1668 for the cross kernel, 73/216/4228 for the materialized cached box) and all VBM goldens still pass byte-exact. Signed-off-by: Jonathan Swartz <jonathan@jswartz.info>
1 parent 62145d5 commit 76b32d3

1 file changed

Lines changed: 47 additions & 39 deletions

File tree

nanovdb/nanovdb/tools/cuda/VoxelBlockManager.cuh

Lines changed: 47 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -68,54 +68,58 @@ struct VoxelBlockManager : nanovdb::tools::VoxelBlockManagerBase<Log2BlockWidth>
6868
/// to MaxCachedLeaves. Shared preamble of the cached resolvers, which stage one table
6969
/// entry group per spanned leaf. Must be called by all threads (uses __syncthreads).
7070
/// @param smem_leafIndex Decoded leaf indices in shared memory
71-
/// @param firstSpanned Leaf index of slot 0, i.e. the first leaf the block spans
71+
/// @param firstLeaf Leaf index of slot 0, i.e. the first leaf the block spans
7272
/// @param myLeaf This thread's leaf index (UnusedLeafIndex past the last voxel)
7373
template <int MaxCachedLeaves>
7474
__device__
75-
static int cachedLeafSpan(const uint32_t *smem_leafIndex, uint32_t firstSpanned, uint32_t myLeaf)
75+
static int cachedLeafSpan(const uint32_t *smem_leafIndex, uint32_t firstLeaf, uint32_t myLeaf)
7676
{
77-
__shared__ int sSpannedCount;
77+
__shared__ int sSpannedLeafCount;
7878
const int tID = threadIdx.x;
79-
if (tID == 0) sSpannedCount = 0;
79+
if (tID == 0) sSpannedLeafCount = 0;
8080
__syncthreads();
8181
// one atomicMax per distinct leaf: only the first slot of each run contributes
8282
if (myLeaf != UnusedLeafIndex && (tID == 0 || smem_leafIndex[tID-1] != myLeaf))
83-
atomicMax(&sSpannedCount, int(myLeaf - firstSpanned) + 1);
83+
atomicMax(&sSpannedLeafCount, int(myLeaf - firstLeaf) + 1);
8484
__syncthreads();
85-
return sSpannedCount < MaxCachedLeaves ? sSpannedCount : MaxCachedLeaves;
85+
return sSpannedLeafCount < MaxCachedLeaves ? sSpannedLeafCount : MaxCachedLeaves;
8686
}
8787

8888
/// @brief Stage the per-spanned-leaf neighbor table shared by the cached resolvers.
8989
///
90-
/// Fills table[slot*N + n] with the leaf node lying at neighbor position n of the slot-th
91-
/// spanned leaf, or nullptr where no such leaf exists; entry SelfIndex stores the spanned
90+
/// Fills table[leafSlot*N + neighborID] with the leaf lying at that neighbor position of
91+
/// the leafSlot-th spanned leaf, or nullptr if absent; entry SelfIndex stores the spanned
9292
/// leaf itself rather than probing for it. Each resolver supplies the shift from a leaf
9393
/// origin to its n-th neighbor's origin, so it keeps whatever indexing its lookup expects.
94-
/// The nSpanned x N entries are distributed across ALL threads, so no thread serializes
94+
/// The spannedLeafCount x N entries are distributed across ALL threads, so no thread serializes
9595
/// the probes.
9696
///
9797
/// Must be called by all threads in the block (ends in __syncthreads).
9898
///
9999
/// @tparam N Table entries per spanned leaf
100100
/// @tparam SelfIndex Entry index holding the spanned leaf itself (not probed for)
101-
/// @tparam OffsetT Device-callable (Coord& origin, int n) shifting a leaf origin to the
102-
/// origin of the leaf at entry n
103-
/// @param table Flattened [MaxCachedLeaves][N] table of leaf pointers in shared memory
104-
/// @param nSpanned Number of spanned leaves (from cachedLeafSpan)
101+
/// @tparam OffsetT Device-callable (Coord& origin, int neighborID) shifting a leaf origin
102+
/// to the origin of the leaf at that neighbor position
103+
/// @param table Flattened [MaxCachedLeaves][N] leaf-pointer table in shared memory
104+
/// @param spannedLeafCount Number of spanned leaves (from cachedLeafSpan)
105+
/// @param firstLeaf Leaf index of the block's first slot
105106
template <int N, int SelfIndex, class BuildT, class LeafT, class OffsetT>
106107
__device__
107108
static void stageLeafTable(const NanoGrid<BuildT> *grid, const LeafT **table,
108-
int nSpanned, uint32_t firstSpanned, OffsetT shiftToNeighbor)
109+
int spannedLeafCount, uint32_t firstLeaf, OffsetT shiftToNeighbor)
109110
{
110111
const int tID = threadIdx.x;
111112
const auto& tree = grid->tree();
112113
const LeafT* leaf0 = tree.template getFirstNode<0>();
113-
for (int c = tID; c < nSpanned * N; c += blockDim.x) {
114-
const int slot = c / N, n = c % N;
115-
if (n == SelfIndex) { table[slot*N + n] = leaf0 + (firstSpanned + slot); continue; }
116-
Coord origin = leaf0[firstSpanned + slot].origin();
117-
shiftToNeighbor(origin, n);
118-
table[slot*N + n] = tree.root().probeLeaf(origin);
114+
for (int entry = tID; entry < spannedLeafCount * N; entry += blockDim.x) {
115+
const int leafSlot = entry / N, neighborID = entry % N;
116+
if (neighborID == SelfIndex) {// this spanned leaf itself; no probe needed
117+
table[leafSlot*N + neighborID] = leaf0 + (firstLeaf + leafSlot);
118+
continue;
119+
}
120+
Coord neighborOrigin = leaf0[firstLeaf + leafSlot].origin();
121+
shiftToNeighbor(neighborOrigin, neighborID);
122+
table[leafSlot*N + neighborID] = tree.root().probeLeaf(neighborOrigin);
119123
}
120124
__syncthreads();
121125
}
@@ -376,29 +380,31 @@ struct VoxelBlockManager : nanovdb::tools::VoxelBlockManagerBase<Log2BlockWidth>
376380
const auto& tree = grid->tree();
377381
const LeafT* leaf0 = tree.template getFirstNode<0>();
378382

379-
const uint32_t firstSpanned = smem_leafIndex[0];
383+
const uint32_t firstLeaf = smem_leafIndex[0];// leaf owning the block's first slot
380384
const uint32_t myLeaf = smem_leafIndex[tID];
381-
const int nSpanned = cachedLeafSpan<MaxCachedLeaves>(smem_leafIndex, firstSpanned, myLeaf);
385+
const int spannedLeafCount = cachedLeafSpan<MaxCachedLeaves>(smem_leafIndex, firstLeaf, myLeaf);
382386
// Entry order 0..5 is -x,+x,-y,+y,-z,+z (axis*2 + dir), which the lookup below assumes.
383-
stageLeafTable<7, 6>(grid, &sFaceLeaves[0][0], nSpanned, firstSpanned,
387+
stageLeafTable<7, 6>(grid, &sFaceLeaves[0][0], spannedLeafCount, firstLeaf,
384388
[](Coord &o, int n) { o[n >> 1] += (n & 1) ? 8 : -8; });
385389

386390
if (myLeaf != UnusedLeafIndex) {
387391
const auto& leaf = leaf0[myLeaf];
388392
const Coord coord = leaf.offsetToGlobalCoord( smem_voxelOffset[tID] );
389-
const uint32_t slot = myLeaf - firstSpanned;
390-
const bool cached = slot < MaxCachedLeaves;
393+
const uint32_t leafSlot = myLeaf - firstLeaf;
394+
const bool isCached = leafSlot < MaxCachedLeaves;
391395
stencilIndices[13] = leaf.getValue( smem_voxelOffset[tID] );
392396
for (int n = 0; n < 6; ++n) {
393397
const int axis = n >> 1, dir = (n & 1) ? 1 : -1;
394398
Coord neighbor = coord;
395399
neighbor[axis] += dir;
396400
// Standard 27-slot spoke id for this face tap
397401
const int spokeID = 13 + dir * (axis == 0 ? 9 : axis == 1 ? 3 : 1);
398-
if (cached) {
399-
const int v = coord[axis] & 7;
400-
const LeafT* nl = ((v + dir) & ~7) ? sFaceLeaves[slot][n] : sFaceLeaves[slot][6];
401-
stencilIndices[spokeID] = nl ? nl->getValue(LeafT::CoordToOffset(neighbor)) : 0;
402+
if (isCached) {
403+
const int voxelOnAxis = coord[axis] & 7;// 0..7 within the leaf
404+
// stepping off the leaf on this axis? then use the face neighbor, else self
405+
const LeafT* neighborLeaf = ((voxelOnAxis + dir) & ~7) ? sFaceLeaves[leafSlot][n]
406+
: sFaceLeaves[leafSlot][6];
407+
stencilIndices[spokeID] = neighborLeaf ? neighborLeaf->getValue(LeafT::CoordToOffset(neighbor)) : 0;
402408
} else {
403409
stencilIndices[spokeID] = tree.getValue( neighbor );
404410
}
@@ -439,30 +445,32 @@ struct VoxelBlockManager : nanovdb::tools::VoxelBlockManagerBase<Log2BlockWidth>
439445
const int tID = threadIdx.x;
440446
const auto& tree = grid->tree();
441447
const LeafT* leaf0 = tree.template getFirstNode<0>();
442-
const uint32_t firstSpanned = smem_leafIndex[0];
448+
const uint32_t firstLeaf = smem_leafIndex[0];// leaf owning the block's first slot
443449
const uint32_t myLeaf = smem_leafIndex[tID];
444450

445451
// Stage the spannedLeaves x 27 leaf-neighborhood table across ALL threads
446-
const int nSpanned = cachedLeafSpan<MaxCachedLeaves>(smem_leafIndex, firstSpanned, myLeaf);
452+
const int spannedLeafCount = cachedLeafSpan<MaxCachedLeaves>(smem_leafIndex, firstLeaf, myLeaf);
447453
// The full box neighborhood: entry n is the 3x3x3 spoke n.
448-
stageLeafTable<27, 13>(grid, &sNeighborLeaves[0][0], nSpanned, firstSpanned,
454+
stageLeafTable<27, 13>(grid, &sNeighborLeaves[0][0], spannedLeafCount, firstLeaf,
449455
[](Coord &o, int n) { o = o.offsetBy((n/9-1)*8, ((n/3)%3-1)*8, (n%3-1)*8); });
450456

451457
if (myLeaf == UnusedLeafIndex) return;
452458
const auto& leaf = leaf0[myLeaf];
453459
const Coord coord = leaf.offsetToGlobalCoord( smem_voxelOffset[tID] );
454-
const uint32_t slot = myLeaf - firstSpanned;
455-
const bool cached = slot < MaxCachedLeaves;
456-
const int vi = coord[0] & 7, vj = coord[1] & 7, vk = coord[2] & 7;
460+
const uint32_t leafSlot = myLeaf - firstLeaf;
461+
const bool isCached = leafSlot < MaxCachedLeaves;
462+
const int voxelX = coord[0] & 7, voxelY = coord[1] & 7, voxelZ = coord[2] & 7;
457463
for (int di = -1; di <= 1; di++)
458464
for (int dj = -1; dj <= 1; dj++)
459465
for (int dk = -1; dk <= 1; dk++) {
460466
const int spokeID = ( di + 1 ) * 9 + ( dj + 1 ) * 3 + dk + 1;
461467
const Coord neighbor = coord.offsetBy( di, dj, dk );
462-
if (cached) {
463-
const int li = ((vi+di)>>3)+1, lj = ((vj+dj)>>3)+1, lk = ((vk+dk)>>3)+1;
464-
const LeafT* nl = sNeighborLeaves[slot][li*9+lj*3+lk];
465-
op(spokeID, nl ? nl->getValue(LeafT::CoordToOffset(neighbor)) : uint64_t(0));
468+
if (isCached) {
469+
// which of the 3x3x3 neighboring leaves this tap falls into
470+
const int leafX = ((voxelX+di)>>3)+1, leafY = ((voxelY+dj)>>3)+1, leafZ = ((voxelZ+dk)>>3)+1;
471+
const LeafT* neighborLeaf = sNeighborLeaves[leafSlot][leafX*9 + leafY*3 + leafZ];
472+
op(spokeID, neighborLeaf ? neighborLeaf->getValue(LeafT::CoordToOffset(neighbor))
473+
: uint64_t(0));
466474
} else {
467475
op(spokeID, tree.getValue( neighbor ));
468476
}

0 commit comments

Comments
 (0)