Initial commit.

This commit is contained in:
hal8174 2024-04-23 10:14:24 +02:00
commit d3bb49b3f5
1073 changed files with 484757 additions and 0 deletions

View file

@ -0,0 +1,266 @@
// Copyright 2009-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
#pragma once
#if defined(ZE_RAYTRACING_RT_SIMULATION)
#include "rtcore.h"
#endif
#if defined(EMBREE_SYCL_RT_VALIDATION_API)
# include "rttrace_validation.h"
#else
#include <cstdint>
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#pragma clang diagnostic ignored "-W#pragma-messages"
#include <sycl/sycl.hpp>
#pragma clang diagnostic pop
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
enum intel_ray_flags_t
{
intel_ray_flags_none = 0x00,
intel_ray_flags_force_opaque = 0x01, // forces geometry to be opaque (no anyhit shader invokation)
intel_ray_flags_force_non_opaque = 0x02, // forces geometry to be non-opqaue (invoke anyhit shader)
intel_ray_flags_accept_first_hit_and_end_search = 0x04, // terminates traversal on the first hit found (shadow rays)
intel_ray_flags_skip_closest_hit_shader = 0x08, // skip execution of the closest hit shader
intel_ray_flags_cull_back_facing_triangles = 0x10, // back facing triangles to not produce a hit
intel_ray_flags_cull_front_facing_triangles = 0x20, // front facing triangles do not produce a hit
intel_ray_flags_cull_opaque = 0x40, // opaque geometry does not produce a hit
intel_ray_flags_cull_non_opaque = 0x80, // non-opaque geometry does not produce a hit
intel_ray_flags_skip_triangles = 0x100, // treat all triangle intersections as misses.
intel_ray_flags_skip_procedural_primitives = 0x200, // skip execution of intersection shaders
};
enum intel_hit_type_t
{
intel_hit_type_committed_hit = 0,
intel_hit_type_potential_hit = 1,
};
enum intel_raytracing_ext_flag_t
{
intel_raytracing_ext_flag_ray_query = 1 << 0, // true if ray queries are supported
};
// opaque types
typedef __attribute__((opencl_private)) struct intel_ray_query_opaque_t* intel_ray_query_t;
typedef __attribute__((opencl_global )) struct intel_raytracing_acceleration_structure_opaque_t* intel_raytracing_acceleration_structure_t;
struct intel_float2
{
float x, y;
intel_float2() {}
intel_float2(float x, float y)
: x(x), y(y) {}
intel_float2(sycl::float2 v)
: x(v.x()), y(v.y()) {}
operator sycl::float2() {
return sycl::float2(x,y);
}
};
struct intel_float3
{
float x, y, z;
intel_float3() {}
intel_float3(float x, float y, float z)
: x(x), y(y), z(z) {}
intel_float3(sycl::float3 v)
: x(v.x()), y(v.y()), z(v.z()) {}
operator sycl::float3() {
return sycl::float3(x,y,z);
}
};
struct intel_float4x3 {
intel_float3 vx, vy, vz, p;
};
struct intel_ray_desc_t
{
intel_float3 origin;
intel_float3 direction;
float tmin;
float tmax;
unsigned int mask;
intel_ray_flags_t flags;
};
// if traversal returns one can test if a triangle or procedural is hit
enum intel_candidate_type_t
{
intel_candidate_type_triangle,
intel_candidate_type_procedural
};
#ifdef __SYCL_DEVICE_ONLY__
// check supported ray tracing features
SYCL_EXTERNAL extern "C" intel_raytracing_ext_flag_t intel_get_raytracing_ext_flag();
// initializes a ray query
SYCL_EXTERNAL extern "C" intel_ray_query_t intel_ray_query_init(
intel_ray_desc_t ray,
intel_raytracing_acceleration_structure_t accel
);
// setup for instance traversal using a transformed ray and bottom-level AS
SYCL_EXTERNAL extern "C" void intel_ray_query_forward_ray(
intel_ray_query_t query,
intel_ray_desc_t ray,
intel_raytracing_acceleration_structure_t accel
);
// commit the potential hit
SYCL_EXTERNAL extern "C" void intel_ray_query_commit_potential_hit(
intel_ray_query_t query
);
// commit the potential hit and override hit distance and UVs
SYCL_EXTERNAL extern "C" void intel_ray_query_commit_potential_hit_override(
intel_ray_query_t query,
float override_hit_distance,
intel_float2 override_uv
);
// start traversal of a ray query
SYCL_EXTERNAL extern "C" void intel_ray_query_start_traversal( intel_ray_query_t query );
// synchronize rayquery execution. If a ray was dispatched,
// This must be called prior to calling any of the accessors below.
SYCL_EXTERNAL extern "C" void intel_ray_query_sync( intel_ray_query_t query );
// signal that a ray query will not be used further. This is the moral equaivalent of a delete
// this function does an implicit sync
SYCL_EXTERNAL extern "C" void intel_ray_query_abandon( intel_ray_query_t query );
// read hit information during shader execution
SYCL_EXTERNAL extern "C" unsigned int intel_get_hit_bvh_level( intel_ray_query_t query, intel_hit_type_t hit_type );
SYCL_EXTERNAL extern "C" float intel_get_hit_distance( intel_ray_query_t query, intel_hit_type_t hit_type );
SYCL_EXTERNAL extern "C" intel_float2 intel_get_hit_barycentrics( intel_ray_query_t query, intel_hit_type_t hit_type );
SYCL_EXTERNAL extern "C" bool intel_get_hit_front_face( intel_ray_query_t query, intel_hit_type_t hit_type );
SYCL_EXTERNAL extern "C" unsigned int intel_get_hit_geometry_id(intel_ray_query_t query, intel_hit_type_t hit_type );
SYCL_EXTERNAL extern "C" unsigned int intel_get_hit_primitive_id( intel_ray_query_t query, intel_hit_type_t hit_type );
SYCL_EXTERNAL extern "C" unsigned int intel_get_hit_triangle_primitive_id( intel_ray_query_t query, intel_hit_type_t hit_type ); // fast path for quad leaves
SYCL_EXTERNAL extern "C" unsigned int intel_get_hit_procedural_primitive_id( intel_ray_query_t query, intel_hit_type_t hit_type ); // fast path for procedural leaves
SYCL_EXTERNAL extern "C" unsigned int intel_get_hit_instance_id( intel_ray_query_t query, intel_hit_type_t hit_type );
SYCL_EXTERNAL extern "C" unsigned int intel_get_hit_instance_user_id( intel_ray_query_t query, intel_hit_type_t hit_type );
SYCL_EXTERNAL extern "C" intel_float4x3 intel_get_hit_world_to_object( intel_ray_query_t query, intel_hit_type_t hit_type );
SYCL_EXTERNAL extern "C" intel_float4x3 intel_get_hit_object_to_world( intel_ray_query_t query, intel_hit_type_t hit_type );
// fetch triangle vertices for a hit
SYCL_EXTERNAL extern "C" void intel_get_hit_triangle_vertices( intel_ray_query_t query, intel_float3 vertices_out[3], intel_hit_type_t hit_type );
// Read ray-data. This is used to read transformed rays produced by HW instancing pipeline
// during any-hit or intersection shader execution.
SYCL_EXTERNAL extern "C" intel_float3 intel_get_ray_origin( intel_ray_query_t query, unsigned int bvh_level );
SYCL_EXTERNAL extern "C" intel_float3 intel_get_ray_direction( intel_ray_query_t query, unsigned int bvh_level );
SYCL_EXTERNAL extern "C" float intel_get_ray_tmin( intel_ray_query_t query, unsigned int bvh_level );
SYCL_EXTERNAL extern "C" intel_ray_flags_t intel_get_ray_flags( intel_ray_query_t query, unsigned int bvh_level );
SYCL_EXTERNAL extern "C" unsigned int intel_get_ray_mask( intel_ray_query_t query, unsigned int bvh_level );
SYCL_EXTERNAL extern "C" intel_candidate_type_t intel_get_hit_candidate( intel_ray_query_t query, intel_hit_type_t hit_type );
// test whether traversal has terminated. If false, the ray has reached
// a procedural leaf or a non-opaque triangle leaf, and requires shader processing
SYCL_EXTERNAL extern "C" bool intel_is_traversal_done( intel_ray_query_t query );
// if traversal is done one can test for the presence of a committed hit to either invoke miss or closest hit shader
SYCL_EXTERNAL extern "C" bool intel_has_committed_hit( intel_ray_query_t query );
#else
inline intel_raytracing_ext_flag_t intel_get_raytracing_ext_flag() {
return intel_raytracing_ext_flag_ray_query;
}
inline intel_ray_query_t intel_ray_query_init(
intel_ray_desc_t ray,
intel_raytracing_acceleration_structure_t accel
) { return NULL; }
// setup for instance traversal using a transformed ray and bottom-level AS
inline void intel_ray_query_forward_ray(
intel_ray_query_t query,
intel_ray_desc_t ray,
intel_raytracing_acceleration_structure_t accel
) {}
// commit the potential hit
inline void intel_ray_query_commit_potential_hit(
intel_ray_query_t query
) {}
// commit the potential hit and override hit distance and UVs
inline void intel_ray_query_commit_potential_hit_override(
intel_ray_query_t query,
float override_hit_distance,
intel_float2 override_uv
) {}
// start traversal of a ray query
inline void intel_ray_query_start_traversal( intel_ray_query_t query ) {}
// synchronize rayquery execution. If a ray was dispatched,
// This must be called prior to calling any of the accessors below.
inline void intel_ray_query_sync( intel_ray_query_t query ) {}
// signal that a ray query will not be used further. This is the moral equaivalent of a delete
// this function does an implicit sync
inline void intel_ray_query_abandon( intel_ray_query_t query ) {}
// read hit information during shader execution
inline unsigned int intel_get_hit_bvh_level( intel_ray_query_t query, intel_hit_type_t hit_type ) { return 0; }
inline float intel_get_hit_distance( intel_ray_query_t query, intel_hit_type_t hit_type ) { return 0.0f; }
inline intel_float2 intel_get_hit_barycentrics( intel_ray_query_t query, intel_hit_type_t hit_type ) { return { 0,0 }; }
inline bool intel_get_hit_front_face( intel_ray_query_t query, intel_hit_type_t hit_type ) { return false; }
inline unsigned int intel_get_hit_geometry_id(intel_ray_query_t query, intel_hit_type_t hit_type ) { return 0; }
inline unsigned int intel_get_hit_primitive_id( intel_ray_query_t query, intel_hit_type_t hit_type ) { return 0; }
inline unsigned int intel_get_hit_triangle_primitive_id( intel_ray_query_t query, intel_hit_type_t hit_type ) { return 0; } // fast path for quad leaves
inline unsigned int intel_get_hit_procedural_primitive_id( intel_ray_query_t query, intel_hit_type_t hit_type ) { return 0; } // fast path for procedural leaves
inline unsigned int intel_get_hit_instance_id( intel_ray_query_t query, intel_hit_type_t hit_type ) { return 0; }
inline unsigned int intel_get_hit_instance_user_id( intel_ray_query_t query, intel_hit_type_t hit_type ) { return 0; }
inline intel_float4x3 intel_get_hit_world_to_object( intel_ray_query_t query, intel_hit_type_t hit_type ) { return { {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0} }; }
inline intel_float4x3 intel_get_hit_object_to_world( intel_ray_query_t query, intel_hit_type_t hit_type ) { return { {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0} }; }
// fetch triangle vertices for a hit
inline void intel_get_hit_triangle_vertices( intel_ray_query_t query, intel_float3 vertices_out[3], intel_hit_type_t hit_type ) {}
// Read ray-data. This is used to read transformed rays produced by HW instancing pipeline
// during any-hit or intersection shader execution.
inline intel_float3 intel_get_ray_origin( intel_ray_query_t query, unsigned int bvh_level ) { return { 0,0,0 }; }
inline intel_float3 intel_get_ray_direction( intel_ray_query_t query, unsigned int bvh_level ) { return { 0,0,0 }; }
inline float intel_get_ray_tmin( intel_ray_query_t query, unsigned int bvh_level ) { return 0.0f; }
inline intel_ray_flags_t intel_get_ray_flags( intel_ray_query_t query, unsigned int bvh_level ) { return intel_ray_flags_none; }
inline unsigned int intel_get_ray_mask( intel_ray_query_t query, unsigned int bvh_level ) { return 0; }
inline intel_candidate_type_t intel_get_hit_candidate( intel_ray_query_t query, intel_hit_type_t hit_type ) { return intel_candidate_type_triangle; }
// test whether traversal has terminated. If false, the ray has reached
// a procedural leaf or a non-opaque triangle leaf, and requires shader processing
inline bool intel_is_traversal_done( intel_ray_query_t query ) { return false; }
// if traversal is done one can test for the presence of a committed hit to either invoke miss or closest hit shader
inline bool intel_has_committed_hit( intel_ray_query_t query ) { return false; }
#endif
#pragma clang diagnostic pop
#endif

View file

@ -0,0 +1,293 @@
// Copyright 2009-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
#pragma once
# define MemRay MemRayV1
# define MemHit MemHitV1
# define QuadLeaf QuadLeafV1
# define InstanceLeaf InstanceLeafV1
#include <cstdint>
enum TraceRayCtrl
{
TRACE_RAY_INITIAL = 0, // Initializes hit and initializes traversal state
TRACE_RAY_INSTANCE = 1, // Loads committed hit and initializes traversal state
TRACE_RAY_COMMIT = 2, // Loads potential hit and loads traversal state
TRACE_RAY_CONTINUE = 3, // Loads committed hit and loads traversal state
TRACE_RAY_DONE = 256, // for internal use only
};
typedef __attribute__((opencl_global)) struct rtglobals_opaque_t* rtglobals_t;
typedef __attribute__((opencl_private)) struct rtfence_opaque_t* rtfence_t;
#if defined(__SYCL_DEVICE_ONLY__) || defined(EMBREE_SYCL_RT_SIMULATION)
SYCL_EXTERNAL extern "C" __attribute__((opencl_global)) void* intel_get_implicit_dispatch_globals();
SYCL_EXTERNAL extern "C" void* intel_get_rt_stack(rtglobals_t rt_dispatch_globals);
SYCL_EXTERNAL extern "C" void* intel_get_thread_btd_stack(rtglobals_t rt_dispatch_globals);
SYCL_EXTERNAL extern "C" void* intel_get_global_btd_stack(rtglobals_t rt_dispatch_globals);
SYCL_EXTERNAL extern "C" rtfence_t intel_dispatch_trace_ray_query(rtglobals_t rt_dispatch_globals, unsigned int bvh_level, unsigned int traceRayCtrl);
SYCL_EXTERNAL extern "C" void intel_rt_sync(rtfence_t fence);
#else
inline void* intel_get_implicit_dispatch_globals() { return nullptr; }
inline void* intel_get_rt_stack(rtglobals_t rt_dispatch_globals) { return nullptr; }
inline void* intel_get_thread_btd_stack(rtglobals_t rt_dispatch_globals) { return nullptr; }
inline void* intel_get_global_btd_stack(rtglobals_t rt_dispatch_globals) { return nullptr; }
inline rtfence_t intel_dispatch_trace_ray_query(rtglobals_t rt_dispatch_globals, unsigned int bvh_level, unsigned int traceRayCtrl) { return nullptr; }
inline void intel_rt_sync(rtfence_t fence) {}
#endif
enum NodeType
{
NODE_TYPE_MIXED = 0x0, // identifies a mixed internal node where each child can have a different type
NODE_TYPE_INTERNAL = 0x0, // internal BVH node with 6 children
NODE_TYPE_INSTANCE = 0x1, // instance leaf
NODE_TYPE_PROCEDURAL = 0x3, // procedural leaf
NODE_TYPE_QUAD = 0x4, // quad leaf
NODE_TYPE_INVALID = 0x7 // indicates invalid node
};
struct __attribute__ ((packed,aligned(32))) MemRayV1
{
void init(intel_ray_desc_t ray, uint64_t rootNodePtr_i)
{
org[0] = ray.origin.x;
org[1] = ray.origin.y;
org[2] = ray.origin.z;
dir[0] = ray.direction.x;
dir[1] = ray.direction.y;
dir[2] = ray.direction.z;
tnear = ray.tmin;
tfar = ray.tmax;
rootNodePtr = rootNodePtr_i;
rayFlags = ray.flags;
hitGroupSRBasePtr = 0;
hitGroupSRStride = 0;
missSRPtr = 0;
pad0 = 0;
shaderIndexMultiplier = 0;
instLeafPtr = 0;
rayMask = ray.mask;
pad1 = 0;
}
// 32 B
float org[3];
float dir[3];
float tnear;
float tfar;
// 32 B
struct { // FIXME: removing these anonymous structs triggers IGC bug
uint64_t rootNodePtr : 48; // root node to start traversal at
uint64_t rayFlags : 16; // ray flags (see RayFlag structure)
};
struct {
uint64_t hitGroupSRBasePtr : 48; // base of hit group shader record array (16-bytes alignment)
uint64_t hitGroupSRStride : 16; // stride of hit group shader record array (16-bytes alignment)
};
struct {
uint64_t missSRPtr : 48; // pointer to miss shader record to invoke on a miss (8-bytes alignment)
uint64_t pad0 : 8; // padding byte (has to be zero)
uint64_t shaderIndexMultiplier : 8; // shader index multiplier
};
struct {
uint64_t instLeafPtr : 48; // the pointer to instance leaf in case we traverse an instance (64-bytes alignment)
uint64_t rayMask : 8; // ray mask used for ray masking
uint64_t pad1 : 8; // padding byte (has to be zero)
};
};
struct __attribute__ ((packed,aligned(32))) MemHitV1
{
inline float getT() const {
return ft;
}
inline void setT(float t) {
ft = t;
}
inline float getU() const {
return fu;
}
inline void setU(float u) {
fu = u;
}
inline float getV() const {
return fv;
}
inline void setV(float v) {
fv = v;
}
inline void* getPrimLeafPtr() {
return sycl::global_ptr<void>((void*)(uint64_t(primLeafPtr)*64)).get();
}
inline void* getInstanceLeafPtr() {
return sycl::global_ptr<void>((void*)(uint64_t(instLeafPtr)*64)).get();
}
public:
float ft; // hit distance of current hit (or initial traversal distance)
float fu,fv; // barycentric hit coordinates
union {
struct {
uint32_t primIndexDelta : 16; // prim index delta for compressed meshlets and quads
uint32_t valid : 1; // set if there is a hit
uint32_t leafType : 3; // type of node primLeafPtr is pointing to
uint32_t primLeafIndex : 4; // index of the hit primitive inside the leaf
uint32_t bvhLevel : 3; // the instancing level at which the hit occured
uint32_t frontFace : 1; // whether we hit the front-facing side of a triangle (also used to pass opaque flag when calling intersection shaders)
uint32_t done : 1; // used in sync mode to indicate that traversal is done
uint32_t pad0 : 3; // unused bits
};
uint32_t data;
};
struct { // FIXME: removing these anonymous structs triggers IGC bug
uint64_t primLeafPtr : 42; // pointer to BVH leaf node (multiple of 64 bytes)
uint64_t hitGroupRecPtr0 : 22; // LSB of hit group record of the hit triangle (multiple of 16 bytes)
};
struct {
uint64_t instLeafPtr : 42; // pointer to BVH instance leaf node (in multiple of 64 bytes)
uint64_t hitGroupRecPtr1 : 22; // MSB of hit group record of the hit triangle (multiple of 16 bytes)
};
void clear(bool _done, bool _valid) {
//*(sycl::int8*) this = sycl::int8(0x7F800000 /* INFINITY */, 0, 0, (_done ? 0x10000000 : 0) | (_valid ? 0x10000), 0, 0, 0, 0);
ft = fu = fv = 0.0f;
data = 0;
done = _done ? 1 : 0;
valid = _valid ? 1 : 0;
}
};
struct __attribute__ ((packed,aligned(64))) RTStack
{
union {
struct {
struct MemHit committedHit; // stores committed hit
struct MemHit potentialHit; // stores potential hit that is passed to any hit shader
};
struct MemHit hit[2]; // committedHit, potentialHit
};
struct MemRay ray[2];
char travStack[32*2];
};
struct __attribute__ ((packed)) HWAccel
{
uint64_t reserved;
float bounds[2][3]; // bounding box of the BVH
uint32_t reserved0[8];
uint32_t numTimeSegments;
uint32_t reserved1[13];
uint64_t dispatchGlobalsPtr;
};
struct __attribute__ ((packed,aligned(8))) PrimLeafDesc
{
struct {
uint32_t shaderIndex : 24; // shader index used for shader record calculations
uint32_t geomMask : 8; // geometry mask used for ray masking
};
struct {
uint32_t geomIndex : 29; // the geometry index specifies the n'th geometry of the scene
uint32_t type : 1; // enable/disable culling for procedurals and instances
uint32_t geomFlags : 2; // geometry flags of this geometry
};
};
struct __attribute__ ((packed,aligned(64))) QuadLeafV1
{
struct PrimLeafDesc leafDesc;
unsigned int primIndex0;
struct {
uint32_t primIndex1Delta : 16; // delta encoded primitive index of second triangle
uint32_t j0 : 2; // specifies first vertex of second triangle
uint32_t j1 : 2; // specified second vertex of second triangle
uint32_t j2 : 2; // specified third vertex of second triangle
uint32_t last : 1; // true if the second triangle is the last triangle in a leaf list
uint32_t pad : 9; // unused bits
};
float v[4][3];
};
struct __attribute__ ((packed,aligned(64))) ProceduralLeaf
{
static const constexpr uint32_t N = 13;
struct PrimLeafDesc leafDesc; // leaf header identifying the geometry
struct {
uint32_t numPrimitives : 4; // number of stored primitives
uint32_t pad : 32-4-N;
uint32_t last : N; // bit vector with a last bit per primitive
};
uint32_t _primIndex[N]; // primitive indices of all primitives stored inside the leaf
};
struct __attribute__ ((packed,aligned(64))) InstanceLeafV1
{
/* first 64 bytes accessed during traversal by hardware */
struct Part0
{
public:
struct {
uint32_t shaderIndex : 24; // shader index used to calculate instancing shader in case of software instancing
uint32_t geomMask : 8; // geometry mask used for ray masking
};
struct {
uint32_t instanceContributionToHitGroupIndex : 24;
uint32_t pad0 : 5;
/* the following two entries are only used for procedural instances */
uint32_t type : 1; // enables/disables opaque culling
uint32_t geomFlags : 2; // unused for instances
};
struct {
uint64_t startNodePtr : 48; // start node where to continue traversal of the instanced object
uint64_t instFlags : 8; // flags for the instance (see InstanceFlags)
uint64_t pad1 : 8; // unused bits
};
float world2obj_vx[3]; // 1st column of Worl2Obj transform
float world2obj_vy[3]; // 2nd column of Worl2Obj transform
float world2obj_vz[3]; // 3rd column of Worl2Obj transform
float obj2world_p[3]; // translation of Obj2World transform (on purpose in first 64 bytes)
} part0;
/* second 64 bytes accessed during shading */
struct Part1
{
struct {
uint64_t bvhPtr : 48; // pointer to BVH where start node belongs too
uint64_t pad : 16; // unused bits
};
uint32_t instanceID; // user defined value per DXR spec
uint32_t instanceIndex; // geometry index of the instance (n'th geometry in scene)
float obj2world_vx[3]; // 1st column of Obj2World transform
float obj2world_vy[3]; // 2nd column of Obj2World transform
float obj2world_vz[3]; // 3rd column of Obj2World transform
float world2obj_p[3]; // translation of World2Obj transform
} part1;
};

View file

@ -0,0 +1,287 @@
// Copyright 2009-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
#include "rttrace_validation.h"
#define sizeof_QBVH6_InternalNode6 64
#define QBVH6_rootNodeOffset 128
/*struct rayquery_impl_t {
rtfence_t fence;
rtglobals_t dispatchGlobalsPtr;
struct RTStack* rtStack;
TraceRayCtrl ctrl;
unsigned int bvh_level;
};*/
void use_rthwif_production()
{
}
SYCL_EXTERNAL intel_raytracing_ext_flag_t intel_get_raytracing_ext_flag()
{
return intel_raytracing_ext_flag_ray_query;
}
SYCL_EXTERNAL intel_ray_query_t intel_ray_query_init(intel_ray_desc_t ray, intel_raytracing_acceleration_structure_t accel_i )
{
unsigned int bvh_level = 0;
//intel_raytracing_acceleration_structure_t* accel_i = sycl::global_ptr<intel_raytracing_acceleration_structure_t>(_accel_i).get();
HWAccel* accel = (HWAccel*)accel_i;
#if defined(EMBREE_SYCL_ALLOC_DISPATCH_GLOBALS)
rtglobals_t dispatchGlobalsPtr = (rtglobals_t) accel->dispatchGlobalsPtr;
#else
rtglobals_t dispatchGlobalsPtr = (rtglobals_t) intel_get_implicit_dispatch_globals();
#endif
struct RTStack* __restrict rtStack = sycl::global_ptr<RTStack>((struct RTStack*)intel_get_rt_stack( (rtglobals_t)dispatchGlobalsPtr )).get();
/* init ray */
rtStack->ray[bvh_level].init(ray,(uint64_t)accel + QBVH6_rootNodeOffset);
rtStack->committedHit.setT(INFINITY);
rtStack->committedHit.setU(0.0f);
rtStack->committedHit.setV(0.0f);
rtStack->committedHit.data = 0;
rtStack->potentialHit.setT(INFINITY);
rtStack->potentialHit.setU(0.0f);
rtStack->potentialHit.setV(0.0f);
rtStack->potentialHit.data = 0;
rtStack->potentialHit.done = 1;
rtStack->potentialHit.valid = 1;
return { nullptr, (void*) dispatchGlobalsPtr, rtStack, TRACE_RAY_INITIAL, bvh_level };
}
SYCL_EXTERNAL void intel_ray_query_forward_ray( intel_ray_query_t& query, intel_ray_desc_t ray, intel_raytracing_acceleration_structure_t accel_i)
{
HWAccel* accel = (HWAccel*)accel_i;
struct RTStack* __restrict rtStack = sycl::global_ptr<RTStack>((struct RTStack*)query.opaque2).get();
/* init ray */
unsigned int bvh_level = query.bvh_level+1;
rtStack->ray[bvh_level].init(ray,(uint64_t)accel + QBVH6_rootNodeOffset);
query = { nullptr, query.opaque1, query.opaque2, TRACE_RAY_INSTANCE, bvh_level };
}
SYCL_EXTERNAL void intel_ray_query_commit_potential_hit( intel_ray_query_t& query )
{
struct RTStack* __restrict rtStack = sycl::global_ptr<RTStack>((struct RTStack*)query.opaque2).get();
unsigned int bvh_level = query.bvh_level;
unsigned int rflags = rtStack->ray[bvh_level].rayFlags;
if (rflags & intel_ray_flags_accept_first_hit_and_end_search) {
rtStack->committedHit = rtStack->potentialHit;
rtStack->committedHit.valid = 1;
query = { nullptr, query.opaque1, query.opaque2, TRACE_RAY_DONE, bvh_level };
} else {
rtStack->potentialHit.valid = 1; // FIXME: is this required?
query = { nullptr, query.opaque1, query.opaque2, TRACE_RAY_COMMIT, bvh_level };
}
}
SYCL_EXTERNAL void intel_ray_query_commit_potential_hit_override( intel_ray_query_t& query, float override_hit_distance, intel_float2 override_uv )
{
//struct RTStack* rtStack = (struct RTStack*) query.opaque2;
struct RTStack* __restrict rtStack = sycl::global_ptr<RTStack>((struct RTStack*)query.opaque2).get();
rtStack->potentialHit.setT(override_hit_distance);
rtStack->potentialHit.setU(override_uv.x);
rtStack->potentialHit.setV(override_uv.y);
intel_ray_query_commit_potential_hit(query);
}
SYCL_EXTERNAL void intel_ray_query_start_traversal( intel_ray_query_t& query )
{
rtglobals_t dispatchGlobalsPtr = (rtglobals_t) query.opaque1;
struct RTStack* __restrict rtStack = sycl::global_ptr<RTStack>((struct RTStack*)query.opaque2).get();
rtStack->potentialHit.done = 1;
rtStack->potentialHit.valid = 1;
if (query.ctrl == TRACE_RAY_DONE) return;
rtfence_t fence = intel_dispatch_trace_ray_query(dispatchGlobalsPtr,query.bvh_level,query.ctrl);
query = { (void*) fence, query.opaque1, query.opaque2, TRACE_RAY_INITIAL, 0 };
}
SYCL_EXTERNAL void intel_ray_query_sync( intel_ray_query_t& query )
{
intel_rt_sync((rtfence_t)query.opaque0);
/* continue is default behaviour */
struct RTStack* __restrict rtStack = sycl::global_ptr<RTStack>((struct RTStack*)query.opaque2).get();
unsigned int bvh_level = rtStack->potentialHit.bvhLevel;
query = { query.opaque0, query.opaque1, query.opaque2, TRACE_RAY_CONTINUE, bvh_level };
}
SYCL_EXTERNAL void intel_sync_ray_query( intel_ray_query_t& query )
{
intel_rt_sync((rtfence_t)query.opaque0);
/* continue is default behaviour */
struct RTStack* __restrict rtStack = sycl::global_ptr<RTStack>((struct RTStack*)query.opaque2).get();
unsigned int bvh_level = rtStack->potentialHit.bvhLevel;
query = { query.opaque0, query.opaque1, query.opaque2, TRACE_RAY_CONTINUE, bvh_level };
}
SYCL_EXTERNAL void intel_ray_query_abandon( intel_ray_query_t& query )
{
intel_ray_query_sync(query);
query = { nullptr, nullptr, nullptr, TRACE_RAY_INITIAL, 0 };
}
SYCL_EXTERNAL unsigned int intel_get_hit_bvh_level( intel_ray_query_t& query, intel_hit_type_t hit_type ) {
return query.hit(hit_type).bvhLevel;
}
SYCL_EXTERNAL float intel_get_hit_distance( intel_ray_query_t& query, intel_hit_type_t hit_type ) {
return query.hit(hit_type).getT();
}
SYCL_EXTERNAL intel_float2 intel_get_hit_barycentrics( intel_ray_query_t& query, intel_hit_type_t hit_type ) {
return { query.hit(hit_type).getU(), query.hit(hit_type).getV() };
}
SYCL_EXTERNAL bool intel_get_hit_front_face( intel_ray_query_t& query, intel_hit_type_t hit_type ) {
return query.hit(hit_type).frontFace;
}
SYCL_EXTERNAL unsigned int intel_get_hit_geometry_id(intel_ray_query_t& query, intel_hit_type_t hit_type )
{
struct PrimLeafDesc* __restrict leaf = (struct PrimLeafDesc*)query.hit(hit_type).getPrimLeafPtr();
return leaf->geomIndex;
}
SYCL_EXTERNAL unsigned int intel_get_hit_primitive_id( intel_ray_query_t& query, intel_hit_type_t hit_type )
{
MemHit& hit = query.hit(hit_type);
void* __restrict leaf = hit.getPrimLeafPtr();
if (hit.leafType == NODE_TYPE_QUAD)
return ((QuadLeaf*)leaf)->primIndex0 + hit.primIndexDelta;
else
return ((ProceduralLeaf*)leaf)->_primIndex[hit.primLeafIndex];
}
SYCL_EXTERNAL unsigned int intel_get_hit_triangle_primitive_id( intel_ray_query_t& query, intel_hit_type_t hit_type )
{
MemHit& hit = query.hit(hit_type);
QuadLeaf* __restrict leaf = (QuadLeaf*) hit.getPrimLeafPtr();
return leaf->primIndex0 + hit.primIndexDelta;
}
SYCL_EXTERNAL unsigned int intel_get_hit_procedural_primitive_id( intel_ray_query_t& query, intel_hit_type_t hit_type )
{
MemHit& hit = query.hit(hit_type);
ProceduralLeaf* __restrict leaf = (ProceduralLeaf*) hit.getPrimLeafPtr();
return leaf->_primIndex[hit.primLeafIndex];
}
SYCL_EXTERNAL unsigned int intel_get_hit_instance_id( intel_ray_query_t& query, intel_hit_type_t hit_type )
{
MemHit& hit = query.hit(hit_type);
InstanceLeaf* __restrict leaf = (InstanceLeaf*) hit.getInstanceLeafPtr();
if (leaf == nullptr) return -1;
return leaf->part1.instanceIndex;
}
SYCL_EXTERNAL unsigned int intel_get_hit_instance_user_id( intel_ray_query_t& query, intel_hit_type_t hit_type )
{
MemHit& hit = query.hit(hit_type);
InstanceLeaf* __restrict leaf = (InstanceLeaf*) hit.getInstanceLeafPtr();
if (leaf == nullptr) return -1;
return leaf->part1.instanceID;
}
SYCL_EXTERNAL intel_float4x3 intel_get_hit_world_to_object( intel_ray_query_t& query, intel_hit_type_t hit_type )
{
MemHit& hit = query.hit(hit_type);
InstanceLeaf* __restrict leaf = (InstanceLeaf*) hit.getInstanceLeafPtr();
if (leaf == nullptr) return { { 1,0,0 }, { 0,1,0 }, { 0,0,1 }, { 0,0,0 } };
return {
{ leaf->part0.world2obj_vx[0], leaf->part0.world2obj_vx[1], leaf->part0.world2obj_vx[2] },
{ leaf->part0.world2obj_vy[0], leaf->part0.world2obj_vy[1], leaf->part0.world2obj_vy[2] },
{ leaf->part0.world2obj_vz[0], leaf->part0.world2obj_vz[1], leaf->part0.world2obj_vz[2] },
{ leaf->part1.world2obj_p [0], leaf->part1.world2obj_p [1], leaf->part1.world2obj_p [2] }
};
}
SYCL_EXTERNAL intel_float4x3 intel_get_hit_object_to_world( intel_ray_query_t& query, intel_hit_type_t hit_type )
{
MemHit& hit = query.hit(hit_type);
InstanceLeaf* __restrict leaf = (InstanceLeaf*) hit.getInstanceLeafPtr();
if (leaf == nullptr) return { { 1,0,0 }, { 0,1,0 }, { 0,0,1 }, { 0,0,0 } };
return {
{ leaf->part1.obj2world_vx[0], leaf->part1.obj2world_vx[1], leaf->part1.obj2world_vx[2] },
{ leaf->part1.obj2world_vy[0], leaf->part1.obj2world_vy[1], leaf->part1.obj2world_vy[2] },
{ leaf->part1.obj2world_vz[0], leaf->part1.obj2world_vz[1], leaf->part1.obj2world_vz[2] },
{ leaf->part0.obj2world_p [0], leaf->part0.obj2world_p [1], leaf->part0.obj2world_p [2] }
};
}
SYCL_EXTERNAL void intel_get_hit_triangle_vertices( intel_ray_query_t& query, intel_float3 verts_out[3], intel_hit_type_t hit_type )
{
const QuadLeaf* __restrict leaf = (const QuadLeaf*) query.hit(hit_type).getPrimLeafPtr();
unsigned int j0 = 0, j1 = 1, j2 = 2;
if (query.hit(hit_type).primLeafIndex != 0)
{
j0 = leaf->j0;
j1 = leaf->j1;
j2 = leaf->j2;
}
verts_out[0] = { leaf->v[j0][0], leaf->v[j0][1], leaf->v[j0][2] };
verts_out[1] = { leaf->v[j1][0], leaf->v[j1][1], leaf->v[j1][2] };
verts_out[2] = { leaf->v[j2][0], leaf->v[j2][1], leaf->v[j2][2] };
}
SYCL_EXTERNAL intel_float3 intel_get_ray_origin( intel_ray_query_t& query, unsigned int bvh_level)
{
struct RTStack* __restrict rtStack = sycl::global_ptr<RTStack>((struct RTStack*)query.opaque2).get();
MemRay& ray = rtStack->ray[bvh_level];
return { ray.org[0], ray.org[1], ray.org[2] };
}
SYCL_EXTERNAL intel_float3 intel_get_ray_direction( intel_ray_query_t& query, unsigned int bvh_level)
{
struct RTStack* __restrict rtStack = sycl::global_ptr<RTStack>((struct RTStack*)query.opaque2).get();
MemRay& ray = rtStack->ray[bvh_level];
return { ray.dir[0], ray.dir[1], ray.dir[2] };
}
SYCL_EXTERNAL float intel_get_ray_tmin( intel_ray_query_t& query, unsigned int bvh_level)
{
struct RTStack* __restrict rtStack = sycl::global_ptr<RTStack>((struct RTStack*)query.opaque2).get();
return rtStack->ray[bvh_level].tnear;
}
SYCL_EXTERNAL intel_ray_flags_t intel_get_ray_flags( intel_ray_query_t& query, unsigned int bvh_level)
{
struct RTStack* __restrict rtStack = sycl::global_ptr<RTStack>((struct RTStack*)query.opaque2).get();
return (intel_ray_flags_t) rtStack->ray[bvh_level].rayFlags;
}
SYCL_EXTERNAL unsigned int intel_get_ray_mask( intel_ray_query_t& query, unsigned int bvh_level)
{
struct RTStack* __restrict rtStack = sycl::global_ptr<RTStack>((struct RTStack*)query.opaque2).get();
return rtStack->ray[bvh_level].rayMask;
}
SYCL_EXTERNAL bool intel_is_traversal_done( intel_ray_query_t& query ) {
return query.hit(intel_hit_type_potential_hit).done;
}
SYCL_EXTERNAL intel_candidate_type_t intel_get_hit_candidate( intel_ray_query_t& query, intel_hit_type_t hit_type) {
return query.hit(hit_type).leafType == NODE_TYPE_QUAD ? intel_candidate_type_triangle : intel_candidate_type_procedural;
}
SYCL_EXTERNAL bool intel_has_committed_hit( intel_ray_query_t& query ) {
return query.hit(intel_hit_type_committed_hit).valid;
}

View file

@ -0,0 +1,180 @@
// Copyright 2009-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <cstdint>
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#pragma clang diagnostic ignored "-W#pragma-messages"
#include <sycl/sycl.hpp>
#pragma clang diagnostic pop
enum intel_ray_flags_t
{
intel_ray_flags_none = 0x00,
intel_ray_flags_force_opaque = 0x01, // forces geometry to be opaque (no anyhit shader invokation)
intel_ray_flags_force_non_opaque = 0x02, // forces geometry to be non-opqaue (invoke anyhit shader)
intel_ray_flags_accept_first_hit_and_end_search = 0x04, // terminates traversal on the first hit found (shadow rays)
intel_ray_flags_skip_closest_hit_shader = 0x08, // skip execution of the closest hit shader
intel_ray_flags_cull_back_facing_triangles = 0x10, // back facing triangles to not produce a hit
intel_ray_flags_cull_front_facing_triangles = 0x20, // front facing triangles do not produce a hit
intel_ray_flags_cull_opaque = 0x40, // opaque geometry does not produce a hit
intel_ray_flags_cull_non_opaque = 0x80, // non-opaque geometry does not produce a hit
intel_ray_flags_skip_triangles = 0x100, // treat all triangle intersections as misses.
intel_ray_flags_skip_procedural_primitives = 0x200, // skip execution of intersection shaders
};
enum intel_hit_type_t
{
intel_hit_type_committed_hit = 0,
intel_hit_type_potential_hit = 1,
};
enum intel_raytracing_ext_flag_t
{
intel_raytracing_ext_flag_ray_query = 1 << 0, // true if ray queries are supported
};
struct intel_float2
{
float x, y;
intel_float2() {}
intel_float2(float x, float y)
: x(x), y(y) {}
intel_float2(sycl::float2 v)
: x(v.x()), y(v.y()) {}
operator sycl::float2() {
return sycl::float2(x,y);
}
};
struct intel_float3
{
float x, y, z;
intel_float3() {}
intel_float3(float x, float y, float z)
: x(x), y(y), z(z) {}
intel_float3(sycl::float3 v)
: x(v.x()), y(v.y()), z(v.z()) {}
operator sycl::float3() {
return sycl::float3(x,y,z);
}
};
struct intel_float4x3 {
intel_float3 vx, vy, vz, p;
};
struct intel_ray_desc_t
{
intel_float3 origin;
intel_float3 direction;
float tmin;
float tmax;
unsigned int mask;
intel_ray_flags_t flags;
};
#include "rttrace_internal.h"
// opaque types
struct intel_ray_query_t {
void* opaque0; void* opaque1; void* opaque2; uint32_t ctrl; uint32_t bvh_level;
MemHit& hit(intel_hit_type_t ty) {
struct RTStack* rtStack = (struct RTStack*) opaque2;
return rtStack->hit[ty];
}
};
typedef __attribute__((opencl_global )) struct intel_raytracing_acceleration_structure_opaque_t* intel_raytracing_acceleration_structure_t;
// check supported ray tracing features
SYCL_EXTERNAL intel_raytracing_ext_flag_t intel_get_raytracing_ext_flag();
// initializes a ray query
SYCL_EXTERNAL intel_ray_query_t intel_ray_query_init(
intel_ray_desc_t ray,
intel_raytracing_acceleration_structure_t accel
);
// setup for instance traversal using a transformed ray and bottom-level AS
SYCL_EXTERNAL void intel_ray_query_forward_ray(
intel_ray_query_t& query,
intel_ray_desc_t ray,
intel_raytracing_acceleration_structure_t accel
);
// commit the potential hit
SYCL_EXTERNAL void intel_ray_query_commit_potential_hit(
intel_ray_query_t& query
);
// commit the potential hit and override hit distance and UVs
SYCL_EXTERNAL void intel_ray_query_commit_potential_hit_override(
intel_ray_query_t& query,
float override_hit_distance,
intel_float2 override_uv
);
// start traversal of a ray query
SYCL_EXTERNAL void intel_ray_query_start_traversal( intel_ray_query_t& query );
// synchronize rayquery execution. If a ray was dispatched,
// This must be called prior to calling any of the accessors below.
SYCL_EXTERNAL void intel_ray_query_sync( intel_ray_query_t& query );
// signal that a ray query will not be used further. This is the moral equaivalent of a delete
// this function does an implicit sync
SYCL_EXTERNAL void intel_ray_query_abandon( intel_ray_query_t& query );
// read hit information during shader execution
SYCL_EXTERNAL unsigned int intel_get_hit_bvh_level( intel_ray_query_t& query, intel_hit_type_t hit_type );
SYCL_EXTERNAL float intel_get_hit_distance( intel_ray_query_t& query, intel_hit_type_t hit_type );
SYCL_EXTERNAL intel_float2 intel_get_hit_barycentrics( intel_ray_query_t& query, intel_hit_type_t hit_type );
SYCL_EXTERNAL bool intel_get_hit_front_face( intel_ray_query_t& query, intel_hit_type_t hit_type );
SYCL_EXTERNAL unsigned int intel_get_hit_geometry_id(intel_ray_query_t& query, intel_hit_type_t hit_type );
SYCL_EXTERNAL unsigned int intel_get_hit_primitive_id( intel_ray_query_t& query, intel_hit_type_t hit_type );
SYCL_EXTERNAL unsigned int intel_get_hit_triangle_primitive_id( intel_ray_query_t& query, intel_hit_type_t hit_type ); // fast path for quad leaves
SYCL_EXTERNAL unsigned int intel_get_hit_procedural_primitive_id( intel_ray_query_t& query, intel_hit_type_t hit_type ); // fast path for procedural leaves
SYCL_EXTERNAL unsigned int intel_get_hit_instance_id( intel_ray_query_t& query, intel_hit_type_t hit_type );
SYCL_EXTERNAL unsigned int intel_get_hit_instance_user_id( intel_ray_query_t& query, intel_hit_type_t hit_type );
SYCL_EXTERNAL intel_float4x3 intel_get_hit_world_to_object( intel_ray_query_t& query, intel_hit_type_t hit_type );
SYCL_EXTERNAL intel_float4x3 intel_get_hit_object_to_world( intel_ray_query_t& query, intel_hit_type_t hit_type );
// fetch triangle vertices for a hit
SYCL_EXTERNAL void intel_get_hit_triangle_vertices( intel_ray_query_t& query, intel_float3 vertices_out[3], intel_hit_type_t hit_type );
// Read ray-data. This is used to read transformed rays produced by HW instancing pipeline
// during any-hit or intersection shader execution.
SYCL_EXTERNAL intel_float3 intel_get_ray_origin( intel_ray_query_t& query, unsigned int bvh_level );
SYCL_EXTERNAL intel_float3 intel_get_ray_direction( intel_ray_query_t& query, unsigned int bvh_level );
SYCL_EXTERNAL float intel_get_ray_tmin( intel_ray_query_t& query, unsigned int bvh_level );
SYCL_EXTERNAL intel_ray_flags_t intel_get_ray_flags( intel_ray_query_t& query, unsigned int bvh_level );
SYCL_EXTERNAL unsigned int intel_get_ray_mask( intel_ray_query_t& query, unsigned int bvh_level );
// if traversal returns one can test if a triangle or procedural is hit
enum intel_candidate_type_t
{
intel_candidate_type_triangle,
intel_candidate_type_procedural
};
SYCL_EXTERNAL intel_candidate_type_t intel_get_hit_candidate( intel_ray_query_t& query, intel_hit_type_t hit_type );
// test whether traversal has terminated. If false, the ray has reached
// a procedural leaf or a non-opaque triangle leaf, and requires shader processing
SYCL_EXTERNAL bool intel_is_traversal_done( intel_ray_query_t& query );
// if traversal is done one can test for the presence of a committed hit to either invoke miss or closest hit shader
SYCL_EXTERNAL bool intel_has_committed_hit( intel_ray_query_t& query );