ray_implicit_intersection improvements#663
Merged
Merged
Conversation
Rewrite the per-ray SDF zero-crossing kernel for performance, precision,
and correctness, surface a shared cache-hint helper that other ops can
reuse, lift compile-time specialisations into `SampleRaysUniform.cu`,
and broaden the test surface with 7 new behavioural tests adapted from
the OpenVDB level-set / volume ray-intersector unit tests.
Indirectly benefits from `HDDAIterators.h` cleanups landed alongside
this change (branchless TimeSpan bookkeeping in `HDDASegmentIterator`,
bounded-loop level convergence in `HDDAVoxelIterator`), which the
ray-implicit, sample-rays-uniform, voxels-along-rays, and
segments-along-rays kernels all reach through the public iterator API.
## Source changes
`src/fvdb/detail/utils/cuda/Caching.cuh` (new):
- `_storeStreaming` / `_storeStreamingPair`: write-once stores via
`__stwt` (`.CS` qualifier in SASS) so write-once output tensors
don't get promoted into L1 and evict the voxel-data working set.
- `_loadReadOnly`: read-mostly load via `__ldg` (`.NC` qualifier) so
side-buffer SDF data shares cache capacity instead of competing
with the active-mask leaf data. Both fall back to plain
assignment/dereference on host and for types without a matching
intrinsic overload (e.g. `c10::Half`); NVCC fully inlines both
branches, so the CPU path is unaffected. Lives in
`fvdb::detail::ops` so any op `.cu` file can reach it via
unqualified name lookup from inside an anonymous namespace.
`src/fvdb/detail/ops/RayImplicitIntersection.cu`:
- Add a `bool EpsZero` template parameter on `rayImplicitCallback`.
The launcher branches once on `eps == 0.0f` (the overwhelmingly
common case) and dispatches the corresponding specialisation on
both CPU and CUDA paths, so NVCC drops the per-voxel
`if (deltaT < eps) continue;` branch and one register entirely
when `eps == 0`.
- Do all interpolation / time arithmetic in
`MathType = at::opmath_type<ScalarT>` so `c10::Half` rays compute
interpolation in fp32 and only cast back to `ScalarT` at the
streaming-store boundary.
- Route the per-voxel `gridScalars` load through `_loadReadOnly`
and every `outTimes` write (early-out, hit, miss) through
`_storeStreaming`.
- Detect sign flips with a single predicated check
(`scalarSign != voxelSign`) instead of nested `if`s.
- Track band continuity via `lastT1`. When the next valid voxel is
contiguous along the ray (`t0 == lastT1`), emit a sub-voxel
linear-interpolated hit time between the bracketing samples; when
there's a gap (inactive voxels in the iterator, or a run of NaN
tile values), fall back to the bracket-entry time, matching
`nanovdb::ZeroCrossing` precision in that case. This prevents the
kernel from interpolating across empty space between disjoint SDF
regions.
- Seed the sign reference from the FIRST valid (non-NaN) voxel along
the ray (matching `nanovdb::ZeroCrossing` semantics) instead of a
fixed sentinel. This handles both rays that start outside the
surface (first sample positive, hit on crossing into the negative
band) AND rays that start inside the surface (first sample
negative, hit on crossing back out) without baking a fixed
"positive = outside" SDF convention into the kernel.
- Add `c10::kHalf` to the `AT_DISPATCH_V2` types so half-precision
rays are actually dispatched on CUDA (previously raised
`NotImplementedError: "RayImplicitIntersection" not implemented
for 'Half'` at runtime once the unconditional fp16 test skip was
removed).
`src/fvdb/detail/ops/SampleRaysUniform.cu`:
- Adopt the shared `Caching.cuh` helpers (drops the local
`_storeStreaming` / `_storeStreamingPair` definitions).
- Factor `_emitSample` out of the per-launcher lambdas as a function
template. NVCC forbids extended `__device__` lambdas inside generic
lambdas (which the launchers use), so a free-function template is
the only place the streaming-store helpers can live without
redundant inline-at-call-site repetition. The template takes the
`(a, b)` pair as separately-deduced types `A, B` so callers don't
have to cast `at::opmath_type<Half> = float` HDDA times back to
`c10::Half` at every call site.
- Compile-time specialise `countSamplesPerRayCallback` and
`generateRaySamplesCallback` on three runtime predicates
(`ConeZero`, `IncludeEndpoints`, `ReturnMidpoint`). NVCC then
prunes the dead branches and, critically, hoists
`stepSize = minStepSize` out of the inner while-loops in the
`ConeZero` case, removing a `Clamp+mul` from the hot per-sample
body and dropping several live registers from this latency-bound
traversal.
`src/fvdb/detail/utils/nanovdb/HDDAIterators.h`:
- `HDDASegmentIterator::nextSegment`: replace the entering / leaving
`if`/`else` ladder around `mTimespan.t0` / `mTimespan.t1` with
predicated select expressions. Only the "active region just ended"
`break` remains a real control-flow branch; rays in the same warp
whose `active` state differs no longer diverge at the setter
level.
- `HDDAVoxelIterator::nextVoxel`: replace the three unrolled
`getDim` / level-update passes with a bounded `for (pass < 3)`
loop. Same worst-case behaviour (the level hierarchy stabilises
in <= 3 passes) but the body collapses to a single descent for
level-aligned iterations, which dominate the trace.
## Python docstrings
`fvdb/grid.py`, `fvdb/grid_batch.py`, `fvdb/functional/_ray.py`:
- Document the new convention-agnostic semantics of
`ray_implicit_intersection*`: the first valid (non-NaN) voxel along
each ray seeds the sign reference, and the first subsequent voxel
with the opposite sign is reported as the intersection. Both
"positive outside" and "negative outside" SDF conventions are
handled identically; rays that enter the bbox already inside the
surface are reported at the *exit* crossing along the ray.
## Tests
`tests/unit/test_basic_ops.py`:
- Drop the unconditional `if dtype == torch.float16: return` early
return in `test_ray_implicit_intersection` so the half-precision
dispatch is now actually exercised by the existing test.
- Two regressions for the algorithmic fixes in this commit:
* `..._starts_inside_surface`: ray whose origin sits inside the
SDF sphere must report the EXIT crossing — not -1, not the
bracket-entry of the very first active voxel. Pins the
`nanovdb::ZeroCrossing`-style "first valid voxel seeds the
reference" semantics.
* `..._two_disjoint_regions`: ray that crosses two separated SDF
spheres must report the FIRST surface, not a time inside the
empty gap between them. Pins the band-continuity gating.
- 7 new `@parameterized.expand(all_device_dtype_combos)` tests
adapted from `openvdb-jswartz/openvdb/openvdb/unittest/`
(`TestLevelSetRayIntersector.cc` + `TestNanoVDB.cc` for sign-of-
zero), giving 34 additional test instances:
| Test | Adapts from | Purpose |
|---|---|---|
| `..._sign_of_zero` | `TestLevelSetRayIntersector.cc:71-215` + `TestNanoVDB.cc:1520-1552` | `dir(1, +0, +0)` and `dir(1, -0, -0)` produce identical hit times across all 6 axis-aligned directions (`torch.equal` exact match). |
| `..._axis_aligned_analytic` | `TestLevelSetRayIntersector.cc:43-247` | Hit time for axis-aligned rays through sphere centre matches the analytic ray-sphere root within a voxel diagonal; covers `±x/±y/±z` (subsumes the OpenVDB negative-direction case). |
| `..._diagonal_analytic` | `TestLevelSetRayIntersector.cc:249-278` | Diagonal ray exercising 3-axis HDDA stepping; hit time within voxel diagonal of analytic root. |
| `..._explicit_misses` | `TestLevelSetRayIntersector.cc:311-389` (`testMissedIntersections`) | Four miss configurations all return `-1`: ray bypassing bbox, ray clipping bbox corner away from sphere, ray pointed away from bbox, ray grazing inside bbox outside sphere. |
| `..._non_trivial_transform` | `TestLevelSetRayIntersector.cc:99-216` | Non-unit `voxel_size=0.25` and non-zero `origins=(10, 20, 30)` — exercises `transform.applyToRay` (`RayImplicitIntersection.cu:82`), previously untested. |
| `..._high_resolution_sweep` | `TestLevelSetRayIntersector.cc:280-308` | 64×64 = 4096 ray sweep; geometric check `(hit_pt - center).norm() ≈ sphere_rad` per ray. fp16 explicitly skipped (precision insufficient for voxel-diagonal tolerance). |
| `..._single_voxel_bracket_entry` | (no direct OpenVDB analogue — pins `RayImplicitIntersection.cu:121-136`) | Symmetric `+1/-1` step SDF; verifies the linear-interp branch lands the zero exactly at the midpoint between two bracketing primal-voxel samples. |
- Convention pinned by the bracket-entry test: under fvdb's
`voxel_to_world`, primal voxel `i` is at world
`i*voxel_size + origin` (treated as a node, not a cell with a
`+0.5` offset). Combined with the dual transform's `+0.5` shift,
the kernel's linear interpolation between SDF samples at primal
voxels 3 (+1) and 4 (-1) produces a zero crossing at world
`x = 3.5`, not `x = 4.0` as you'd get under a cell-centred
convention. The test comment documents this for future readers.
## Test plan
- Build: `./build.sh install` (cp312, fvdb conda env).
- Targeted: `cd tests && pytest unit/test_basic_ops.py -v -k ray_implicit`
-> 49 passed, 1 skipped (deliberate fp16 skip in
`..._high_resolution_sweep`).
- Adjacent regressions (no behavioural changes expected, sanity
only):
* `pytest unit/test_basic_ops.py` -> 265 passed, 1 skipped.
* `pytest unit/test_basic_ops_single.py` -> 154 passed.
* `pytest unit/test_ray_marching.py unit/test_sample.py`
-> 455 passed, 4 skipped.
- C++: `RayImplicitIntersection` has no `gtest` coverage today, so
`./build.sh ctest` would not exercise this change.
Signed-off-by: Jonathan Swartz <jonathan@jswartz.info>
Signed-off-by: Jonathan Swartz <jonathan@jswartz.info>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR optimizes ray traversal kernels and updates ray_implicit_intersection semantics to be sign-convention agnostic, including CUDA half dispatch and broader behavioral coverage.
Changes:
- Adds shared CUDA cache-hint helpers for read-only loads and streaming stores.
- Reworks
ray_implicit_intersection,uniform_ray_samples, and HDDA iterators with compile-time specialization and traversal optimizations. - Updates Python docs and adds/expands tests for ray implicit intersection edge cases.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
src/fvdb/detail/utils/cuda/Caching.cuh |
Adds reusable cache-hint load/store helpers. |
src/fvdb/detail/ops/RayImplicitIntersection.cu |
Rewrites zero-crossing traversal semantics and dispatch specialization. |
src/fvdb/detail/ops/SampleRaysUniform.cu |
Specializes sampling callbacks and reuses streaming-store helpers. |
src/fvdb/detail/utils/nanovdb/HDDAIterators.h |
Refactors HDDA segment/voxel iteration control flow. |
fvdb/grid.py |
Documents updated single-grid ray intersection semantics. |
fvdb/grid_batch.py |
Documents updated batch ray intersection semantics. |
fvdb/functional/_ray.py |
Documents functional ray intersection semantics. |
tests/unit/test_basic_ops.py |
Enables half coverage and adds ray intersection behavioral tests. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Rename the misnamed HDDAVoxelIterator (it yields active values at any node level, not just voxels) to HDDAActiveValueIterator, and add a leaf-only HDDALeafVoxelIterator alias. Both are aliases over a shared HDDAValueIteratorImpl<AccT, ScalarT, bool LeafOnly>; the LeafOnly gate reuses the dim already computed by the realign loop, so the active-value path costs nothing extra. ray_implicit_intersection now iterates with HDDALeafVoxelIterator. It indexes gridScalars by getValue(ijk)-1, valid only for leaf voxels; the old iterator also yielded active coarse tiles, which the kernel ran through its full per-voxel body. Skipping them in a single coarse HDDA step is the dominant speedup (ray_implicit_intersection 1.3-1.5x -> 1.7-1.95x vs main, ~-50% kernel instructions) and removes a latent mis-index on externally-loaded tile-bearing grids. Output is bit-identical to the previous active-value traversal on all tested SDF datasets. Matches nanovdb::ZeroCrossing's narrow-band structure. VoxelsAlongRays.cu moves to the renamed HDDAActiveValueIterator with no behaviour change. The gridScalars validation message now names the iterator contract. Tests: - New C++ gtest HDDAIteratorsTest.cpp: builds a NanoGrid<float> with an active 128^3 tile and drives both aliases on the host, asserting the active-value iterator surfaces the tile (getDim > 1) while the leaf iterator skips it. Only way to exercise the active-tile path, since fvdb's Python grid builders produce leaf-only grids. - New test_ray_implicit_intersection_wrong_scalar_count_errors checks the sharpened validation message. Signed-off-by: Jonathan Swartz <jonathan@jswartz.info> Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Jonathan Swartz <jonathan@jswartz.info>
Signed-off-by: Jonathan Swartz <jonathan@jswartz.info>
1b98ba6 to
82bdc8f
Compare
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Signed-off-by: Jonathan Swartz <jonathan@jswartz.info>
areidmeyer
reviewed
Jun 5, 2026
areidmeyer
approved these changes
Jun 5, 2026
areidmeyer
left a comment
Contributor
There was a problem hiding this comment.
Approved, but one experiment I think worth trying.
The bounded `for (pass < 3 && mHdda.dim() != dim)` realign loop in nextVoxel does not auto-unroll: its body is two getDim tree-walks plus an HDDA update, which ptxas keeps rolled, emitting a data-dependent backedge. That backedge adds warp divergence whenever lanes in a warp need different numbers of realign passes (i.e. at level transitions). Forcing `#pragma unroll` turns the <=3 passes into predicated straight-line code with no backedge. Verified in SASS (sm_120): the data-dependent backedge present in the rolled form is gone in the unrolled form, leaving only the unrelated 3-axis loops inside HDDA::init/update. Output is bit-identical to the rolled loop (checksum match vs main ~1e-8 across dragon/emu/crawler) and timing is neutral (-0.7% to +1.9% vs the rolled loop, within noise); the ray_implicit_intersection speedup vs main (1.7-1.95x) is unchanged. Collapsing the loop to a single pass instead was rejected: the multi-pass descent is not redundant and a single pass changes results on rays crossing several node levels at once (~0.12% on crawler). The pragma is guarded by `#if defined(__CUDA_ARCH__)` because this header is also included by host translation units, where the host compiler rejects unknown pragmas under -Werror=unknown-pragmas. Signed-off-by: Jonathan Swartz <jonathan@jswartz.info> Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Optimise the per-ray SDF zero-crossing kernel (
ray_implicit_intersection) and the shared HDDA traversal layer it sits on, fixing a few correctness issues along the way and carrying two adjacent ray-marching ops (uniform_ray_samples,voxels_along_rays) along for the ride.The structural heart of the PR is a reorganization of the HDDA iterators: the formerly named
HDDAVoxelIteratorbecomesHDDAActiveValueIterator, and a new leaf-onlyHDDALeafVoxelIteratorletsray_implicit_intersectionskip active coarse tiles entirely (à lananovdb::ZeroCrossing). Both are aliases overHDDAValueIteratorImpl, so they share a lot of functionality in one class. The rest of this PR is supporting infrastructure (a shared__ldg/__stwtcache-hint helper), compile-time specialisations, warp-divergence cleanups, and broadened tests.This started after being inspired by Efty's 'branchless getValue' work in NanoVDB and wanting to apply the same principles to the ray-marching kernels; as I pulled the thread, more fruit fell out of the tree (to branch metaphors).
End-to-end on my RTX PRO 6000 Blackwell, 1 M rays per workload: 1.67×–1.95× speedup for
ray_implicit_intersection(−48 to −51% kernel instructions, −2 registers/thread) and 1.05×–1.10× speedup foruniform_ray_samples(−6 registers/thread on the count pass).c10::Halfinputs are now dispatched forray_implicit_intersection(previouslyNotImplementedError). All fp32 outputs are bit-identical tomain.1. HDDA iterator reorganization (
HDDAIterators.h) — the foundational changeThe slight misnomer.
HDDAVoxelIteratordid not yield voxels — it yielded active values at any node level: active coarse tiles (getDim > 1) as well as active leaf voxels (getDim == 1). Callers were expected to branch ongetDim()to tell them apart. Anything indexing a strictly per-leaf-voxel buffer (likeray_implicit_intersection, which readsgridScalars[getValue(ijk) - 1]) was therefore walking tiles it never needs to see.The fix — one impl, two named aliases:
HDDAVoxelIterator→HDDAActiveValueIterator(honest name: walks every active value node, tiles included).HDDALeafVoxelIterator: yields only active leaf voxels; active tiles are skipped in a single coarse HDDA step.HDDAValueIteratorImpl<AccT, ScalarT, bool LeafOnly>.LeafOnlyis a compile-time gate (likeEpsZero/ConeZerobelow) that reuses thedimalready computed by the realign loop, so the active-value path costs nothing extra and the leaf path gets free tile-skipping.Why it matters: the leaf alias is exactly the narrow-band structure
nanovdb::ZeroCrossingwalks, and adopting it inray_implicit_intersectionis the single biggest performance lever in this PR (see §3). It also removes a latent mis-index on tile-bearing grids.Control-flow / warp-divergence cleanups in the same header (benefit every consumer):
HDDASegmentIterator::nextSegment: predicatedTimeSpansetters instead of anif/elseladder; only the "active region ended"breakstays a real branch, so rays in a warp with differingactivestate no longer diverge at the setter level.nextVoxel: a boundedfor (pass < 3)level-realign loop instead of three unrolledgetDim/level-update passes; collapses to a single descent in the common level-aligned case.Blast radius. The iterators are public API reached by
ray_implicit_intersection,uniform_ray_samples,voxels_along_rays, andsegments_along_rays.VoxelsAlongRays.cumoves to the renamedHDDAActiveValueIteratorwith no behaviour change (it intentionally walks all active values).2. Shared CUDA cache-hint helpers (
Caching.cuh, new) — the other shared building blockA small header surfacing reusable, host-safe cache hints, consumed by both ops in §3 and §4:
_loadReadOnly—__ldg(.NC) for read-only SDF data, keeping it off the active-mask working set._storeStreaming/_storeStreamingPair—__stwt(.CS) for write-once outputs so they aren't promoted into L1 (where they'd evict active-mask leaf data).Both fall back to a plain load/store on host and for types without the intrinsic (e.g.
c10::Half).3.
ray_implicit_intersection(RayImplicitIntersection.cu) — the headline opWith the building blocks in place, the op rewrite splits cleanly into correctness and performance.
Correctness / semantics
nanovdb::ZeroCrossing.lastT1. Sub-voxel-interpolate the hit only when the previous voxel is contiguous along the ray (t0 == lastT1); otherwise fall back to bracket-entry time. This stops the kernel from interpolating a "hit" across empty space — a gap between two disjoint SDF regions, or a run of NaN tile values.c10::kHalftoAT_DISPATCH_V2so half-precision rays are actually dispatched (previouslyNotImplementedErroronce the fp16 test skip was removed).gridScalars.rsize(0) == totalVoxels(), naming the iterator contract (leaf iterator needs one scalar per voxel; per-active-value data wantsHDDAActiveValueIterator).Performance
HDDALeafVoxelIteratorfrom §1) — the dominant speedup. The old active-value traversal ran each coarse tile through the full per-voxel body even though a tile can never be the leaf-level zero crossing; the leaf iterator skips them in one coarse HDDA step.bool EpsZerospecialisation. The launcher dispatches oneps == 0.0f(the common case), dropping the per-voxeldeltaT < epsbranch and a register.gridScalarsvia_loadReadOnly,outTimesvia_storeStreaming.at::opmath_type<ScalarT>, cast back only at the store.scalarSign != voxelSign).4.
uniform_ray_samples(SampleRaysUniform.cu) — adjacent op tighteningSame playbook applied to the neighbouring sampler:
Caching.cuhhelpers (drop the local copies)._emitSampleinto a free function template — extended__device__lambdas can't nest in the launchers' generic lambdas; separately-deduced pair types avoid per-call casts ofat::opmath_type<Half>back toc10::Half.countSamplesPerRayCallback/generateRaySamplesCallbackonConeZero/IncludeEndpoints/ReturnMidpoint. TheConeZerocase hoistsstepSize = minStepSizeout of the inner loop, dropping aClamp+muland registers (count pass goes from 80 → 74 registers).5. Docs & tests
Docstrings (
fvdb/grid.py,fvdb/grid_batch.py,fvdb/functional/_ray.py): document the convention-agnostic semantics — first valid voxel seeds the sign reference, first opposite-sign voxel is the hit; both conventions work, inside-surface rays report the exit crossing.Python (
tests/unit/test_basic_ops.py):..._starts_inside_surface(inside-origin ray reports the exit crossing) and..._two_disjoint_regions(reports the first surface, not the empty gap).all_device_dtype_combostests (34 instances) adapted from OpenVDB'sTestLevelSetRayIntersector.cc/TestNanoVDB.cc: sign-of-zero equivalence, axis-aligned & diagonal analytic roots, four miss configs, non-trivial transform, a 64×64 sweep, and single-voxel bracket-entry interpolation...._wrong_scalar_count_errors: a mismatchedgridScalarscount raises an error naming the iterator contract.C++ (
src/tests/HDDAIteratorsTest.cpp, new gtest): builds aNanoGrid<float>and drives both aliases on the host. A pure-leaf region yields identical voxels; on a ray crossing an active 128³ tile,HDDAActiveValueIteratorsurfaces it (getDim > 1) whileHDDALeafVoxelIteratorskips it. (Only way to exercise the active-tile path — fvdb's Python builders produce leaf-only grids.)6. Performance
Measured on RTX PRO 6000 Blackwell. Timing uses
torch.cuda.Eventover a 1024² = 1,048,576-ray camera-pinhole bundle aimed at each grid's active bbox; median of 20 iterations after trimming the top and bottom two outliers. ncu metrics use--profile-from-start offwith acudaProfilerStart/Stopwindow around a single 512² = 262,144-ray launch, fp32, on the optimization-engaged setting (eps = 0/cone_angle = 0).Wall-clock timing (median ms per call, 1 M rays)
ray_implicit_intersectionray_implicit_intersectionray_implicit_intersectionray_implicit_intersectionray_implicit_intersectionray_implicit_intersectionray_implicit_intersectionray_implicit_intersectionray_implicit_intersectionray_implicit_intersectionray_implicit_intersectionray_implicit_intersectionuniform_ray_samplesuniform_ray_samplesuniform_ray_samplesuniform_ray_samplesuniform_ray_samplesuniform_ray_samplesuniform_ray_samplesuniform_ray_samplesAll fp32 outputs are bit-equivalent main vs this PR branch (output checksum match within
atol=1e-3 * max(|main|, |wip|)), including theray_implicit_intersectionrows where the leaf iterator now skips tiles.ncu microarchitecture (single launch, fp32, 262k rays)
Columns are main → wip. Lower-is-better for registers, instructions, cycles, and DRAM bytes; higher-is-better for occupancy, SIMD efficiency (
smsp__thread_inst_executed_per_inst_executed.ratio, out of 32), and L1 hit rate.ray_implicit_intersectionray_implicit_intersectionray_implicit_intersectionuniform_ray_samplesuniform_ray_samplesuniform_ray_samplesuniform_ray_samplesReading the numbers:
ray_implicit_intersectionis overwhelmingly the leaf-iterator switch (§1). Skipped tile steps no longer run the full per-voxel body; output is bit-identical, confirming that work never affected the result.EpsZero, the__ldg/__stwthints, and the predicatedHDDAIteratorssetters contribute the remainder.uniform_ray_samplescount pass (theConeZerostep-size hoist).ray_implicit_intersectionfalls (10.62 → 8.46 on dragon) — expected and benign: the skipped tile steps were perfectly convergent, so removing them lowers the per-instruction average while removing far more total instructions.uniform_ray_samplesSIMD efficiency improves from theHDDAIteratorspredication.ray_implicit_intersection(94.5 → 87.8 on dragon): the streaming-store path bypasses L1 deliberately and tile-skipping removes trivially cache-friendly reads, so narrow-band accesses dominate the average. Net wall-clock is ~2× faster.uniform_ray_samplescount pass (+8.2% dragon) even as cycles fall — the specialised count callback does more per-thread work but with a better register profile, keeping more eligible warps in flight.7. Notes / risks / migration
ray_implicit_intersection. Now SDF-sign-agnostic; reports the EXIT crossing for rays that start inside the surface (previously-1or a spurious bracket-entry). Matchesnanovdb::ZeroCrossing. Pinned by..._starts_inside_surfaceand..._two_disjoint_regions. Callers relying on the old "positive-outside-only" assumption will see different outputs on inside-surface rays — but those were almost certainly being treated as no-hit anyway.c10::Halfis now dispatched. Code that caughtNotImplementedErrorand fell back to fp32 conversion at the Python boundary should drop that branch.from_nanovdbmay contain active coarse tiles authored elsewhere; the old iterator would have walked those into the per-voxel body (mis-indexing or readinggridScalars[-1]). The leaf iterator skips them, andHDDAIteratorsTestexercises this directly.