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