From c5aba737354f9cabc2df4917f705d0c2ed05e197 Mon Sep 17 00:00:00 2001 From: manuelkNVDA Date: Wed, 11 Feb 2026 17:10:51 -0800 Subject: [PATCH 1/2] Implement WideBVH fixedRadius and shrinkingRadius ray intersection queries --- cuBQL/traversal/rayQueries.h | 240 ++++++++++++++++++++++++++++++++--- 1 file changed, 224 insertions(+), 16 deletions(-) diff --git a/cuBQL/traversal/rayQueries.h b/cuBQL/traversal/rayQueries.h index f09bdb8..6aef373 100644 --- a/cuBQL/traversal/rayQueries.h +++ b/cuBQL/traversal/rayQueries.h @@ -21,17 +21,24 @@ namespace cuBQL { _terminate_ a traveral, but ordering child nodes is not required because ordering shouldn't matter */ namespace fixedRayQuery { - template + template inline __cubql_both void forEachLeaf(const Lambda &lambdaToExecuteForEachCandidate, - cuBQL::bvh3f bvh, + cuBQL::bvh_t bvh, + cuBQL::ray3f ray, + bool dbg=false); + + template + inline __cubql_both + void forEachLeaf(const Lambda &lambdaToExecuteForEachCandidate, + cuBQL::WideBVH bvh, cuBQL::ray3f ray, bool dbg=false); - template + template inline __cubql_both void forEachPrim(const Lambda &lambdaToExecuteForEachCandidate, - cuBQL::bvh3f bvh, + bvh_t bvh, cuBQL::ray3f ray, bool dbg=false); @@ -77,10 +84,20 @@ namespace cuBQL { /*! single level BVH ray traversal, provided lambda covers what happens when a ray wants to intersect a given prim within that bvh */ - template + template + inline __cubql_both + float forEachLeaf(const Lambda &lambdaToCallOnEachLeaf, + bvh_t bvh, + ray_t ray, + bool dbg=false); + + /*! single level BVH ray traversal, provided lambda covers what + happens when a ray wants to intersect a given prim within that + bvh */ + template inline __cubql_both float forEachLeaf(const Lambda &lambdaToCallOnEachLeaf, - bvh_t bvh, + WideBVH bvh, ray_t ray, bool dbg=false); @@ -243,12 +260,10 @@ namespace cuBQL { forEachLeaf(leafCode,bvh,ray,dbg); } - - - template + template inline __cubql_both void fixedRayQuery::forEachLeaf(const Lambda &lambdaToCallOnEachLeaf, - cuBQL::bvh3f bvh, + cuBQL::bvh_t bvh, cuBQL::ray3f ray, bool dbg) { @@ -314,12 +329,121 @@ namespace cuBQL { } } + template + struct ChildOrder { + inline __cubql_both void clear(int i) { v[i] = (uint64_t)-1; } + inline __cubql_both void set(int i, float dist, uint32_t payload) { + v[i] = (uint64_t(__float_as_int(dist)) << 32) | payload; + } + uint64_t v[N]; + }; + + template + inline __cubql_both void sort(ChildOrder& children) + { +#pragma unroll + for (int i = N - 1; i > 0; --i) { +#pragma unroll + for (int j = 0; j < i; j++) { + uint64_t c0 = children.v[j + 0]; + uint64_t c1 = children.v[j + 1]; + children.v[j + 0] = min(c0, c1); + children.v[j + 1] = max(c0, c1); + } + } + } + + template + inline __cubql_both + void fixedRayQuery::forEachLeaf(const Lambda& lambdaToCallOnEachLeaf, + cuBQL::WideBVH bvh, + cuBQL::ray3f ray, + bool dbg) + { + using node_t = typename WideBVH::node_t; + + int traversalStack[64], * stackPtr = traversalStack; + int nodeID = 0; + + if (ray.direction.x == (T)0) ray.direction.x = T(1e-20); + if (ray.direction.y == (T)0) ray.direction.y = T(1e-20); + if (ray.direction.z == (T)0) ray.direction.z = T(1e-20); + vec_t rcp_dir = rcp(ray.direction); + + ChildOrder childOrder; + + // ------------------------------------------------------------------ + // traverse until there's nothing left to traverse: + // ------------------------------------------------------------------ + while (true) { + while (true) { + while (nodeID == -1) { + if (stackPtr == traversalStack) + return; + nodeID = *--stackPtr; + // pop.... + } + if (nodeID & (1 << 31)) + break; + + node_t const& node = bvh.nodes[nodeID]; +#pragma unroll + for (int c = 0; c < W; c++) { + const auto child = node.children[c]; + if (!node.children[c].valid) + childOrder.clear(c); + else { + float dist2; + bool o = rayIntersectsBox(dist2, ray, rcp_dir, node.children[c].bounds); + if (!o) + childOrder.clear(c); + else { + uint32_t payload = child.count ? + ((1 << 31) | (nodeID << log_of::value) | c) : child.offset; + childOrder.set(c, dist2, payload); + } + } + } + sort(childOrder); +#pragma unroll + for (int c = W - 1; c > 0; --c) { + uint64_t coc = childOrder.v[c]; + if (coc != uint64_t(-1)) { + *stackPtr++ = coc; + // if (stackPtr - stackBase == stackSize) + // printf("stack overrun!\n"); + } + } + if (childOrder.v[0] == uint64_t(-1)) { + nodeID = -1; + continue; + } + nodeID = uint32_t(childOrder.v[0]); + } + + int c = nodeID & ((1 << log_of::value) - 1); + int n = (nodeID & 0x7fffffff) >> log_of::value; + int offset = bvh.nodes[n].children[c].offset; + int count = bvh.nodes[n].children[c].count; + + if (count != 0) { + // we're at a valid leaf: call the lambda and see if that gave + // us a new, closer cull radius + int leafResult + = lambdaToCallOnEachLeaf(bvh.primIDs + offset, count); + if (leafResult == CUBQL_TERMINATE_TRAVERSAL) + return; + } + nodeID = -1; + } + } + /*! this query assumes lambads that return CUBQL_CONTINUE_TRAVERSAL or CUBQL_TERMINATE_TRAVERSAL */ - template + template inline __cubql_both void fixedRayQuery::forEachPrim(const Lambda &lambdaToExecuteForEachCandidate, - cuBQL::bvh3f bvh, + bvh_t bvh, cuBQL::ray3f ray, bool dbg) { @@ -341,15 +465,15 @@ namespace cuBQL { forEachLeaf(leafCode,bvh,ray,dbg); } - template + template inline __cubql_both float shrinkingRayQuery::forEachLeaf(const Lambda &lambdaToCallOnEachLeaf, - bvh_t bvh, + bvh_t bvh, ray_t ray, bool dbg) { - using node_t = typename bvh_t::node_t; - using T = typename bvh_t::scalar_t; + using node_t = typename bvh_t::node_t; + using T = typename bvh_t::scalar_t; struct StackEntry { uint32_t idx; }; @@ -419,6 +543,90 @@ namespace cuBQL { } } + template + inline __cubql_both + float shrinkingRayQuery::forEachLeaf(const Lambda& lambdaToCallOnEachLeaf, + WideBVH bvh, + ray_t ray, + bool dbg) + { + using node_t = typename WideBVH::node_t; + + int traversalStack[64], * stackPtr = traversalStack; + int nodeID = 0; + + if (ray.direction.x == (T)0) ray.direction.x = T(1e-20); + if (ray.direction.y == (T)0) ray.direction.y = T(1e-20); + if (ray.direction.z == (T)0) ray.direction.z = T(1e-20); + vec_t rcp_dir = rcp(ray.direction); + + ChildOrder childOrder; + + // ------------------------------------------------------------------ + // traverse until there's nothing left to traverse: + // ------------------------------------------------------------------ + while (true) { + while (true) { + while (nodeID == -1) { + if (stackPtr == traversalStack) + return ray.tMax; + nodeID = *--stackPtr; + // pop.... + } + if (nodeID & (1 << 31)) + break; + + node_t const& node = bvh.nodes[nodeID]; +#pragma unroll + for (int c = 0; c < W; c++) { + const auto child = node.children[c]; + if (!node.children[c].valid) + childOrder.clear(c); + else { + float dist2; + bool o = rayIntersectsBox(dist2, ray, rcp_dir, node.children[c].bounds); + if (!o) + childOrder.clear(c); + else { + uint32_t payload = child.count ? + ((1 << 31) | (nodeID << log_of::value) | c) : child.offset; + childOrder.set(c, dist2, payload); + } + } + } + sort(childOrder); +#pragma unroll + for (int c = W - 1; c > 0; --c) { + uint64_t coc = childOrder.v[c]; + if (coc != uint64_t(-1)) { + *stackPtr++ = coc; + // if (stackPtr - stackBase == stackSize) + // printf("stack overrun!\n"); + } + } + if (childOrder.v[0] == uint64_t(-1)) { + nodeID = -1; + continue; + } + nodeID = uint32_t(childOrder.v[0]); + } + + int c = nodeID & ((1 << log_of::value) - 1); + int n = (nodeID & 0x7fffffff) >> log_of::value; + int offset = bvh.nodes[n].children[c].offset; + int count = bvh.nodes[n].children[c].count; + + if (count != 0) { + // we're at a valid leaf: call the lambda and see if that gave + // us a new, closer cull radius + ray.tMax + = lambdaToCallOnEachLeaf(bvh.primIDs + offset, count); + } + nodeID = -1; + } + return T(CUBQL_INF); + } + template inline __cubql_both void shrinkingRayQuery::forEachPrim(const Lambda &lambdaToExecuteForEachCandidate, From 6c48fa6b0848c3aa6d242b92b18cb0501d6c8073 Mon Sep 17 00:00:00 2001 From: manuelkNVDA Date: Wed, 11 Feb 2026 17:23:06 -0800 Subject: [PATCH 2/2] Fix linux build --- cuBQL/traversal/rayQueries.h | 1 - 1 file changed, 1 deletion(-) diff --git a/cuBQL/traversal/rayQueries.h b/cuBQL/traversal/rayQueries.h index 6aef373..ef8820c 100644 --- a/cuBQL/traversal/rayQueries.h +++ b/cuBQL/traversal/rayQueries.h @@ -473,7 +473,6 @@ namespace cuBQL { bool dbg) { using node_t = typename bvh_t::node_t; - using T = typename bvh_t::scalar_t; struct StackEntry { uint32_t idx; };