mirror of
				https://github.com/godotengine/godot.git
				synced 2025-10-31 05:31:01 +00:00 
			
		
		
		
	 767e374dce
			
		
	
	
		767e374dce
		
	
	
	
	
		
			
			Since Embree v3.13.0 supports AARCH64, switch back to the official repo instead of using Embree-aarch64. `thirdparty/embree/patches/godot-changes.patch` should now contain an accurate diff of the changes done to the library.
		
			
				
	
	
		
			979 lines
		
	
	
	
		
			32 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			979 lines
		
	
	
	
		
			32 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // Copyright 2009-2021 Intel Corporation
 | |
| // SPDX-License-Identifier: Apache-2.0
 | |
| 
 | |
| #pragma once
 | |
| 
 | |
| #include "../common/ray.h"
 | |
| #include "../common/context.h"
 | |
| #include "filter.h"
 | |
| 
 | |
| namespace embree
 | |
| {
 | |
|   namespace isa
 | |
|   {
 | |
|     template<int M>
 | |
|     struct UVIdentity {
 | |
|       __forceinline void operator() (vfloat<M>& u, vfloat<M>& v, Vec3vf<M>& Ng) const {}
 | |
|     };
 | |
| 
 | |
| 
 | |
|     template<bool filter>
 | |
|     struct Intersect1Epilog1
 | |
|     {
 | |
|       RayHit& ray;
 | |
|       IntersectContext* context;
 | |
|       const unsigned int geomID;
 | |
|       const unsigned int primID;
 | |
| 
 | |
|       __forceinline Intersect1Epilog1(RayHit& ray,
 | |
|                                       IntersectContext* context,
 | |
|                                       const unsigned int geomID,
 | |
|                                       const unsigned int primID)
 | |
|         : ray(ray), context(context), geomID(geomID), primID(primID) {}
 | |
| 
 | |
|       template<typename Hit>
 | |
|       __forceinline bool operator() (Hit& hit) const
 | |
|       {
 | |
|         /* ray mask test */
 | |
|         Scene* scene MAYBE_UNUSED = context->scene;
 | |
|         Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
 | |
| #if defined(EMBREE_RAY_MASK)
 | |
|         if ((geometry->mask & ray.mask) == 0) return false;
 | |
| #endif
 | |
|         hit.finalize();
 | |
| 
 | |
|         /* intersection filter test */
 | |
| #if defined(EMBREE_FILTER_FUNCTION)
 | |
|         if (filter) {
 | |
|           if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter())) {
 | |
|             HitK<1> h(context->user,geomID,primID,hit.u,hit.v,hit.Ng);
 | |
|             const float old_t = ray.tfar;
 | |
|             ray.tfar = hit.t;
 | |
|             bool found = runIntersectionFilter1(geometry,ray,context,h);
 | |
|             if (!found) ray.tfar = old_t;
 | |
|             return found;
 | |
|           }
 | |
|         }
 | |
| #endif
 | |
| 
 | |
|         /* update hit information */
 | |
|         ray.tfar = hit.t;
 | |
|         ray.Ng = hit.Ng;
 | |
|         ray.u = hit.u;
 | |
|         ray.v = hit.v;
 | |
|         ray.primID = primID;
 | |
|         ray.geomID = geomID;
 | |
|         instance_id_stack::copy_UU(context->user->instID, ray.instID);
 | |
|         return true;
 | |
|       }
 | |
|     };
 | |
| 
 | |
|     template<bool filter>
 | |
|     struct Occluded1Epilog1
 | |
|     {
 | |
|       Ray& ray;
 | |
|       IntersectContext* context;
 | |
|       const unsigned int geomID;
 | |
|       const unsigned int primID;
 | |
| 
 | |
|       __forceinline Occluded1Epilog1(Ray& ray,
 | |
|                                      IntersectContext* context,
 | |
|                                      const unsigned int geomID,
 | |
|                                      const unsigned int primID)
 | |
|         : ray(ray), context(context), geomID(geomID), primID(primID) {}
 | |
| 
 | |
|       template<typename Hit>
 | |
|       __forceinline bool operator() (Hit& hit) const
 | |
|       {
 | |
|         /* ray mask test */
 | |
|         Scene* scene MAYBE_UNUSED = context->scene;
 | |
|         Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
 | |
| 
 | |
| 
 | |
| #if defined(EMBREE_RAY_MASK)
 | |
|         if ((geometry->mask & ray.mask) == 0) return false;
 | |
| #endif
 | |
|         hit.finalize();
 | |
| 
 | |
|         /* intersection filter test */
 | |
| #if defined(EMBREE_FILTER_FUNCTION)
 | |
|         if (filter) {
 | |
|           if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter())) {
 | |
|             HitK<1> h(context->user,geomID,primID,hit.u,hit.v,hit.Ng);
 | |
|             const float old_t = ray.tfar;
 | |
|             ray.tfar = hit.t;
 | |
|             const bool found = runOcclusionFilter1(geometry,ray,context,h);
 | |
|             if (!found) ray.tfar = old_t;
 | |
|             return found;
 | |
|           }
 | |
|         }
 | |
| #endif
 | |
|         return true;
 | |
|       }
 | |
|     };
 | |
| 
 | |
|     template<int K, bool filter>
 | |
|     struct Intersect1KEpilog1
 | |
|     {
 | |
|       RayHitK<K>& ray;
 | |
|       size_t k;
 | |
|       IntersectContext* context;
 | |
|       const unsigned int geomID;
 | |
|       const unsigned int primID;
 | |
| 
 | |
|       __forceinline Intersect1KEpilog1(RayHitK<K>& ray, size_t k,
 | |
|                                        IntersectContext* context,
 | |
|                                        const unsigned int geomID,
 | |
|                                        const unsigned int primID)
 | |
|         : ray(ray), k(k), context(context), geomID(geomID), primID(primID) {}
 | |
| 
 | |
|       template<typename Hit>
 | |
|       __forceinline bool operator() (Hit& hit) const
 | |
|       {
 | |
|         /* ray mask test */
 | |
|         Scene* scene MAYBE_UNUSED = context->scene;
 | |
|         Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
 | |
| #if defined(EMBREE_RAY_MASK)
 | |
|         if ((geometry->mask & ray.mask[k]) == 0)
 | |
|           return false;
 | |
| #endif
 | |
|         hit.finalize();
 | |
| 
 | |
|         /* intersection filter test */
 | |
| #if defined(EMBREE_FILTER_FUNCTION)
 | |
|         if (filter) {
 | |
|           if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter())) {
 | |
|             HitK<K> h(context->user,geomID,primID,hit.u,hit.v,hit.Ng);
 | |
|             const float old_t = ray.tfar[k];
 | |
|             ray.tfar[k] = hit.t;
 | |
|             const bool found = any(runIntersectionFilter(vbool<K>(1<<k),geometry,ray,context,h));
 | |
|             if (!found) ray.tfar[k] = old_t;
 | |
|             return found;
 | |
|           }
 | |
|         }
 | |
| #endif
 | |
| 
 | |
|         /* update hit information */
 | |
|         ray.tfar[k] = hit.t;
 | |
|         ray.Ng.x[k] = hit.Ng.x;
 | |
|         ray.Ng.y[k] = hit.Ng.y;
 | |
|         ray.Ng.z[k] = hit.Ng.z;
 | |
|         ray.u[k] = hit.u;
 | |
|         ray.v[k] = hit.v;
 | |
|         ray.primID[k] = primID;
 | |
|         ray.geomID[k] = geomID;
 | |
|         instance_id_stack::copy_UV<K>(context->user->instID, ray.instID, k);
 | |
|         return true;
 | |
|       }
 | |
|     };
 | |
|     
 | |
|     template<int K, bool filter>
 | |
|     struct Occluded1KEpilog1
 | |
|     {
 | |
|       RayK<K>& ray;
 | |
|       size_t k;
 | |
|       IntersectContext* context;
 | |
|       const unsigned int geomID;
 | |
|       const unsigned int primID;
 | |
| 
 | |
|       __forceinline Occluded1KEpilog1(RayK<K>& ray, size_t k,
 | |
|                                       IntersectContext* context,
 | |
|                                       const unsigned int geomID,
 | |
|                                       const unsigned int primID)
 | |
|         : ray(ray), k(k), context(context), geomID(geomID), primID(primID) {}
 | |
| 
 | |
|       template<typename Hit>
 | |
|       __forceinline bool operator() (Hit& hit) const
 | |
|       {
 | |
|         /* ray mask test */
 | |
|         Scene* scene MAYBE_UNUSED = context->scene;
 | |
|         Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
 | |
| #if defined(EMBREE_RAY_MASK)
 | |
|         if ((geometry->mask & ray.mask[k]) == 0)
 | |
|           return false;
 | |
| #endif
 | |
| 
 | |
|         /* intersection filter test */
 | |
| #if defined(EMBREE_FILTER_FUNCTION)
 | |
|         if (filter) {
 | |
|           if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter())) {
 | |
|             hit.finalize();
 | |
|             HitK<K> h(context->user,geomID,primID,hit.u,hit.v,hit.Ng);
 | |
|             const float old_t = ray.tfar[k];
 | |
|             ray.tfar[k] = hit.t;
 | |
|             const bool found = any(runOcclusionFilter(vbool<K>(1<<k),geometry,ray,context,h));
 | |
|             if (!found) ray.tfar[k] = old_t;
 | |
|             return found;
 | |
|           }
 | |
|         }
 | |
| #endif 
 | |
|         return true;
 | |
|       }
 | |
|     };
 | |
|     
 | |
|     template<int M, bool filter>
 | |
|     struct Intersect1EpilogM
 | |
|     {
 | |
|       RayHit& ray;
 | |
|       IntersectContext* context;
 | |
|       const vuint<M>& geomIDs;
 | |
|       const vuint<M>& primIDs;
 | |
| 
 | |
|       __forceinline Intersect1EpilogM(RayHit& ray,
 | |
|                                       IntersectContext* context,
 | |
|                                       const vuint<M>& geomIDs,
 | |
|                                       const vuint<M>& primIDs)
 | |
|         : ray(ray), context(context), geomIDs(geomIDs), primIDs(primIDs) {}
 | |
| 
 | |
|       template<typename Hit>
 | |
|       __forceinline bool operator() (const vbool<M>& valid_i, Hit& hit) const
 | |
|       {
 | |
|         Scene* scene MAYBE_UNUSED = context->scene;
 | |
|         vbool<M> valid = valid_i;
 | |
|         hit.finalize();
 | |
|         size_t i = select_min(valid,hit.vt);
 | |
|         unsigned int geomID = geomIDs[i];
 | |
| 
 | |
|         /* intersection filter test */
 | |
| #if defined(EMBREE_FILTER_FUNCTION) || defined(EMBREE_RAY_MASK)
 | |
|         bool foundhit = false;
 | |
|         goto entry;
 | |
|         while (true)
 | |
|         {
 | |
|           if (unlikely(none(valid))) return foundhit;
 | |
|           i = select_min(valid,hit.vt);
 | |
| 
 | |
|           geomID = geomIDs[i];
 | |
|         entry:
 | |
|           Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
 | |
| 
 | |
| #if defined(EMBREE_RAY_MASK)
 | |
|           /* goto next hit if mask test fails */
 | |
|           if ((geometry->mask & ray.mask) == 0) {
 | |
|             clear(valid,i);
 | |
|             continue;
 | |
|           }
 | |
| #endif
 | |
| 
 | |
| #if defined(EMBREE_FILTER_FUNCTION) 
 | |
|           /* call intersection filter function */
 | |
|           if (filter) {
 | |
|             if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter())) {
 | |
|               const Vec2f uv = hit.uv(i);
 | |
|               HitK<1> h(context->user,geomID,primIDs[i],uv.x,uv.y,hit.Ng(i));
 | |
|               const float old_t = ray.tfar;
 | |
|               ray.tfar = hit.t(i);
 | |
|               const bool found = runIntersectionFilter1(geometry,ray,context,h);
 | |
|               if (!found) ray.tfar = old_t;
 | |
|               foundhit |= found;
 | |
|               clear(valid,i);
 | |
|               valid &= hit.vt <= ray.tfar; // intersection filters may modify tfar value
 | |
|               continue;
 | |
|             }
 | |
|           }
 | |
| #endif
 | |
|           break;
 | |
|         }
 | |
