Path: blob/master/thirdparty/embree/kernels/bvh/node_intersector_packet.h
9912 views
// Copyright 2009-2021 Intel Corporation1// SPDX-License-Identifier: Apache-2.023#pragma once45#include "node_intersector.h"67namespace embree8{9namespace isa10{11//////////////////////////////////////////////////////////////////////////////////////12// Ray packet structure used in hybrid traversal13//////////////////////////////////////////////////////////////////////////////////////1415template<int K, bool robust>16struct TravRayK;1718/* Fast variant */19template<int K>20struct TravRayK<K, false>21{22__forceinline TravRayK() {}2324__forceinline TravRayK(const Vec3vf<K>& ray_org, const Vec3vf<K>& ray_dir, int N)25{26init(ray_org, ray_dir, N);27}2829__forceinline TravRayK(const Vec3vf<K>& ray_org, const Vec3vf<K>& ray_dir, const vfloat<K>& ray_tnear, const vfloat<K>& ray_tfar, int N)30{31init(ray_org, ray_dir, N);32tnear = ray_tnear;33tfar = ray_tfar;34}3536__forceinline void init(const Vec3vf<K>& ray_org, const Vec3vf<K>& ray_dir, int N)37{38org = ray_org;39dir = ray_dir;40rdir = rcp_safe(ray_dir);41#if defined(__aarch64__)42neg_org_rdir = -(org * rdir);43#elif defined(__AVX2__)44org_rdir = org * rdir;45#endif4647if (N)48{49const int size = sizeof(float)*N;50nearXYZ.x = select(rdir.x >= 0.0f, vint<K>(0*size), vint<K>(1*size));51nearXYZ.y = select(rdir.y >= 0.0f, vint<K>(2*size), vint<K>(3*size));52nearXYZ.z = select(rdir.z >= 0.0f, vint<K>(4*size), vint<K>(5*size));53}54}5556Vec3vf<K> org;57Vec3vf<K> dir;58Vec3vf<K> rdir;59#if defined(__aarch64__)60Vec3vf<K> neg_org_rdir;61#elif defined(__AVX2__)62Vec3vf<K> org_rdir;63#endif64Vec3vi<K> nearXYZ;65vfloat<K> tnear;66vfloat<K> tfar;67};6869template<int K>70using TravRayKFast = TravRayK<K, false>;7172/* Robust variant */73template<int K>74struct TravRayK<K, true>75{76__forceinline TravRayK() {}7778__forceinline TravRayK(const Vec3vf<K>& ray_org, const Vec3vf<K>& ray_dir, int N)79{80init(ray_org, ray_dir, N);81}8283__forceinline TravRayK(const Vec3vf<K>& ray_org, const Vec3vf<K>& ray_dir, const vfloat<K>& ray_tnear, const vfloat<K>& ray_tfar, int N)84{85init(ray_org, ray_dir, N);86tnear = ray_tnear;87tfar = ray_tfar;88}8990__forceinline void init(const Vec3vf<K>& ray_org, const Vec3vf<K>& ray_dir, int N)91{92org = ray_org;93dir = ray_dir;94rdir = vfloat<K>(1.0f)/(zero_fix(ray_dir));9596if (N)97{98const int size = sizeof(float)*N;99nearXYZ.x = select(rdir.x >= 0.0f, vint<K>(0*size), vint<K>(1*size));100nearXYZ.y = select(rdir.y >= 0.0f, vint<K>(2*size), vint<K>(3*size));101nearXYZ.z = select(rdir.z >= 0.0f, vint<K>(4*size), vint<K>(5*size));102}103}104105Vec3vf<K> org;106Vec3vf<K> dir;107Vec3vf<K> rdir;108Vec3vi<K> nearXYZ;109vfloat<K> tnear;110vfloat<K> tfar;111};112113template<int K>114using TravRayKRobust = TravRayK<K, true>;115116//////////////////////////////////////////////////////////////////////////////////////117// Fast AABBNode intersection118//////////////////////////////////////////////////////////////////////////////////////119120template<int N, int K>121__forceinline vbool<K> intersectNodeK(const typename BVHN<N>::AABBNode* node, size_t i,122const TravRayKFast<K>& ray, vfloat<K>& dist)123124{125#if defined(__aarch64__)126const vfloat<K> lclipMinX = madd(node->lower_x[i], ray.rdir.x, ray.neg_org_rdir.x);127const vfloat<K> lclipMinY = madd(node->lower_y[i], ray.rdir.y, ray.neg_org_rdir.y);128const vfloat<K> lclipMinZ = madd(node->lower_z[i], ray.rdir.z, ray.neg_org_rdir.z);129const vfloat<K> lclipMaxX = madd(node->upper_x[i], ray.rdir.x, ray.neg_org_rdir.x);130const vfloat<K> lclipMaxY = madd(node->upper_y[i], ray.rdir.y, ray.neg_org_rdir.y);131const vfloat<K> lclipMaxZ = madd(node->upper_z[i], ray.rdir.z, ray.neg_org_rdir.z);132#elif defined(__AVX2__)133const vfloat<K> lclipMinX = msub(node->lower_x[i], ray.rdir.x, ray.org_rdir.x);134const vfloat<K> lclipMinY = msub(node->lower_y[i], ray.rdir.y, ray.org_rdir.y);135const vfloat<K> lclipMinZ = msub(node->lower_z[i], ray.rdir.z, ray.org_rdir.z);136const vfloat<K> lclipMaxX = msub(node->upper_x[i], ray.rdir.x, ray.org_rdir.x);137const vfloat<K> lclipMaxY = msub(node->upper_y[i], ray.rdir.y, ray.org_rdir.y);138const vfloat<K> lclipMaxZ = msub(node->upper_z[i], ray.rdir.z, ray.org_rdir.z);139#else140const vfloat<K> lclipMinX = (node->lower_x[i] - ray.org.x) * ray.rdir.x;141const vfloat<K> lclipMinY = (node->lower_y[i] - ray.org.y) * ray.rdir.y;142const vfloat<K> lclipMinZ = (node->lower_z[i] - ray.org.z) * ray.rdir.z;143const vfloat<K> lclipMaxX = (node->upper_x[i] - ray.org.x) * ray.rdir.x;144const vfloat<K> lclipMaxY = (node->upper_y[i] - ray.org.y) * ray.rdir.y;145const vfloat<K> lclipMaxZ = (node->upper_z[i] - ray.org.z) * ray.rdir.z;146#endif147148#if defined(__AVX512F__) // SKX149if (K == 16)150{151/* use mixed float/int min/max */152const vfloat<K> lnearP = maxi(min(lclipMinX, lclipMaxX), min(lclipMinY, lclipMaxY), min(lclipMinZ, lclipMaxZ));153const vfloat<K> lfarP = mini(max(lclipMinX, lclipMaxX), max(lclipMinY, lclipMaxY), max(lclipMinZ, lclipMaxZ));154const vbool<K> lhit = asInt(maxi(lnearP, ray.tnear)) <= asInt(mini(lfarP, ray.tfar));155dist = lnearP;156return lhit;157}158else159#endif160{161const vfloat<K> lnearP = maxi(mini(lclipMinX, lclipMaxX), mini(lclipMinY, lclipMaxY), mini(lclipMinZ, lclipMaxZ));162const vfloat<K> lfarP = mini(maxi(lclipMinX, lclipMaxX), maxi(lclipMinY, lclipMaxY), maxi(lclipMinZ, lclipMaxZ));163#if defined(__AVX512F__) // SKX164const vbool<K> lhit = asInt(maxi(lnearP, ray.tnear)) <= asInt(mini(lfarP, ray.tfar));165#else166const vbool<K> lhit = maxi(lnearP, ray.tnear) <= mini(lfarP, ray.tfar);167#endif168dist = lnearP;169return lhit;170}171}172173//////////////////////////////////////////////////////////////////////////////////////174// Robust AABBNode intersection175//////////////////////////////////////////////////////////////////////////////////////176177template<int N, int K>178__forceinline vbool<K> intersectNodeKRobust(const typename BVHN<N>::AABBNode* node, size_t i,179const TravRayKRobust<K>& ray, vfloat<K>& dist)180{181// FIXME: use per instruction rounding for AVX512182const vfloat<K> lclipMinX = (node->lower_x[i] - ray.org.x) * ray.rdir.x;183const vfloat<K> lclipMinY = (node->lower_y[i] - ray.org.y) * ray.rdir.y;184const vfloat<K> lclipMinZ = (node->lower_z[i] - ray.org.z) * ray.rdir.z;185const vfloat<K> lclipMaxX = (node->upper_x[i] - ray.org.x) * ray.rdir.x;186const vfloat<K> lclipMaxY = (node->upper_y[i] - ray.org.y) * ray.rdir.y;187const vfloat<K> lclipMaxZ = (node->upper_z[i] - ray.org.z) * ray.rdir.z;188const float round_up = 1.0f+3.0f*float(ulp);189const float round_down = 1.0f-3.0f*float(ulp);190const vfloat<K> lnearP = round_down*max(max(min(lclipMinX, lclipMaxX), min(lclipMinY, lclipMaxY)), min(lclipMinZ, lclipMaxZ));191const vfloat<K> lfarP = round_up *min(min(max(lclipMinX, lclipMaxX), max(lclipMinY, lclipMaxY)), max(lclipMinZ, lclipMaxZ));192const vbool<K> lhit = max(lnearP, ray.tnear) <= min(lfarP, ray.tfar);193dist = lnearP;194return lhit;195}196197//////////////////////////////////////////////////////////////////////////////////////198// Fast AABBNodeMB intersection199//////////////////////////////////////////////////////////////////////////////////////200201template<int N, int K>202__forceinline vbool<K> intersectNodeK(const typename BVHN<N>::AABBNodeMB* node, const size_t i,203const TravRayKFast<K>& ray, const vfloat<K>& time, vfloat<K>& dist)204{205const vfloat<K> vlower_x = madd(time, vfloat<K>(node->lower_dx[i]), vfloat<K>(node->lower_x[i]));206const vfloat<K> vlower_y = madd(time, vfloat<K>(node->lower_dy[i]), vfloat<K>(node->lower_y[i]));207const vfloat<K> vlower_z = madd(time, vfloat<K>(node->lower_dz[i]), vfloat<K>(node->lower_z[i]));208const vfloat<K> vupper_x = madd(time, vfloat<K>(node->upper_dx[i]), vfloat<K>(node->upper_x[i]));209const vfloat<K> vupper_y = madd(time, vfloat<K>(node->upper_dy[i]), vfloat<K>(node->upper_y[i]));210const vfloat<K> vupper_z = madd(time, vfloat<K>(node->upper_dz[i]), vfloat<K>(node->upper_z[i]));211212#if defined(__aarch64__)213const vfloat<K> lclipMinX = madd(vlower_x, ray.rdir.x, ray.neg_org_rdir.x);214const vfloat<K> lclipMinY = madd(vlower_y, ray.rdir.y, ray.neg_org_rdir.y);215const vfloat<K> lclipMinZ = madd(vlower_z, ray.rdir.z, ray.neg_org_rdir.z);216const vfloat<K> lclipMaxX = madd(vupper_x, ray.rdir.x, ray.neg_org_rdir.x);217const vfloat<K> lclipMaxY = madd(vupper_y, ray.rdir.y, ray.neg_org_rdir.y);218const vfloat<K> lclipMaxZ = madd(vupper_z, ray.rdir.z, ray.neg_org_rdir.z);219#elif defined(__AVX2__)220const vfloat<K> lclipMinX = msub(vlower_x, ray.rdir.x, ray.org_rdir.x);221const vfloat<K> lclipMinY = msub(vlower_y, ray.rdir.y, ray.org_rdir.y);222const vfloat<K> lclipMinZ = msub(vlower_z, ray.rdir.z, ray.org_rdir.z);223const vfloat<K> lclipMaxX = msub(vupper_x, ray.rdir.x, ray.org_rdir.x);224const vfloat<K> lclipMaxY = msub(vupper_y, ray.rdir.y, ray.org_rdir.y);225const vfloat<K> lclipMaxZ = msub(vupper_z, ray.rdir.z, ray.org_rdir.z);226#else227const vfloat<K> lclipMinX = (vlower_x - ray.org.x) * ray.rdir.x;228const vfloat<K> lclipMinY = (vlower_y - ray.org.y) * ray.rdir.y;229const vfloat<K> lclipMinZ = (vlower_z - ray.org.z) * ray.rdir.z;230const vfloat<K> lclipMaxX = (vupper_x - ray.org.x) * ray.rdir.x;231const vfloat<K> lclipMaxY = (vupper_y - ray.org.y) * ray.rdir.y;232const vfloat<K> lclipMaxZ = (vupper_z - ray.org.z) * ray.rdir.z;233#endif234235#if defined(__AVX512F__) // SKX236if (K == 16)237{238/* use mixed float/int min/max */239const vfloat<K> lnearP = maxi(min(lclipMinX, lclipMaxX), min(lclipMinY, lclipMaxY), min(lclipMinZ, lclipMaxZ));240const vfloat<K> lfarP = mini(max(lclipMinX, lclipMaxX), max(lclipMinY, lclipMaxY), max(lclipMinZ, lclipMaxZ));241const vbool<K> lhit = asInt(maxi(lnearP, ray.tnear)) <= asInt(mini(lfarP, ray.tfar));242dist = lnearP;243return lhit;244}245else246#endif247{248const vfloat<K> lnearP = maxi(mini(lclipMinX, lclipMaxX), mini(lclipMinY, lclipMaxY), mini(lclipMinZ, lclipMaxZ));249const vfloat<K> lfarP = mini(maxi(lclipMinX, lclipMaxX), maxi(lclipMinY, lclipMaxY), maxi(lclipMinZ, lclipMaxZ));250#if defined(__AVX512F__) // SKX251const vbool<K> lhit = asInt(maxi(lnearP, ray.tnear)) <= asInt(mini(lfarP, ray.tfar));252#else253const vbool<K> lhit = maxi(lnearP, ray.tnear) <= mini(lfarP, ray.tfar);254#endif255dist = lnearP;256return lhit;257}258}259260//////////////////////////////////////////////////////////////////////////////////////261// Robust AABBNodeMB intersection262//////////////////////////////////////////////////////////////////////////////////////263264template<int N, int K>265__forceinline vbool<K> intersectNodeKRobust(const typename BVHN<N>::AABBNodeMB* node, const size_t i,266const TravRayKRobust<K>& ray, const vfloat<K>& time, vfloat<K>& dist)267{268const vfloat<K> vlower_x = madd(time, vfloat<K>(node->lower_dx[i]), vfloat<K>(node->lower_x[i]));269const vfloat<K> vlower_y = madd(time, vfloat<K>(node->lower_dy[i]), vfloat<K>(node->lower_y[i]));270const vfloat<K> vlower_z = madd(time, vfloat<K>(node->lower_dz[i]), vfloat<K>(node->lower_z[i]));271const vfloat<K> vupper_x = madd(time, vfloat<K>(node->upper_dx[i]), vfloat<K>(node->upper_x[i]));272const vfloat<K> vupper_y = madd(time, vfloat<K>(node->upper_dy[i]), vfloat<K>(node->upper_y[i]));273const vfloat<K> vupper_z = madd(time, vfloat<K>(node->upper_dz[i]), vfloat<K>(node->upper_z[i]));274275const vfloat<K> lclipMinX = (vlower_x - ray.org.x) * ray.rdir.x;276const vfloat<K> lclipMinY = (vlower_y - ray.org.y) * ray.rdir.y;277const vfloat<K> lclipMinZ = (vlower_z - ray.org.z) * ray.rdir.z;278const vfloat<K> lclipMaxX = (vupper_x - ray.org.x) * ray.rdir.x;279const vfloat<K> lclipMaxY = (vupper_y - ray.org.y) * ray.rdir.y;280const vfloat<K> lclipMaxZ = (vupper_z - ray.org.z) * ray.rdir.z;281282const float round_up = 1.0f+3.0f*float(ulp);283const float round_down = 1.0f-3.0f*float(ulp);284285#if defined(__AVX512F__) // SKX286if (K == 16)287{288const vfloat<K> lnearP = round_down*maxi(min(lclipMinX, lclipMaxX), min(lclipMinY, lclipMaxY), min(lclipMinZ, lclipMaxZ));289const vfloat<K> lfarP = round_up *mini(max(lclipMinX, lclipMaxX), max(lclipMinY, lclipMaxY), max(lclipMinZ, lclipMaxZ));290const vbool<K> lhit = maxi(lnearP, ray.tnear) <= mini(lfarP, ray.tfar);291dist = lnearP;292return lhit;293}294else295#endif296{297const vfloat<K> lnearP = round_down*maxi(mini(lclipMinX, lclipMaxX), mini(lclipMinY, lclipMaxY), mini(lclipMinZ, lclipMaxZ));298const vfloat<K> lfarP = round_up *mini(maxi(lclipMinX, lclipMaxX), maxi(lclipMinY, lclipMaxY), maxi(lclipMinZ, lclipMaxZ));299const vbool<K> lhit = maxi(lnearP, ray.tnear) <= mini(lfarP, ray.tfar);300dist = lnearP;301return lhit;302}303}304305//////////////////////////////////////////////////////////////////////////////////////306// Fast AABBNodeMB4D intersection307//////////////////////////////////////////////////////////////////////////////////////308309template<int N, int K>310__forceinline vbool<K> intersectNodeKMB4D(const typename BVHN<N>::NodeRef ref, const size_t i,311const TravRayKFast<K>& ray, const vfloat<K>& time, vfloat<K>& dist)312{313const typename BVHN<N>::AABBNodeMB* node = ref.getAABBNodeMB();314315const vfloat<K> vlower_x = madd(time, vfloat<K>(node->lower_dx[i]), vfloat<K>(node->lower_x[i]));316const vfloat<K> vlower_y = madd(time, vfloat<K>(node->lower_dy[i]), vfloat<K>(node->lower_y[i]));317const vfloat<K> vlower_z = madd(time, vfloat<K>(node->lower_dz[i]), vfloat<K>(node->lower_z[i]));318const vfloat<K> vupper_x = madd(time, vfloat<K>(node->upper_dx[i]), vfloat<K>(node->upper_x[i]));319const vfloat<K> vupper_y = madd(time, vfloat<K>(node->upper_dy[i]), vfloat<K>(node->upper_y[i]));320const vfloat<K> vupper_z = madd(time, vfloat<K>(node->upper_dz[i]), vfloat<K>(node->upper_z[i]));321322#if defined(__aarch64__)323const vfloat<K> lclipMinX = madd(vlower_x, ray.rdir.x, ray.neg_org_rdir.x);324const vfloat<K> lclipMinY = madd(vlower_y, ray.rdir.y, ray.neg_org_rdir.y);325const vfloat<K> lclipMinZ = madd(vlower_z, ray.rdir.z, ray.neg_org_rdir.z);326const vfloat<K> lclipMaxX = madd(vupper_x, ray.rdir.x, ray.neg_org_rdir.x);327const vfloat<K> lclipMaxY = madd(vupper_y, ray.rdir.y, ray.neg_org_rdir.y);328const vfloat<K> lclipMaxZ = madd(vupper_z, ray.rdir.z, ray.neg_org_rdir.z);329#elif defined(__AVX2__)330const vfloat<K> lclipMinX = msub(vlower_x, ray.rdir.x, ray.org_rdir.x);331const vfloat<K> lclipMinY = msub(vlower_y, ray.rdir.y, ray.org_rdir.y);332const vfloat<K> lclipMinZ = msub(vlower_z, ray.rdir.z, ray.org_rdir.z);333const vfloat<K> lclipMaxX = msub(vupper_x, ray.rdir.x, ray.org_rdir.x);334const vfloat<K> lclipMaxY = msub(vupper_y, ray.rdir.y, ray.org_rdir.y);335const vfloat<K> lclipMaxZ = msub(vupper_z, ray.rdir.z, ray.org_rdir.z);336#else337const vfloat<K> lclipMinX = (vlower_x - ray.org.x) * ray.rdir.x;338const vfloat<K> lclipMinY = (vlower_y - ray.org.y) * ray.rdir.y;339const vfloat<K> lclipMinZ = (vlower_z - ray.org.z) * ray.rdir.z;340const vfloat<K> lclipMaxX = (vupper_x - ray.org.x) * ray.rdir.x;341const vfloat<K> lclipMaxY = (vupper_y - ray.org.y) * ray.rdir.y;342const vfloat<K> lclipMaxZ = (vupper_z - ray.org.z) * ray.rdir.z;343#endif344345const vfloat<K> lnearP = maxi(maxi(mini(lclipMinX, lclipMaxX), mini(lclipMinY, lclipMaxY)), mini(lclipMinZ, lclipMaxZ));346const vfloat<K> lfarP = mini(mini(maxi(lclipMinX, lclipMaxX), maxi(lclipMinY, lclipMaxY)), maxi(lclipMinZ, lclipMaxZ));347vbool<K> lhit = maxi(lnearP, ray.tnear) <= mini(lfarP, ray.tfar);348if (unlikely(ref.isAABBNodeMB4D())) {349const typename BVHN<N>::AABBNodeMB4D* node1 = (const typename BVHN<N>::AABBNodeMB4D*) node;350lhit = lhit & (vfloat<K>(node1->lower_t[i]) <= time) & (time < vfloat<K>(node1->upper_t[i]));351}352dist = lnearP;353return lhit;354}355356//////////////////////////////////////////////////////////////////////////////////////357// Robust AABBNodeMB4D intersection358//////////////////////////////////////////////////////////////////////////////////////359360template<int N, int K>361__forceinline vbool<K> intersectNodeKMB4DRobust(const typename BVHN<N>::NodeRef ref, const size_t i,362const TravRayKRobust<K>& ray, const vfloat<K>& time, vfloat<K>& dist)363{364const typename BVHN<N>::AABBNodeMB* node = ref.getAABBNodeMB();365366const vfloat<K> vlower_x = madd(time, vfloat<K>(node->lower_dx[i]), vfloat<K>(node->lower_x[i]));367const vfloat<K> vlower_y = madd(time, vfloat<K>(node->lower_dy[i]), vfloat<K>(node->lower_y[i]));368const vfloat<K> vlower_z = madd(time, vfloat<K>(node->lower_dz[i]), vfloat<K>(node->lower_z[i]));369const vfloat<K> vupper_x = madd(time, vfloat<K>(node->upper_dx[i]), vfloat<K>(node->upper_x[i]));370const vfloat<K> vupper_y = madd(time, vfloat<K>(node->upper_dy[i]), vfloat<K>(node->upper_y[i]));371const vfloat<K> vupper_z = madd(time, vfloat<K>(node->upper_dz[i]), vfloat<K>(node->upper_z[i]));372373const vfloat<K> lclipMinX = (vlower_x - ray.org.x) * ray.rdir.x;374const vfloat<K> lclipMinY = (vlower_y - ray.org.y) * ray.rdir.y;375const vfloat<K> lclipMinZ = (vlower_z - ray.org.z) * ray.rdir.z;376const vfloat<K> lclipMaxX = (vupper_x - ray.org.x) * ray.rdir.x;377const vfloat<K> lclipMaxY = (vupper_y - ray.org.y) * ray.rdir.y;378const vfloat<K> lclipMaxZ = (vupper_z - ray.org.z) * ray.rdir.z;379380const float round_up = 1.0f+3.0f*float(ulp);381const float round_down = 1.0f-3.0f*float(ulp);382const vfloat<K> lnearP = round_down*maxi(maxi(mini(lclipMinX, lclipMaxX), mini(lclipMinY, lclipMaxY)), mini(lclipMinZ, lclipMaxZ));383const vfloat<K> lfarP = round_up *mini(mini(maxi(lclipMinX, lclipMaxX), maxi(lclipMinY, lclipMaxY)), maxi(lclipMinZ, lclipMaxZ));384vbool<K> lhit = maxi(lnearP, ray.tnear) <= mini(lfarP, ray.tfar);385386if (unlikely(ref.isAABBNodeMB4D())) {387const typename BVHN<N>::AABBNodeMB4D* node1 = (const typename BVHN<N>::AABBNodeMB4D*) node;388lhit = lhit & (vfloat<K>(node1->lower_t[i]) <= time) & (time < vfloat<K>(node1->upper_t[i]));389}390dist = lnearP;391return lhit;392}393394//////////////////////////////////////////////////////////////////////////////////////395// Fast OBBNode intersection396//////////////////////////////////////////////////////////////////////////////////////397398template<int N, int K, bool robust>399__forceinline vbool<K> intersectNodeK(const typename BVHN<N>::OBBNode* node, const size_t i,400const TravRayK<K,robust>& ray, vfloat<K>& dist)401{402const AffineSpace3vf<K> naabb(Vec3f(node->naabb.l.vx.x[i], node->naabb.l.vx.y[i], node->naabb.l.vx.z[i]),403Vec3f(node->naabb.l.vy.x[i], node->naabb.l.vy.y[i], node->naabb.l.vy.z[i]),404Vec3f(node->naabb.l.vz.x[i], node->naabb.l.vz.y[i], node->naabb.l.vz.z[i]),405Vec3f(node->naabb.p .x[i], node->naabb.p .y[i], node->naabb.p .z[i]));406407const Vec3vf<K> dir = xfmVector(naabb, ray.dir);408const Vec3vf<K> nrdir = Vec3vf<K>(vfloat<K>(-1.0f)) * rcp_safe(dir); // FIXME: negate instead of mul with -1?409const Vec3vf<K> org = xfmPoint(naabb, ray.org);410411const vfloat<K> lclipMinX = org.x * nrdir.x; // (Vec3fa(zero) - org) * rdir;412const vfloat<K> lclipMinY = org.y * nrdir.y;413const vfloat<K> lclipMinZ = org.z * nrdir.z;414const vfloat<K> lclipMaxX = lclipMinX - nrdir.x; // (Vec3fa(one) - org) * rdir;415const vfloat<K> lclipMaxY = lclipMinY - nrdir.y;416const vfloat<K> lclipMaxZ = lclipMinZ - nrdir.z;417418vfloat<K> lnearP = maxi(mini(lclipMinX, lclipMaxX), mini(lclipMinY, lclipMaxY), mini(lclipMinZ, lclipMaxZ));419vfloat<K> lfarP = mini(maxi(lclipMinX, lclipMaxX), maxi(lclipMinY, lclipMaxY), maxi(lclipMinZ, lclipMaxZ));420if (robust) {421lnearP = lnearP*vfloat<K>(1.0f-3.0f*float(ulp));422lfarP = lfarP *vfloat<K>(1.0f+3.0f*float(ulp));423}424const vbool<K> lhit = maxi(lnearP, ray.tnear) <= mini(lfarP, ray.tfar);425dist = lnearP;426return lhit;427}428429//////////////////////////////////////////////////////////////////////////////////////430// Fast OBBNodeMB intersection431//////////////////////////////////////////////////////////////////////////////////////432433template<int N, int K, bool robust>434__forceinline vbool<K> intersectNodeK(const typename BVHN<N>::OBBNodeMB* node, const size_t i,435const TravRayK<K,robust>& ray, const vfloat<K>& time, vfloat<K>& dist)436{437const AffineSpace3vf<K> xfm(Vec3f(node->space0.l.vx.x[i], node->space0.l.vx.y[i], node->space0.l.vx.z[i]),438Vec3f(node->space0.l.vy.x[i], node->space0.l.vy.y[i], node->space0.l.vy.z[i]),439Vec3f(node->space0.l.vz.x[i], node->space0.l.vz.y[i], node->space0.l.vz.z[i]),440Vec3f(node->space0.p .x[i], node->space0.p .y[i], node->space0.p .z[i]));441442const Vec3vf<K> b0_lower = zero;443const Vec3vf<K> b0_upper = one;444const Vec3vf<K> b1_lower(node->b1.lower.x[i], node->b1.lower.y[i], node->b1.lower.z[i]);445const Vec3vf<K> b1_upper(node->b1.upper.x[i], node->b1.upper.y[i], node->b1.upper.z[i]);446const Vec3vf<K> lower = lerp(b0_lower, b1_lower, time);447const Vec3vf<K> upper = lerp(b0_upper, b1_upper, time);448449const Vec3vf<K> dir = xfmVector(xfm, ray.dir);450const Vec3vf<K> rdir = rcp_safe(dir);451const Vec3vf<K> org = xfmPoint(xfm, ray.org);452453const vfloat<K> lclipMinX = (lower.x - org.x) * rdir.x;454const vfloat<K> lclipMinY = (lower.y - org.y) * rdir.y;455const vfloat<K> lclipMinZ = (lower.z - org.z) * rdir.z;456const vfloat<K> lclipMaxX = (upper.x - org.x) * rdir.x;457const vfloat<K> lclipMaxY = (upper.y - org.y) * rdir.y;458const vfloat<K> lclipMaxZ = (upper.z - org.z) * rdir.z;459460vfloat<K> lnearP = maxi(mini(lclipMinX, lclipMaxX), mini(lclipMinY, lclipMaxY), mini(lclipMinZ, lclipMaxZ));461vfloat<K> lfarP = mini(maxi(lclipMinX, lclipMaxX), maxi(lclipMinY, lclipMaxY), maxi(lclipMinZ, lclipMaxZ));462if (robust) {463lnearP = lnearP*vfloat<K>(1.0f-3.0f*float(ulp));464lfarP = lfarP *vfloat<K>(1.0f+3.0f*float(ulp));465}466467const vbool<K> lhit = maxi(lnearP, ray.tnear) <= mini(lfarP, ray.tfar);468dist = lnearP;469return lhit;470}471472473474//////////////////////////////////////////////////////////////////////////////////////475// QuantizedBaseNode intersection476//////////////////////////////////////////////////////////////////////////////////////477478template<int N, int K>479__forceinline vbool<K> intersectQuantizedNodeK(const typename BVHN<N>::QuantizedBaseNode* node, size_t i,480const TravRayK<K,false>& ray, vfloat<K>& dist)481482{483assert(movemask(node->validMask()) & ((size_t)1 << i));484const vfloat<N> lower_x = node->dequantizeLowerX();485const vfloat<N> upper_x = node->dequantizeUpperX();486const vfloat<N> lower_y = node->dequantizeLowerY();487const vfloat<N> upper_y = node->dequantizeUpperY();488const vfloat<N> lower_z = node->dequantizeLowerZ();489const vfloat<N> upper_z = node->dequantizeUpperZ();490491#if defined(__aarch64__)492const vfloat<K> lclipMinX = madd(lower_x[i], ray.rdir.x, ray.neg_org_rdir.x);493const vfloat<K> lclipMinY = madd(lower_y[i], ray.rdir.y, ray.neg_org_rdir.y);494const vfloat<K> lclipMinZ = madd(lower_z[i], ray.rdir.z, ray.neg_org_rdir.z);495const vfloat<K> lclipMaxX = madd(upper_x[i], ray.rdir.x, ray.neg_org_rdir.x);496const vfloat<K> lclipMaxY = madd(upper_y[i], ray.rdir.y, ray.neg_org_rdir.y);497const vfloat<K> lclipMaxZ = madd(upper_z[i], ray.rdir.z, ray.neg_org_rdir.z);498#elif defined(__AVX2__)499const vfloat<K> lclipMinX = msub(lower_x[i], ray.rdir.x, ray.org_rdir.x);500const vfloat<K> lclipMinY = msub(lower_y[i], ray.rdir.y, ray.org_rdir.y);501const vfloat<K> lclipMinZ = msub(lower_z[i], ray.rdir.z, ray.org_rdir.z);502const vfloat<K> lclipMaxX = msub(upper_x[i], ray.rdir.x, ray.org_rdir.x);503const vfloat<K> lclipMaxY = msub(upper_y[i], ray.rdir.y, ray.org_rdir.y);504const vfloat<K> lclipMaxZ = msub(upper_z[i], ray.rdir.z, ray.org_rdir.z);505#else506const vfloat<K> lclipMinX = (lower_x[i] - ray.org.x) * ray.rdir.x;507const vfloat<K> lclipMinY = (lower_y[i] - ray.org.y) * ray.rdir.y;508const vfloat<K> lclipMinZ = (lower_z[i] - ray.org.z) * ray.rdir.z;509const vfloat<K> lclipMaxX = (upper_x[i] - ray.org.x) * ray.rdir.x;510const vfloat<K> lclipMaxY = (upper_y[i] - ray.org.y) * ray.rdir.y;511const vfloat<K> lclipMaxZ = (upper_z[i] - ray.org.z) * ray.rdir.z;512#endif513514#if defined(__AVX512F__) // SKX515if (K == 16)516{517/* use mixed float/int min/max */518const vfloat<K> lnearP = maxi(min(lclipMinX, lclipMaxX), min(lclipMinY, lclipMaxY), min(lclipMinZ, lclipMaxZ));519const vfloat<K> lfarP = mini(max(lclipMinX, lclipMaxX), max(lclipMinY, lclipMaxY), max(lclipMinZ, lclipMaxZ));520const vbool<K> lhit = asInt(maxi(lnearP, ray.tnear)) <= asInt(mini(lfarP, ray.tfar));521dist = lnearP;522return lhit;523}524else525#endif526{527const vfloat<K> lnearP = maxi(mini(lclipMinX, lclipMaxX), mini(lclipMinY, lclipMaxY), mini(lclipMinZ, lclipMaxZ));528const vfloat<K> lfarP = mini(maxi(lclipMinX, lclipMaxX), maxi(lclipMinY, lclipMaxY), maxi(lclipMinZ, lclipMaxZ));529#if defined(__AVX512F__) // SKX530const vbool<K> lhit = asInt(maxi(lnearP, ray.tnear)) <= asInt(mini(lfarP, ray.tfar));531#else532const vbool<K> lhit = maxi(lnearP, ray.tnear) <= mini(lfarP, ray.tfar);533#endif534dist = lnearP;535return lhit;536}537}538539template<int N, int K>540__forceinline vbool<K> intersectQuantizedNodeK(const typename BVHN<N>::QuantizedBaseNode* node, size_t i,541const TravRayK<K,true>& ray, vfloat<K>& dist)542543{544assert(movemask(node->validMask()) & ((size_t)1 << i));545const vfloat<N> lower_x = node->dequantizeLowerX();546const vfloat<N> upper_x = node->dequantizeUpperX();547const vfloat<N> lower_y = node->dequantizeLowerY();548const vfloat<N> upper_y = node->dequantizeUpperY();549const vfloat<N> lower_z = node->dequantizeLowerZ();550const vfloat<N> upper_z = node->dequantizeUpperZ();551552const vfloat<K> lclipMinX = (lower_x[i] - ray.org.x) * ray.rdir.x;553const vfloat<K> lclipMinY = (lower_y[i] - ray.org.y) * ray.rdir.y;554const vfloat<K> lclipMinZ = (lower_z[i] - ray.org.z) * ray.rdir.z;555const vfloat<K> lclipMaxX = (upper_x[i] - ray.org.x) * ray.rdir.x;556const vfloat<K> lclipMaxY = (upper_y[i] - ray.org.y) * ray.rdir.y;557const vfloat<K> lclipMaxZ = (upper_z[i] - ray.org.z) * ray.rdir.z;558559const float round_up = 1.0f+3.0f*float(ulp);560const float round_down = 1.0f-3.0f*float(ulp);561562const vfloat<K> lnearP = round_down*max(min(lclipMinX, lclipMaxX), min(lclipMinY, lclipMaxY), min(lclipMinZ, lclipMaxZ));563const vfloat<K> lfarP = round_up *min(max(lclipMinX, lclipMaxX), max(lclipMinY, lclipMaxY), max(lclipMinZ, lclipMaxZ));564const vbool<K> lhit = max(lnearP, ray.tnear) <= min(lfarP, ray.tfar);565dist = lnearP;566return lhit;567}568569template<int N, int K>570__forceinline vbool<K> intersectQuantizedNodeMBK(const typename BVHN<N>::QuantizedBaseNodeMB* node, const size_t i,571const TravRayK<K,false>& ray, const vfloat<K>& time, vfloat<K>& dist)572573{574assert(movemask(node->validMask()) & ((size_t)1 << i));575576const vfloat<K> lower_x = node->template dequantizeLowerX<K>(i,time);577const vfloat<K> upper_x = node->template dequantizeUpperX<K>(i,time);578const vfloat<K> lower_y = node->template dequantizeLowerY<K>(i,time);579const vfloat<K> upper_y = node->template dequantizeUpperY<K>(i,time);580const vfloat<K> lower_z = node->template dequantizeLowerZ<K>(i,time);581const vfloat<K> upper_z = node->template dequantizeUpperZ<K>(i,time);582583#if defined(__aarch64__)584const vfloat<K> lclipMinX = madd(lower_x, ray.rdir.x, ray.neg_org_rdir.x);585const vfloat<K> lclipMinY = madd(lower_y, ray.rdir.y, ray.neg_org_rdir.y);586const vfloat<K> lclipMinZ = madd(lower_z, ray.rdir.z, ray.neg_org_rdir.z);587const vfloat<K> lclipMaxX = madd(upper_x, ray.rdir.x, ray.neg_org_rdir.x);588const vfloat<K> lclipMaxY = madd(upper_y, ray.rdir.y, ray.neg_org_rdir.y);589const vfloat<K> lclipMaxZ = madd(upper_z, ray.rdir.z, ray.neg_org_rdir.z);590#elif defined(__AVX2__)591const vfloat<K> lclipMinX = msub(lower_x, ray.rdir.x, ray.org_rdir.x);592const vfloat<K> lclipMinY = msub(lower_y, ray.rdir.y, ray.org_rdir.y);593const vfloat<K> lclipMinZ = msub(lower_z, ray.rdir.z, ray.org_rdir.z);594const vfloat<K> lclipMaxX = msub(upper_x, ray.rdir.x, ray.org_rdir.x);595const vfloat<K> lclipMaxY = msub(upper_y, ray.rdir.y, ray.org_rdir.y);596const vfloat<K> lclipMaxZ = msub(upper_z, ray.rdir.z, ray.org_rdir.z);597#else598const vfloat<K> lclipMinX = (lower_x - ray.org.x) * ray.rdir.x;599const vfloat<K> lclipMinY = (lower_y - ray.org.y) * ray.rdir.y;600const vfloat<K> lclipMinZ = (lower_z - ray.org.z) * ray.rdir.z;601const vfloat<K> lclipMaxX = (upper_x - ray.org.x) * ray.rdir.x;602const vfloat<K> lclipMaxY = (upper_y - ray.org.y) * ray.rdir.y;603const vfloat<K> lclipMaxZ = (upper_z - ray.org.z) * ray.rdir.z;604#endif605const vfloat<K> lnearP = max(min(lclipMinX, lclipMaxX), min(lclipMinY, lclipMaxY), min(lclipMinZ, lclipMaxZ));606const vfloat<K> lfarP = min(max(lclipMinX, lclipMaxX), max(lclipMinY, lclipMaxY), max(lclipMinZ, lclipMaxZ));607const vbool<K> lhit = max(lnearP, ray.tnear) <= min(lfarP, ray.tfar);608dist = lnearP;609return lhit;610}611612613template<int N, int K>614__forceinline vbool<K> intersectQuantizedNodeMBK(const typename BVHN<N>::QuantizedBaseNodeMB* node, const size_t i,615const TravRayK<K,true>& ray, const vfloat<K>& time, vfloat<K>& dist)616617{618assert(movemask(node->validMask()) & ((size_t)1 << i));619620const vfloat<K> lower_x = node->template dequantizeLowerX<K>(i,time);621const vfloat<K> upper_x = node->template dequantizeUpperX<K>(i,time);622const vfloat<K> lower_y = node->template dequantizeLowerY<K>(i,time);623const vfloat<K> upper_y = node->template dequantizeUpperY<K>(i,time);624const vfloat<K> lower_z = node->template dequantizeLowerZ<K>(i,time);625const vfloat<K> upper_z = node->template dequantizeUpperZ<K>(i,time);626627const vfloat<K> lclipMinX = (lower_x - ray.org.x) * ray.rdir.x;628const vfloat<K> lclipMinY = (lower_y - ray.org.y) * ray.rdir.y;629const vfloat<K> lclipMinZ = (lower_z - ray.org.z) * ray.rdir.z;630const vfloat<K> lclipMaxX = (upper_x - ray.org.x) * ray.rdir.x;631const vfloat<K> lclipMaxY = (upper_y - ray.org.y) * ray.rdir.y;632const vfloat<K> lclipMaxZ = (upper_z - ray.org.z) * ray.rdir.z;633634const float round_up = 1.0f+3.0f*float(ulp);635const float round_down = 1.0f-3.0f*float(ulp);636637const vfloat<K> lnearP = round_down*max(min(lclipMinX, lclipMaxX), min(lclipMinY, lclipMaxY), min(lclipMinZ, lclipMaxZ));638const vfloat<K> lfarP = round_up *min(max(lclipMinX, lclipMaxX), max(lclipMinY, lclipMaxY), max(lclipMinZ, lclipMaxZ));639const vbool<K> lhit = max(lnearP, ray.tnear) <= min(lfarP, ray.tfar);640dist = lnearP;641return lhit;642}643644645//////////////////////////////////////////////////////////////////////////////////////646// Node intersectors used in hybrid traversal647//////////////////////////////////////////////////////////////////////////////////////648649/*! Intersects N nodes with K rays */650template<int N, int K, int types, bool robust>651struct BVHNNodeIntersectorK;652653template<int N, int K>654struct BVHNNodeIntersectorK<N, K, BVH_AN1, false>655{656/* vmask is both an input and an output parameter! Its initial value should be the parent node657hit mask, which is used for correctly computing the current hit mask. The parent hit mask658is actually required only for motion blur node intersections (because different rays may659have different times), so for regular nodes vmask is simply overwritten. */660static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, size_t i,661const TravRayKFast<K>& ray, const vfloat<K>& time, vfloat<K>& dist, vbool<K>& vmask)662{663vmask = intersectNodeK<N,K>(node.getAABBNode(), i, ray, dist);664return true;665}666};667668template<int N, int K>669struct BVHNNodeIntersectorK<N, K, BVH_AN1, true>670{671static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, size_t i,672const TravRayKRobust<K>& ray, const vfloat<K>& time, vfloat<K>& dist, vbool<K>& vmask)673{674vmask = intersectNodeKRobust<N,K>(node.getAABBNode(), i, ray, dist);675return true;676}677};678679template<int N, int K>680struct BVHNNodeIntersectorK<N, K, BVH_AN2, false>681{682static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, size_t i,683const TravRayKFast<K>& ray, const vfloat<K>& time, vfloat<K>& dist, vbool<K>& vmask)684{685vmask = intersectNodeK<N,K>(node.getAABBNodeMB(), i, ray, time, dist);686return true;687}688};689690template<int N, int K>691struct BVHNNodeIntersectorK<N, K, BVH_AN2, true>692{693static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, size_t i,694const TravRayKRobust<K>& ray, const vfloat<K>& time, vfloat<K>& dist, vbool<K>& vmask)695{696vmask = intersectNodeKRobust<N,K>(node.getAABBNodeMB(), i, ray, time, dist);697return true;698}699};700701template<int N, int K>702struct BVHNNodeIntersectorK<N, K, BVH_AN1_UN1, false>703{704static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, size_t i,705const TravRayKFast<K>& ray, const vfloat<K>& time, vfloat<K>& dist, vbool<K>& vmask)706{707if (likely(node.isAABBNode())) vmask = intersectNodeK<N,K>(node.getAABBNode(), i, ray, dist);708else /*if (unlikely(node.isOBBNode()))*/ vmask = intersectNodeK<N,K>(node.ungetAABBNode(), i, ray, dist);709return true;710}711};712713template<int N, int K>714struct BVHNNodeIntersectorK<N, K, BVH_AN1_UN1, true>715{716static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, size_t i,717const TravRayKRobust<K>& ray, const vfloat<K>& time, vfloat<K>& dist, vbool<K>& vmask)718{719if (likely(node.isAABBNode())) vmask = intersectNodeKRobust<N,K>(node.getAABBNode(), i, ray, dist);720else /*if (unlikely(node.isOBBNode()))*/ vmask = intersectNodeK<N,K>(node.ungetAABBNode(), i, ray, dist);721return true;722}723};724725template<int N, int K>726struct BVHNNodeIntersectorK<N, K, BVH_AN2_UN2, false>727{728static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, size_t i,729const TravRayKFast<K>& ray, const vfloat<K>& time, vfloat<K>& dist, vbool<K>& vmask)730{731if (likely(node.isAABBNodeMB())) vmask = intersectNodeK<N,K>(node.getAABBNodeMB(), i, ray, time, dist);732else /*if (unlikely(node.isOBBNodeMB()))*/ vmask = intersectNodeK<N,K>(node.ungetAABBNodeMB(), i, ray, time, dist);733return true;734}735};736737template<int N, int K>738struct BVHNNodeIntersectorK<N, K, BVH_AN2_UN2, true>739{740static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, size_t i,741const TravRayKRobust<K>& ray, const vfloat<K>& time, vfloat<K>& dist, vbool<K>& vmask)742{743if (likely(node.isAABBNodeMB())) vmask = intersectNodeKRobust<N,K>(node.getAABBNodeMB(), i, ray, time, dist);744else /*if (unlikely(node.isOBBNodeMB()))*/ vmask = intersectNodeK<N,K>(node.ungetAABBNodeMB(), i, ray, time, dist);745return true;746}747};748749template<int N, int K>750struct BVHNNodeIntersectorK<N, K, BVH_AN2_AN4D, false>751{752static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, size_t i,753const TravRayKFast<K>& ray, const vfloat<K>& time, vfloat<K>& dist, vbool<K>& vmask)754{755vmask &= intersectNodeKMB4D<N,K>(node, i, ray, time, dist);756return true;757}758};759760template<int N, int K>761struct BVHNNodeIntersectorK<N, K, BVH_AN2_AN4D, true>762{763static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, size_t i,764const TravRayKRobust<K>& ray, const vfloat<K>& time, vfloat<K>& dist, vbool<K>& vmask)765{766vmask &= intersectNodeKMB4DRobust<N,K>(node, i, ray, time, dist);767return true;768}769};770771template<int N, int K>772struct BVHNNodeIntersectorK<N, K, BVH_AN2_AN4D_UN2, false>773{774static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, size_t i,775const TravRayKFast<K>& ray, const vfloat<K>& time, vfloat<K>& dist, vbool<K>& vmask)776{777if (likely(node.isAABBNodeMB() || node.isAABBNodeMB4D())) {778vmask &= intersectNodeKMB4D<N,K>(node, i, ray, time, dist);779} else /*if (unlikely(node.isOBBNodeMB()))*/ {780assert(node.isOBBNodeMB());781vmask &= intersectNodeK<N,K>(node.ungetAABBNodeMB(), i, ray, time, dist);782}783return true;784}785};786787template<int N, int K>788struct BVHNNodeIntersectorK<N, K, BVH_AN2_AN4D_UN2, true>789{790static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, size_t i,791const TravRayKRobust<K>& ray, const vfloat<K>& time, vfloat<K>& dist, vbool<K>& vmask)792{793if (likely(node.isAABBNodeMB() || node.isAABBNodeMB4D())) {794vmask &= intersectNodeKMB4DRobust<N,K>(node, i, ray, time, dist);795} else /*if (unlikely(node.isOBBNodeMB()))*/ {796assert(node.isOBBNodeMB());797vmask &= intersectNodeK<N,K>(node.ungetAABBNodeMB(), i, ray, time, dist);798}799return true;800}801};802803804/*! Intersects N nodes with K rays */805template<int N, int K, bool robust>806struct BVHNQuantizedBaseNodeIntersectorK;807808template<int N, int K>809struct BVHNQuantizedBaseNodeIntersectorK<N, K, false>810{811static __forceinline vbool<K> intersectK(const typename BVHN<N>::QuantizedBaseNode* node, const size_t i,812const TravRayK<K,false>& ray, vfloat<K>& dist)813{814return intersectQuantizedNodeK<N,K>(node,i,ray,dist);815}816817static __forceinline vbool<K> intersectK(const typename BVHN<N>::QuantizedBaseNodeMB* node, const size_t i,818const TravRayK<K,false>& ray, const vfloat<K>& time, vfloat<K>& dist)819{820return intersectQuantizedNodeMBK<N,K>(node,i,ray,time,dist);821}822823};824825template<int N, int K>826struct BVHNQuantizedBaseNodeIntersectorK<N, K, true>827{828static __forceinline vbool<K> intersectK(const typename BVHN<N>::QuantizedBaseNode* node, const size_t i,829const TravRayK<K,true>& ray, vfloat<K>& dist)830{831return intersectQuantizedNodeK<N,K>(node,i,ray,dist);832}833834static __forceinline vbool<K> intersectK(const typename BVHN<N>::QuantizedBaseNodeMB* node, const size_t i,835const TravRayK<K,true>& ray, const vfloat<K>& time, vfloat<K>& dist)836{837return intersectQuantizedNodeMBK<N,K>(node,i,ray,time,dist);838}839};840841842}843}844845846