scene.cpp 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954
  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. setModified ();
  586. accels_deleteGeometry(unsigned(geomID));
  587. id_pool.deallocate((unsigned)geomID);
  588. geometries[geomID] = null;
  589. vertices[geomID] = nullptr;
  590. geometryModCounters_[geomID] = 0;
  591. }
  592. void Scene::updateInterface()
  593. {
  594. is_build = true;
  595. }
  596. void Scene::commit_task ()
  597. {
  598. checkIfModifiedAndSet ();
  599. if (!isModified()) {
  600. return;
  601. }
  602. /* print scene statistics */
  603. if (device->verbosity(2))
  604. printStatistics();
  605. progress_monitor_counter = 0;
  606. /* gather scene stats and call preCommit function of each geometry */
  607. this->world = parallel_reduce (size_t(0), geometries.size(), GeometryCounts (),
  608. [this](const range<size_t>& r)->GeometryCounts
  609. {
  610. GeometryCounts c;
  611. for (auto i=r.begin(); i<r.end(); ++i)
  612. {
  613. if (geometries[i] && geometries[i]->isEnabled())
  614. {
  615. geometries[i]->preCommit();
  616. geometries[i]->addElementsToCount (c);
  617. c.numFilterFunctions += (int) geometries[i]->hasFilterFunctions();
  618. }
  619. }
  620. return c;
  621. },
  622. std::plus<GeometryCounts>()
  623. );
  624. /* select acceleration structures to build */
  625. unsigned int new_enabled_geometry_types = world.enabledGeometryTypesMask();
  626. if (flags_modified || new_enabled_geometry_types != enabled_geometry_types)
  627. {
  628. accels_init();
  629. /* we need to make all geometries modified, otherwise two level builder will
  630. not rebuild currently not modified geometries */
  631. parallel_for(geometryModCounters_.size(), [&] ( const size_t i ) {
  632. geometryModCounters_[i] = 0;
  633. });
  634. if (getNumPrimitives(TriangleMesh::geom_type,false)) createTriangleAccel();
  635. if (getNumPrimitives(TriangleMesh::geom_type,true)) createTriangleMBAccel();
  636. if (getNumPrimitives(QuadMesh::geom_type,false)) createQuadAccel();
  637. if (getNumPrimitives(QuadMesh::geom_type,true)) createQuadMBAccel();
  638. if (getNumPrimitives(GridMesh::geom_type,false)) createGridAccel();
  639. if (getNumPrimitives(GridMesh::geom_type,true)) createGridMBAccel();
  640. if (getNumPrimitives(SubdivMesh::geom_type,false)) createSubdivAccel();
  641. if (getNumPrimitives(SubdivMesh::geom_type,true)) createSubdivMBAccel();
  642. if (getNumPrimitives(Geometry::MTY_CURVES,false)) createHairAccel();
  643. if (getNumPrimitives(Geometry::MTY_CURVES,true)) createHairMBAccel();
  644. if (getNumPrimitives(UserGeometry::geom_type,false)) createUserGeometryAccel();
  645. if (getNumPrimitives(UserGeometry::geom_type,true)) createUserGeometryMBAccel();
  646. if (getNumPrimitives(Geometry::MTY_INSTANCE_CHEAP,false)) createInstanceAccel();
  647. if (getNumPrimitives(Geometry::MTY_INSTANCE_CHEAP,true)) createInstanceMBAccel();
  648. if (getNumPrimitives(Geometry::MTY_INSTANCE_EXPENSIVE,false)) createInstanceExpensiveAccel();
  649. if (getNumPrimitives(Geometry::MTY_INSTANCE_EXPENSIVE,true)) createInstanceExpensiveMBAccel();
  650. flags_modified = false;
  651. enabled_geometry_types = new_enabled_geometry_types;
  652. }
  653. /* select fast code path if no filter function is present */
  654. accels_select(hasFilterFunction());
  655. /* build all hierarchies of this scene */
  656. accels_build();
  657. /* make static geometry immutable */
  658. if (!isDynamicAccel()) {
  659. accels_immutable();
  660. flags_modified = true; // in non-dynamic mode we have to re-create accels
  661. }
  662. /* call postCommit function of each geometry */
  663. parallel_for(geometries.size(), [&] ( const size_t i ) {
  664. if (geometries[i] && geometries[i]->isEnabled()) {
  665. geometries[i]->postCommit();
  666. vertices[i] = geometries[i]->getCompactVertexArray();
  667. geometryModCounters_[i] = geometries[i]->getModCounter();
  668. }
  669. });
  670. updateInterface();
  671. if (device->verbosity(2)) {
  672. std::cout << "created scene intersector" << std::endl;
  673. accels_print(2);
  674. std::cout << "selected scene intersector" << std::endl;
  675. intersectors.print(2);
  676. }
  677. setModified(false);
  678. }
  679. void Scene::setBuildQuality(RTCBuildQuality quality_flags_i)
  680. {
  681. if (quality_flags == quality_flags_i) return;
  682. quality_flags = quality_flags_i;
  683. flags_modified = true;
  684. }
  685. RTCBuildQuality Scene::getBuildQuality() const {
  686. return quality_flags;
  687. }
  688. void Scene::setSceneFlags(RTCSceneFlags scene_flags_i)
  689. {
  690. if (scene_flags == scene_flags_i) return;
  691. scene_flags = scene_flags_i;
  692. flags_modified = true;
  693. }
  694. RTCSceneFlags Scene::getSceneFlags() const {
  695. return scene_flags;
  696. }
  697. #if defined(TASKING_INTERNAL)
  698. void Scene::commit (bool join)
  699. {
  700. Lock<MutexSys> buildLock(buildMutex,false);
  701. /* allocates own taskscheduler for each build */
  702. Ref<TaskScheduler> scheduler = nullptr;
  703. {
  704. Lock<MutexSys> lock(schedulerMutex);
  705. scheduler = this->scheduler;
  706. if (scheduler == null) {
  707. buildLock.lock();
  708. this->scheduler = scheduler = new TaskScheduler;
  709. }
  710. }
  711. /* worker threads join build */
  712. if (!buildLock.isLocked())
  713. {
  714. if (!join)
  715. throw_RTCError(RTC_ERROR_INVALID_OPERATION,"use rtcJoinCommitScene to join a build operation");
  716. scheduler->join();
  717. return;
  718. }
  719. /* initiate build */
  720. // -- GODOT start --
  721. // try {
  722. scheduler->spawn_root([&]() { commit_task(); Lock<MutexSys> lock(schedulerMutex); this->scheduler = nullptr; }, 1, !join);
  723. // }
  724. // catch (...) {
  725. // accels_clear();
  726. // updateInterface();
  727. // Lock<MutexSys> lock(schedulerMutex);
  728. // this->scheduler = nullptr;
  729. // throw;
  730. // }
  731. // -- GODOT end --
  732. }
  733. #endif
  734. #if defined(TASKING_TBB)
  735. void Scene::commit (bool join)
  736. {
  737. #if defined(TASKING_TBB) && (TBB_INTERFACE_VERSION_MAJOR < 8)
  738. if (join)
  739. throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcJoinCommitScene not supported with this TBB version");
  740. #endif
  741. /* try to obtain build lock */
  742. Lock<MutexSys> lock(buildMutex,buildMutex.try_lock());
  743. /* join hierarchy build */
  744. if (!lock.isLocked())
  745. {
  746. #if !TASKING_TBB_USE_TASK_ISOLATION
  747. if (!join)
  748. throw_RTCError(RTC_ERROR_INVALID_OPERATION,"invoking rtcCommitScene from multiple threads is not supported with this TBB version");
  749. #endif
  750. do {
  751. #if USE_TASK_ARENA
  752. if (join) {
  753. device->arena->execute([&]{ group.wait(); });
  754. }
  755. else
  756. #endif
  757. {
  758. group.wait();
  759. }
  760. pause_cpu();
  761. yield();
  762. } while (!buildMutex.try_lock());
  763. buildMutex.unlock();
  764. return;
  765. }
  766. /* for best performance set FTZ and DAZ flags in the MXCSR control and status register */
  767. const unsigned int mxcsr = _mm_getcsr();
  768. _mm_setcsr(mxcsr | /* FTZ */ (1<<15) | /* DAZ */ (1<<6));
  769. try {
  770. #if TBB_INTERFACE_VERSION_MAJOR < 8
  771. tbb::task_group_context ctx( tbb::task_group_context::isolated, tbb::task_group_context::default_traits);
  772. #else
  773. tbb::task_group_context ctx( tbb::task_group_context::isolated, tbb::task_group_context::default_traits | tbb::task_group_context::fp_settings );
  774. #endif
  775. //ctx.set_priority(tbb::priority_high);
  776. #if USE_TASK_ARENA
  777. if (join)
  778. {
  779. device->arena->execute([&]{
  780. group.run([&]{
  781. tbb::parallel_for (size_t(0), size_t(1), size_t(1), [&] (size_t) { commit_task(); }, ctx);
  782. });
  783. group.wait();
  784. });
  785. }
  786. else
  787. #endif
  788. {
  789. group.run([&]{
  790. tbb::parallel_for (size_t(0), size_t(1), size_t(1), [&] (size_t) { commit_task(); }, ctx);
  791. });
  792. group.wait();
  793. }
  794. /* reset MXCSR register again */
  795. _mm_setcsr(mxcsr);
  796. }
  797. catch (...)
  798. {
  799. /* reset MXCSR register again */
  800. _mm_setcsr(mxcsr);
  801. accels_clear();
  802. updateInterface();
  803. throw;
  804. }
  805. }
  806. #endif
  807. #if defined(TASKING_PPL)
  808. void Scene::commit (bool join)
  809. {
  810. #if defined(TASKING_PPL)
  811. if (join)
  812. throw_RTCError(RTC_ERROR_INVALID_OPERATION,"rtcJoinCommitScene not supported with PPL");
  813. #endif
  814. /* try to obtain build lock */
  815. Lock<MutexSys> lock(buildMutex);
  816. checkIfModifiedAndSet ();
  817. if (!isModified()) {
  818. return;
  819. }
  820. /* for best performance set FTZ and DAZ flags in the MXCSR control and status register */
  821. const unsigned int mxcsr = _mm_getcsr();
  822. _mm_setcsr(mxcsr | /* FTZ */ (1<<15) | /* DAZ */ (1<<6));
  823. try {
  824. group.run([&]{
  825. concurrency::parallel_for(size_t(0), size_t(1), size_t(1), [&](size_t) { commit_task(); });
  826. });
  827. group.wait();
  828. /* reset MXCSR register again */
  829. _mm_setcsr(mxcsr);
  830. }
  831. catch (...)
  832. {
  833. /* reset MXCSR register again */
  834. _mm_setcsr(mxcsr);
  835. accels_clear();
  836. updateInterface();
  837. throw;
  838. }
  839. }
  840. #endif
  841. void Scene::setProgressMonitorFunction(RTCProgressMonitorFunction func, void* ptr)
  842. {
  843. progress_monitor_function = func;
  844. progress_monitor_ptr = ptr;
  845. }
  846. void Scene::progressMonitor(double dn)
  847. {
  848. if (progress_monitor_function) {
  849. size_t n = size_t(dn) + progress_monitor_counter.fetch_add(size_t(dn));
  850. if (!progress_monitor_function(progress_monitor_ptr, n / (double(numPrimitives())))) {
  851. throw_RTCError(RTC_ERROR_CANCELLED,"progress monitor forced termination");
  852. }
  853. }
  854. }
  855. }