1 | // Copyright 2009-2021 Intel Corporation |
2 | // SPDX-License-Identifier: Apache-2.0 |
3 | |
4 | #pragma once |
5 | |
6 | #include "quadv.h" |
7 | #include "quad_intersector_moeller.h" |
8 | #include "quad_intersector_pluecker.h" |
9 | |
10 | namespace embree |
11 | { |
12 | namespace isa |
13 | { |
14 | /*! Intersects M quads with 1 ray */ |
15 | template<int M, bool filter> |
16 | struct QuadMvIntersector1Moeller |
17 | { |
18 | typedef QuadMv<M> Primitive; |
19 | typedef QuadMIntersector1MoellerTrumbore<M,filter> Precalculations; |
20 | |
21 | /*! Intersect a ray with the M quads and updates the hit. */ |
22 | static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& quad) |
23 | { |
24 | STAT3(normal.trav_prims,1,1,1); |
25 | pre.intersect(ray,context,quad.v0,quad.v1,quad.v2,quad.v3,quad.geomID(),quad.primID()); |
26 | } |
27 | |
28 | /*! Test if the ray is occluded by one of M quads. */ |
29 | static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& quad) |
30 | { |
31 | STAT3(shadow.trav_prims,1,1,1); |
32 | return pre.occluded(ray,context, quad.v0,quad.v1,quad.v2,quad.v3,quad.geomID(),quad.primID()); |
33 | } |
34 | |
35 | static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& quad) |
36 | { |
37 | return PrimitivePointQuery1<Primitive>::pointQuery(query, context, quad); |
38 | } |
39 | }; |
40 | |
41 | /*! Intersects M triangles with K rays. */ |
42 | template<int M, int K, bool filter> |
43 | struct QuadMvIntersectorKMoeller |
44 | { |
45 | typedef QuadMv<M> Primitive; |
46 | typedef QuadMIntersectorKMoellerTrumbore<M,K,filter> Precalculations; |
47 | |
48 | /*! Intersects K rays with M triangles. */ |
49 | static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const QuadMv<M>& quad) |
50 | { |
51 | for (size_t i=0; i<QuadMv<M>::max_size(); i++) |
52 | { |
53 | if (!quad.valid(i)) break; |
54 | STAT3(normal.trav_prims,1,popcnt(valid_i),K); |
55 | const Vec3vf<K> p0 = broadcast<vfloat<K>>(quad.v0,i); |
56 | const Vec3vf<K> p1 = broadcast<vfloat<K>>(quad.v1,i); |
57 | const Vec3vf<K> p2 = broadcast<vfloat<K>>(quad.v2,i); |
58 | const Vec3vf<K> p3 = broadcast<vfloat<K>>(quad.v3,i); |
59 | pre.intersectK(valid_i,ray,p0,p1,p2,p3,IntersectKEpilogM<M,K,filter>(ray,context,quad.geomID(),quad.primID(),i)); |
60 | } |
61 | } |
62 | |
63 | /*! Test for K rays if they are occluded by any of the M triangles. */ |
64 | static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const QuadMv<M>& quad) |
65 | { |
66 | vbool<K> valid0 = valid_i; |
67 | |
68 | for (size_t i=0; i<QuadMv<M>::max_size(); i++) |
69 | { |
70 | if (!quad.valid(i)) break; |
71 | STAT3(shadow.trav_prims,1,popcnt(valid0),K); |
72 | const Vec3vf<K> p0 = broadcast<vfloat<K>>(quad.v0,i); |
73 | const Vec3vf<K> p1 = broadcast<vfloat<K>>(quad.v1,i); |
74 | const Vec3vf<K> p2 = broadcast<vfloat<K>>(quad.v2,i); |
75 | const Vec3vf<K> p3 = broadcast<vfloat<K>>(quad.v3,i); |
76 | if (pre.intersectK(valid0,ray,p0,p1,p2,p3,OccludedKEpilogM<M,K,filter>(valid0,ray,context,quad.geomID(),quad.primID(),i))) |
77 | break; |
78 | } |
79 | return !valid0; |
80 | } |
81 | |
82 | /*! Intersect a ray with M triangles and updates the hit. */ |
83 | static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const QuadMv<M>& quad) |
84 | { |
85 | STAT3(normal.trav_prims,1,1,1); |
86 | pre.intersect1(ray,k,context,quad.v0,quad.v1,quad.v2,quad.v3,quad.geomID(),quad.primID()); |
87 | } |
88 | |
89 | /*! Test if the ray is occluded by one of the M triangles. */ |
90 | static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const QuadMv<M>& quad) |
91 | { |
92 | STAT3(shadow.trav_prims,1,1,1); |
93 | return pre.occluded1(ray,k,context,quad.v0,quad.v1,quad.v2,quad.v3,quad.geomID(),quad.primID()); |
94 | } |
95 | }; |
96 | |
97 | /*! Intersects M quads with 1 ray */ |
98 | template<int M, bool filter> |
99 | struct QuadMvIntersector1Pluecker |
100 | { |
101 | typedef QuadMv<M> Primitive; |
102 | typedef QuadMIntersector1Pluecker<M,filter> Precalculations; |
103 | |
104 | /*! Intersect a ray with the M quads and updates the hit. */ |
105 | static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& quad) |
106 | { |
107 | STAT3(normal.trav_prims,1,1,1); |
108 | pre.intersect(ray,context,quad.v0,quad.v1,quad.v2,quad.v3,quad.geomID(),quad.primID()); |
109 | } |
110 | |
111 | /*! Test if the ray is occluded by one of M quads. */ |
112 | static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& quad) |
113 | { |
114 | STAT3(shadow.trav_prims,1,1,1); |
115 | return pre.occluded(ray,context, quad.v0,quad.v1,quad.v2,quad.v3,quad.geomID(),quad.primID()); |
116 | } |
117 | |
118 | static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& quad) |
119 | { |
120 | return PrimitivePointQuery1<Primitive>::pointQuery(query, context, quad); |
121 | } |
122 | }; |
123 | |
124 | /*! Intersects M triangles with K rays. */ |
125 | template<int M, int K, bool filter> |
126 | struct QuadMvIntersectorKPluecker |
127 | { |
128 | typedef QuadMv<M> Primitive; |
129 | typedef QuadMIntersectorKPluecker<M,K,filter> Precalculations; |
130 | |
131 | /*! Intersects K rays with M triangles. */ |
132 | static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const QuadMv<M>& quad) |
133 | { |
134 | for (size_t i=0; i<QuadMv<M>::max_size(); i++) |
135 | { |
136 | if (!quad.valid(i)) break; |
137 | STAT3(normal.trav_prims,1,popcnt(valid_i),K); |
138 | const Vec3vf<K> p0 = broadcast<vfloat<K>>(quad.v0,i); |
139 | const Vec3vf<K> p1 = broadcast<vfloat<K>>(quad.v1,i); |
140 | const Vec3vf<K> p2 = broadcast<vfloat<K>>(quad.v2,i); |
141 | const Vec3vf<K> p3 = broadcast<vfloat<K>>(quad.v3,i); |
142 | pre.intersectK(valid_i,ray,p0,p1,p2,p3,IntersectKEpilogM<M,K,filter>(ray,context,quad.geomID(),quad.primID(),i)); |
143 | } |
144 | } |
145 | |
146 | /*! Test for K rays if they are occluded by any of the M triangles. */ |
147 | static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const QuadMv<M>& quad) |
148 | { |
149 | vbool<K> valid0 = valid_i; |
150 | |
151 | for (size_t i=0; i<QuadMv<M>::max_size(); i++) |
152 | { |
153 | if (!quad.valid(i)) break; |
154 | STAT3(shadow.trav_prims,1,popcnt(valid0),K); |
155 | const Vec3vf<K> p0 = broadcast<vfloat<K>>(quad.v0,i); |
156 | const Vec3vf<K> p1 = broadcast<vfloat<K>>(quad.v1,i); |
157 | const Vec3vf<K> p2 = broadcast<vfloat<K>>(quad.v2,i); |
158 | const Vec3vf<K> p3 = broadcast<vfloat<K>>(quad.v3,i); |
159 | if (pre.intersectK(valid0,ray,p0,p1,p2,p3,OccludedKEpilogM<M,K,filter>(valid0,ray,context,quad.geomID(),quad.primID(),i))) |
160 | break; |
161 | } |
162 | return !valid0; |
163 | } |
164 | |
165 | /*! Intersect a ray with M triangles and updates the hit. */ |
166 | static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const QuadMv<M>& quad) |
167 | { |
168 | STAT3(normal.trav_prims,1,1,1); |
169 | pre.intersect1(ray,k,context,quad.v0,quad.v1,quad.v2,quad.v3,quad.geomID(),quad.primID()); |
170 | } |
171 | |
172 | /*! Test if the ray is occluded by one of the M triangles. */ |
173 | static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const QuadMv<M>& quad) |
174 | { |
175 | STAT3(shadow.trav_prims,1,1,1); |
176 | return pre.occluded1(ray,k,context,quad.v0,quad.v1,quad.v2,quad.v3,quad.geomID(),quad.primID()); |
177 | } |
178 | }; |
179 | } |
180 | } |
181 | |
182 | |