| #endif
 | |
| 
 | |
|         /* update hit information */
 | |
|         const Vec2f uv = hit.uv(i);
 | |
|         ray.tfar = hit.vt[i];
 | |
|         ray.Ng.x = hit.vNg.x[i];
 | |
|         ray.Ng.y = hit.vNg.y[i];
 | |
|         ray.Ng.z = hit.vNg.z[i];
 | |
|         ray.u = uv.x;
 | |
|         ray.v = uv.y;
 | |
|         ray.primID = primIDs[i];
 | |
|         ray.geomID = geomID;
 | |
|         instance_id_stack::copy_UU(context->user->instID, ray.instID);
 | |
|         return true;
 | |
| 
 | |
|       }
 | |
|     };
 | |
| 
 | |
|     template<int M, bool filter>
 | |
|     struct Occluded1EpilogM
 | |
|     {
 | |
|       Ray& ray;
 | |
|       IntersectContext* context;
 | |
|       const vuint<M>& geomIDs;
 | |
|       const vuint<M>& primIDs;
 | |
| 
 | |
|       __forceinline Occluded1EpilogM(Ray& ray,
 | |
|                                      IntersectContext* context,
 | |
|                                      const vuint<M>& geomIDs,
 | |
|                                      const vuint<M>& primIDs)
 | |
|         : ray(ray), context(context), geomIDs(geomIDs), primIDs(primIDs) {}
 | |
| 
 | |
|       template<typename Hit>
 | |
|       __forceinline bool operator() (const vbool<M>& valid_i, Hit& hit) const
 | |
|       {
 | |
|         Scene* scene MAYBE_UNUSED = context->scene;
 | |
|         /* intersection filter test */
 | |
| #if defined(EMBREE_FILTER_FUNCTION) || defined(EMBREE_RAY_MASK)
 | |
|         if (unlikely(filter))
 | |
|           hit.finalize(); /* called only once */
 | |
| 
 | |
|         vbool<M> valid = valid_i;
 | |
|         size_t m=movemask(valid);
 | |
|         goto entry;
 | |
|         while (true)
 | |
|         {
 | |
|           if (unlikely(m == 0)) return false;
 | |
|         entry:
 | |
|           size_t i=bsf(m);
 | |
| 
 | |
|           const unsigned int geomID = geomIDs[i];
 | |
|           Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
 | |
| 
 | |
| #if defined(EMBREE_RAY_MASK)
 | |
|           /* goto next hit if mask test fails */
 | |
|           if ((geometry->mask & ray.mask) == 0) {
 | |
|             m=btc(m,i);
 | |
|             continue;
 | |
|           }
 | |
| #endif
 | |
| 
 | |
| #if defined(EMBREE_FILTER_FUNCTION)
 | |
|           /* if we have no filter then the test passed */
 | |
|           if (filter) {
 | |
|             if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter()))
 | |
|             {
 | |
|               const Vec2f uv = hit.uv(i);
 | |
|               HitK<1> h(context->user,geomID,primIDs[i],uv.x,uv.y,hit.Ng(i));
 | |
|               const float old_t = ray.tfar;
 | |
|               ray.tfar = hit.t(i);
 | |
|               if (runOcclusionFilter1(geometry,ray,context,h)) return true;
 | |
|               ray.tfar = old_t;
 | |
|               m=btc(m,i);
 | |
|               continue;
 | |
|             }
 | |
|           }
 | |
| #endif
 | |
|           break;
 | |
|         }
 | |
| #endif
 | |
| 
 | |
|         return true;
 | |
|       }
 | |
|     };
 | |
| 
 | |
|     template<int M, bool filter>
 | |
|     struct Intersect1EpilogMU
 | |
|     {
 | |
|       RayHit& ray;
 | |
|       IntersectContext* context;
 | |
|       const unsigned int geomID;
 | |
|       const unsigned int primID;
 | |
| 
 | |
|       __forceinline Intersect1EpilogMU(RayHit& ray,
 | |
|                                        IntersectContext* context,
 | |
|                                        const unsigned int geomID,
 | |
|                                        const unsigned int primID)
 | |
|         : ray(ray), context(context), geomID(geomID), primID(primID) {}
 | |
| 
 | |
|       template<typename Hit>
 | |
|       __forceinline bool operator() (const vbool<M>& valid_i, Hit& hit) const
 | |
|       {
 | |
|         /* ray mask test */
 | |
|         Scene* scene MAYBE_UNUSED = context->scene;
 | |
|         Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
 | |
| #if defined(EMBREE_RAY_MASK)
 | |
|         if ((geometry->mask & ray.mask) == 0) return false;
 | |
| #endif
 | |
| 
 | |
|         vbool<M> valid = valid_i;
 | |
|         hit.finalize();
 | |
| 
 | |
|         size_t i = select_min(valid,hit.vt);
 | |
| 
 | |
|         /* intersection filter test */
 | |
| #if defined(EMBREE_FILTER_FUNCTION)
 | |
|         if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter()))
 | |
|         {
 | |
|           bool foundhit = false;
 | |
|           while (true)
 | |
|           {
 | |
|             /* call intersection filter function */
 | |
|             Vec2f uv = hit.uv(i);
 | |
|             const float old_t = ray.tfar;
 | |
|             ray.tfar = hit.t(i);
 | |
|             HitK<1> h(context->user,geomID,primID,uv.x,uv.y,hit.Ng(i));
 | |
|             const bool found = runIntersectionFilter1(geometry,ray,context,h);
 | |
|             if (!found) ray.tfar = old_t;
 | |
|             foundhit |= found;
 | |
|             clear(valid,i);
 | |
|             valid &= hit.vt <= ray.tfar; // intersection filters may modify tfar value
 | |
|             if (unlikely(none(valid))) break;
 | |
|             i = select_min(valid,hit.vt);
 | |
|           }
 | |
|           return foundhit;
 | |
|         }
 | |
| #endif
 | |
| 
 | |
|         /* update hit information */
 | |
|         const Vec2f uv = hit.uv(i);
 | |
|         const Vec3fa Ng = hit.Ng(i);
 | |
|         ray.tfar = hit.t(i);
 | |
|         ray.Ng.x = Ng.x;
 | |
|         ray.Ng.y = Ng.y;
 | |
|         ray.Ng.z = Ng.z;
 | |
|         ray.u = uv.x;
 | |
|         ray.v = uv.y;
 | |
|         ray.primID = primID;
 | |
|         ray.geomID = geomID;
 | |
|         instance_id_stack::copy_UU(context->user->instID, ray.instID);
 | |
|         return true;
 | |
|       }
 | |
|     };
 | |
|     
 | |
|     template<int M, bool filter>
 | |
|     struct Occluded1EpilogMU
 | |
|     {
 | |
|       Ray& ray;
 | |
|       IntersectContext* context;
 | |
|       const unsigned int geomID;
 | |
|       const unsigned int primID;
 | |
| 
 | |
|       __forceinline Occluded1EpilogMU(Ray& ray,
 | |
|                                       IntersectContext* context,
 | |
|                                       const unsigned int geomID,
 | |
|                                       const unsigned int primID)
 | |
|         : ray(ray), context(context), geomID(geomID), primID(primID) {}
 | |
| 
 | |
|       template<typename Hit>
 | |
|       __forceinline bool operator() (const vbool<M>& valid, Hit& hit) const
 | |
|       {
 | |
|         /* ray mask test */
 | |
|         Scene* scene MAYBE_UNUSED = context->scene;
 | |
|         Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
 | |
| #if defined(EMBREE_RAY_MASK)
 | |
|         if ((geometry->mask & ray.mask) == 0) return false;
 | |
| #endif
 | |
| 
 | |
|         /* intersection filter test */
 | |
| #if defined(EMBREE_FILTER_FUNCTION)
 | |
|         if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter()))
 | |
|         {
 | |
|           hit.finalize();
 | |
|           for (size_t m=movemask(valid), i=bsf(m); m!=0; m=btc(m,i), i=bsf(m))
 | |
|           {
 | |
|             const Vec2f uv = hit.uv(i);
 | |
|             const float old_t = ray.tfar;
 | |
|             ray.tfar = hit.t(i);
 | |
|             HitK<1> h(context->user,geomID,primID,uv.x,uv.y,hit.Ng(i));
 | |
|             if (runOcclusionFilter1(geometry,ray,context,h)) return true;
 | |
|             ray.tfar = old_t;
 | |
|           }
 | |
|           return false;
 | |
|         }
 | |
| #endif
 | |
|         return true;
 | |
|       }
 | |
|     };
 | |
|         
 | |
|     template<int M, int K, bool filter>
 | |
|     struct IntersectKEpilogM
 | |
|     {
 | |
|       RayHitK<K>& ray;
 | |
|       IntersectContext* context;
 | |
|       const vuint<M>& geomIDs;
 | |
|       const vuint<M>& primIDs;
 | |
|       const size_t i;
 | |
| 
 | |
|       __forceinline IntersectKEpilogM(RayHitK<K>& ray,
 | |
|                                       IntersectContext* context,
 | |
|                                      const vuint<M>& geomIDs,
 | |
|                                      const vuint<M>& primIDs,
 | |
|                                      size_t i)
 | |
|         : ray(ray), context(context), geomIDs(geomIDs), primIDs(primIDs), i(i) {}
 | |
| 
 | |
|       template<typename Hit>
 | |
|       __forceinline vbool<K> operator() (const vbool<K>& valid_i, const Hit& hit) const
 | |
|       {
 | |
|         Scene* scene MAYBE_UNUSED = context->scene;
 | |
| 
 | |
|         vfloat<K> u, v, t;
 | |
|         Vec3vf<K> Ng;
 | |
|         vbool<K> valid = valid_i;
 | |
| 
 | |
|         std::tie(u,v,t,Ng) = hit();
 | |
| 
 | |
|         const unsigned int geomID = geomIDs[i];
 | |
|         const unsigned int primID = primIDs[i];
 | |
|         Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
 | |
| 
 | |
|         /* ray masking test */
 | |
| #if defined(EMBREE_RAY_MASK)
 | |
|         valid &= (geometry->mask & ray.mask) != 0;
 | |
|         if (unlikely(none(valid))) return false;
 | |
| #endif
 | |
| 
 | |
|         /* occlusion filter test */
 | |
| #if defined(EMBREE_FILTER_FUNCTION)
 | |
|         if (filter) {
 | |
|           if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter())) {
 | |
|             HitK<K> h(context->user,geomID,primID,u,v,Ng);
 | |
|             const vfloat<K> old_t = ray.tfar;
 | |
|             ray.tfar = select(valid,t,ray.tfar);
 | |
|             const vbool<K> m_accept = runIntersectionFilter(valid,geometry,ray,context,h);
 | |
|             ray.tfar = select(m_accept,ray.tfar,old_t);
 | |
|             return m_accept;
 | |
|           }
 | |
|         }
 | |
| #endif
 | |
| 
 | |
|         /* update hit information */
 | |
|         vfloat<K>::store(valid,&ray.tfar,t);
 | |
|         vfloat<K>::store(valid,&ray.Ng.x,Ng.x);
 | |
|         vfloat<K>::store(valid,&ray.Ng.y,Ng.y);
 | |
|         vfloat<K>::store(valid,&ray.Ng.z,Ng.z);
 | |
|         vfloat<K>::store(valid,&ray.u,u);
 | |
|         vfloat<K>::store(valid,&ray.v,v);
 | |
|         vuint<K>::store(valid,&ray.primID,primID);
 | |
|         vuint<K>::store(valid,&ray.geomID,geomID);
 | |
|         instance_id_stack::copy_UV<K>(context->user->instID, ray.instID, valid);
 | |
|         return valid;
 | |
|       }
 | |
|     };
 | |
|     
 | |
|     template<int M, int K, bool filter>
 | |
|     struct OccludedKEpilogM
 | |
|     {
 | |
|       vbool<K>& valid0;
 | |
|       RayK<K>& ray;
 | |
|       IntersectContext* context;
 | |
|       const vuint<M>& geomIDs;
 | |
|       const vuint<M>& primIDs;
 | |
|       const size_t i;
 | |
| 
 | |
|       __forceinline OccludedKEpilogM(vbool<K>& valid0,
 | |
|                                      RayK<K>& ray,
 | |
|                                      IntersectContext* context,
 | |
|                                      const vuint<M>& geomIDs,
 | |
|                                      const vuint<M>& primIDs,
 | |
|                                      size_t i)
 | |
|         : valid0(valid0), ray(ray), context(context), geomIDs(geomIDs), primIDs(primIDs), i(i) {}
 | |
| 
 | |
|       template<typename Hit>
 | |
|       __forceinline vbool<K> operator() (const vbool<K>& valid_i, const Hit& hit) const
 | |
|       {
 | |
|         vbool<K> valid = valid_i;
 | |
| 
 | |
|         /* ray masking test */
 | |
|         Scene* scene MAYBE_UNUSED = context->scene;
 | |
|         const unsigned int geomID MAYBE_UNUSED = geomIDs[i];
 | |
|         const unsigned int primID MAYBE_UNUSED = primIDs[i];
 | |
|         Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
 | |
| #if defined(EMBREE_RAY_MASK)
 | |
|         valid &= (geometry->mask & ray.mask) != 0;
 | |
|         if (unlikely(none(valid))) return valid;
 | |
| #endif
 | |
| 
 | |
|         /* intersection filter test */
 | |
| #if defined(EMBREE_FILTER_FUNCTION)
 | |
|         if (filter) {
 | |
|           if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter()))
 | |
|           {
 | |
|             vfloat<K> u, v, t;
 | |
|             Vec3vf<K> Ng;
 | |
|             std::tie(u,v,t,Ng) = hit();
 | |
|             HitK<K> h(context->user,geomID,primID,u,v,Ng);
 | |
|             const vfloat<K> old_t = ray.tfar;
 | |
|             ray.tfar = select(valid,t,ray.tfar);
 | |
|             valid = runOcclusionFilter(valid,geometry,ray,context,h);
 | |
|             ray.tfar = select(valid,ray.tfar,old_t);
 | |
|           }
 | |
|         }
 | |
| #endif
 | |
| 
 | |
|         /* update occlusion */
 | |
|         valid0 = valid0 & !valid;
 | |
|         return valid;
 | |
|       }
 | |
|     };
 | |
|     
 | |
|     template<int M, int K, bool filter>
 | |
|     struct IntersectKEpilogMU
 | |
|     {
 | |
|       RayHitK<K>& ray;
 | |
|       IntersectContext* context;
 | |
|       const unsigned int geomID;
 | |
|       const unsigned int primID;
 | |
| 
 | |
|       __forceinline IntersectKEpilogMU(RayHitK<K>& ray,
 | |
|                                        IntersectContext* context,
 | |
|                                        const unsigned int geomID,
 | |
|                                        const unsigned int primID)
 | |
|         : ray(ray), context(context), geomID(geomID), primID(primID) {}
 | |
| 
 | |
|       template<typename Hit>
 | |
|       __forceinline vbool<K> operator() (const vbool<K>& valid_org, const Hit& hit) const
 | |
|       {
 | |
|         vbool<K> valid = valid_org;
 | |
|         vfloat<K> u, v, t;
 | |
|         Vec3vf<K> Ng;
 | |
|         std::tie(u,v,t,Ng) = hit();
 | |
| 
 | |
|         Scene* scene MAYBE_UNUSED = context->scene;
 | |
|         Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
 | |
| 
 | |
|         /* ray masking test */
 | |
| #if defined(EMBREE_RAY_MASK)
 | |
|         valid &= (geometry->mask & ray.mask) != 0;
 | |
|         if (unlikely(none(valid))) return false;
 | |
| #endif
 | |
| 
 | |
|         /* intersection filter test */
 | |
| #if defined(EMBREE_FILTER_FUNCTION)
 | |
|         if (filter) {
 | |
|           if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter())) {
 | |
|             HitK<K> h(context->user,geomID,primID,u,v,Ng);
 | |
|             const vfloat<K> old_t = ray.tfar;
 | |
|             ray.tfar = select(valid,t,ray.tfar);
 | |
|             const vbool<K> m_accept = runIntersectionFilter(valid,geometry,ray,context,h);
 | |
|             ray.tfar = select(m_accept,ray.tfar,old_t);
 | |
|             return m_accept;
 | |
|           }
 | |
|         }
 | |
| #endif
 | |
| 
 | |
|         /* update hit information */
 | |
|         vfloat<K>::store(valid,&ray.tfar,t);
 | |
|         vfloat<K>::store(valid,&ray.Ng.x,Ng.x);
 | |
|         vfloat<K>::store(valid,&ray.Ng.y,Ng.y);
 | |
|         vfloat<K>::store(valid,&ray.Ng.z,Ng.z);
 | |
|         vfloat<K>::store(valid,&ray.u,u);
 | |
|         vfloat<K>::store(valid,&ray.v,v);
 | |
|         vuint<K>::store(valid,&ray.primID,primID);
 | |
|         vuint<K>::store(valid,&ray.geomID,geomID);
 | |
|         instance_id_stack::copy_UV<K>(context->user->instID, ray.instID, valid);
 | |
|         return valid;
 | |
|       }
 | |
|     };
 | |
|     
 | |
|     template<int M, int K, bool filter>
 | |
|     struct OccludedKEpilogMU
 | |
|     {
 | |
|       vbool<K>& valid0;
 | |
|       RayK<K>& ray;
 | |
|       IntersectContext* context;
 | |
|       const unsigned int geomID;
 | |
|       const unsigned int primID;
 | |
| 
 | |
|       __forceinline OccludedKEpilogMU(vbool<K>& valid0,
 | |
|                                       RayK<K>& ray,
 | |
|                                       IntersectContext* context,
 | |
|                                       const unsigned int geomID,
 | |
|                                       const unsigned int primID)
 | |
|         : valid0(valid0), ray(ray), context(context), geomID(geomID), primID(primID) {}
 | |
| 
 | |
|       template<typename Hit>
 | |
|       __forceinline vbool<K> operator() (const vbool<K>& valid_i, const Hit& hit) const
 | |
|       {
 | |
|         vbool<K> valid = valid_i;
 | |
|         Scene* scene MAYBE_UNUSED = context->scene;
 | |
|         Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
 | |
| 
 | |
| #if defined(EMBREE_RAY_MASK)
 | |
|         valid &= (geometry->mask & ray.mask) != 0;
 | |
|         if (unlikely(none(valid))) return false;
 | |
| #endif
 | |
| 
 | |
|         /* occlusion filter test */
 | |
| #if defined(EMBREE_FILTER_FUNCTION)
 | |
|         if (filter) {
 | |
|           if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter()))
 | |
|           {
 | |
|             vfloat<K> u, v, t;
 | |
|             Vec3vf<K> Ng;
 | |
|             std::tie(u,v,t,Ng) = hit();
 | |
|             HitK<K> h(context->user,geomID,primID,u,v,Ng);
 | |
|             const vfloat<K> old_t = ray.tfar;
 | |
|             ray.tfar = select(valid,t,ray.tfar);
 | |
|             valid = runOcclusionFilter(valid,geometry,ray,context,h);
 | |
|             ray.tfar = select(valid,ray.tfar,old_t);
 | |
|           }
 | |
|         }
 | |
| #endif
 | |
| 
 | |
|         /* update occlusion */
 | |
|         valid0 = valid0 & !valid;
 | |
|         return valid;
 | |
|       }
 | |
|     };
 | |
|     
 | |
|     template<int M, int K, bool filter>
 | |
|     struct Intersect1KEpilogM
 | |
|     {
 | |
|       RayHitK<K>& ray;
 | |
|       size_t k;
 | |
|       IntersectContext* context;
 | |
|       const vuint<M>& geomIDs;
 | |
|       const vuint<M>& primIDs;
 | |
| 
 | |
|       __forceinline Intersect1KEpilogM(RayHitK<K>& ray, size_t k,
 | |
|                                        IntersectContext* context,
 | |
|                                        const vuint<M>& geomIDs,
 | |
|                                        const vuint<M>& primIDs)
 | |
|         : ray(ray), k(k), context(context), geomIDs(geomIDs), primIDs(primIDs) {}
 | |
| 
 | |
|       template<typename Hit>
 | |
|       __forceinline bool operator() (const vbool<M>& valid_i, Hit& hit) const
 | |
|       {
 | |
|         Scene* scene MAYBE_UNUSED = context->scene;
 | |
|         vbool<M> valid = valid_i;
 | |
|         hit.finalize();
 | |
|         size_t i = select_min(valid,hit.vt);
 | |
|         assert(i<M);
 | |
|         unsigned int geomID = geomIDs[i];
 | |
| 
 | |
|         /* intersection filter test */
 | |
| #if defined(EMBREE_FILTER_FUNCTION) || defined(EMBREE_RAY_MASK)
 | |
|         bool foundhit = false;
 | |
|         goto entry;
 | |
|         while (true)
 | |
|         {
 | |
|           if (unlikely(none(valid))) return foundhit;
 | |
|           i = select_min(valid,hit.vt);
 | |
|           assert(i<M);
 | |
|           geomID = geomIDs[i];
 | |
|         entry:
 | |
|           Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
 | |
| 
 | |
| #if defined(EMBREE_RAY_MASK)
 | |
|           /* goto next hit if mask test fails */
 | |
|           if ((geometry->mask & ray.mask[k]) == 0) {
 | |
|             clear(valid,i);
 | |
|             continue;
 | |
|           }
 | |
| #endif
 | |
| 
 | |
| #if defined(EMBREE_FILTER_FUNCTION) 
 | |
|           /* call intersection filter function */
 | |
|           if (filter) {
 | |
|             if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter())) {
 | |
|               assert(i<M);
 | |
|               const Vec2f uv = hit.uv(i);
 | |
|               HitK<K> h(context->user,geomID,primIDs[i],uv.x,uv.y,hit.Ng(i));
 | |
|               const float old_t = ray.tfar[k];
 | |
|               ray.tfar[k] = hit.t(i);
 | |
|               const bool found = any(runIntersectionFilter(vbool<K>(1<<k),geometry,ray,context,h));
 | |
|               if (!found) ray.tfar[k] = old_t;
 | |
|               foundhit = foundhit | found;
 | |
|               clear(valid,i);
 | |
|               valid &= hit.vt <= ray.tfar[k]; // intersection filters may modify tfar value
 | |
|               continue;
 | |
|             }
 | |
|           }
 | |
| #endif
 | |
|           break;
 | |
|         }
 | |
| #endif
 | |
|         assert(i<M);
 | |
|         /* update hit information */
 | |
|         const Vec2f uv = hit.uv(i);
 | |
|         ray.tfar[k] = hit.t(i);
 | |
|         ray.Ng.x[k] = hit.vNg.x[i];
 | |
|         ray.Ng.y[k] = hit.vNg.y[i];
 | |
|         ray.Ng.z[k] = hit.vNg.z[i];
 | |
|         ray.u[k] = uv.x;
 | |
|         ray.v[k] = uv.y;
 | |
|         ray.primID[k] = primIDs[i];
 | |
|         ray.geomID[k] = geomID;
 | |
|         instance_id_stack::copy_UV<K>(context->user->instID, ray.instID, k);
 | |
|         return true;
 | |
|       }
 | |
|     };
 | |
|     
 | |
|     template<int M, int K, bool filter>
 | |
|     struct Occluded1KEpilogM
 | |
|     {
 | |
|       RayK<K>& ray;
 | |
|       size_t k;
 | |
|       IntersectContext* context;
 | |
|       const vuint<M>& geomIDs;
 | |
|       const vuint<M>& primIDs;
 | |
| 
 | |
|       __forceinline Occluded1KEpilogM(RayK<K>& ray, size_t k,
 | |
|                                       IntersectContext* context,
 | |
|                                       const vuint<M>& geomIDs,
 | |
|                                       const vuint<M>& primIDs)
 | |
|         : ray(ray), k(k), context(context), geomIDs(geomIDs), primIDs(primIDs) {}
 | |
| 
 | |
|       template<typename Hit>
 | |
|       __forceinline bool operator() (const vbool<M>& valid_i, Hit& hit) const
 | |
|       {
 | |
|         Scene* scene MAYBE_UNUSED = context->scene;
 | |
| 
 | |
|         /* intersection filter test */
 | |
| #if defined(EMBREE_FILTER_FUNCTION) || defined(EMBREE_RAY_MASK)
 | |
|         if (unlikely(filter))
 | |
|           hit.finalize(); /* called only once */
 | |
| 
 | |
|         vbool<M> valid = valid_i;
 | |
|         size_t m=movemask(valid);
 | |
|         goto entry;
 | |
|         while (true)
 | |
|         {
 | |
|           if (unlikely(m == 0)) return false;
 | |
|         entry:
 | |
|           size_t i=bsf(m);
 | |
| 
 | |
|           const unsigned int geomID = geomIDs[i];
 | |
|           Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
 | |
| 
 | |
| #if defined(EMBREE_RAY_MASK)
 | |
|           /* goto next hit if mask test fails */
 | |
|           if ((geometry->mask & ray.mask[k]) == 0) {
 | |
|             m=btc(m,i);
 | |
|             continue;
 | |
|           }
 | |
| #endif
 | |
| 
 | |
| #if defined(EMBREE_FILTER_FUNCTION)
 | |
|           /* execute occlusion filer */
 | |
|           if (filter) {
 | |
|             if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter()))
 | |
|             {
 | |
|               const Vec2f uv = hit.uv(i);
 | |
|               const float old_t = ray.tfar[k];
 | |
|               ray.tfar[k] = hit.t(i);
 | |
|               HitK<K> h(context->user,geomID,primIDs[i],uv.x,uv.y,hit.Ng(i));
 | |
|               if (any(runOcclusionFilter(vbool<K>(1<<k),geometry,ray,context,h))) return true;
 | |
|               ray.tfar[k] = old_t;
 | |
|               m=btc(m,i);
 | |
|               continue;
 | |
|             }
 | |
|           }
 | |
| #endif
 | |
|           break;
 | |
|         }
 | |
| #endif
 | |
|         return true;
 | |
|       }
 | |
|     };
 | |
|     
 | |
|     template<int M, int K, bool filter>
 | |
|     struct Intersect1KEpilogMU
 | |
|     {
 | |
|       RayHitK<K>& ray;
 | |
|       size_t k;
 | |
|       IntersectContext* context;
 | |
|       const unsigned int geomID;
 | |
|       const unsigned int primID;
 | |
| 
 | |
|       __forceinline Intersect1KEpilogMU(RayHitK<K>& ray, size_t k,
 | |
|                                         IntersectContext* context,
 | |
|                                         const unsigned int geomID,
 | |
|                                         const unsigned int primID)
 | |
|         : ray(ray), k(k), context(context), geomID(geomID), primID(primID) {}
 | |
| 
 | |
|       template<typename Hit>
 | |
|       __forceinline bool operator() (const vbool<M>& valid_i, Hit& hit) const
 | |
|       {
 | |
|         Scene* scene MAYBE_UNUSED = context->scene;
 | |
|         Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
 | |
| #if defined(EMBREE_RAY_MASK)
 | |
|         /* ray mask test */
 | |
|         if ((geometry->mask & ray.mask[k]) == 0)
 | |
|           return false;
 | |
| #endif
 | |
| 
 | |
|         /* finalize hit calculation */
 | |
|         vbool<M> valid = valid_i;
 | |
|         hit.finalize();
 | |
|         size_t i = select_min(valid,hit.vt);
 | |
| 
 | |
|         /* intersection filter test */
 | |
| #if defined(EMBREE_FILTER_FUNCTION)
 | |
|         if (filter) {
 | |
|           if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter()))
 | |
|           {
 | |
|             bool foundhit = false;
 | |
|             while (true)
 | |
|             {
 | |
|               const Vec2f uv = hit.uv(i);
 | |
|               const float old_t = ray.tfar[k];
 | |
|               ray.tfar[k] = hit.t(i);
 | |
|               HitK<K> h(context->user,geomID,primID,uv.x,uv.y,hit.Ng(i));
 | |
|               const bool found = any(runIntersectionFilter(vbool<K>(1<<k),geometry,ray,context,h));
 | |
|               if (!found) ray.tfar[k] = old_t;
 | |
|               foundhit = foundhit | found;
 | |
|               clear(valid,i);
 | |
|               valid &= hit.vt <= ray.tfar[k]; // intersection filters may modify tfar value
 | |
|               if (unlikely(none(valid))) break;
 | |
|               i = select_min(valid,hit.vt);
 | |
|             }
 | |
|             return foundhit;
 | |
|           }
 | |
|         }
 | |
| #endif
 | |
| 
 | |
|         /* update hit information */
 | |
|         const Vec2f uv = hit.uv(i);
 | |
|         const Vec3fa Ng = hit.Ng(i);
 | |
|         ray.tfar[k] = hit.t(i);
 | |
|         ray.Ng.x[k] = Ng.x;
 | |
|         ray.Ng.y[k] = Ng.y;
 | |
|         ray.Ng.z[k] = Ng.z;
 | |
|         ray.u[k] = uv.x;
 | |
|         ray.v[k] = uv.y;
 | |
|         ray.primID[k] = primID;
 | |
|         ray.geomID[k] = geomID;
 | |
|         instance_id_stack::copy_UV<K>(context->user->instID, ray.instID, k);
 | |
|         return true;
 | |
|       }
 | |
|     };
 | |
|     
 | |
|     template<int M, int K, bool filter>
 | |
|     struct Occluded1KEpilogMU
 | |
|     {
 | |
|       RayK<K>& ray;
 | |
|       size_t k;
 | |
|       IntersectContext* context;
 | |
|       const unsigned int geomID;
 | |
|       const unsigned int primID;
 | |
| 
 | |
|       __forceinline Occluded1KEpilogMU(RayK<K>& ray, size_t k,
 | |
|                                        IntersectContext* context,
 | |
|                                        const unsigned int geomID,
 | |
|                                        const unsigned int primID)
 | |
|         : ray(ray), k(k), context(context), geomID(geomID), primID(primID) {}
 | |
| 
 | |
|       template<typename Hit>
 | |
|       __forceinline bool operator() (const vbool<M>& valid_i, Hit& hit) const
 | |
|       {
 | |
|         Scene* scene MAYBE_UNUSED = context->scene;
 | |
|         Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
 | |
| #if defined(EMBREE_RAY_MASK)
 | |
|         /* ray mask test */
 | |
|         if ((geometry->mask & ray.mask[k]) == 0)
 | |
|           return false;
 | |
| #endif
 | |
| 
 | |
|         /* intersection filter test */
 | |
| #if defined(EMBREE_FILTER_FUNCTION)
 | |
|         if (filter) {
 | |
|           if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter()))
 | |
|           {
 | |
|             hit.finalize();
 | |
|             for (size_t m=movemask(valid_i), i=bsf(m); m!=0; m=btc(m,i), i=bsf(m))
 | |
|             {
 | |
|               const Vec2f uv = hit.uv(i);
 | |
|               const float old_t = ray.tfar[k];
 | |
|               ray.tfar[k] = hit.t(i);
 | |
|               HitK<K> h(context->user,geomID,primID,uv.x,uv.y,hit.Ng(i));
 | |
|               if (any(runOcclusionFilter(vbool<K>(1<<k),geometry,ray,context,h))) return true;
 | |
|               ray.tfar[k] = old_t;
 | |
|             }
 | |
|             return false;
 | |
|           }
 | |
|         }
 | |
| #endif 
 | |
|         return true;
 | |
|       }
 | |
|     };
 | |
|   }
 | |
| }
 |