Skip to content

NanoVDB: VoxelBlockManagerHandle accessors don't compile for buffer types whose data()/deviceData() return typed pointers #2274

Description

@swahtz

Problem

nanovdb::tools::VoxelBlockManagerHandle<BufferT>'s eight pointer accessors static_cast directly from the buffer's data() / deviceData():

// nanovdb/tools/VoxelBlockManager.h:152 (and 159, 166, 173, 185, 188, 191, 194)
deviceFirstLeafID() { return static_cast<uint32_t*>(mFirstLeafID.deviceData()); }

This compiles when deviceData() returns void* (as NanoVDB's own HostBuffer / DeviceBuffer / UnifiedBuffer do), but a static_cast from any typed pointer to uint32_t* is ill-formed. A custom BufferT whose data() / deviceData() return e.g. uint8_t* fails to compile as soon as one of these accessors is instantiated:

nanovdb/tools/VoxelBlockManager.h(152): error: invalid type conversion
      deviceFirstLeafID() { return static_cast<uint32_t*>(mFirstLeafID.deviceData()); }
          detected during instantiation of ... VoxelBlockManagerHandle<BufferT>::deviceFirstLeafID()
          [with BufferT=fvdb::TorchDeviceBuffer, U=fvdb::TorchDeviceBuffer]

Nothing in the BufferTraits contract requires void* returns — and the rest of the generic surface (GridHandle, cuda::mergeGridHandles, buildVoxelBlockManager's BufferT::create path, etc.) works fine with typed-pointer buffers because a typed pointer converts implicitly to void*. VoxelBlockManagerHandle is the outlier: it's the only place that needs the conversion in the other direction and spells it as a single static_cast.

Where this bites

fvdb-core's TorchDeviceBuffer (its BufferT backed by PyTorch's caching allocator, uint8_t* data()/deviceData()) is used as the buffer type for grid handles throughout fvdb. Building a VoxelBlockManagerHandle<TorchDeviceBuffer> — the natural way to keep the VBM's firstLeafID / jumpMap arrays in the same memory pool as everything else, per the #2232 direction — fails to compile. fvdb currently works around it by allocating the arrays itself and launching BuildVoxelBlockManagerFunctor directly, bypassing the handle (openvdb/fvdb-core#733).

Proposed fix

Route the casts through void*, which is valid for both void* and typed-pointer buffers and is a no-op for the existing types:

deviceFirstLeafID() { return static_cast<uint32_t*>(static_cast<void*>(mFirstLeafID.deviceData())); }

(equivalently on the const overloads via const void*), applied to all eight accessors: hostFirstLeafID ×2, hostJumpMap ×2, deviceFirstLeafID ×2, deviceJumpMap ×2.

A TestNanoVDB-side guard could instantiate the handle over a minimal buffer whose data()/deviceData() return uint8_t* to keep this from regressing.

Happy to put up the one-file PR. Related context: the injectable-memory-resource roadmap #2232, where downstream buffer/resource types are expected to plug into these generic seams.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions