patch_eval_simd.h 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. // Copyright 2009-2021 Intel Corporation
  2. // SPDX-License-Identifier: Apache-2.0
  3. #pragma once
  4. #include "patch.h"
  5. #include "feature_adaptive_eval_simd.h"
  6. namespace embree
  7. {
  8. namespace isa
  9. {
  10. template<typename vbool, typename vint, typename vfloat, typename Vertex, typename Vertex_t = Vertex>
  11. struct PatchEvalSimd
  12. {
  13. public:
  14. typedef PatchT<Vertex,Vertex_t> Patch;
  15. typedef typename Patch::Ref Ref;
  16. typedef CatmullClarkPatchT<Vertex,Vertex_t> CatmullClarkPatch;
  17. PatchEvalSimd (SharedLazyTessellationCache::CacheEntry& entry, size_t commitCounter,
  18. const HalfEdge* edge, const char* vertices, size_t stride, const vbool& valid0, const vfloat& u, const vfloat& v,
  19. float* P, float* dPdu, float* dPdv, float* ddPdudu, float* ddPdvdv, float* ddPdudv, const size_t dstride, const size_t N)
  20. : P(P), dPdu(dPdu), dPdv(dPdv), ddPdudu(ddPdudu), ddPdvdv(ddPdvdv), ddPdudv(ddPdudv), dstride(dstride), N(N)
  21. {
  22. /* conservative time for the very first allocation */
  23. auto time = SharedLazyTessellationCache::sharedLazyTessellationCache.getTime(commitCounter);
  24. Ref patch = SharedLazyTessellationCache::lookup(entry,commitCounter,[&] () {
  25. auto alloc = [](size_t bytes) { return SharedLazyTessellationCache::malloc(bytes); };
  26. return Patch::create(alloc,edge,vertices,stride);
  27. }, true);
  28. auto curTime = SharedLazyTessellationCache::sharedLazyTessellationCache.getTime(commitCounter);
  29. const bool allAllocationsValid = SharedLazyTessellationCache::validTime(time,curTime);
  30. patch = allAllocationsValid ? patch : nullptr;
  31. /* use cached data structure for calculations */
  32. const vbool valid1 = patch ? eval(valid0,patch,u,v,1.0f,0) : vbool(false);
  33. SharedLazyTessellationCache::unlock();
  34. const vbool valid2 = valid0 & !valid1;
  35. if (any(valid2)) {
  36. FeatureAdaptiveEvalSimd<vbool,vint,vfloat,Vertex,Vertex_t>(edge,vertices,stride,valid2,u,v,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,dstride,N);
  37. }
  38. }
  39. vbool eval_quad(const vbool& valid, const typename Patch::SubdividedQuadPatch* This, const vfloat& u, const vfloat& v, const float dscale, const size_t depth)
  40. {
  41. vbool ret = false;
  42. const vbool u0_mask = u < 0.5f, u1_mask = u >= 0.5f;
  43. const vbool v0_mask = v < 0.5f, v1_mask = v >= 0.5f;
  44. const vbool u0v0_mask = valid & u0_mask & v0_mask;
  45. const vbool u0v1_mask = valid & u0_mask & v1_mask;
  46. const vbool u1v0_mask = valid & u1_mask & v0_mask;
  47. const vbool u1v1_mask = valid & u1_mask & v1_mask;
  48. if (any(u0v0_mask)) ret |= eval(u0v0_mask,This->child[0],2.0f*u,2.0f*v,2.0f*dscale,depth+1);
  49. if (any(u1v0_mask)) ret |= eval(u1v0_mask,This->child[1],2.0f*u-1.0f,2.0f*v,2.0f*dscale,depth+1);
  50. if (any(u1v1_mask)) ret |= eval(u1v1_mask,This->child[2],2.0f*u-1.0f,2.0f*v-1.0f,2.0f*dscale,depth+1);
  51. if (any(u0v1_mask)) ret |= eval(u0v1_mask,This->child[3],2.0f*u,2.0f*v-1.0f,2.0f*dscale,depth+1);
  52. return ret;
  53. }
  54. vbool eval_general(const vbool& valid, const typename Patch::SubdividedGeneralPatch* patch, const vfloat& U, const vfloat& V, const size_t depth)
  55. {
  56. vbool ret = false;
  57. const vint l = (vint)floor(0.5f*U); const vfloat u = 2.0f*frac(0.5f*U)-0.5f;
  58. const vint h = (vint)floor(0.5f*V); const vfloat v = 2.0f*frac(0.5f*V)-0.5f;
  59. const vint i = (h<<2)+l; assert(all(valid,i<patch->N));
  60. foreach_unique(valid,i,[&](const vbool& valid, const int i) {
  61. ret |= eval(valid,patch->child[i],u,v,1.0f,depth+1);
  62. });
  63. return ret;
  64. }
  65. vbool eval(const vbool& valid, Ref This, const vfloat& u, const vfloat& v, const float dscale, const size_t depth)
  66. {
  67. if (!This) return false;
  68. switch (This.type())
  69. {
  70. case Patch::BILINEAR_PATCH: {
  71. ((typename Patch::BilinearPatch*)This.object())->patch.eval(valid,u,v,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,dscale,dstride,N);
  72. return valid;
  73. }
  74. case Patch::BSPLINE_PATCH: {
  75. ((typename Patch::BSplinePatch*)This.object())->patch.eval(valid,u,v,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,dscale,dstride,N);
  76. return valid;
  77. }
  78. case Patch::BEZIER_PATCH: {
  79. ((typename Patch::BezierPatch*)This.object())->patch.eval(valid,u,v,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,dscale,dstride,N);
  80. return valid;
  81. }
  82. case Patch::GREGORY_PATCH: {
  83. ((typename Patch::GregoryPatch*)This.object())->patch.eval(valid,u,v,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,dscale,dstride,N);
  84. return valid;
  85. }
  86. case Patch::SUBDIVIDED_QUAD_PATCH: {
  87. return eval_quad(valid,((typename Patch::SubdividedQuadPatch*)This.object()),u,v,dscale,depth);
  88. }
  89. case Patch::SUBDIVIDED_GENERAL_PATCH: {
  90. assert(dscale == 1.0f);
  91. return eval_general(valid,((typename Patch::SubdividedGeneralPatch*)This.object()),u,v,depth);
  92. }
  93. case Patch::EVAL_PATCH: {
  94. CatmullClarkPatch patch; patch.deserialize(This.object());
  95. FeatureAdaptiveEvalSimd<vbool,vint,vfloat,Vertex,Vertex_t>(patch,valid,u,v,dscale,depth,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,dstride,N);
  96. return valid;
  97. }
  98. default:
  99. assert(false);
  100. return false;
  101. }
  102. }
  103. private:
  104. float* const P;
  105. float* const dPdu;
  106. float* const dPdv;
  107. float* const ddPdudu;
  108. float* const ddPdvdv;
  109. float* const ddPdudv;
  110. const size_t dstride;
  111. const size_t N;
  112. };
  113. }
  114. }