Skip to content

NanoVDB: type the CUDA scratch buffers as cuda::Buffer<T> (CUDA) - #2322

Open
harrism wants to merge 2 commits into
AcademySoftwareFoundation:masterfrom
harrism:nanovdb-typed-mask-buffers
Open

NanoVDB: type the CUDA scratch buffers as cuda::Buffer<T> (CUDA)#2322
harrism wants to merge 2 commits into
AcademySoftwareFoundation:masterfrom
harrism:nanovdb-typed-mask-buffers

Conversation

@harrism

@harrism harrism commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Closes #2312. Also lands the sweep portion of #2327 (everything but VoxelBlockManagerHandle, which stays open there pending coordination with #2291).

What

Mask became trivially copyable in #2310, which removed the last reason for the CUDA tools to hold typed arrays in byte buffers reinterpreted at every use. Two commits:

1. The Mask sidecars (#2312)TopologyBuilder's upper/lower masks become cuda::Buffer<Mask<5>> / cuda::Buffer<Mask<4>>; deviceUpperMasks() returns Mask<5>* and deviceLowerMasks() returns the row-shaped Mask<4> (*)[Mask<5>::SIZE], so the stride is fixed once beside the allocation and the seven morphology functors and every caller take typed pointers (eight casts gone). MeshToGrid's two retain-mask buffers and hit-mask buffer, the dilation example, and the dilation test (off the deprecated dual DeviceBuffer) become cuda::Buffer<Mask<3>>.

2. Every remaining single-type scratch buffer — TopologyBuilder's upper/lower/leaf/voxel offsets, lower/leaf parents, the three enumerate-pass count arrays and its device Data staging; MeshToGrid's transformed triangles, box-triangle pairs, unique root origins and nine local key/count/offset/pair buffers (its byte ScratchT alias is gone); SignedFloodFill's root-child array. The lower/leaf offsets expose their per-upper-node row shape via lowerOffsetRows()/leafOffsetRows(), same pattern as the masks. TopologyBuilder's variable-length root staging stays a byte buffer (its size is RootT::memUsage(tileCount), not an element count) and is now the only thing its alignment static_assert guards — strengthened to NANOVDB_DATA_ALIGNMENT, which is what the root reinterpret actually needs. MeshToGrid gains an equivalent assert for its 16-byte-aligned pair struct, which previously had none.

Allocations are sized in elements and memsets use size_bytes(), so the byte arithmetic disappears and Buffer's count×sizeof overflow check applies where hand-multiplied sizes had none.

Verification

Full build clean under NANOVDB_CUDA_WERROR; 156 CPU / 65 CUDA / 48 buffer / 19 memory-resource tests pass. Explore self-review and Codex review passes on both commits; every element type was checked against Buffer's is_trivially_copyable requirement (including RootChild, whose converting constructor leaves its copy operations trivial).

Mask became trivially copyable in AcademySoftwareFoundation#2310, so the scratch that exists only
to hold arrays of masks no longer needs to be a byte buffer reinterpreted
at every use. TopologyBuilder's upper and lower mask members become
Buffer<Mask<5>> and Buffer<Mask<4>>, and deviceUpperMasks/deviceLowerMasks
return typed pointers, which the seven morphology functors and MeshToGrid
now take directly - the only cast left is the array-shape view of the
flat lower masks as one Mask<5>::SIZE row per upper node. MeshToGrid's
two retain-mask buffers and its per-pass hit-mask buffer, the dilation
example's leaf masks, and the dilation test's mask buffer (previously on
the deprecated dual DeviceBuffer) are Buffer<Mask<3>>. Allocation sizes
are element counts and memsets use size_bytes().

Closes AcademySoftwareFoundation#2312.

Signed-off-by: Mark Harris <mharris@nvidia.com>
…oGrid and SignedFloodFill (CUDA)

The same pattern as the mask buffers, applied to every other scratch
allocation that holds a single element type for its whole life:
TopologyBuilder's upper/lower/leaf/voxel offsets, lower/leaf parents,
the three count arrays of its enumerate pass and its device Data
staging; MeshToGrid's transformed triangles, box-triangle pairs, unique
root origins, and its nine local key/count/offset/pair buffers;
SignedFloodFill's root-child array. Allocations are sized in elements,
the reinterpret_casts at every use are gone, and the accessors return
typed pointers. The lower and leaf offsets, which the node-processing
kernels read as one row of Mask<5>::SIZE per upper node, expose that
row shape from accessors beside the allocation, as deviceLowerMasks
does. TopologyBuilder's root staging stays a byte buffer (its size is
RootT::memUsage(tileCount), not an element count), which is now the
only reinterpretation its alignment static_assert guards.

Addresses the sweep portion of AcademySoftwareFoundation#2327.

Signed-off-by: Mark Harris <mharris@nvidia.com>
@harrism harrism changed the title NanoVDB: type the Mask scratch buffers as cuda::Buffer<Mask<N>> (CUDA) NanoVDB: type the CUDA scratch buffers as cuda::Buffer<T> (CUDA) Sep 10, 2026

@swahtz swahtz left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

NanoVDB: type the Mask scratch buffers as Buffer<Mask<N>> once Mask is trivially copyable

2 participants