// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/default.h" #include "../common/device.h" #include "../common/scene.h" #include "../common/context.h" #include "../../include/embree4/rtcore.h" #include "../geometry/disc_intersector.h" #include "../geometry/sphere_intersector.h" #include "../geometry/roundline_intersector.h" #include "../geometry/curve_intersector_ribbon.h" #include "../geometry/curve_intersector_oriented.h" #include "../geometry/curve_intersector_sweep.h" #include "../geometry/curve_intersector_distance.h" #include "../geometry/curve_intersector_ribbon.h" #include "../geometry/curveNi_intersector.h" #include "../geometry/instance_intersector.h" #include "../geometry/instance_array_intersector.h" #include "../geometry/intersector_epilog_sycl.h" #include "../geometry/triangle_intersector_moeller.h" #include "../geometry/triangle_intersector_pluecker.h" #include "rthwif_embree.h" #include "../rthwif/rttrace/rttrace.h" using namespace embree; intel_ray_flags_t operator |(intel_ray_flags_t a, intel_ray_flags_t b) { return (intel_ray_flags_t) ((uint32_t)a | (uint32_t)b); } intel_ray_flags_t operator |= (intel_ray_flags_t& a, intel_ray_flags_t b) { return a = a | b; } RTC_NAMESPACE_BEGIN; //#if defined(EMBREE_SYCL_ROBUST) #define TriangleIntersector isa::PlueckerIntersector1<1,true> #define ROBUST_MODE true //#else //#define TriangleIntersector isa::MoellerTrumboreIntersector1<1,true> //#define ROBUST_MODE false //#endif const constexpr uint32_t TRAV_LOOP_FEATURES = #if (RTC_MAX_INSTANCE_LEVEL_COUNT > 1) RTC_FEATURE_FLAG_TRIANGLE | // filter function enforced for triangles and quads in this case RTC_FEATURE_FLAG_QUAD | #endif #if defined(EMBREE_RAY_MASK) RTC_FEATURE_FLAG_32_BIT_RAY_MASK | #endif RTC_FEATURE_FLAG_MOTION_BLUR | RTC_FEATURE_FLAG_CURVES | RTC_FEATURE_FLAG_GRID | RTC_FEATURE_FLAG_POINT | RTC_FEATURE_FLAG_USER_GEOMETRY | RTC_FEATURE_FLAG_INSTANCE | RTC_FEATURE_FLAG_INSTANCE_ARRAY | RTC_FEATURE_FLAG_FILTER_FUNCTION; void use_rthwif_embree() { } __forceinline Vec3f intel_get_hit_triangle_normal(intel_ray_query_t& query, intel_hit_type_t hit_type) { intel_float3 v[3]; intel_get_hit_triangle_vertices(query, v, hit_type); const Vec3f v0(v[0].x, v[0].y, v[0].z); const Vec3f v1(v[1].x, v[1].y, v[1].z); const Vec3f v2(v[2].x, v[2].y, v[2].z); return cross(v1-v0, v2-v0); } __forceinline bool intersect_user_geometry(intel_ray_query_t& query, RayHit& ray, UserGeometry* geom, Scene* scenes[RTC_MAX_INSTANCE_LEVEL_COUNT+1], sycl::private_ptr context, uint32_t geomID, uint32_t primID) { /* perform ray mask test */ #if defined(EMBREE_RAY_MASK) if ((ray.mask & geom->mask) == 0) return false; #endif RTCScene forward_scene = nullptr; const bool ishit = geom->intersect(ray,geomID,primID,context,forward_scene); if (!forward_scene) return ishit; /* forward ray to instanced scene */ unsigned int bvh_level = intel_get_hit_bvh_level( query, intel_hit_type_potential_hit ) + 1; Scene* scene = (Scene*) forward_scene; scenes[bvh_level] = scene; intel_ray_desc_t raydesc; raydesc.origin = float3(ray.org.x, ray.org.y, ray.org.z); raydesc.direction = float3(ray.dir.x, ray.dir.y, ray.dir.z); raydesc.tmin = ray.tnear(); raydesc.tmax = inf; // unused raydesc.mask = mask32_to_mask8(ray.mask); raydesc.flags = intel_ray_flags_force_non_opaque; //if (context.enforceArgumentFilterFunction()) // raydesc.flags |= intel_ray_flags_force_non_opaque; #if defined(EMBREE_BACKFACE_CULLING) raydesc.flags |= intel_ray_flags_cull_back_facing_triangles; #endif intel_raytracing_acceleration_structure_t hwaccel_ptr = (intel_raytracing_acceleration_structure_t) scene->hwaccel.data(); EmbreeHWAccel* hwaccel = (EmbreeHWAccel*) hwaccel_ptr; hwaccel_ptr = (intel_raytracing_acceleration_structure_t) hwaccel->AccelTable[0]; intel_ray_query_forward_ray(query, raydesc, hwaccel_ptr); return false; } __forceinline bool intersect_user_geometry(intel_ray_query_t& query, Ray& ray, UserGeometry* geom, Scene* scenes[RTC_MAX_INSTANCE_LEVEL_COUNT+1], sycl::private_ptr context, uint32_t geomID, uint32_t primID) { /* perform ray mask test */ #if defined(EMBREE_RAY_MASK) if ((ray.mask & geom->mask) == 0) return false; #endif RTCScene forward_scene = nullptr; const bool ishit = geom->occluded(ray,geomID,primID,context,forward_scene); if (!forward_scene) return ishit; /* forward ray to instanced scene */ unsigned int bvh_level = intel_get_hit_bvh_level( query, intel_hit_type_potential_hit ) + 1; Scene* scene = (Scene*) forward_scene; scenes[bvh_level] = scene; intel_ray_desc_t raydesc; raydesc.origin = float3(ray.org.x, ray.org.y, ray.org.z); raydesc.direction = float3(ray.dir.x, ray.dir.y, ray.dir.z); raydesc.tmin = ray.tnear(); raydesc.tmax = inf; // unused raydesc.mask = mask32_to_mask8(ray.mask); raydesc.flags = intel_ray_flags_force_non_opaque | intel_ray_flags_accept_first_hit_and_end_search; //if (context.enforceArgumentFilterFunction()) // raydesc.flags |= intel_ray_flags_force_non_opaque; #if defined(EMBREE_BACKFACE_CULLING) raydesc.flags |= intel_ray_flags_cull_back_facing_triangles; #endif intel_raytracing_acceleration_structure_t hwaccel_ptr = (intel_raytracing_acceleration_structure_t) scene->hwaccel.data(); EmbreeHWAccel* hwaccel = (EmbreeHWAccel*) hwaccel_ptr; hwaccel_ptr = (intel_raytracing_acceleration_structure_t) hwaccel->AccelTable[0]; intel_ray_query_forward_ray(query, raydesc, hwaccel_ptr); return false; } template __forceinline bool intersect_instance(intel_ray_query_t& query, Ray& ray, Instance* instance, Scene* scenes[RTC_MAX_INSTANCE_LEVEL_COUNT+1], sycl::private_ptr context, uint32_t geomID, uint32_t primID); template<> __forceinline bool intersect_instance(intel_ray_query_t& query, RayHit& ray, Instance* instance, Scene* scenes[RTC_MAX_INSTANCE_LEVEL_COUNT+1], sycl::private_ptr context, uint32_t geomID, uint32_t primID) { /* perform ray mask test */ #if defined(EMBREE_RAY_MASK) if ((ray.mask & instance->mask) == 0) return false; #endif if (!instance_id_stack::push(context->user, geomID, 0)) return false; unsigned int bvh_level = intel_get_hit_bvh_level( query, intel_hit_type_potential_hit ) + 1; Scene* object = (Scene*) instance->object; const AffineSpace3fa world2local = instance->getWorld2Local(ray.time()); const Vec3fa ray_org = xfmPoint (world2local, (Vec3f) ray.org); const Vec3fa ray_dir = xfmVector(world2local, (Vec3f) ray.dir); scenes[bvh_level] = object; intel_ray_desc_t raydesc; raydesc.origin = float3(ray_org.x, ray_org.y, ray_org.z); raydesc.direction = float3(ray_dir.x, ray_dir.y, ray_dir.z); raydesc.tmin = ray.tnear(); raydesc.tmax = inf; // unused raydesc.mask = mask32_to_mask8(ray.mask); raydesc.flags = intel_ray_flags_force_non_opaque; //if (context.enforceArgumentFilterFunction()) // raydesc.flags |= intel_ray_flags_force_non_opaque; #if defined(EMBREE_BACKFACE_CULLING) raydesc.flags |= intel_ray_flags_cull_back_facing_triangles; #endif intel_raytracing_acceleration_structure_t hwaccel_ptr = (intel_raytracing_acceleration_structure_t) object->hwaccel.data(); uint32_t bvh_id = 0; EmbreeHWAccel* hwaccel = (EmbreeHWAccel*) hwaccel_ptr; if (context->args->feature_mask & RTC_FEATURE_FLAG_MOTION_BLUR) { float time = clamp(ray.time(),0.0f,1.0f); bvh_id = (uint32_t) clamp(uint32_t(hwaccel->numTimeSegments*time), 0u, hwaccel->numTimeSegments-1); } hwaccel_ptr = (intel_raytracing_acceleration_structure_t) hwaccel->AccelTable[bvh_id]; intel_ray_query_forward_ray(query, raydesc, hwaccel_ptr); return false; } template<> __forceinline bool intersect_instance(intel_ray_query_t& query, Ray& ray, Instance* instance, Scene* scenes[RTC_MAX_INSTANCE_LEVEL_COUNT+1], sycl::private_ptr context, uint32_t geomID, uint32_t primID) { /* perform ray mask test */ #if defined(EMBREE_RAY_MASK) if ((ray.mask & instance->mask) == 0) return false; #endif if (!instance_id_stack::push(context->user, geomID, 0)) return false; unsigned int bvh_level = intel_get_hit_bvh_level( query, intel_hit_type_potential_hit ) + 1; Scene* object = (Scene*) instance->object; const AffineSpace3fa world2local = instance->getWorld2Local(ray.time()); const Vec3fa ray_org = xfmPoint (world2local, (Vec3f) ray.org); const Vec3fa ray_dir = xfmVector(world2local, (Vec3f) ray.dir); scenes[bvh_level] = object; intel_ray_desc_t raydesc; raydesc.origin = float3(ray_org.x, ray_org.y, ray_org.z); raydesc.direction = float3(ray_dir.x, ray_dir.y, ray_dir.z); raydesc.tmin = ray.tnear(); raydesc.tmax = inf; // unused raydesc.mask = mask32_to_mask8(ray.mask); raydesc.flags = intel_ray_flags_accept_first_hit_and_end_search; if (context->enforceArgumentFilterFunction()) raydesc.flags |= intel_ray_flags_force_non_opaque; #if defined(EMBREE_BACKFACE_CULLING) raydesc.flags |= intel_ray_flags_cull_back_facing_triangles; #endif intel_raytracing_acceleration_structure_t hwaccel_ptr = (intel_raytracing_acceleration_structure_t) object->hwaccel.data(); uint32_t bvh_id = 0; EmbreeHWAccel* hwaccel = (EmbreeHWAccel*) hwaccel_ptr; if (context->args->feature_mask & RTC_FEATURE_FLAG_MOTION_BLUR) { float time = clamp(ray.time(),0.0f,1.0f); bvh_id = (uint32_t) clamp(uint32_t(hwaccel->numTimeSegments*time), 0u, hwaccel->numTimeSegments-1); } hwaccel_ptr = (intel_raytracing_acceleration_structure_t) hwaccel->AccelTable[bvh_id]; intel_ray_query_forward_ray(query, raydesc, hwaccel_ptr); return false; } template __forceinline bool intersect_instance_array(intel_ray_query_t& query, Ray& ray, InstanceArray* instance, Scene* scenes[RTC_MAX_INSTANCE_LEVEL_COUNT+1], sycl::private_ptr context, uint32_t geomID, uint32_t primID); template<> __forceinline bool intersect_instance_array(intel_ray_query_t& query, RayHit& ray, InstanceArray* instance, Scene* scenes[RTC_MAX_INSTANCE_LEVEL_COUNT+1], sycl::private_ptr context, uint32_t geomID, uint32_t primID) { Scene* object = (Scene*) instance->getObject(primID); if (!object) return false; /* perform ray mask test */ #if defined(EMBREE_RAY_MASK) if ((ray.mask & instance->mask) == 0) return false; #endif if (!instance_id_stack::push(context->user, geomID, primID)) return false; unsigned int bvh_level = intel_get_hit_bvh_level( query, intel_hit_type_potential_hit ) + 1; const AffineSpace3fa world2local = instance->getWorld2Local(primID, ray.time()); const Vec3fa ray_org = xfmPoint (world2local, (Vec3f) ray.org); const Vec3fa ray_dir = xfmVector(world2local, (Vec3f) ray.dir); scenes[bvh_level] = object; intel_ray_desc_t raydesc; raydesc.origin = float3(ray_org.x, ray_org.y, ray_org.z); raydesc.direction = float3(ray_dir.x, ray_dir.y, ray_dir.z); raydesc.tmin = ray.tnear(); raydesc.tmax = inf; // unused raydesc.mask = mask32_to_mask8(ray.mask); raydesc.flags = intel_ray_flags_force_non_opaque; //if (context.enforceArgumentFilterFunction()) // raydesc.flags |= intel_ray_flags_force_non_opaque; #if defined(EMBREE_BACKFACE_CULLING) raydesc.flags |= intel_ray_flags_cull_back_facing_triangles; #endif intel_raytracing_acceleration_structure_t hwaccel_ptr = (intel_raytracing_acceleration_structure_t) object->hwaccel.data(); uint32_t bvh_id = 0; EmbreeHWAccel* hwaccel = (EmbreeHWAccel*) hwaccel_ptr; if (context->args->feature_mask & RTC_FEATURE_FLAG_MOTION_BLUR) { float time = clamp(ray.time(),0.0f,1.0f); bvh_id = (uint32_t) clamp(uint32_t(hwaccel->numTimeSegments*time), 0u, hwaccel->numTimeSegments-1); } hwaccel_ptr = (intel_raytracing_acceleration_structure_t) hwaccel->AccelTable[bvh_id]; intel_ray_query_forward_ray(query, raydesc, hwaccel_ptr); return false; } template<> __forceinline bool intersect_instance_array(intel_ray_query_t& query, Ray& ray, InstanceArray* instance, Scene* scenes[RTC_MAX_INSTANCE_LEVEL_COUNT+1], sycl::private_ptr context, uint32_t geomID, uint32_t primID) { Scene* object = (Scene*) instance->getObject(primID); if (!object) return false; /* perform ray mask test */ #if defined(EMBREE_RAY_MASK) if ((ray.mask & instance->mask) == 0) return false; #endif if (!instance_id_stack::push(context->user, geomID, primID)) return false; unsigned int bvh_level = intel_get_hit_bvh_level( query, intel_hit_type_potential_hit ) + 1; const AffineSpace3fa world2local = instance->getWorld2Local(primID, ray.time()); const Vec3fa ray_org = xfmPoint (world2local, (Vec3f) ray.org); const Vec3fa ray_dir = xfmVector(world2local, (Vec3f) ray.dir); scenes[bvh_level] = object; intel_ray_desc_t raydesc; raydesc.origin = float3(ray_org.x, ray_org.y, ray_org.z); raydesc.direction = float3(ray_dir.x, ray_dir.y, ray_dir.z); raydesc.tmin = ray.tnear(); raydesc.tmax = inf; // unused raydesc.mask = mask32_to_mask8(ray.mask); raydesc.flags = intel_ray_flags_accept_first_hit_and_end_search; if (context->enforceArgumentFilterFunction()) raydesc.flags |= intel_ray_flags_force_non_opaque; #if defined(EMBREE_BACKFACE_CULLING) raydesc.flags |= intel_ray_flags_cull_back_facing_triangles; #endif intel_raytracing_acceleration_structure_t hwaccel_ptr = (intel_raytracing_acceleration_structure_t) object->hwaccel.data(); uint32_t bvh_id = 0; EmbreeHWAccel* hwaccel = (EmbreeHWAccel*) hwaccel_ptr; if (context->args->feature_mask & RTC_FEATURE_FLAG_MOTION_BLUR) { float time = clamp(ray.time(),0.0f,1.0f); bvh_id = (uint32_t) clamp(uint32_t(hwaccel->numTimeSegments*time), 0u, hwaccel->numTimeSegments-1); } hwaccel_ptr = (intel_raytracing_acceleration_structure_t) hwaccel->AccelTable[bvh_id]; intel_ray_query_forward_ray(query, raydesc, hwaccel_ptr); return false; } template __forceinline bool intersect_primitive(intel_ray_query_t& query, Ray& ray, Scene* scenes[RTC_MAX_INSTANCE_LEVEL_COUNT+1], Geometry* geom, sycl::private_ptr context, uint32_t geomID, uint32_t primID, const RTCFeatureFlags feature_mask) { #if defined(EMBREE_SYCL_SUPPORT) && defined(__SYCL_DEVICE_ONLY__) bool filter = feature_mask & (RTC_FEATURE_FLAG_FILTER_FUNCTION_IN_ARGUMENTS | RTC_FEATURE_FLAG_FILTER_FUNCTION_IN_GEOMETRY); if (feature_mask & RTC_FEATURE_FLAG_MOTION_BLUR) { if (ray.time() < geom->time_range.lower || geom->time_range.upper < ray.time()) return false; } #if defined(EMBREE_GEOMETRY_USER) if ((feature_mask & RTC_FEATURE_FLAG_USER_GEOMETRY) && (geom->getType() == Geometry::GTY_USER_GEOMETRY)) { return intersect_user_geometry(query,ray,(UserGeometry*)geom, scenes, context, geomID, primID); } #endif #if defined(EMBREE_GEOMETRY_INSTANCE) if ((feature_mask & RTC_FEATURE_FLAG_INSTANCE) && (geom->getTypeMask() & Geometry::MTY_INSTANCE)) { return intersect_instance(query,ray,(Instance*)geom, scenes, context, geomID, primID); } #endif #if defined(EMBREE_GEOMETRY_INSTANCE_ARRAY) if ((feature_mask & RTC_FEATURE_FLAG_INSTANCE_ARRAY) && (geom->getTypeMask() & Geometry::MTY_INSTANCE_ARRAY)) { return intersect_instance_array(query,ray,(InstanceArray*)geom, scenes, context, geomID, primID); } #endif isa::CurvePrecalculations1 pre(ray,context->scene); const Geometry::GType gtype MAYBE_UNUSED = geom->getType(); const Geometry::GType stype MAYBE_UNUSED = (Geometry::GType)(gtype & Geometry::GTY_SUBTYPE_MASK); const Geometry::GType basis MAYBE_UNUSED = (Geometry::GType)(gtype & Geometry::GTY_BASIS_MASK); #if defined(EMBREE_GEOMETRY_TRIANGLE) if (gtype == Geometry::GTY_TRIANGLE_MESH && (feature_mask & RTC_FEATURE_FLAG_TRIANGLE) && (feature_mask & RTC_FEATURE_FLAG_MOTION_BLUR)) { const TriangleMesh* geom = context->scene->get(geomID); const TriangleMesh::Triangle triangle = geom->triangle(primID); Vec3fa v0 = geom->vertex(triangle.v[0], ray.time()); Vec3fa v1 = geom->vertex(triangle.v[1], ray.time()); Vec3fa v2 = geom->vertex(triangle.v[2], ray.time()); return TriangleIntersector().intersect(ray,v0,v1,v2,Intersect1Epilog1_HWIF(ray, context, geomID, primID, filter)); } else #endif #if defined(EMBREE_GEOMETRY_QUAD) if (gtype == Geometry::GTY_QUAD_MESH && (feature_mask & RTC_FEATURE_FLAG_QUAD) && (feature_mask & RTC_FEATURE_FLAG_MOTION_BLUR)) { const QuadMesh* geom = context->scene->get(geomID); const QuadMesh::Quad quad = geom->quad(primID); Vec3fa v0 = geom->vertex(quad.v[0], ray.time()); Vec3fa v1 = geom->vertex(quad.v[1], ray.time()); Vec3fa v2 = geom->vertex(quad.v[2], ray.time()); Vec3fa v3 = geom->vertex(quad.v[3], ray.time()); bool ishit0 = TriangleIntersector().intersect(ray,v0,v1,v3,Intersect1Epilog1_HWIF(ray, context, geomID, primID, filter)); bool ishit1 = TriangleIntersector().intersect(ray,v2,v3,v1,[&](float &u, float &v, Vec3f& Ng) { u = 1.f - u; v = 1.f - v; }, Intersect1Epilog1_HWIF(ray, context, geomID, primID, filter)); return ishit0 || ishit1; } else #endif #if defined(EMBREE_GEOMETRY_GRID) if (gtype == Geometry::GTY_GRID_MESH && (feature_mask & RTC_FEATURE_FLAG_GRID)) { const GridMesh* mesh = context->scene->get(geomID); const GridMesh::PrimID_XY c = mesh->quadID_to_primID_xy[primID]; const GridMesh::Grid& g = mesh->grid(c.primID); auto map_uv0 = [&](float &u, float &v, Vec3f& Ng) { const Vec2f uv(u,v); u = (c.x + uv.x)/(g.resX-1); v = (c.y + uv.y)/(g.resY-1); }; auto map_uv1 = [&](float &u, float &v, Vec3f& Ng) { const Vec2f uv(1.0f-u, 1.0f-v); u = (c.x + uv.x)/(g.resX-1); v = (c.y + uv.y)/(g.resY-1); }; Vec3fa v0,v1,v2,v3; mesh->gather_quad_vertices_safe(v0,v1,v2,v3,g,c.x,c.y,ray.time()); bool ishit0 = TriangleIntersector().intersect(ray,v0,v1,v3,map_uv0,Intersect1Epilog1_HWIF(ray, context, geomID, c.primID, filter)); bool ishit1 = TriangleIntersector().intersect(ray,v2,v3,v1,map_uv1,Intersect1Epilog1_HWIF(ray, context, geomID, c.primID, filter)); return ishit0 || ishit1; } else #endif #if defined(EMBREE_GEOMETRY_POINT) if (gtype == Geometry::GTY_SPHERE_POINT && (feature_mask & RTC_FEATURE_FLAG_SPHERE_POINT)) { const Points* geom = context->scene->get(geomID); const Vec3ff xyzr = geom->vertex_safe(primID, ray.time()); const Vec4f vr(xyzr.x,xyzr.y,xyzr.z,xyzr.w); return isa::SphereIntersector1<1>::intersect(true, ray, pre, vr, Intersect1Epilog1_HWIF(ray,context,geomID,primID,filter)); } else if (gtype == Geometry::GTY_DISC_POINT && (feature_mask & RTC_FEATURE_FLAG_DISC_POINT)) { const Points* geom = context->scene->get(geomID); const Vec3ff xyzr = geom->vertex_safe(primID, ray.time()); const Vec4f vr(xyzr.x,xyzr.y,xyzr.z,xyzr.w); return isa::DiscIntersector1<1>::intersect(true, ray, nullptr, nullptr, pre, vr, Intersect1Epilog1_HWIF(ray,context,geomID,primID,filter)); } else if (gtype == Geometry::GTY_ORIENTED_DISC_POINT && (feature_mask & RTC_FEATURE_FLAG_ORIENTED_DISC_POINT)) { const Points* geom = context->scene->get(geomID); const Vec3ff xyzr = geom->vertex_safe(primID, ray.time()); const Vec4f vr(xyzr.x,xyzr.y,xyzr.z,xyzr.w); const Vec3f n = geom->normal_safe(primID, ray.time()); return isa::DiscIntersector1<1>::intersect(true, ray, nullptr, nullptr, pre, vr, n, Intersect1Epilog1_HWIF(ray,context,geomID,primID,filter)); } else #endif #if defined(EMBREE_GEOMETRY_CURVE) if (geom->getTypeMask() & Geometry::MTY_CURVES) { if (gtype == Geometry::GTY_FLAT_LINEAR_CURVE && (feature_mask & RTC_FEATURE_FLAG_FLAT_LINEAR_CURVE)) { LineSegments* geom = context->scene->get(geomID); Vec3ff v0, v1; geom->gather_safe(v0,v1,geom->segment(primID),ray.time()); return isa::FlatLinearCurveIntersector1<1>::intersect(true,ray,context,geom,pre,v0,v1,Intersect1Epilog1_HWIF(ray,context,geomID,primID,filter)); } else if (gtype == Geometry::GTY_ROUND_LINEAR_CURVE && (feature_mask & RTC_FEATURE_FLAG_ROUND_LINEAR_CURVE)) { LineSegments* geom = context->scene->get(geomID); Vec3ff v0,v1,v2,v3; geom->gather_safe(v0,v1,v2,v3,primID,geom->segment(primID),ray.time()); return isa::RoundLinearCurveIntersector1<1>().intersect(true,ray,context,geom,pre,v0,v1,v2,v3,Intersect1Epilog1_HWIF(ray,context,geomID,primID,filter)); } else if (gtype == Geometry::GTY_CONE_LINEAR_CURVE && (feature_mask & RTC_FEATURE_FLAG_CONE_LINEAR_CURVE)) { LineSegments* geom = context->scene->get(geomID); Vec3ff v0 = zero, v1 = zero; bool cL = false, cR = false; geom->gather_safe(v0,v1,cL,cR,primID,geom->segment(primID),ray.time()); return isa::ConeCurveIntersector1<1>().intersect(true,ray,context,geom,pre,v0,v1,cL,cR,Intersect1Epilog1_HWIF(ray,context,geomID,primID,filter)); } else { CurveGeometry* geom = context->scene->get(geomID); if (stype == Geometry::GTY_SUBTYPE_ORIENTED_CURVE && (feature_mask & RTC_FEATURE_FLAG_NORMAL_ORIENTED_CURVES)) { using Intersector = isa::OrientedCurve1Intersector1; using Curve = isa::TensorLinearCubicBezierSurface3fa; if (geom->numTimeSegments() > 0 && (feature_mask & RTC_FEATURE_FLAG_MOTION_BLUR)) { Curve curve; if (basis == Geometry::GTY_BASIS_HERMITE && (feature_mask & RTC_FEATURE_FLAG_NORMAL_ORIENTED_HERMITE_CURVE)) { curve = geom->getNormalOrientedHermiteCurveSafe, HermiteCurveT, Curve>(context,ray.org,primID,ray.time()); } else if (basis == Geometry::GTY_BASIS_BSPLINE && (feature_mask & RTC_FEATURE_FLAG_NORMAL_ORIENTED_BSPLINE_CURVE)) { curve = geom->getNormalOrientedCurveSafe, BSplineCurveT, Curve>(context,ray.org,primID,ray.time()); } else if (basis == Geometry::GTY_BASIS_CATMULL_ROM && (feature_mask & RTC_FEATURE_FLAG_NORMAL_ORIENTED_CATMULL_ROM_CURVE)) { curve = geom->getNormalOrientedCurveSafe, CatmullRomCurveT, Curve>(context,ray.org,primID,ray.time()); } else { curve = geom->getNormalOrientedCurveSafe(context,ray.org,primID,ray.time()); } return Intersector().intersect(pre,ray,context,geom,primID,curve,Intersect1Epilog1_HWIF(ray,context,geomID,primID,filter)); } else { Vec3ff v0,v1,v2,v3; Vec3fa n0,n1,n2,n3; if (basis == Geometry::GTY_BASIS_HERMITE && (feature_mask & RTC_FEATURE_FLAG_NORMAL_ORIENTED_HERMITE_CURVE)) geom->gather_hermite_safe(v0,v1,n0,n1,v2,v3,n2,n3,geom->curve(primID),ray.time()); else geom->gather_safe(v0,v1,v2,v3,n0,n1,n2,n3,geom->curve(primID),ray.time()); isa::convert_to_bezier(gtype, v0,v1,v2,v3, n0,n1,n2,n3); return Intersector().intersect(pre,ray,context,geom,primID,v0,v1,v2,v3,n0,n1,n2,n3,Intersect1Epilog1_HWIF(ray,context,geomID,primID,filter)); } } else if (feature_mask & (RTC_FEATURE_FLAG_FLAT_CURVES | RTC_FEATURE_FLAG_ROUND_CURVES)) { Vec3ff v0,v1,v2,v3; if (basis == Geometry::GTY_BASIS_HERMITE && (feature_mask & (RTC_FEATURE_FLAG_ROUND_HERMITE_CURVE | RTC_FEATURE_FLAG_FLAT_HERMITE_CURVE))) geom->gather_hermite_safe(v0,v1,v2,v3,geom->curve(primID),ray.time()); else geom->gather_safe(v0,v1,v2,v3,geom->curve(primID),ray.time()); isa::convert_to_bezier(gtype, v0,v1,v2,v3); if (stype == Geometry::GTY_SUBTYPE_FLAT_CURVE && (feature_mask & RTC_FEATURE_FLAG_FLAT_CURVES)) { isa::RibbonCurve1Intersector1 intersector; return intersector.intersect(pre,ray,context,geom,primID,v0,v1,v2,v3,Intersect1Epilog1_HWIF(ray,context,geomID,primID,filter)); } else if (stype == Geometry::GTY_SUBTYPE_ROUND_CURVE && (feature_mask & RTC_FEATURE_FLAG_ROUND_CURVES)) { isa::SweepCurve1Intersector1 intersector; return intersector.intersect(pre,ray,context,geom,primID,v0,v1,v2,v3,Intersect1Epilog1_HWIF(ray,context,geomID,primID,filter)); } return false; } return false; } } else #endif #endif return false; } __forceinline bool invokeTriangleIntersectionFilter(intel_ray_query_t& query, Geometry* geom, uint32_t bvh_level, RayHit& ray, Hit& hit, sycl::private_ptr context, const RTCFeatureFlags feature_mask) { #if defined(EMBREE_FILTER_FUNCTION) if (!(feature_mask & RTC_FEATURE_FLAG_FILTER_FUNCTION) || runIntersectionFilter1SYCL(geom, ray, context, hit)) #endif { intel_ray_query_commit_potential_hit_override (query, ray.tfar, float2(hit.u, hit.v)); for (unsigned l = 0; l < RTC_MAX_INSTANCE_LEVEL_COUNT; ++l) { ray.instID[l] = hit.instID[l]; #if defined(EMBREE_GEOMETRY_INSTANCE_ARRAY) ray.instPrimID[l] = hit.instPrimID[l]; #endif } } return false; } __forceinline bool invokeTriangleIntersectionFilter(intel_ray_query_t& query, Geometry* geom, uint32_t bvh_level, Ray& ray, Hit& hit, sycl::private_ptr context, const RTCFeatureFlags feature_mask) { bool ishit = true; #if defined(EMBREE_FILTER_FUNCTION) ishit = !(feature_mask & RTC_FEATURE_FLAG_FILTER_FUNCTION) || runIntersectionFilter1SYCL(geom, ray, context, hit); if (ishit) #endif { intel_ray_query_commit_potential_hit_override (query, ray.tfar, float2(hit.u, hit.v)); } return ishit; } __forceinline bool commit_potential_hit(intel_ray_query_t& query, RayHit& ray) { intel_ray_query_commit_potential_hit_override (query, ray.tfar, float2(ray.u, ray.v)); return false; } __forceinline bool commit_potential_hit(intel_ray_query_t& query, Ray& ray) { intel_ray_query_commit_potential_hit_override (query, ray.tfar, float2(0.0f, 0.0f)); return true; } template __forceinline void trav_loop(intel_ray_query_t& query, Ray& ray, Scene* scenes[RTC_MAX_INSTANCE_LEVEL_COUNT+1], sycl::private_ptr context, const RTCFeatureFlags feature_mask) { while (!intel_is_traversal_done(query)) { intel_candidate_type_t candidate = intel_get_hit_candidate(query, intel_hit_type_potential_hit); const unsigned int bvh_level = intel_get_hit_bvh_level( query, intel_hit_type_potential_hit ); const float3 org = intel_get_ray_origin ( query, bvh_level ); const float3 dir = intel_get_ray_direction( query, bvh_level ); const float t = intel_get_hit_distance(query, intel_hit_type_potential_hit); const float2 uv = intel_get_hit_barycentrics (query, intel_hit_type_potential_hit); const unsigned int geomID = intel_get_hit_geometry_id(query, intel_hit_type_potential_hit); const unsigned int primID = intel_get_hit_primitive_id(query, intel_hit_type_potential_hit); ray.org = Vec3ff(org.x(), org.y(), org.z(), ray.tnear()); ray.dir = Vec3ff(dir.x(), dir.y(), dir.z(), ray.time ()); ray.tfar = intel_get_hit_distance(query, intel_hit_type_committed_hit); #if RTC_MAX_INSTANCE_LEVEL_COUNT > 1 context->user->instStackSize = bvh_level; Scene* scene = scenes[bvh_level]; #else const unsigned int instID = intel_get_hit_instance_id(query, intel_hit_type_potential_hit); /* assume software instancing mode by default (required for rtcForwardRay) */ Scene* scene = scenes[bvh_level]; /* if we are in hardware instancing mode and we need to read the scene from the instance */ if (bvh_level > 0 && instID != RTC_INVALID_GEOMETRY_ID) { Instance* inst = scenes[0]->get(instID); scene = (Scene*) inst->object; context->user->instID[0] = instID; } else if (bvh_level == 0) context->user->instID[0] = RTC_INVALID_GEOMETRY_ID; #endif context->scene = scene; Geometry* geom = scene->get(geomID); /* perform ray masking */ #if defined(EMBREE_RAY_MASK) if (ray.mask & geom->mask) #endif { if (candidate == intel_candidate_type_procedural) { if (intersect_primitive(query,ray,scenes,geom,context,geomID,primID,feature_mask)) if (commit_potential_hit (query, ray)) break; // shadow rays break at first hit } else // if (candidate == TRIANGLE) { ray.tfar = t; Vec3f Ng = intel_get_hit_triangle_normal(query, intel_hit_type_potential_hit); Hit hit(context->user,geomID,primID,Vec2f(uv.x(),uv.y()),Ng); if (invokeTriangleIntersectionFilter(query, geom, bvh_level, ray, hit, context, feature_mask)) break; // shadow rays break at first hit } } intel_ray_query_start_traversal(query); intel_ray_query_sync(query); } } SYCL_EXTERNAL __attribute__((always_inline)) void rtcIntersectRTHW(sycl::global_ptr hscene, sycl::private_ptr ucontext, sycl::private_ptr rayhit_i, sycl::private_ptr args) { Scene* scene = (Scene*) hscene.get(); intel_raytracing_acceleration_structure_t hwaccel_ptr = (intel_raytracing_acceleration_structure_t) scene->hwaccel.data(); Scene* scenes[RTC_MAX_INSTANCE_LEVEL_COUNT+1]; scenes[0] = scene; RayQueryContext context(scene, ucontext, args); RayHit ray; ray.org = Vec3ff(rayhit_i->ray.org_x, rayhit_i->ray.org_y, rayhit_i->ray.org_z, rayhit_i->ray.tnear); ray.dir = Vec3ff(rayhit_i->ray.dir_x, rayhit_i->ray.dir_y, rayhit_i->ray.dir_z, rayhit_i->ray.time); ray.tfar = rayhit_i->ray.tfar; ray.mask = rayhit_i->ray.mask; ray.id = rayhit_i->ray.id; ray.flags = rayhit_i->ray.flags; ray.Ng = Vec3f(0,0,0); ray.u = 0; ray.v = 0; ray.primID = RTC_INVALID_GEOMETRY_ID; ray.geomID = RTC_INVALID_GEOMETRY_ID; #if RTC_MAX_INSTANCE_LEVEL_COUNT > 1 for (uint32_t l=0; l 1 raydesc.flags |= intel_ray_flags_force_non_opaque; #endif #if defined(EMBREE_BACKFACE_CULLING) raydesc.flags |= intel_ray_flags_cull_back_facing_triangles; #endif if (context.enforceArgumentFilterFunction()) raydesc.flags |= intel_ray_flags_force_non_opaque; uint32_t bvh_id = 0; EmbreeHWAccel* hwaccel = (EmbreeHWAccel*) hwaccel_ptr; if (args->feature_mask & RTC_FEATURE_FLAG_MOTION_BLUR) { float time = clamp(ray.time(),0.0f,1.0f); bvh_id = (uint32_t) clamp(uint32_t(hwaccel->numTimeSegments*time), 0u, hwaccel->numTimeSegments-1); } hwaccel_ptr = (intel_raytracing_acceleration_structure_t) hwaccel->AccelTable[bvh_id]; intel_ray_query_t query = intel_ray_query_init(raydesc, hwaccel_ptr); intel_ray_query_start_traversal(query); intel_ray_query_sync(query); if (args->feature_mask & TRAV_LOOP_FEATURES) { trav_loop(query,ray,scenes,&context,args->feature_mask); } bool valid = intel_has_committed_hit(query); if (valid) { float t = intel_get_hit_distance(query, intel_hit_type_committed_hit); float2 uv = intel_get_hit_barycentrics (query, intel_hit_type_committed_hit); unsigned int geomID = intel_get_hit_geometry_id(query, intel_hit_type_committed_hit); unsigned int primID = ray.primID; if (intel_get_hit_candidate(query, intel_hit_type_committed_hit) == intel_candidate_type_triangle) primID = intel_get_hit_triangle_primitive_id(query, intel_hit_type_committed_hit); rayhit_i->ray.tfar = t; rayhit_i->hit.geomID = geomID; rayhit_i->hit.primID = primID; rayhit_i->hit.u = uv.x(); rayhit_i->hit.v = uv.y(); #if RTC_MAX_INSTANCE_LEVEL_COUNT > 1 for (uint32_t l=0; lhit.instID[l] = ray.instID[l]; #if defined(EMBREE_GEOMETRY_INSTANCE_ARRAY) rayhit_i->hit.instPrimID[l] = ray.instPrimID[l]; #endif } #else unsigned int bvh_level = intel_get_hit_bvh_level(query, intel_hit_type_committed_hit); unsigned int instID = intel_get_hit_instance_id(query, intel_hit_type_committed_hit); /* when rtcForwardRay was used then we are in software instancing mode */ if (bvh_level > 0 && instID == RTC_INVALID_GEOMETRY_ID) instID = ray.instID[0]; rayhit_i->hit.instID[0] = instID; #if defined(EMBREE_GEOMETRY_INSTANCE_ARRAY) rayhit_i->hit.instPrimID[0] = ray.instPrimID[0]; #endif #endif /* calculate geometry normal for hardware accelerated triangles */ if (intel_get_hit_candidate(query, intel_hit_type_committed_hit) == intel_candidate_type_triangle) ray.Ng = intel_get_hit_triangle_normal(query, intel_hit_type_committed_hit); rayhit_i->hit.Ng_x = ray.Ng.x; rayhit_i->hit.Ng_y = ray.Ng.y; rayhit_i->hit.Ng_z = ray.Ng.z; } else { rayhit_i->hit.geomID = -1; } intel_ray_query_abandon(query); } SYCL_EXTERNAL __attribute__((always_inline)) void rtcOccludedRTHW(sycl::global_ptr hscene, sycl::private_ptr ucontext, sycl::private_ptr ray_i, sycl::private_ptr args) { Scene* scene = (Scene*) hscene.get(); intel_raytracing_acceleration_structure_t hwaccel_ptr = (intel_raytracing_acceleration_structure_t) scene->hwaccel.data(); Scene* scenes[RTC_MAX_INSTANCE_LEVEL_COUNT+1]; scenes[0] = scene; RayQueryContext context(scene, ucontext, args); Ray ray; ray.org = Vec3ff(ray_i->org_x, ray_i->org_y, ray_i->org_z, ray_i->tnear); ray.dir = Vec3ff(ray_i->dir_x, ray_i->dir_y, ray_i->dir_z, ray_i->time); ray.tfar = ray_i->tfar; ray.mask = ray_i->mask; ray.id = ray_i->id; ray.flags = ray_i->flags; intel_ray_desc_t raydesc; raydesc.origin = float3(ray.org.x, ray.org.y, ray.org.z); raydesc.direction = float3(ray.dir.x, ray.dir.y, ray.dir.z); raydesc.tmin = ray.tnear(); raydesc.tmax = ray.tfar; raydesc.mask = mask32_to_mask8(ray.mask); raydesc.flags = intel_ray_flags_accept_first_hit_and_end_search; #if defined(EMBREE_BACKFACE_CULLING) raydesc.flags |= intel_ray_flags_cull_back_facing_triangles; #endif if (context.enforceArgumentFilterFunction()) raydesc.flags |= intel_ray_flags_force_non_opaque; uint32_t bvh_id = 0; EmbreeHWAccel* hwaccel = (EmbreeHWAccel*) hwaccel_ptr; if (args->feature_mask & RTC_FEATURE_FLAG_MOTION_BLUR) { float time = clamp(ray.time(),0.0f,1.0f); bvh_id = (uint32_t) clamp(uint32_t(hwaccel->numTimeSegments*time), 0u, hwaccel->numTimeSegments-1); } hwaccel_ptr = (intel_raytracing_acceleration_structure_t) hwaccel->AccelTable[bvh_id]; intel_ray_query_t query = intel_ray_query_init(raydesc, hwaccel_ptr); intel_ray_query_start_traversal(query); intel_ray_query_sync(query); if (args->feature_mask & TRAV_LOOP_FEATURES) { trav_loop(query,ray,scenes,&context,args->feature_mask); } if (intel_has_committed_hit(query)) ray_i->tfar = -INFINITY; intel_ray_query_abandon(query); } RTC_NAMESPACE_END;