1 // Copyright 2009-2021 Intel Corporation 2 // SPDX-License-Identifier: Apache-2.0 3 4 #pragma once 5 6 #include "primitive.h" 7 8 namespace embree 9 { 10 template<int M> 11 struct PointMi 12 { 13 /* Virtual interface to query information about the line segment type */ 14 struct Type : public PrimitiveType 15 { 16 const char* name() const; 17 size_t sizeActive(const char* This) const; 18 size_t sizeTotal(const char* This) const; 19 size_t getBytes(const char* This) const; 20 }; 21 static Type type; 22 23 public: 24 /* primitive supports multiple time segments */ 25 static const bool singleTimeSegment = false; 26 27 /* Returns maximum number of stored line segments */ max_sizePointMi28 static __forceinline size_t max_size() 29 { 30 return M; 31 } 32 33 /* Returns required number of primitive blocks for N line segments */ blocksPointMi34 static __forceinline size_t blocks(size_t N) 35 { 36 return (N + max_size() - 1) / max_size(); 37 } 38 39 /* Returns required number of bytes for N line segments */ bytesPointMi40 static __forceinline size_t bytes(size_t N) 41 { 42 return blocks(N) * sizeof(PointMi); 43 } 44 45 public: 46 /* Default constructor */ PointMiPointMi47 __forceinline PointMi() {} 48 49 /* Construction from vertices and IDs */ PointMiPointMi50 __forceinline PointMi(const vuint<M>& geomIDs, const vuint<M>& primIDs, Geometry::GType gtype, uint32_t numPrimitives) 51 : gtype((unsigned char)gtype), 52 numPrimitives(numPrimitives), 53 sharedGeomID(geomIDs[0]), 54 primIDs(primIDs) 55 { 56 assert(all(vuint<M>(geomID()) == geomIDs)); 57 } 58 59 /* Returns a mask that tells which line segments are valid */ validPointMi60 __forceinline vbool<M> valid() const { 61 return vint<M>(step) < vint<M>(numPrimitives); 62 } 63 64 /* Returns if the specified line segment is valid */ validPointMi65 __forceinline bool valid(const size_t i) const 66 { 67 assert(i < M); 68 return i < numPrimitives; 69 } 70 71 /* Returns the number of stored line segments */ sizePointMi72 __forceinline size_t size() const { 73 return numPrimitives; 74 } 75 76 __forceinline unsigned int geomID(unsigned int i = 0) const { 77 return sharedGeomID; 78 } 79 primIDPointMi80 __forceinline vuint<M>& primID() { 81 return primIDs; 82 } primIDPointMi83 __forceinline const vuint<M>& primID() const { 84 return primIDs; 85 } primIDPointMi86 __forceinline unsigned int primID(const size_t i) const { 87 assert(i < M); 88 return primIDs[i]; 89 } 90 91 /* gather the line segments */ 92 __forceinline void gather(Vec4vf<M>& p0, const Points* geom) const; 93 __forceinline void gather(Vec4vf<M>& p0, Vec3vf<M>& n0, const Points* geom) const; 94 95 __forceinline void gatheri(Vec4vf<M>& p0, const Points* geom, const int itime) const; 96 __forceinline void gatheri(Vec4vf<M>& p0, Vec3vf<M>& n0, const Points* geom, const int itime) const; 97 98 __forceinline void gather(Vec4vf<M>& p0, const Points* geom, float time) const; 99 __forceinline void gather(Vec4vf<M>& p0, Vec3vf<M>& n0, const Points* geom, float time) const; 100 101 /* Calculate the bounds of the line segments */ 102 __forceinline const BBox3fa bounds(const Scene* scene, size_t itime = 0) const 103 { 104 BBox3fa bounds = empty; 105 for (size_t i = 0; i < M && valid(i); i++) { 106 const Points* geom = scene->get<Points>(geomID(i)); 107 bounds.extend(geom->bounds(primID(i),itime)); 108 } 109 return bounds; 110 } 111 112 /* Calculate the linear bounds of the primitive */ linearBoundsPointMi113 __forceinline LBBox3fa linearBounds(const Scene* scene, size_t itime) { 114 return LBBox3fa(bounds(scene, itime + 0), bounds(scene, itime + 1)); 115 } 116 linearBoundsPointMi117 __forceinline LBBox3fa linearBounds(const Scene* const scene, size_t itime, size_t numTimeSteps) 118 { 119 LBBox3fa allBounds = empty; 120 for (size_t i = 0; i < M && valid(i); i++) { 121 const Points* geom = scene->get<Points>(geomID(i)); 122 allBounds.extend(geom->linearBounds(primID(i), itime, numTimeSteps)); 123 } 124 return allBounds; 125 } 126 linearBoundsPointMi127 __forceinline LBBox3fa linearBounds(const Scene* const scene, const BBox1f time_range) 128 { 129 LBBox3fa allBounds = empty; 130 for (size_t i = 0; i < M && valid(i); i++) { 131 const Points* geom = scene->get<Points>(geomID((unsigned int)i)); 132 allBounds.extend(geom->linearBounds(primID(i), time_range)); 133 } 134 return allBounds; 135 } 136 137 /* Fill line segment from line segment list */ 138 template<typename PrimRefT> fillPointMi139 __forceinline void fill(const PrimRefT* prims, size_t& begin, size_t end, Scene* scene) 140 { 141 Geometry::GType gty = scene->get(prims[begin].geomID())->getType(); 142 vuint<M> geomID, primID; 143 vuint<M> v0; 144 const PrimRefT* prim = &prims[begin]; 145 146 int numPrimitives = 0; 147 for (size_t i = 0; i < M; i++) { 148 if (begin < end) { 149 geomID[i] = prim->geomID(); 150 primID[i] = prim->primID(); 151 begin++; 152 numPrimitives++; 153 } else { 154 assert(i); 155 if (i > 0) { 156 geomID[i] = geomID[i - 1]; 157 primID[i] = primID[i - 1]; 158 } 159 } 160 if (begin < end) 161 prim = &prims[begin]; // FIXME: remove this line 162 } 163 new (this) PointMi(geomID, primID, gty, numPrimitives); // FIXME: use non temporal store 164 } 165 166 template<typename BVH, typename Allocator> createLeafPointMi167 __forceinline static typename BVH::NodeRef createLeaf(BVH* bvh, 168 const PrimRef* prims, 169 const range<size_t>& set, 170 const Allocator& alloc) 171 { 172 size_t start = set.begin(); 173 size_t items = PointMi::blocks(set.size()); 174 size_t numbytes = PointMi::bytes(set.size()); 175 PointMi* accel = (PointMi*)alloc.malloc1(numbytes, M * sizeof(float)); 176 for (size_t i = 0; i < items; i++) { 177 accel[i].fill(prims, start, set.end(), bvh->scene); 178 } 179 return bvh->encodeLeaf((char*)accel, items); 180 }; 181 fillMBPointMi182 __forceinline LBBox3fa fillMB(const PrimRef* prims, size_t& begin, size_t end, Scene* scene, size_t itime) 183 { 184 fill(prims, begin, end, scene); 185 return linearBounds(scene, itime); 186 } 187 fillMBPointMi188 __forceinline LBBox3fa fillMB( 189 const PrimRefMB* prims, size_t& begin, size_t end, Scene* scene, const BBox1f time_range) 190 { 191 fill(prims, begin, end, scene); 192 return linearBounds(scene, time_range); 193 } 194 195 template<typename BVH, typename SetMB, typename Allocator> createLeafMBPointMi196 __forceinline static typename BVH::NodeRecordMB4D createLeafMB(BVH* bvh, const SetMB& prims, const Allocator& alloc) 197 { 198 size_t start = prims.object_range.begin(); 199 size_t end = prims.object_range.end(); 200 size_t items = PointMi::blocks(prims.object_range.size()); 201 size_t numbytes = PointMi::bytes(prims.object_range.size()); 202 PointMi* accel = (PointMi*)alloc.malloc1(numbytes, M * sizeof(float)); 203 const typename BVH::NodeRef node = bvh->encodeLeaf((char*)accel, items); 204 205 LBBox3fa bounds = empty; 206 for (size_t i = 0; i < items; i++) 207 bounds.extend(accel[i].fillMB(prims.prims->data(), start, end, bvh->scene, prims.time_range)); 208 209 return typename BVH::NodeRecordMB4D(node, bounds, prims.time_range); 210 }; 211 212 /*! output operator */ 213 friend __forceinline embree_ostream operator<<(embree_ostream cout, const PointMi& line) 214 { 215 return cout << "Line" << M << "i {" << line.v0 << ", " << line.geomID() << ", " << line.primID() << "}"; 216 } 217 218 public: 219 unsigned char gtype; 220 unsigned char numPrimitives; 221 unsigned int sharedGeomID; 222 223 private: 224 vuint<M> primIDs; // primitive ID 225 }; 226 227 template<> gather(Vec4vf4 & p0,const Points * geom)228 __forceinline void PointMi<4>::gather(Vec4vf4& p0, const Points* geom) const 229 { 230 const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(primID(0))); 231 const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(primID(1))); 232 const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(primID(2))); 233 const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(primID(3))); 234 transpose(a0, a1, a2, a3, p0.x, p0.y, p0.z, p0.w); 235 } 236 237 template<> gather(Vec4vf4 & p0,Vec3vf4 & n0,const Points * geom)238 __forceinline void PointMi<4>::gather(Vec4vf4& p0, Vec3vf4& n0, const Points* geom) const 239 { 240 const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(primID(0))); 241 const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(primID(1))); 242 const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(primID(2))); 243 const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(primID(3))); 244 transpose(a0, a1, a2, a3, p0.x, p0.y, p0.z, p0.w); 245 const vfloat4 b0 = vfloat4(geom->normal(primID(0))); 246 const vfloat4 b1 = vfloat4(geom->normal(primID(1))); 247 const vfloat4 b2 = vfloat4(geom->normal(primID(2))); 248 const vfloat4 b3 = vfloat4(geom->normal(primID(3))); 249 transpose(b0, b1, b2, b3, n0.x, n0.y, n0.z); 250 } 251 252 template<> gatheri(Vec4vf4 & p0,const Points * geom,const int itime)253 __forceinline void PointMi<4>::gatheri(Vec4vf4& p0, const Points* geom, const int itime) const 254 { 255 const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(primID(0), itime)); 256 const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(primID(1), itime)); 257 const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(primID(2), itime)); 258 const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(primID(3), itime)); 259 transpose(a0, a1, a2, a3, p0.x, p0.y, p0.z, p0.w); 260 } 261 262 template<> gatheri(Vec4vf4 & p0,Vec3vf4 & n0,const Points * geom,const int itime)263 __forceinline void PointMi<4>::gatheri(Vec4vf4& p0, Vec3vf4& n0, const Points* geom, const int itime) const 264 { 265 const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(primID(0), itime)); 266 const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(primID(1), itime)); 267 const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(primID(2), itime)); 268 const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(primID(3), itime)); 269 transpose(a0, a1, a2, a3, p0.x, p0.y, p0.z, p0.w); 270 const vfloat4 b0 = vfloat4(geom->normal(primID(0), itime)); 271 const vfloat4 b1 = vfloat4(geom->normal(primID(1), itime)); 272 const vfloat4 b2 = vfloat4(geom->normal(primID(2), itime)); 273 const vfloat4 b3 = vfloat4(geom->normal(primID(3), itime)); 274 transpose(b0, b1, b2, b3, n0.x, n0.y, n0.z); 275 } 276 277 template<> gather(Vec4vf4 & p0,const Points * geom,float time)278 __forceinline void PointMi<4>::gather(Vec4vf4& p0, const Points* geom, float time) const 279 { 280 float ftime; 281 const int itime = geom->timeSegment(time, ftime); 282 283 Vec4vf4 a0; gatheri(a0, geom, itime); 284 Vec4vf4 b0; gatheri(b0, geom, itime + 1); 285 p0 = lerp(a0, b0, vfloat4(ftime)); 286 } 287 288 template<> gather(Vec4vf4 & p0,Vec3vf4 & n0,const Points * geom,float time)289 __forceinline void PointMi<4>::gather(Vec4vf4& p0, Vec3vf4& n0, const Points* geom, float time) const 290 { 291 float ftime; 292 const int itime = geom->timeSegment(time, ftime); 293 294 Vec4vf4 a0, b0; 295 Vec3vf4 norm0, norm1; 296 gatheri(a0, norm0, geom, itime); 297 gatheri(b0, norm1, geom, itime + 1); 298 p0 = lerp(a0, b0, vfloat4(ftime)); 299 n0 = lerp(norm0, norm1, vfloat4(ftime)); 300 } 301 302 #if defined(__AVX__) 303 304 template<> gather(Vec4vf8 & p0,const Points * geom)305 __forceinline void PointMi<8>::gather(Vec4vf8& p0, const Points* geom) const 306 { 307 const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(primID(0))); 308 const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(primID(1))); 309 const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(primID(2))); 310 const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(primID(3))); 311 const vfloat4 a4 = vfloat4::loadu(geom->vertexPtr(primID(4))); 312 const vfloat4 a5 = vfloat4::loadu(geom->vertexPtr(primID(5))); 313 const vfloat4 a6 = vfloat4::loadu(geom->vertexPtr(primID(6))); 314 const vfloat4 a7 = vfloat4::loadu(geom->vertexPtr(primID(7))); 315 transpose(a0, a1, a2, a3, a4, a5, a6, a7, p0.x, p0.y, p0.z, p0.w); 316 } 317 318 template<> gather(Vec4vf8 & p0,Vec3vf8 & n0,const Points * geom)319 __forceinline void PointMi<8>::gather(Vec4vf8& p0, Vec3vf8& n0, const Points* geom) const 320 { 321 const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(primID(0))); 322 const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(primID(1))); 323 const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(primID(2))); 324 const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(primID(3))); 325 const vfloat4 a4 = vfloat4::loadu(geom->vertexPtr(primID(4))); 326 const vfloat4 a5 = vfloat4::loadu(geom->vertexPtr(primID(5))); 327 const vfloat4 a6 = vfloat4::loadu(geom->vertexPtr(primID(6))); 328 const vfloat4 a7 = vfloat4::loadu(geom->vertexPtr(primID(7))); 329 transpose(a0, a1, a2, a3, a4, a5, a6, a7, p0.x, p0.y, p0.z, p0.w); 330 const vfloat4 b0 = vfloat4(geom->normal(primID(0))); 331 const vfloat4 b1 = vfloat4(geom->normal(primID(1))); 332 const vfloat4 b2 = vfloat4(geom->normal(primID(2))); 333 const vfloat4 b3 = vfloat4(geom->normal(primID(3))); 334 const vfloat4 b4 = vfloat4(geom->normal(primID(4))); 335 const vfloat4 b5 = vfloat4(geom->normal(primID(5))); 336 const vfloat4 b6 = vfloat4(geom->normal(primID(6))); 337 const vfloat4 b7 = vfloat4(geom->normal(primID(7))); 338 transpose(b0, b1, b2, b3, b4, b5, b6, b7, n0.x, n0.y, n0.z); 339 } 340 341 template<> gatheri(Vec4vf8 & p0,const Points * geom,const int itime)342 __forceinline void PointMi<8>::gatheri(Vec4vf8& p0, const Points* geom, const int itime) const 343 { 344 const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(primID(0), itime)); 345 const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(primID(1), itime)); 346 const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(primID(2), itime)); 347 const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(primID(3), itime)); 348 const vfloat4 a4 = vfloat4::loadu(geom->vertexPtr(primID(4), itime)); 349 const vfloat4 a5 = vfloat4::loadu(geom->vertexPtr(primID(5), itime)); 350 const vfloat4 a6 = vfloat4::loadu(geom->vertexPtr(primID(6), itime)); 351 const vfloat4 a7 = vfloat4::loadu(geom->vertexPtr(primID(7), itime)); 352 transpose(a0, a1, a2, a3, a4, a5, a6, a7, p0.x, p0.y, p0.z, p0.w); 353 } 354 355 template<> gatheri(Vec4vf8 & p0,Vec3vf8 & n0,const Points * geom,const int itime)356 __forceinline void PointMi<8>::gatheri(Vec4vf8& p0, Vec3vf8& n0, const Points* geom, const int itime) const 357 { 358 const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(primID(0), itime)); 359 const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(primID(1), itime)); 360 const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(primID(2), itime)); 361 const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(primID(3), itime)); 362 const vfloat4 a4 = vfloat4::loadu(geom->vertexPtr(primID(4), itime)); 363 const vfloat4 a5 = vfloat4::loadu(geom->vertexPtr(primID(5), itime)); 364 const vfloat4 a6 = vfloat4::loadu(geom->vertexPtr(primID(6), itime)); 365 const vfloat4 a7 = vfloat4::loadu(geom->vertexPtr(primID(7), itime)); 366 transpose(a0, a1, a2, a3, a4, a5, a6, a7, p0.x, p0.y, p0.z, p0.w); 367 const vfloat4 b0 = vfloat4(geom->normal(primID(0), itime)); 368 const vfloat4 b1 = vfloat4(geom->normal(primID(1), itime)); 369 const vfloat4 b2 = vfloat4(geom->normal(primID(2), itime)); 370 const vfloat4 b3 = vfloat4(geom->normal(primID(3), itime)); 371 const vfloat4 b4 = vfloat4(geom->normal(primID(4), itime)); 372 const vfloat4 b5 = vfloat4(geom->normal(primID(5), itime)); 373 const vfloat4 b6 = vfloat4(geom->normal(primID(6), itime)); 374 const vfloat4 b7 = vfloat4(geom->normal(primID(7), itime)); 375 transpose(b0, b1, b2, b3, b4, b5, b6, b7, n0.x, n0.y, n0.z); 376 } 377 378 template<> gather(Vec4vf8 & p0,const Points * geom,float time)379 __forceinline void PointMi<8>::gather(Vec4vf8& p0, const Points* geom, float time) const 380 { 381 float ftime; 382 const int itime = geom->timeSegment(time, ftime); 383 384 Vec4vf8 a0; 385 gatheri(a0, geom, itime); 386 Vec4vf8 b0; 387 gatheri(b0, geom, itime + 1); 388 p0 = lerp(a0, b0, vfloat8(ftime)); 389 } 390 391 template<> gather(Vec4vf8 & p0,Vec3vf8 & n0,const Points * geom,float time)392 __forceinline void PointMi<8>::gather(Vec4vf8& p0, Vec3vf8& n0, const Points* geom, float time) const 393 { 394 float ftime; 395 const int itime = geom->timeSegment(time, ftime); 396 397 Vec4vf8 a0, b0; 398 Vec3vf8 norm0, norm1; 399 gatheri(a0, norm0, geom, itime); 400 gatheri(b0, norm1, geom, itime + 1); 401 p0 = lerp(a0, b0, vfloat8(ftime)); 402 n0 = lerp(norm0, norm1, vfloat8(ftime)); 403 } 404 #endif 405 406 template<int M> 407 typename PointMi<M>::Type PointMi<M>::type; 408 409 typedef PointMi<4> Point4i; 410 typedef PointMi<8> Point8i; 411 412 } // namespace embree 413