Skip to content

NanoVDB: make every public CUDA header includable first (CUDA) - #2377

Merged
swahtz merged 2 commits into
AcademySoftwareFoundation:masterfrom
harrism:nanovdb-handlestorage-include-order
Oct 21, 2026
Merged

swahtz merged 2 commits into
AcademySoftwareFoundation:masterfrom
harrism:nanovdb-handlestorage-include-order

Conversation

@harrism

@harrism harrism commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Under nvcc, #include <nanovdb/cuda/HandleStorage.h> fails to compile when it comes before any header that includes nanovdb/GridHandle.h. That's the header users include for cuda::copyTo, and the deprecation messages and docs in progress point to it. tools/cuda/TopologyBuilder.cuh and tools/cuda/VoxelBlockManager.cuh fail the same way. These three regressed with #2370; v13.1.0 and the commit before #2370 compile them fine.

The cause is an include cycle:

  • Under nvcc, GridHandle.h includes cuda/GridHandle.cuh at its end.
  • cuda/GridHandle.cuh depends on cuda/HandleStorage.h and tools/cuda/GridChecksum.cuh.
  • Both of those include GridHandle.h before their own definitions.

So including either of them first compiles cuda/GridHandle.cuh against their half-parsed contents. #2370's single-space merge/split code names HandleStorage.h helpers outside any template-dependent context, which exposed the cycle for HandleStorage.h. GridChecksum.cuh and GridValidator.cuh were already broken the same way in v13.1.0.

The fix:

  • Deferral: while either header is being parsed it defines a marker. GridHandle.h skips its trailing include while a marker is set, and the outermost of the two headers includes cuda/GridHandle.cuh at its own end, once its definitions exist. A translation unit that got cuda/GridHandle.cuh before still gets it, and HandleStorage.h still compiles in a host-only translation unit.
  • Missing includes: tools/cuda/GridStats.cuh (cuda/NodeManager.cuh, also broken in v13.1.0) and util/cuda/MorphologyHelpers.cuh (NanoVDB.h, <stdint.h>) gain the includes they use, and a few standard headers are now included directly.
  • Compile check: a compile-only target, nanovdb_cuda_header_check, compiles each installed C++ header (host and CUDA, 63 in all) as the first include of its own CUDA translation unit. The deprecated forwarding headers are skipped because they warn by design, the C headers are skipped, and tools/NanoToOpenVDB.h is checked only with OpenVDB. It's built whenever the CUDA unit tests are configured, before the GTest check.

Validation on one RTX PRO 6000 Blackwell GPU with nvcc 12.6:

  • The 63 checked headers compile as first includes, and all 20 ordered pairs of the five headers in the cycle compile. With master's GridHandle.h and HandleStorage.h put back, the check fails on exactly the five headers listed above.
  • All single-GPU ctest targets and the 38 Python tests pass. Unit tests, tools, examples and the Python module build with -Werror.
  • Not verified locally: each header compiling as a first include under MSVC; this PR's Windows CI run will show it.

🤖 Generated with Claude Code

Under nvcc, nanovdb/GridHandle.h includes cuda/GridHandle.cuh at its
end, and that header depends on cuda/HandleStorage.h and
tools/cuda/GridChecksum.cuh, which both include GridHandle.h before
their own definitions. Including either of them first therefore
compiled cuda/GridHandle.cuh against their half-parsed contents. Since
the single-space merge/split landed in cuda/GridHandle.cuh this broke
HandleStorage.h, TopologyBuilder.cuh and VoxelBlockManager.cuh as a
first include; GridChecksum.cuh and GridValidator.cuh were already
broken the same way.

While either header is being parsed it now defers cuda/GridHandle.cuh
to its own end, and GridHandle.h skips it. Also give GridStats.cuh and
util/cuda/MorphologyHelpers.cuh the includes they use, and add a
compile-only target that builds each public CUDA header (except the
deprecated forwarding headers) as the first include of its own
translation unit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Mark Harris <mharris@nvidia.com>

@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.

Thanks for finding this and fixing it. I think there's just two small changes for consistency, but otherwise looks pretty good to me.

Comment thread nanovdb/nanovdb/tools/cuda/GridChecksum.cuh Outdated
Comment thread nanovdb/nanovdb/unittest/CMakeLists.txt Outdated
The header check now also compiles every installed C++ host header
(GridHandle.h, io/IO.h, tools/CreateNanoGrid.h, ...) as the first
include of a CUDA translation unit, since those are the headers whose
behaviour under nvcc changes with the deferred cuda/GridHandle.cuh
include. The C headers are skipped, and tools/NanoToOpenVDB.h is checked
only with OpenVDB. Also gate GridChecksum.cuh's deferred include on
__CUDACC__, like the other two.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Mark Harris <mharris@nvidia.com>

@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, thanks for fixing this.

@swahtz
swahtz merged commit 8cf8d1f into AcademySoftwareFoundation:master Oct 21, 2026
16 checks passed
sifakis added a commit to sifakis/openvdb that referenced this pull request Oct 22, 2026
DeviceGridTraits.cuh used cudaCheck without including util/cuda/Util.h, where
it is defined. This went unnoticed because every cudaCheck argument depended on
the template parameter, so the name was only looked up at instantiation. The
cudaStreamSynchronize(stream) calls added with the stream parameter are not
dependent, so the header no longer compiled on its own, which the header
self-containment check from AcademySoftwareFoundation#2377 enforces.

Signed-off-by: Efty Sifakis <esifakis@nvidia.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants