scene.cpp 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955
  1. // Copyright 2009-2021 Intel Corporation
  2. // SPDX-License-Identifier: Apache-2.0
  3. #include "scene.h"
  4. #include "../bvh/bvh4_factory.h"
  5. #include "../bvh/bvh8_factory.h"
  6. #include "../../common/algorithms/parallel_reduce.h"
  7. namespace embree
  8. {
  9. /* error raising rtcIntersect and rtcOccluded functions */
  10. void missing_rtcCommit() { throw_RTCError(RTC_ERROR_INVALID_OPERATION,"scene not committed"); }
  11. void invalid_rtcIntersect1() { throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcIntersect and rtcOccluded not enabled"); }
  12. void invalid_rtcIntersect4() { throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcIntersect4 and rtcOccluded4 not enabled"); }
  13. void invalid_rtcIntersect8() { throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcIntersect8 and rtcOccluded8 not enabled"); }
  14. void invalid_rtcIntersect16() { throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcIntersect16 and rtcOccluded16 not enabled"); }
  15. void invalid_rtcIntersectN() { throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcIntersectN and rtcOccludedN not enabled"); }
  16. Scene::Scene (Device* device)
  17. : device(device),
  18. flags_modified(true), enabled_geometry_types(0),
  19. scene_flags(RTC_SCENE_FLAG_NONE),
  20. quality_flags(RTC_BUILD_QUALITY_MEDIUM),
  21. is_build(false), modified(true),
  22. progressInterface(this), progress_monitor_function(nullptr), progress_monitor_ptr(nullptr), progress_monitor_counter(0)
  23. {
  24. device->refInc();
  25. intersectors = Accel::Intersectors(missing_rtcCommit);
  26. /* one can overwrite flags through device for debugging */
  27. if (device->quality_flags != -1)
  28. quality_flags = (RTCBuildQuality) device->quality_flags;
  29. if (device->scene_flags != -1)
  30. scene_flags = (RTCSceneFlags) device->scene_flags;
  31. }
  32. Scene::~Scene() noexcept
  33. {
  34. device->refDec();
  35. }
  36. void Scene::printStatistics()
  37. {
  38. /* calculate maximum number of time segments */
  39. unsigned max_time_steps = 0;
  40. for (size_t i=0; i<size(); i++) {
  41. if (!get(i)) continue;
  42. max_time_steps = max(max_time_steps,get(i)->numTimeSteps);
  43. }
  44. /* initialize vectors*/
  45. std::vector<size_t> statistics[Geometry::GTY_END];
  46. for (size_t i=0; i<Geometry::GTY_END; i++)
  47. statistics[i].resize(max_time_steps);
  48. /* gather statistics */
  49. for (size_t i=0; i<size(); i++)
  50. {
  51. if (!get(i)) continue;
  52. int ty = get(i)->getType();
  53. assert(ty<Geometry::GTY_END);
  54. int timesegments = get(i)->numTimeSegments();
  55. assert((unsigned int)timesegments < max_time_steps);
  56. statistics[ty][timesegments] += get(i)->size();
  57. }
  58. /* print statistics */
  59. std::cout << std::setw(23) << "segments" << ": ";
  60. for (size_t t=0; t<max_time_steps; t++)
  61. std::cout << std::setw(10) << t;
  62. std::cout << std::endl;
  63. std::cout << "-------------------------";
  64. for (size_t t=0; t<max_time_steps; t++)
  65. std::cout << "----------";
  66. std::cout << std::endl;
  67. for (size_t p=0; p<Geometry::GTY_END; p++)
  68. {
  69. if (std::string(Geometry::gtype_names[p]) == "") continue;
  70. std::cout << std::setw(23) << Geometry::gtype_names[p] << ": ";
  71. for (size_t t=0; t<max_time_steps; t++)
  72. std::cout << std::setw(10) << statistics[p][t];
  73. std::cout << std::endl;
  74. }
  75. }
  76. void Scene::createTriangleAccel()
  77. {
  78. #if defined(EMBREE_GEOMETRY_TRIANGLE)
  79. if (device->tri_accel == "default")
  80. {
  81. if (quality_flags != RTC_BUILD_QUALITY_LOW)
  82. {
  83. int mode = 2*(int)isCompactAccel() + 1*(int)isRobustAccel();
  84. switch (mode) {
  85. case /*0b00*/ 0:
  86. #if defined (EMBREE_TARGET_SIMD8)
  87. if (device->canUseAVX())
  88. {
  89. if (quality_flags == RTC_BUILD_QUALITY_HIGH)
  90. accels_add(device->bvh8_factory->BVH8Triangle4(this,BVHFactory::BuildVariant::HIGH_QUALITY,BVHFactory::IntersectVariant::FAST));
  91. else
  92. accels_add(device->bvh8_factory->BVH8Triangle4(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST));
  93. }
  94. else
  95. #endif
  96. {
  97. if (quality_flags == RTC_BUILD_QUALITY_HIGH)
  98. accels_add(device->bvh4_factory->BVH4Triangle4(this,BVHFactory::BuildVariant::HIGH_QUALITY,BVHFactory::IntersectVariant::FAST));
  99. else
  100. accels_add(device->bvh4_factory->BVH4Triangle4(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST));
  101. }
  102. break;
  103. case /*0b01*/ 1:
  104. #if defined (EMBREE_TARGET_SIMD8)
  105. if (device->canUseAVX())
  106. accels_add(device->bvh8_factory->BVH8Triangle4v(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST));
  107. else
  108. #endif
  109. accels_add(device->bvh4_factory->BVH4Triangle4v(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST));
  110. break;
  111. case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4Triangle4i(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST )); break;
  112. case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4Triangle4i(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST)); break;
  113. }
  114. }
  115. else /* dynamic */
  116. {
  117. #if defined (EMBREE_TARGET_SIMD8)
  118. if (device->canUseAVX())
  119. {
  120. int mode = 2*(int)isCompactAccel() + 1*(int)isRobustAccel();
  121. switch (mode) {
  122. case /*0b00*/ 0: accels_add(device->bvh8_factory->BVH8Triangle4 (this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::FAST )); break;
  123. case /*0b01*/ 1: accels_add(device->bvh8_factory->BVH8Triangle4v(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::ROBUST)); break;
  124. case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4Triangle4i(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::FAST )); break;
  125. case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4Triangle4i(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::ROBUST)); break;
  126. }
  127. }
  128. else
  129. #endif
  130. {
  131. int mode = 2*(int)isCompactAccel() + 1*(int)isRobustAccel();
  132. switch (mode) {
  133. case /*0b00*/ 0: accels_add(device->bvh4_factory->BVH4Triangle4 (this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::FAST )); break;
  134. case /*0b01*/ 1: accels_add(device->bvh4_factory->BVH4Triangle4v(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::ROBUST)); break;
  135. case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4Triangle4i(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::FAST )); break;
  136. case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4Triangle4i(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::ROBUST)); break;
  137. }
  138. }
  139. }
  140. }
  141. else if (device->tri_accel == "bvh4.triangle4") accels_add(device->bvh4_factory->BVH4Triangle4 (this));
  142. else if (device->tri_accel == "bvh4.triangle4v") accels_add(device->bvh4_factory->BVH4Triangle4v(this));
  143. else if (device->tri_accel == "bvh4.triangle4i") accels_add(device->bvh4_factory->BVH4Triangle4i(this));
  144. else if (device->tri_accel == "qbvh4.triangle4i") accels_add(device->bvh4_factory->BVH4QuantizedTriangle4i(this));
  145. #if defined (EMBREE_TARGET_SIMD8)
  146. else if (device->tri_accel == "bvh8.triangle4") accels_add(device->bvh8_factory->BVH8Triangle4 (this));
  147. else if (device->tri_accel == "bvh8.triangle4v") accels_add(device->bvh8_factory->BVH8Triangle4v(this));
  148. else if (device->tri_accel == "bvh8.triangle4i") accels_add(device->bvh8_factory->BVH8Triangle4i(this));
  149. else if (device->tri_accel == "qbvh8.triangle4i") accels_add(device->bvh8_factory->BVH8QuantizedTriangle4i(this));
  150. else if (device->tri_accel == "qbvh8.triangle4") accels_add(device->bvh8_factory->BVH8QuantizedTriangle4(this));
  151. #endif
  152. else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown triangle acceleration structure "+device->tri_accel);
  153. #endif
  154. }
  155. void Scene::createTriangleMBAccel()
  156. {
  157. #if defined(EMBREE_GEOMETRY_TRIANGLE)
  158. if (device->tri_accel_mb == "default")
  159. {
  160. int mode = 2*(int)isCompactAccel() + 1*(int)isRobustAccel();
  161. #if defined (EMBREE_TARGET_SIMD8)
  162. if (device->canUseAVX2()) // BVH8 reduces performance on AVX only-machines
  163. {
  164. switch (mode) {
  165. case /*0b00*/ 0: accels_add(device->bvh8_factory->BVH8Triangle4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST )); break;
  166. case /*0b01*/ 1: accels_add(device->bvh8_factory->BVH8Triangle4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST)); break;
  167. case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4Triangle4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST )); break;
  168. case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4Triangle4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST)); break;
  169. }
  170. }
  171. else
  172. #endif
  173. {
  174. switch (mode) {
  175. case /*0b00*/ 0: accels_add(device->bvh4_factory->BVH4Triangle4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST )); break;
  176. case /*0b01*/ 1: accels_add(device->bvh4_factory->BVH4Triangle4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST)); break;
  177. case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4Triangle4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST )); break;
  178. case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4Triangle4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST)); break;
  179. }
  180. }
  181. }
  182. else if (device->tri_accel_mb == "bvh4.triangle4imb") accels_add(device->bvh4_factory->BVH4Triangle4iMB(this));
  183. else if (device->tri_accel_mb == "bvh4.triangle4vmb") accels_add(device->bvh4_factory->BVH4Triangle4vMB(this));
  184. #if defined (EMBREE_TARGET_SIMD8)
  185. else if (device->tri_accel_mb == "bvh8.triangle4imb") accels_add(device->bvh8_factory->BVH8Triangle4iMB(this));
  186. else if (device->tri_accel_mb == "bvh8.triangle4vmb") accels_add(device->bvh8_factory->BVH8Triangle4vMB(this));
  187. #endif
  188. else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown motion blur triangle acceleration structure "+device->tri_accel_mb);
  189. #endif
  190. }
  191. void Scene::createQuadAccel()
  192. {
  193. #if defined(EMBREE_GEOMETRY_QUAD)
  194. if (device->quad_accel == "default")
  195. {
  196. if (quality_flags != RTC_BUILD_QUALITY_LOW)
  197. {
  198. /* static */
  199. int mode = 2*(int)isCompactAccel() + 1*(int)isRobustAccel();
  200. switch (mode) {
  201. case /*0b00*/ 0:
  202. #if defined (EMBREE_TARGET_SIMD8)
  203. if (device->canUseAVX())
  204. {
  205. if (quality_flags == RTC_BUILD_QUALITY_HIGH)
  206. accels_add(device->bvh8_factory->BVH8Quad4v(this,BVHFactory::BuildVariant::HIGH_QUALITY,BVHFactory::IntersectVariant::FAST));
  207. else
  208. accels_add(device->bvh8_factory->BVH8Quad4v(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST));
  209. }
  210. else
  211. #endif
  212. {
  213. if (quality_flags == RTC_BUILD_QUALITY_HIGH)
  214. accels_add(device->bvh4_factory->BVH4Quad4v(this,BVHFactory::BuildVariant::HIGH_QUALITY,BVHFactory::IntersectVariant::FAST));
  215. else
  216. accels_add(device->bvh4_factory->BVH4Quad4v(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST));
  217. }
  218. break;
  219. case /*0b01*/ 1:
  220. #if defined (EMBREE_TARGET_SIMD8)
  221. if (device->canUseAVX())
  222. accels_add(device->bvh8_factory->BVH8Quad4v(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST));
  223. else
  224. #endif
  225. accels_add(device->bvh4_factory->BVH4Quad4v(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST));
  226. break;
  227. case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4Quad4i(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST)); break;
  228. case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4Quad4i(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST)); break;
  229. }
  230. }
  231. else /* dynamic */
  232. {
  233. #if defined (EMBREE_TARGET_SIMD8)
  234. if (device->canUseAVX())
  235. {
  236. int mode = 2*(int)isCompactAccel() + 1*(int)isRobustAccel();
  237. switch (mode) {
  238. case /*0b00*/ 0: accels_add(device->bvh8_factory->BVH8Quad4v(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::FAST)); break;
  239. case /*0b01*/ 1: accels_add(device->bvh8_factory->BVH8Quad4v(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::ROBUST)); break;
  240. case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4Quad4v(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::FAST)); break;
  241. case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4Quad4v(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::ROBUST)); break;
  242. }
  243. }
  244. else
  245. #endif
  246. {
  247. int mode = 2*(int)isCompactAccel() + 1*(int)isRobustAccel();
  248. switch (mode) {
  249. case /*0b00*/ 0: accels_add(device->bvh4_factory->BVH4Quad4v(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::FAST)); break;
  250. case /*0b01*/ 1: accels_add(device->bvh4_factory->BVH4Quad4v(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::ROBUST)); break;
  251. case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4Quad4v(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::FAST)); break;
  252. case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4Quad4v(this,BVHFactory::BuildVariant::DYNAMIC,BVHFactory::IntersectVariant::ROBUST)); break;
  253. }
  254. }
  255. }
  256. }
  257. else if (device->quad_accel == "bvh4.quad4v") accels_add(device->bvh4_factory->BVH4Quad4v(this));
  258. else if (device->quad_accel == "bvh4.quad4i") accels_add(device->bvh4_factory->BVH4Quad4i(this));
  259. else if (device->quad_accel == "qbvh4.quad4i") accels_add(device->bvh4_factory->BVH4QuantizedQuad4i(this));
  260. #if defined (EMBREE_TARGET_SIMD8)
  261. else if (device->quad_accel == "bvh8.quad4v") accels_add(device->bvh8_factory->BVH8Quad4v(this));
  262. else if (device->quad_accel == "bvh8.quad4i") accels_add(device->bvh8_factory->BVH8Quad4i(this));
  263. else if (device->quad_accel == "qbvh8.quad4i") accels_add(device->bvh8_factory->BVH8QuantizedQuad4i(this));
  264. #endif
  265. else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown quad acceleration structure "+device->quad_accel);
  266. #endif
  267. }
  268. void Scene::createQuadMBAccel()
  269. {
  270. #if defined(EMBREE_GEOMETRY_QUAD)
  271. if (device->quad_accel_mb == "default")
  272. {
  273. int mode = 2*(int)isCompactAccel() + 1*(int)isRobustAccel();
  274. switch (mode) {
  275. case /*0b00*/ 0:
  276. #if defined (EMBREE_TARGET_SIMD8)
  277. if (device->canUseAVX())
  278. accels_add(device->bvh8_factory->BVH8Quad4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST));
  279. else
  280. #endif
  281. accels_add(device->bvh4_factory->BVH4Quad4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST));
  282. break;
  283. case /*0b01*/ 1:
  284. #if defined (EMBREE_TARGET_SIMD8)
  285. if (device->canUseAVX())
  286. accels_add(device->bvh8_factory->BVH8Quad4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST));
  287. else
  288. #endif
  289. accels_add(device->bvh4_factory->BVH4Quad4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST));
  290. break;
  291. case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4Quad4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST )); break;
  292. case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4Quad4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST)); break;
  293. }
  294. }
  295. else if (device->quad_accel_mb == "bvh4.quad4imb") accels_add(device->bvh4_factory->BVH4Quad4iMB(this));
  296. #if defined (EMBREE_TARGET_SIMD8)
  297. else if (device->quad_accel_mb == "bvh8.quad4imb") accels_add(device->bvh8_factory->BVH8Quad4iMB(this));
  298. #endif
  299. else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown quad motion blur acceleration structure "+device->quad_accel_mb);
  300. #endif
  301. }
  302. void Scene::createHairAccel()
  303. {
  304. #if defined(EMBREE_GEOMETRY_CURVE) || defined(EMBREE_GEOMETRY_POINT)
  305. if (device->hair_accel == "default")
  306. {
  307. int mode = 2*(int)isCompactAccel() + 1*(int)isRobustAccel();
  308. #if defined (EMBREE_TARGET_SIMD8)
  309. if (device->canUseAVX2()) // only enable on HSW machines, for SNB this codepath is slower
  310. {
  311. switch (mode) {
  312. case /*0b00*/ 0: accels_add(device->bvh8_factory->BVH8OBBVirtualCurve8v(this,BVHFactory::IntersectVariant::FAST)); break;
  313. case /*0b01*/ 1: accels_add(device->bvh8_factory->BVH8OBBVirtualCurve8v(this,BVHFactory::IntersectVariant::ROBUST)); break;
  314. case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4OBBVirtualCurve8i(this,BVHFactory::IntersectVariant::FAST)); break;
  315. case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4OBBVirtualCurve8i(this,BVHFactory::IntersectVariant::ROBUST)); break;
  316. }
  317. }
  318. else
  319. #endif
  320. {
  321. switch (mode) {
  322. case /*0b00*/ 0: accels_add(device->bvh4_factory->BVH4OBBVirtualCurve4v(this,BVHFactory::IntersectVariant::FAST)); break;
  323. case /*0b01*/ 1: accels_add(device->bvh4_factory->BVH4OBBVirtualCurve4v(this,BVHFactory::IntersectVariant::ROBUST)); break;
  324. case /*0b10*/ 2: accels_add(device->bvh4_factory->BVH4OBBVirtualCurve4i(this,BVHFactory::IntersectVariant::FAST)); break;
  325. case /*0b11*/ 3: accels_add(device->bvh4_factory->BVH4OBBVirtualCurve4i(this,BVHFactory::IntersectVariant::ROBUST)); break;
  326. }
  327. }
  328. }
  329. else if (device->hair_accel == "bvh4obb.virtualcurve4v" ) accels_add(device->bvh4_factory->BVH4OBBVirtualCurve4v(this,BVHFactory::IntersectVariant::FAST));
  330. else if (device->hair_accel == "bvh4obb.virtualcurve4i" ) accels_add(device->bvh4_factory->BVH4OBBVirtualCurve4i(this,BVHFactory::IntersectVariant::FAST));
  331. #if defined (EMBREE_TARGET_SIMD8)
  332. else if (device->hair_accel == "bvh8obb.virtualcurve8v" ) accels_add(device->bvh8_factory->BVH8OBBVirtualCurve8v(this,BVHFactory::IntersectVariant::FAST));
  333. else if (device->hair_accel == "bvh4obb.virtualcurve8i" ) accels_add(device->bvh4_factory->BVH4OBBVirtualCurve8i(this,BVHFactory::IntersectVariant::FAST));
  334. #endif
  335. else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown hair acceleration structure "+device->hair_accel);
  336. #endif
  337. }
  338. void Scene::createHairMBAccel()
  339. {
  340. #if defined(EMBREE_GEOMETRY_CURVE) || defined(EMBREE_GEOMETRY_POINT)
  341. if (device->hair_accel_mb == "default")
  342. {
  343. #if defined (EMBREE_TARGET_SIMD8)
  344. if (device->canUseAVX2()) // only enable on HSW machines, on SNB this codepath is slower
  345. {
  346. if (isRobustAccel()) accels_add(device->bvh8_factory->BVH8OBBVirtualCurve8iMB(this,BVHFactory::IntersectVariant::ROBUST));
  347. else accels_add(device->bvh8_factory->BVH8OBBVirtualCurve8iMB(this,BVHFactory::IntersectVariant::FAST));
  348. }
  349. else
  350. #endif
  351. {
  352. if (isRobustAccel()) accels_add(device->bvh4_factory->BVH4OBBVirtualCurve4iMB(this,BVHFactory::IntersectVariant::ROBUST));
  353. else accels_add(device->bvh4_factory->BVH4OBBVirtualCurve4iMB(this,BVHFactory::IntersectVariant::FAST));
  354. }
  355. }
  356. else if (device->hair_accel_mb == "bvh4.virtualcurve4imb") accels_add(device->bvh4_factory->BVH4OBBVirtualCurve4iMB(this,BVHFactory::IntersectVariant::FAST));
  357. #if defined (EMBREE_TARGET_SIMD8)
  358. else if (device->hair_accel_mb == "bvh4.virtualcurve8imb") accels_add(device->bvh4_factory->BVH4OBBVirtualCurve8iMB(this,BVHFactory::IntersectVariant::FAST));
  359. else if (device->hair_accel_mb == "bvh8.virtualcurve8imb") accels_add(device->bvh8_factory->BVH8OBBVirtualCurve8iMB(this,BVHFactory::IntersectVariant::FAST));
  360. #endif
  361. else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown motion blur hair acceleration structure "+device->hair_accel_mb);
  362. #endif
  363. }
  364. void Scene::createSubdivAccel()
  365. {
  366. #if defined(EMBREE_GEOMETRY_SUBDIVISION)
  367. if (device->subdiv_accel == "default") {
  368. accels_add(device->bvh4_factory->BVH4SubdivPatch1(this));
  369. }
  370. else if (device->subdiv_accel == "bvh4.grid.eager" ) accels_add(device->bvh4_factory->BVH4SubdivPatch1(this));
  371. else if (device->subdiv_accel == "bvh4.subdivpatch1eager" ) accels_add(device->bvh4_factory->BVH4SubdivPatch1(this));
  372. else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown subdiv accel "+device->subdiv_accel);
  373. #endif
  374. }
  375. void Scene::createSubdivMBAccel()
  376. {
  377. #if defined(EMBREE_GEOMETRY_SUBDIVISION)
  378. if (device->subdiv_accel_mb == "default") {
  379. accels_add(device->bvh4_factory->BVH4SubdivPatch1MB(this));
  380. }
  381. else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown subdiv mblur accel "+device->subdiv_accel_mb);
  382. #endif
  383. }
  384. void Scene::createUserGeometryAccel()
  385. {
  386. #if defined(EMBREE_GEOMETRY_USER)
  387. if (device->object_accel == "default")
  388. {
  389. #if defined (EMBREE_TARGET_SIMD8)
  390. if (device->canUseAVX() && !isCompactAccel())
  391. {
  392. if (quality_flags != RTC_BUILD_QUALITY_LOW) {
  393. accels_add(device->bvh8_factory->BVH8UserGeometry(this,BVHFactory::BuildVariant::STATIC));
  394. } else {
  395. accels_add(device->bvh8_factory->BVH8UserGeometry(this,BVHFactory::BuildVariant::DYNAMIC));
  396. }
  397. }
  398. else
  399. #endif
  400. {
  401. if (quality_flags != RTC_BUILD_QUALITY_LOW) {
  402. accels_add(device->bvh4_factory->BVH4UserGeometry(this,BVHFactory::BuildVariant::STATIC));
  403. } else {
  404. accels_add(device->bvh4_factory->BVH4UserGeometry(this,BVHFactory::BuildVariant::DYNAMIC));
  405. }
  406. }
  407. }
  408. else if (device->object_accel == "bvh4.object") accels_add(device->bvh4_factory->BVH4UserGeometry(this));
  409. #if defined (EMBREE_TARGET_SIMD8)
  410. else if (device->object_accel == "bvh8.object") accels_add(device->bvh8_factory->BVH8UserGeometry(this));
  411. #endif
  412. else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown user geometry accel "+device->object_accel);
  413. #endif
  414. }
  415. void Scene::createUserGeometryMBAccel()
  416. {
  417. #if defined(EMBREE_GEOMETRY_USER)
  418. if (device->object_accel_mb == "default" ) {
  419. #if defined (EMBREE_TARGET_SIMD8)
  420. if (device->canUseAVX() && !isCompactAccel())
  421. accels_add(device->bvh8_factory->BVH8UserGeometryMB(this));
  422. else
  423. #endif
  424. accels_add(device->bvh4_factory->BVH4UserGeometryMB(this));
  425. }
  426. else if (device->object_accel_mb == "bvh4.object") accels_add(device->bvh4_factory->BVH4UserGeometryMB(this));
  427. #if defined (EMBREE_TARGET_SIMD8)
  428. else if (device->object_accel_mb == "bvh8.object") accels_add(device->bvh8_factory->BVH8UserGeometryMB(this));
  429. #endif
  430. else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown user geometry mblur accel "+device->object_accel_mb);
  431. #endif
  432. }
  433. void Scene::createInstanceAccel()
  434. {
  435. #if defined(EMBREE_GEOMETRY_INSTANCE)
  436. // if (device->object_accel == "default")
  437. {
  438. #if defined (EMBREE_TARGET_SIMD8)
  439. if (device->canUseAVX() && !isCompactAccel()) {
  440. if (quality_flags != RTC_BUILD_QUALITY_LOW) {
  441. accels_add(device->bvh8_factory->BVH8Instance(this, false, BVHFactory::BuildVariant::STATIC));
  442. } else {
  443. accels_add(device->bvh8_factory->BVH8Instance(this, false, BVHFactory::BuildVariant::DYNAMIC));
  444. }
  445. }
  446. else
  447. #endif
  448. {
  449. if (quality_flags != RTC_BUILD_QUALITY_LOW) {
  450. accels_add(device->bvh4_factory->BVH4Instance(this, false, BVHFactory::BuildVariant::STATIC));
  451. } else {
  452. accels_add(device->bvh4_factory->BVH4Instance(this, false, BVHFactory::BuildVariant::DYNAMIC));
  453. }
  454. }
  455. }
  456. // else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown instance accel "+device->instance_accel);
  457. #endif
  458. }
  459. void Scene::createInstanceMBAccel()
  460. {
  461. #if defined(EMBREE_GEOMETRY_INSTANCE)
  462. //if (device->instance_accel_mb == "default")
  463. {
  464. #if defined (EMBREE_TARGET_SIMD8)
  465. if (device->canUseAVX() && !isCompactAccel())
  466. accels_add(device->bvh8_factory->BVH8InstanceMB(this, false));
  467. else
  468. #endif
  469. accels_add(device->bvh4_factory->BVH4InstanceMB(this, false));
  470. }
  471. //else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown instance mblur accel "+device->instance_accel_mb);
  472. #endif
  473. }
  474. void Scene::createInstanceExpensiveAccel()
  475. {
  476. #if defined(EMBREE_GEOMETRY_INSTANCE)
  477. // if (device->object_accel == "default")
  478. {
  479. #if defined (EMBREE_TARGET_SIMD8)
  480. if (device->canUseAVX() && !isCompactAccel()) {
  481. if (quality_flags != RTC_BUILD_QUALITY_LOW) {
  482. accels_add(device->bvh8_factory->BVH8Instance(this, true, BVHFactory::BuildVariant::STATIC));
  483. } else {
  484. accels_add(device->bvh8_factory->BVH8Instance(this, true, BVHFactory::BuildVariant::DYNAMIC));
  485. }
  486. }
  487. else
  488. #endif
  489. {
  490. if (quality_flags != RTC_BUILD_QUALITY_LOW) {
  491. accels_add(device->bvh4_factory->BVH4Instance(this, true, BVHFactory::BuildVariant::STATIC));
  492. } else {
  493. accels_add(device->bvh4_factory->BVH4Instance(this, true, BVHFactory::BuildVariant::DYNAMIC));
  494. }
  495. }
  496. }
  497. // else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown instance accel "+device->instance_accel);
  498. #endif
  499. }
  500. void Scene::createInstanceExpensiveMBAccel()
  501. {
  502. #if defined(EMBREE_GEOMETRY_INSTANCE)
  503. //if (device->instance_accel_mb == "default")
  504. {
  505. #if defined (EMBREE_TARGET_SIMD8)
  506. if (device->canUseAVX() && !isCompactAccel())
  507. accels_add(device->bvh8_factory->BVH8InstanceMB(this, true));
  508. else
  509. #endif
  510. accels_add(device->bvh4_factory->BVH4InstanceMB(this, true));
  511. }
  512. //else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown instance mblur accel "+device->instance_accel_mb);
  513. #endif
  514. }
  515. void Scene::createGridAccel()
  516. {
  517. BVHFactory::IntersectVariant ivariant = isRobustAccel() ? BVHFactory::IntersectVariant::ROBUST : BVHFactory::IntersectVariant::FAST;
  518. #if defined(EMBREE_GEOMETRY_GRID)
  519. if (device->grid_accel == "default")
  520. {
  521. #if defined (EMBREE_TARGET_SIMD8)
  522. if (device->canUseAVX() && !isCompactAccel())
  523. {
  524. accels_add(device->bvh8_factory->BVH8Grid(this,BVHFactory::BuildVariant::STATIC,ivariant));
  525. }
  526. else
  527. #endif
  528. {
  529. accels_add(device->bvh4_factory->BVH4Grid(this,BVHFactory::BuildVariant::STATIC,ivariant));
  530. }
  531. }
  532. else if (device->grid_accel == "bvh4.grid") accels_add(device->bvh4_factory->BVH4Grid(this,BVHFactory::BuildVariant::STATIC,ivariant));
  533. #if defined (EMBREE_TARGET_SIMD8)
  534. else if (device->grid_accel == "bvh8.grid") accels_add(device->bvh8_factory->BVH8Grid(this,BVHFactory::BuildVariant::STATIC,ivariant));
  535. #endif
  536. else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown grid accel "+device->grid_accel);
  537. #endif
  538. }
  539. void Scene::createGridMBAccel()
  540. {
  541. #if defined(EMBREE_GEOMETRY_GRID)
  542. if (device->grid_accel_mb == "default")
  543. {
  544. accels_add(device->bvh4_factory->BVH4GridMB(this,BVHFactory::BuildVariant::STATIC));
  545. }
  546. else if (device->grid_accel_mb == "bvh4mb.grid") accels_add(device->bvh4_factory->BVH4GridMB(this));
  547. else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown grid mb accel "+device->grid_accel);
  548. #endif
  549. }
  550. void Scene::clear() {
  551. }
  552. unsigned Scene::bind(unsigned geomID, Ref<Geometry> geometry)
  553. {
  554. Lock<SpinLock> lock(geometriesMutex);
  555. if (geomID == RTC_INVALID_GEOMETRY_ID) {
  556. geomID = id_pool.allocate();
  557. if (geomID == RTC_INVALID_GEOMETRY_ID)
  558. throw_RTCError(RTC_ERROR_INVALID_OPERATION,"too many geometries inside scene");
  559. }
  560. else
  561. {
  562. if (!id_pool.add(geomID))
  563. throw_RTCError(RTC_ERROR_INVALID_OPERATION,"invalid geometry ID provided");
  564. }
  565. if (geomID >= geometries.size()) {
  566. geometries.resize(geomID+1);
  567. vertices.resize(geomID+1);
  568. geometryModCounters_.resize(geomID+1);
  569. }
  570. geometries[geomID] = geometry;
  571. geometryModCounters_[geomID] = 0;
  572. if (geometry->isEnabled()) {
  573. setModified ();
  574. }
  575. return geomID;
  576. }
  577. void Scene::detachGeometry(size_t geomID)
  578. {
  579. Lock<SpinLock> lock(geometriesMutex);
  580. if (geomID >= geometries.size())
  581. throw_RTCError(RTC_ERROR_INVALID_OPERATION,"invalid geometry ID");
  582. Ref<Geometry>& geometry = geometries[geomID];
  583. if (geometry == null)
  584. throw_RTCError(RTC_ERROR_INVALID_OPERATION,"invalid geometry");
  585. if (geometry->isEnabled()) {
  586. setModified ();
  587. }
  588. accels_deleteGeometry(unsigned(geomID));
  589. id_pool.deallocate((unsigned)geomID);
  590. geometries[geomID] = null;
  591. vertices[geomID] = nullptr;
  592. geometryModCounters_[geomID] = 0;
  593. }
  594. void Scene::updateInterface()
  595. {
  596. is_build = true;
  597. }
  598. void Scene::commit_task ()
  599. {
  600. checkIfModifiedAndSet ();
  601. if (!isModified()) {
  602. return;
  603. }
  604. /* print scene statistics */
  605. if (device->verbosity(2))
  606. printStatistics();
  607. progress_monitor_counter = 0;
  608. /* gather scene stats and call preCommit function of each geometry */
  609. this->world = parallel_reduce (size_t(0), geometries.size(), GeometryCounts (),
  610. [this](const range<size_t>& r)->GeometryCounts
  611. {
  612. GeometryCounts c;
  613. for (auto i=r.begin(); i<r.end(); ++i)
  614. {
  615. if (geometries[i] && geometries[i]->isEnabled())
  616. {
  617. geometries[i]->preCommit();
  618. geometries[i]->addElementsToCount (c);
  619. c.numFilterFunctions += (int) geometries[i]->hasFilterFunctions();
  620. }
  621. }
  622. return c;
  623. },
  624. std::plus<GeometryCounts>()
  625. );
  626. /* select acceleration structures to build */
  627. unsigned int new_enabled_geometry_types = world.enabledGeometryTypesMask();
  628. if (flags_modified || new_enabled_geometry_types != enabled_geometry_types)
  629. {
  630. accels_init();
  631. /* we need to make all geometries modified, otherwise two level builder will
  632. not rebuild currently not modified geometries */
  633. parallel_for(geometryModCounters_.size(), [&] ( const size_t i ) {
  634. geometryModCounters_[i] = 0;
  635. });
  636. if (getNumPrimitives(TriangleMesh::geom_type,false)) createTriangleAccel();
  637. if (getNumPrimitives(TriangleMesh::geom_type,true)) createTriangleMBAccel();
  638. if (getNumPrimitives(QuadMesh::geom_type,false)) createQuadAccel();
  639. if (getNumPrimitives(QuadMesh::geom_type,true)) createQuadMBAccel();
  640. if (getNumPrimitives(GridMesh::geom_type,false)) createGridAccel();
  641. if (getNumPrimitives(GridMesh::geom_type,true)) createGridMBAccel();
  642. if (getNumPrimitives(SubdivMesh::geom_type,false)) createSubdivAccel();
  643. if (getNumPrimitives(SubdivMesh::geom_type,true)) createSubdivMBAccel();
  644. if (getNumPrimitives(Geometry::MTY_CURVES,false)) createHairAccel();
  645. if (getNumPrimitives(Geometry::MTY_CURVES,true)) createHairMBAccel();
  646. if (getNumPrimitives(UserGeometry::geom_type,false)) createUserGeometryAccel();
  647. if (getNumPrimitives(UserGeometry::geom_type,true)) createUserGeometryMBAccel();
  648. if (getNumPrimitives(Geometry::MTY_INSTANCE_CHEAP,false)) createInstanceAccel();
  649. if (getNumPrimitives(Geometry::MTY_INSTANCE_CHEAP,true)) createInstanceMBAccel();
  650. if (getNumPrimitives(Geometry::MTY_INSTANCE_EXPENSIVE,false)) createInstanceExpensiveAccel();
  651. if (getNumPrimitives(Geometry::MTY_INSTANCE_EXPENSIVE,true)) createInstanceExpensiveMBAccel();
  652. flags_modified = false;
  653. enabled_geometry_types = new_enabled_geometry_types;
  654. }
  655. /* select fast code path if no filter function is present */
  656. accels_select(hasFilterFunction());
  657. /* build all hierarchies of this scene */
  658. accels_build();
  659. /* make static geometry immutable */
  660. if (!isDynamicAccel()) {
  661. accels_immutable();
  662. flags_modified = true; // in non-dynamic mode we have to re-create accels
  663. }
  664. /* call postCommit function of each geometry */
  665. parallel_for(geometries.size(), [&] ( const size_t i ) {
  666. if (geometries[i] && geometries[i]->isEnabled()) {
  667. geometries[i]->postCommit();
  668. vertices[i] = geometries[i]->getCompactVertexArray();
  669. geometryModCounters_[i] = geometries[i]->getModCounter();
  670. }
  671. });
  672. updateInterface();
  673. if (device->verbosity(2)) {
  674. std::cout << "created scene intersector" << std::endl;
  675. accels_print(2);
  676. std::cout << "selected scene intersector" << std::endl;
  677. intersectors.print(2);
  678. }
  679. setModified(false);
  680. }
  681. void Scene::setBuildQuality(RTCBuildQuality quality_flags_i)
  682. {
  683. if (quality_flags == quality_flags_i) return;
  684. quality_flags = quality_flags_i;
  685. flags_modified = true;
  686. }
  687. RTCBuildQuality Scene::getBuildQuality() const {
  688. return quality_flags;
  689. }
  690. void Scene::setSceneFlags(RTCSceneFlags scene_flags_i)
  691. {
  692. if (scene_flags == scene_flags_i) return;
  693. scene_flags = scene_flags_i;
  694. flags_modified = true;
  695. }
  696. RTCSceneFlags Scene::getSceneFlags() const {
  697. return scene_flags;
  698. }
  699. #if defined(TASKING_INTERNAL)
  700. void Scene::commit (bool join)
  701. {
  702. Lock<MutexSys> buildLock(buildMutex,false);
  703. /* allocates own taskscheduler for each build */
  704. Ref<TaskScheduler> scheduler = nullptr;
  705. {
  706. Lock<MutexSys> lock(schedulerMutex);
  707. scheduler = this->scheduler;
  708. if (scheduler == null) {
  709. buildLock.lock();
  710. this->scheduler = scheduler = new TaskScheduler;
  711. }
  712. }
  713. /* worker threads join build */
  714. if (!buildLock.isLocked())
  715. {
  716. if (!join)
  717. throw_RTCError(RTC_ERROR_INVALID_OPERATION,"use rtcJoinCommitScene to join a build operation");
  718. scheduler->join();
  719. return;
  720. }
  721. /* initiate build */
  722. // -- GODOT start --
  723. // try {
  724. scheduler->spawn_root([&]() { commit_task(); Lock<MutexSys> lock(schedulerMutex); this->scheduler = nullptr; }, 1, !join);
  725. // }
  726. // catch (...) {
  727. // accels_clear();
  728. // updateInterface();
  729. // Lock<MutexSys> lock(schedulerMutex);
  730. // this->scheduler = nullptr;
  731. // throw;
  732. // }
  733. // -- GODOT end --
  734. }
  735. #endif
  736. #if defined(TASKING_TBB)
  737. void Scene::commit (bool join)
  738. {
  739. #if defined(TASKING_TBB) && (TBB_INTERFACE_VERSION_MAJOR < 8)
  740. if (join)
  741. throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcJoinCommitScene not supported with this TBB version");
  742. #endif
  743. /* try to obtain build lock */
  744. Lock<MutexSys> lock(buildMutex,buildMutex.try_lock());
  745. /* join hierarchy build */
  746. if (!lock.isLocked())
  747. {
  748. #if !TASKING_TBB_USE_TASK_ISOLATION
  749. if (!join)
  750. throw_RTCError(RTC_ERROR_INVALID_OPERATION,"invoking rtcCommitScene from multiple threads is not supported with this TBB version");
  751. #endif
  752. do {
  753. #if USE_TASK_ARENA
  754. if (join) {
  755. device->arena->execute([&]{ group.wait(); });
  756. }
  757. else
  758. #endif
  759. {
  760. group.wait();
  761. }
  762. pause_cpu();
  763. yield();
  764. } while (!buildMutex.try_lock());
  765. buildMutex.unlock();
  766. return;
  767. }
  768. /* for best performance set FTZ and DAZ flags in the MXCSR control and status register */
  769. const unsigned int mxcsr = _mm_getcsr();
  770. _mm_setcsr(mxcsr | /* FTZ */ (1<<15) | /* DAZ */ (1<<6));
  771. try {
  772. #if TBB_INTERFACE_VERSION_MAJOR < 8
  773. tbb::task_group_context ctx( tbb::task_group_context::isolated, tbb::task_group_context::default_traits);
  774. #else
  775. tbb::task_group_context ctx( tbb::task_group_context::isolated, tbb::task_group_context::default_traits | tbb::task_group_context::fp_settings );
  776. #endif
  777. //ctx.set_priority(tbb::priority_high);
  778. #if USE_TASK_ARENA
  779. if (join)
  780. {
  781. device->arena->execute([&]{
  782. group.run([&]{
  783. tbb::parallel_for (size_t(0), size_t(1), size_t(1), [&] (size_t) { commit_task(); }, ctx);
  784. });
  785. group.wait();
  786. });
  787. }
  788. else
  789. #endif
  790. {
  791. group.run([&]{
  792. tbb::parallel_for (size_t(0), size_t(1), size_t(1), [&] (size_t) { commit_task(); }, ctx);
  793. });
  794. group.wait();
  795. }
  796. /* reset MXCSR register again */
  797. _mm_setcsr(mxcsr);
  798. }
  799. catch (...)
  800. {
  801. /* reset MXCSR register again */
  802. _mm_setcsr(mxcsr);
  803. accels_clear();
  804. updateInterface();
  805. throw;
  806. }
  807. }
  808. #endif
  809. #if defined(TASKING_PPL)
  810. void Scene::commit (bool join)
  811. {
  812. #if defined(TASKING_PPL)
  813. if (join)
  814. throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcJoinCommitScene not supported with PPL");
  815. #endif
  816. /* try to obtain build lock */
  817. Lock<MutexSys> lock(buildMutex);
  818. checkIfModifiedAndSet ();
  819. if (!isModified()) {
  820. return;
  821. }
  822. /* for best performance set FTZ and DAZ flags in the MXCSR control and status register */
  823. const unsigned int mxcsr = _mm_getcsr();
  824. _mm_setcsr(mxcsr | /* FTZ */ (1<<15) | /* DAZ */ (1<<6));
  825. try {
  826. group.run([&]{
  827. concurrency::parallel_for(size_t(0), size_t(1), size_t(1), [&](size_t) { commit_task(); });
  828. });
  829. group.wait();
  830. /* reset MXCSR register again */
  831. _mm_setcsr(mxcsr);
  832. }
  833. catch (...)
  834. {
  835. /* reset MXCSR register again */
  836. _mm_setcsr(mxcsr);
  837. accels_clear();
  838. updateInterface();
  839. throw;
  840. }
  841. }
  842. #endif
  843. void Scene::setProgressMonitorFunction(RTCProgressMonitorFunction func, void* ptr)
  844. {
  845. progress_monitor_function = func;
  846. progress_monitor_ptr = ptr;
  847. }
  848. void Scene::progressMonitor(double dn)
  849. {
  850. if (progress_monitor_function) {
  851. size_t n = size_t(dn) + progress_monitor_counter.fetch_add(size_t(dn));
  852. if (!progress_monitor_function(progress_monitor_ptr, n / (double(numPrimitives())))) {
  853. throw_RTCError(RTC_ERROR_CANCELLED,"progress monitor forced termination");
  854. }
  855. }
  856. }
  857. }