ClangFormat: apply to source, most of intern
[blender.git] / intern / cycles / bvh / bvh_embree.cpp
1 /*
2  * Copyright 2018, Blender Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /* This class implemens a ray accelerator for Cycles using Intel's Embree library.
18  * It supports triangles, curves, object and deformation blur and instancing.
19  * Not supported are thick line segments, those have no native equivalent in Embree.
20  * They could be implemented using Embree's thick curves, at the expense of wasted memory.
21  * User defined intersections for Embree could also be an option, but since Embree only uses aligned BVHs
22  * for user geometry, this would come with reduced performance and/or higher memory usage.
23  *
24  * Since Embree allows object to be either curves or triangles but not both, Cycles object IDs are maapped
25  * to Embree IDs by multiplying by two and adding one for curves.
26  *
27  * This implementation shares RTCDevices between Cycles instances. Eventually each instance should get
28  * a separate RTCDevice to correctly keep track of memory usage.
29  *
30  * Vertex and index buffers are duplicated between Cycles device arrays and Embree. These could be merged,
31  * which would requrie changes to intersection refinement, shader setup, mesh light sampling and a few
32  * other places in Cycles where direct access to vertex data is required.
33  */
34
35 #ifdef WITH_EMBREE
36
37 #  include <pmmintrin.h>
38 #  include <xmmintrin.h>
39 #  include <embree3/rtcore_geometry.h>
40
41 #  include "bvh/bvh_embree.h"
42
43 /* Kernel includes are necessary so that the filter function for Embree can access the packed BVH. */
44 #  include "kernel/bvh/bvh_embree.h"
45 #  include "kernel/kernel_compat_cpu.h"
46 #  include "kernel/split/kernel_split_data_types.h"
47 #  include "kernel/kernel_globals.h"
48 #  include "kernel/kernel_random.h"
49
50 #  include "render/mesh.h"
51 #  include "render/object.h"
52 #  include "util/util_foreach.h"
53 #  include "util/util_logging.h"
54 #  include "util/util_progress.h"
55
56 CCL_NAMESPACE_BEGIN
57
58 #  define IS_HAIR(x) (x & 1)
59
60 /* This gets called by Embree at every valid ray/object intersection.
61  * Things like recording subsurface or shadow hits for later evaluation
62  * as well as filtering for volume objects happen here.
63  * Cycles' own BVH does that directly inside the traversal calls.
64  */
65 static void rtc_filter_func(const RTCFilterFunctionNArguments *args)
66 {
67   /* Current implementation in Cycles assumes only single-ray intersection queries. */
68   assert(args->N == 1);
69
70   const RTCRay *ray = (RTCRay *)args->ray;
71   const RTCHit *hit = (RTCHit *)args->hit;
72   CCLIntersectContext *ctx = ((IntersectContext *)args->context)->userRayExt;
73   KernelGlobals *kg = ctx->kg;
74
75   /* Check if there is backfacing hair to ignore. */
76   if (IS_HAIR(hit->geomID) && (kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE) &&
77       !(kernel_data.curve.curveflags & CURVE_KN_BACKFACING) &&
78       !(kernel_data.curve.curveflags & CURVE_KN_RIBBONS)) {
79     if (dot(make_float3(ray->dir_x, ray->dir_y, ray->dir_z),
80             make_float3(hit->Ng_x, hit->Ng_y, hit->Ng_z)) > 0.0f) {
81       *args->valid = 0;
82       return;
83     }
84   }
85 }
86
87 static void rtc_filter_occluded_func(const RTCFilterFunctionNArguments *args)
88 {
89   assert(args->N == 1);
90
91   const RTCRay *ray = (RTCRay *)args->ray;
92   RTCHit *hit = (RTCHit *)args->hit;
93   CCLIntersectContext *ctx = ((IntersectContext *)args->context)->userRayExt;
94   KernelGlobals *kg = ctx->kg;
95
96   /* For all ray types: Check if there is backfacing hair to ignore */
97   if (IS_HAIR(hit->geomID) && (kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE) &&
98       !(kernel_data.curve.curveflags & CURVE_KN_BACKFACING) &&
99       !(kernel_data.curve.curveflags & CURVE_KN_RIBBONS)) {
100     if (dot(make_float3(ray->dir_x, ray->dir_y, ray->dir_z),
101             make_float3(hit->Ng_x, hit->Ng_y, hit->Ng_z)) > 0.0f) {
102       *args->valid = 0;
103       return;
104     }
105   }
106
107   switch (ctx->type) {
108     case CCLIntersectContext::RAY_SHADOW_ALL: {
109       /* Append the intersection to the end of the array. */
110       if (ctx->num_hits < ctx->max_hits) {
111         Intersection current_isect;
112         kernel_embree_convert_hit(kg, ray, hit, &current_isect);
113         for (size_t i = 0; i < ctx->max_hits; ++i) {
114           if (current_isect.object == ctx->isect_s[i].object &&
115               current_isect.prim == ctx->isect_s[i].prim && current_isect.t == ctx->isect_s[i].t) {
116             /* This intersection was already recorded, skip it. */
117             *args->valid = 0;
118             break;
119           }
120         }
121         Intersection *isect = &ctx->isect_s[ctx->num_hits];
122         ++ctx->num_hits;
123         *isect = current_isect;
124         int prim = kernel_tex_fetch(__prim_index, isect->prim);
125         int shader = 0;
126         if (kernel_tex_fetch(__prim_type, isect->prim) & PRIMITIVE_ALL_TRIANGLE) {
127           shader = kernel_tex_fetch(__tri_shader, prim);
128         }
129         else {
130           float4 str = kernel_tex_fetch(__curves, prim);
131           shader = __float_as_int(str.z);
132         }
133         int flag = kernel_tex_fetch(__shaders, shader & SHADER_MASK).flags;
134         /* If no transparent shadows, all light is blocked. */
135         if (flag & (SD_HAS_TRANSPARENT_SHADOW)) {
136           /* This tells Embree to continue tracing. */
137           *args->valid = 0;
138         }
139       }
140       else {
141         /* Increase the number of hits beyond ray.max_hits
142          * so that the caller can detect this as opaque. */
143         ++ctx->num_hits;
144       }
145       break;
146     }
147     case CCLIntersectContext::RAY_SSS: {
148       /* No intersection information requested, just return a hit. */
149       if (ctx->max_hits == 0) {
150         break;
151       }
152
153       /* Ignore curves. */
154       if (hit->geomID & 1) {
155         /* This tells Embree to continue tracing. */
156         *args->valid = 0;
157         break;
158       }
159
160       /* See triangle_intersect_subsurface() for the native equivalent. */
161       for (int i = min(ctx->max_hits, ctx->ss_isect->num_hits) - 1; i >= 0; --i) {
162         if (ctx->ss_isect->hits[i].t == ray->tfar) {
163           /* This tells Embree to continue tracing. */
164           *args->valid = 0;
165           break;
166         }
167       }
168
169       ++ctx->ss_isect->num_hits;
170       int hit_idx;
171
172       if (ctx->ss_isect->num_hits <= ctx->max_hits) {
173         hit_idx = ctx->ss_isect->num_hits - 1;
174       }
175       else {
176         /* reservoir sampling: if we are at the maximum number of
177          * hits, randomly replace element or skip it */
178         hit_idx = lcg_step_uint(ctx->lcg_state) % ctx->ss_isect->num_hits;
179
180         if (hit_idx >= ctx->max_hits) {
181           /* This tells Embree to continue tracing. */
182           *args->valid = 0;
183           break;
184         }
185       }
186       /* record intersection */
187       kernel_embree_convert_local_hit(
188           kg, ray, hit, &ctx->ss_isect->hits[hit_idx], ctx->sss_object_id);
189       ctx->ss_isect->Ng[hit_idx].x = hit->Ng_x;
190       ctx->ss_isect->Ng[hit_idx].y = hit->Ng_y;
191       ctx->ss_isect->Ng[hit_idx].z = hit->Ng_z;
192       ctx->ss_isect->Ng[hit_idx] = normalize(ctx->ss_isect->Ng[hit_idx]);
193       /* This tells Embree to continue tracing .*/
194       *args->valid = 0;
195       break;
196     }
197     case CCLIntersectContext::RAY_VOLUME_ALL: {
198       /* Append the intersection to the end of the array. */
199       if (ctx->num_hits < ctx->max_hits) {
200         Intersection current_isect;
201         kernel_embree_convert_hit(kg, ray, hit, &current_isect);
202         for (size_t i = 0; i < ctx->max_hits; ++i) {
203           if (current_isect.object == ctx->isect_s[i].object &&
204               current_isect.prim == ctx->isect_s[i].prim && current_isect.t == ctx->isect_s[i].t) {
205             /* This intersection was already recorded, skip it. */
206             *args->valid = 0;
207             break;
208           }
209         }
210         Intersection *isect = &ctx->isect_s[ctx->num_hits];
211         ++ctx->num_hits;
212         *isect = current_isect;
213         /* Only primitives from volume object. */
214         uint tri_object = (isect->object == OBJECT_NONE) ?
215                               kernel_tex_fetch(__prim_object, isect->prim) :
216                               isect->object;
217         int object_flag = kernel_tex_fetch(__object_flag, tri_object);
218         if ((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
219           --ctx->num_hits;
220         }
221         /* This tells Embree to continue tracing. */
222         *args->valid = 0;
223         break;
224       }
225     }
226     case CCLIntersectContext::RAY_REGULAR:
227     default:
228       /* Nothing to do here. */
229       break;
230   }
231 }
232
233 static size_t unaccounted_mem = 0;
234
235 static bool rtc_memory_monitor_func(void *userPtr, const ssize_t bytes, const bool)
236 {
237   Stats *stats = (Stats *)userPtr;
238   if (stats) {
239     if (bytes > 0) {
240       stats->mem_alloc(bytes);
241     }
242     else {
243       stats->mem_free(-bytes);
244     }
245   }
246   else {
247     /* A stats pointer may not yet be available. Keep track of the memory usage for later. */
248     if (bytes >= 0) {
249       atomic_add_and_fetch_z(&unaccounted_mem, bytes);
250     }
251     else {
252       atomic_sub_and_fetch_z(&unaccounted_mem, -bytes);
253     }
254   }
255   return true;
256 }
257
258 static void rtc_error_func(void *, enum RTCError, const char *str)
259 {
260   VLOG(1) << str;
261 }
262
263 static double progress_start_time = 0.0f;
264
265 static bool rtc_progress_func(void *user_ptr, const double n)
266 {
267   Progress *progress = (Progress *)user_ptr;
268
269   if (time_dt() - progress_start_time < 0.25) {
270     return true;
271   }
272
273   string msg = string_printf("Building BVH %.0f%%", n * 100.0);
274   progress->set_substatus(msg);
275   progress_start_time = time_dt();
276
277   return !progress->get_cancel();
278 }
279
280 /* This is to have a shared device between all BVH instances.
281    It would be useful to actually to use a separte RTCDevice per Cycles instance\10. */
282 RTCDevice BVHEmbree::rtc_shared_device = NULL;
283 int BVHEmbree::rtc_shared_users = 0;
284 thread_mutex BVHEmbree::rtc_shared_mutex;
285
286 BVHEmbree::BVHEmbree(const BVHParams &params_, const vector<Object *> &objects_)
287     : BVH(params_, objects_),
288       scene(NULL),
289       mem_used(0),
290       top_level(NULL),
291       stats(NULL),
292       curve_subdivisions(params.curve_subdivisions),
293       build_quality(RTC_BUILD_QUALITY_REFIT),
294       use_curves(params_.curve_flags & CURVE_KN_INTERPOLATE),
295       use_ribbons(params.curve_flags & CURVE_KN_RIBBONS),
296       dynamic_scene(true)
297 {
298   _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
299   _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);
300   thread_scoped_lock lock(rtc_shared_mutex);
301   if (rtc_shared_users == 0) {
302     rtc_shared_device = rtcNewDevice("verbose=0");
303     /* Check here if Embree was built with the correct flags. */
304     ssize_t ret = rtcGetDeviceProperty(rtc_shared_device, RTC_DEVICE_PROPERTY_RAY_MASK_SUPPORTED);
305     if (ret != 1) {
306       assert(0);
307       VLOG(1) << "Embree is compiled without the RTC_DEVICE_PROPERTY_RAY_MASK_SUPPORTED flag."
308                  "Ray visiblity will not work.";
309     }
310     ret = rtcGetDeviceProperty(rtc_shared_device, RTC_DEVICE_PROPERTY_FILTER_FUNCTION_SUPPORTED);
311     if (ret != 1) {
312       assert(0);
313       VLOG(1)
314           << "Embree is compiled without the RTC_DEVICE_PROPERTY_FILTER_FUNCTION_SUPPORTED flag."
315              "Renders may not look as expected.";
316     }
317     ret = rtcGetDeviceProperty(rtc_shared_device, RTC_DEVICE_PROPERTY_CURVE_GEOMETRY_SUPPORTED);
318     if (ret != 1) {
319       assert(0);
320       VLOG(1)
321           << "Embree is compiled without the RTC_DEVICE_PROPERTY_CURVE_GEOMETRY_SUPPORTED flag. "
322              "Line primitives will not be rendered.";
323     }
324     ret = rtcGetDeviceProperty(rtc_shared_device, RTC_DEVICE_PROPERTY_TRIANGLE_GEOMETRY_SUPPORTED);
325     if (ret != 1) {
326       assert(0);
327       VLOG(1) << "Embree is compiled without the RTC_DEVICE_PROPERTY_TRIANGLE_GEOMETRY_SUPPORTED "
328                  "flag. "
329                  "Triangle primitives will not be rendered.";
330     }
331     ret = rtcGetDeviceProperty(rtc_shared_device, RTC_DEVICE_PROPERTY_BACKFACE_CULLING_ENABLED);
332     if (ret != 0) {
333       assert(0);
334       VLOG(1) << "Embree is compiled with the RTC_DEVICE_PROPERTY_BACKFACE_CULLING_ENABLED flag. "
335                  "Renders may not look as expected.";
336     }
337   }
338   ++rtc_shared_users;
339
340   rtcSetDeviceErrorFunction(rtc_shared_device, rtc_error_func, NULL);
341
342   pack.root_index = -1;
343 }
344
345 BVHEmbree::~BVHEmbree()
346 {
347   if (!params.top_level) {
348     destroy(scene);
349   }
350 }
351
352 void BVHEmbree::destroy(RTCScene scene)
353 {
354   if (scene) {
355     rtcReleaseScene(scene);
356     scene = NULL;
357   }
358   thread_scoped_lock lock(rtc_shared_mutex);
359   --rtc_shared_users;
360   if (rtc_shared_users == 0) {
361     rtcReleaseDevice(rtc_shared_device);
362     rtc_shared_device = NULL;
363   }
364 }
365
366 void BVHEmbree::delete_rtcScene()
367 {
368   if (scene) {
369     /* When this BVH is used as an instance in a top level BVH, don't delete now
370      * Let the top_level BVH know that it should delete it later. */
371     if (top_level) {
372       top_level->add_delayed_delete_scene(scene);
373     }
374     else {
375       rtcReleaseScene(scene);
376       if (delayed_delete_scenes.size()) {
377         foreach (RTCScene s, delayed_delete_scenes) {
378           rtcReleaseScene(s);
379         }
380       }
381       delayed_delete_scenes.clear();
382     }
383     scene = NULL;
384   }
385 }
386
387 void BVHEmbree::build(Progress &progress, Stats *stats_)
388 {
389   assert(rtc_shared_device);
390   stats = stats_;
391   rtcSetDeviceMemoryMonitorFunction(rtc_shared_device, rtc_memory_monitor_func, stats);
392
393   progress.set_substatus("Building BVH");
394
395   if (scene) {
396     rtcReleaseScene(scene);
397     scene = NULL;
398   }
399
400   const bool dynamic = params.bvh_type == SceneParams::BVH_DYNAMIC;
401
402   scene = rtcNewScene(rtc_shared_device);
403   const RTCSceneFlags scene_flags = (dynamic ? RTC_SCENE_FLAG_DYNAMIC : RTC_SCENE_FLAG_NONE) |
404                                     RTC_SCENE_FLAG_COMPACT | RTC_SCENE_FLAG_ROBUST;
405   rtcSetSceneFlags(scene, scene_flags);
406   build_quality = dynamic ? RTC_BUILD_QUALITY_LOW :
407                             (params.use_spatial_split ? RTC_BUILD_QUALITY_HIGH :
408                                                         RTC_BUILD_QUALITY_MEDIUM);
409   rtcSetSceneBuildQuality(scene, build_quality);
410
411   /* Count triangles and curves first, reserve arrays once. */
412   size_t prim_count = 0;
413
414   foreach (Object *ob, objects) {
415     if (params.top_level) {
416       if (!ob->is_traceable()) {
417         continue;
418       }
419       if (!ob->mesh->is_instanced()) {
420         if (params.primitive_mask & PRIMITIVE_ALL_TRIANGLE) {
421           prim_count += ob->mesh->num_triangles();
422         }
423         if (params.primitive_mask & PRIMITIVE_ALL_CURVE) {
424           for (size_t j = 0; j < ob->mesh->num_curves(); ++j) {
425             prim_count += ob->mesh->get_curve(j).num_segments();
426           }
427         }
428       }
429       else {
430         ++prim_count;
431       }
432     }
433     else {
434       if (params.primitive_mask & PRIMITIVE_ALL_TRIANGLE && ob->mesh->num_triangles() > 0) {
435         prim_count += ob->mesh->num_triangles();
436       }
437       if (params.primitive_mask & PRIMITIVE_ALL_CURVE) {
438         for (size_t j = 0; j < ob->mesh->num_curves(); ++j) {
439           prim_count += ob->mesh->get_curve(j).num_segments();
440         }
441       }
442     }
443   }
444
445   pack.prim_object.reserve(prim_count);
446   pack.prim_type.reserve(prim_count);
447   pack.prim_index.reserve(prim_count);
448   pack.prim_tri_index.reserve(prim_count);
449
450   int i = 0;
451
452   pack.object_node.clear();
453
454   foreach (Object *ob, objects) {
455     if (params.top_level) {
456       if (!ob->is_traceable()) {
457         ++i;
458         continue;
459       }
460       if (!ob->mesh->is_instanced()) {
461         add_object(ob, i);
462       }
463       else {
464         add_instance(ob, i);
465       }
466     }
467     else {
468       add_object(ob, i);
469     }
470     ++i;
471     if (progress.get_cancel())
472       return;
473   }
474
475   if (progress.get_cancel()) {
476     delete_rtcScene();
477     stats = NULL;
478     return;
479   }
480
481   rtcSetSceneProgressMonitorFunction(scene, rtc_progress_func, &progress);
482   rtcCommitScene(scene);
483
484   pack_primitives();
485
486   if (progress.get_cancel()) {
487     delete_rtcScene();
488     stats = NULL;
489     return;
490   }
491
492   progress.set_substatus("Packing geometry");
493   pack_nodes(NULL);
494
495   stats = NULL;
496 }
497
498 BVHNode *BVHEmbree::widen_children_nodes(const BVHNode * /*root*/)
499 {
500   assert(!"Must not be called.");
501   return NULL;
502 }
503
504 void BVHEmbree::add_object(Object *ob, int i)
505 {
506   Mesh *mesh = ob->mesh;
507   if (params.primitive_mask & PRIMITIVE_ALL_TRIANGLE && mesh->num_triangles() > 0) {
508     add_triangles(ob, i);
509   }
510   if (params.primitive_mask & PRIMITIVE_ALL_CURVE && mesh->num_curves() > 0) {
511     add_curves(ob, i);
512   }
513 }
514
515 void BVHEmbree::add_instance(Object *ob, int i)
516 {
517   if (!ob || !ob->mesh) {
518     assert(0);
519     return;
520   }
521   BVHEmbree *instance_bvh = (BVHEmbree *)(ob->mesh->bvh);
522
523   if (instance_bvh->top_level != this) {
524     instance_bvh->top_level = this;
525   }
526
527   const size_t num_motion_steps = ob->use_motion() ? ob->motion.size() : 1;
528   RTCGeometry geom_id = rtcNewGeometry(rtc_shared_device, RTC_GEOMETRY_TYPE_INSTANCE);
529   rtcSetGeometryInstancedScene(geom_id, instance_bvh->scene);
530   rtcSetGeometryTimeStepCount(geom_id, num_motion_steps);
531
532   if (ob->use_motion()) {
533     for (size_t step = 0; step < num_motion_steps; ++step) {
534       rtcSetGeometryTransform(
535           geom_id, step, RTC_FORMAT_FLOAT3X4_ROW_MAJOR, (const float *)&ob->motion[step]);
536     }
537   }
538   else {
539     rtcSetGeometryTransform(geom_id, 0, RTC_FORMAT_FLOAT3X4_ROW_MAJOR, (const float *)&ob->tfm);
540   }
541
542   pack.prim_index.push_back_slow(-1);
543   pack.prim_object.push_back_slow(i);
544   pack.prim_type.push_back_slow(PRIMITIVE_NONE);
545   pack.prim_tri_index.push_back_slow(-1);
546
547   rtcSetGeometryUserData(geom_id, (void *)instance_bvh->scene);
548   rtcSetGeometryMask(geom_id, ob->visibility);
549
550   rtcCommitGeometry(geom_id);
551   rtcAttachGeometryByID(scene, geom_id, i * 2);
552   rtcReleaseGeometry(geom_id);
553 }
554
555 void BVHEmbree::add_triangles(Object *ob, int i)
556 {
557   size_t prim_offset = pack.prim_index.size();
558   Mesh *mesh = ob->mesh;
559   const Attribute *attr_mP = NULL;
560   size_t num_motion_steps = 1;
561   if (mesh->has_motion_blur()) {
562     attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
563     if (attr_mP) {
564       num_motion_steps = mesh->motion_steps;
565       if (num_motion_steps > RTC_MAX_TIME_STEP_COUNT) {
566         assert(0);
567         num_motion_steps = RTC_MAX_TIME_STEP_COUNT;
568       }
569     }
570   }
571
572   const size_t num_triangles = mesh->num_triangles();
573   RTCGeometry geom_id = rtcNewGeometry(rtc_shared_device, RTC_GEOMETRY_TYPE_TRIANGLE);
574   rtcSetGeometryBuildQuality(geom_id, build_quality);
575   rtcSetGeometryTimeStepCount(geom_id, num_motion_steps);
576
577   unsigned *rtc_indices = (unsigned *)rtcSetNewGeometryBuffer(
578       geom_id, RTC_BUFFER_TYPE_INDEX, 0, RTC_FORMAT_UINT3, sizeof(int) * 3, num_triangles);
579   assert(rtc_indices);
580   if (!rtc_indices) {
581     VLOG(1) << "Embree could not create new geometry buffer for mesh " << mesh->name.c_str()
582             << ".\n";
583     return;
584   }
585   for (size_t j = 0; j < num_triangles; ++j) {
586     Mesh::Triangle t = mesh->get_triangle(j);
587     rtc_indices[j * 3] = t.v[0];
588     rtc_indices[j * 3 + 1] = t.v[1];
589     rtc_indices[j * 3 + 2] = t.v[2];
590   }
591
592   update_tri_vertex_buffer(geom_id, mesh);
593
594   size_t prim_object_size = pack.prim_object.size();
595   pack.prim_object.resize(prim_object_size + num_triangles);
596   size_t prim_type_size = pack.prim_type.size();
597   pack.prim_type.resize(prim_type_size + num_triangles);
598   size_t prim_index_size = pack.prim_index.size();
599   pack.prim_index.resize(prim_index_size + num_triangles);
600   pack.prim_tri_index.resize(prim_index_size + num_triangles);
601   int prim_type = (num_motion_steps > 1 ? PRIMITIVE_MOTION_TRIANGLE : PRIMITIVE_TRIANGLE);
602
603   for (size_t j = 0; j < num_triangles; ++j) {
604     pack.prim_object[prim_object_size + j] = i;
605     pack.prim_type[prim_type_size + j] = prim_type;
606     pack.prim_index[prim_index_size + j] = j;
607     pack.prim_tri_index[prim_index_size + j] = j;
608   }
609
610   rtcSetGeometryUserData(geom_id, (void *)prim_offset);
611   rtcSetGeometryIntersectFilterFunction(geom_id, rtc_filter_func);
612   rtcSetGeometryOccludedFilterFunction(geom_id, rtc_filter_occluded_func);
613   rtcSetGeometryMask(geom_id, ob->visibility);
614
615   rtcCommitGeometry(geom_id);
616   rtcAttachGeometryByID(scene, geom_id, i * 2);
617   rtcReleaseGeometry(geom_id);
618 }
619
620 void BVHEmbree::update_tri_vertex_buffer(RTCGeometry geom_id, const Mesh *mesh)
621 {
622   const Attribute *attr_mP = NULL;
623   size_t num_motion_steps = 1;
624   int t_mid = 0;
625   if (mesh->has_motion_blur()) {
626     attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
627     if (attr_mP) {
628       num_motion_steps = mesh->motion_steps;
629       t_mid = (num_motion_steps - 1) / 2;
630       if (num_motion_steps > RTC_MAX_TIME_STEP_COUNT) {
631         assert(0);
632         num_motion_steps = RTC_MAX_TIME_STEP_COUNT;
633       }
634     }
635   }
636   const size_t num_verts = mesh->verts.size();
637
638   for (int t = 0; t < num_motion_steps; ++t) {
639     const float3 *verts;
640     if (t == t_mid) {
641       verts = &mesh->verts[0];
642     }
643     else {
644       int t_ = (t > t_mid) ? (t - 1) : t;
645       verts = &attr_mP->data_float3()[t_ * num_verts];
646     }
647
648     float *rtc_verts = (float *)rtcSetNewGeometryBuffer(
649         geom_id, RTC_BUFFER_TYPE_VERTEX, t, RTC_FORMAT_FLOAT3, sizeof(float) * 3, num_verts + 1);
650     assert(rtc_verts);
651     if (rtc_verts) {
652       for (size_t j = 0; j < num_verts; ++j) {
653         rtc_verts[0] = verts[j].x;
654         rtc_verts[1] = verts[j].y;
655         rtc_verts[2] = verts[j].z;
656         rtc_verts += 3;
657       }
658     }
659   }
660 }
661
662 void BVHEmbree::update_curve_vertex_buffer(RTCGeometry geom_id, const Mesh *mesh)
663 {
664   const Attribute *attr_mP = NULL;
665   size_t num_motion_steps = 1;
666   if (mesh->has_motion_blur()) {
667     attr_mP = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
668     if (attr_mP) {
669       num_motion_steps = mesh->motion_steps;
670     }
671   }
672
673   const size_t num_curves = mesh->num_curves();
674   size_t num_keys = 0;
675   for (size_t j = 0; j < num_curves; ++j) {
676     const Mesh::Curve c = mesh->get_curve(j);
677     num_keys += c.num_keys;
678   }
679
680   /* Copy the CV data to Embree */
681   const int t_mid = (num_motion_steps - 1) / 2;
682   const float *curve_radius = &mesh->curve_radius[0];
683   for (int t = 0; t < num_motion_steps; ++t) {
684     const float3 *verts;
685     if (t == t_mid || attr_mP == NULL) {
686       verts = &mesh->curve_keys[0];
687     }
688     else {
689       int t_ = (t > t_mid) ? (t - 1) : t;
690       verts = &attr_mP->data_float3()[t_ * num_keys];
691     }
692
693     float4 *rtc_verts = (float4 *)rtcSetNewGeometryBuffer(
694         geom_id, RTC_BUFFER_TYPE_VERTEX, t, RTC_FORMAT_FLOAT4, sizeof(float) * 4, num_keys);
695     float4 *rtc_tangents = NULL;
696     if (use_curves) {
697       rtc_tangents = (float4 *)rtcSetNewGeometryBuffer(
698           geom_id, RTC_BUFFER_TYPE_TANGENT, t, RTC_FORMAT_FLOAT4, sizeof(float) * 4, num_keys);
699       assert(rtc_tangents);
700     }
701     assert(rtc_verts);
702     if (rtc_verts) {
703       if (use_curves && rtc_tangents) {
704         const size_t num_curves = mesh->num_curves();
705         for (size_t j = 0; j < num_curves; ++j) {
706           Mesh::Curve c = mesh->get_curve(j);
707           int fk = c.first_key;
708           rtc_verts[0] = float3_to_float4(verts[fk]);
709           rtc_verts[0].w = curve_radius[fk];
710           rtc_tangents[0] = float3_to_float4(verts[fk + 1] - verts[fk]);
711           rtc_tangents[0].w = curve_radius[fk + 1] - curve_radius[fk];
712           ++fk;
713           int k = 1;
714           for (; k < c.num_segments(); ++k, ++fk) {
715             rtc_verts[k] = float3_to_float4(verts[fk]);
716             rtc_verts[k].w = curve_radius[fk];
717             rtc_tangents[k] = float3_to_float4((verts[fk + 1] - verts[fk - 1]) * 0.5f);
718             rtc_tangents[k].w = (curve_radius[fk + 1] - curve_radius[fk - 1]) * 0.5f;
719           }
720           rtc_verts[k] = float3_to_float4(verts[fk]);
721           rtc_verts[k].w = curve_radius[fk];
722           rtc_tangents[k] = float3_to_float4(verts[fk] - verts[fk - 1]);
723           rtc_tangents[k].w = curve_radius[fk] - curve_radius[fk - 1];
724           rtc_verts += c.num_keys;
725           rtc_tangents += c.num_keys;
726         }
727       }
728       else {
729         for (size_t j = 0; j < num_keys; ++j) {
730           rtc_verts[j] = float3_to_float4(verts[j]);
731           rtc_verts[j].w = curve_radius[j];
732         }
733       }
734     }
735   }
736 }
737
738 void BVHEmbree::add_curves(Object *ob, int i)
739 {
740   size_t prim_offset = pack.prim_index.size();
741   const Mesh *mesh = ob->mesh;
742   const Attribute *attr_mP = NULL;
743   size_t num_motion_steps = 1;
744   if (mesh->has_motion_blur()) {
745     attr_mP = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
746     if (attr_mP) {
747       num_motion_steps = mesh->motion_steps;
748     }
749   }
750
751   const size_t num_curves = mesh->num_curves();
752   size_t num_segments = 0;
753   for (size_t j = 0; j < num_curves; ++j) {
754     Mesh::Curve c = mesh->get_curve(j);
755     assert(c.num_segments() > 0);
756     num_segments += c.num_segments();
757   }
758
759   /* Make room for Cycles specific data. */
760   size_t prim_object_size = pack.prim_object.size();
761   pack.prim_object.resize(prim_object_size + num_segments);
762   size_t prim_type_size = pack.prim_type.size();
763   pack.prim_type.resize(prim_type_size + num_segments);
764   size_t prim_index_size = pack.prim_index.size();
765   pack.prim_index.resize(prim_index_size + num_segments);
766   size_t prim_tri_index_size = pack.prim_index.size();
767   pack.prim_tri_index.resize(prim_tri_index_size + num_segments);
768
769   enum RTCGeometryType type = (!use_curves) ?
770                                   RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE :
771                                   (use_ribbons ? RTC_GEOMETRY_TYPE_FLAT_HERMITE_CURVE :
772                                                  RTC_GEOMETRY_TYPE_ROUND_HERMITE_CURVE);
773
774   RTCGeometry geom_id = rtcNewGeometry(rtc_shared_device, type);
775   rtcSetGeometryTessellationRate(geom_id, curve_subdivisions);
776   unsigned *rtc_indices = (unsigned *)rtcSetNewGeometryBuffer(
777       geom_id, RTC_BUFFER_TYPE_INDEX, 0, RTC_FORMAT_UINT, sizeof(int), num_segments);
778   size_t rtc_index = 0;
779   for (size_t j = 0; j < num_curves; ++j) {
780     Mesh::Curve c = mesh->get_curve(j);
781     for (size_t k = 0; k < c.num_segments(); ++k) {
782       rtc_indices[rtc_index] = c.first_key + k;
783       /* Cycles specific data. */
784       pack.prim_object[prim_object_size + rtc_index] = i;
785       pack.prim_type[prim_type_size + rtc_index] = (PRIMITIVE_PACK_SEGMENT(
786           num_motion_steps > 1 ? PRIMITIVE_MOTION_CURVE : PRIMITIVE_CURVE, k));
787       pack.prim_index[prim_index_size + rtc_index] = j;
788       pack.prim_tri_index[prim_tri_index_size + rtc_index] = rtc_index;
789
790       ++rtc_index;
791     }
792   }
793
794   rtcSetGeometryBuildQuality(geom_id, build_quality);
795   rtcSetGeometryTimeStepCount(geom_id, num_motion_steps);
796
797   update_curve_vertex_buffer(geom_id, mesh);
798
799   rtcSetGeometryUserData(geom_id, (void *)prim_offset);
800   rtcSetGeometryIntersectFilterFunction(geom_id, rtc_filter_func);
801   rtcSetGeometryOccludedFilterFunction(geom_id, rtc_filter_occluded_func);
802   rtcSetGeometryMask(geom_id, ob->visibility);
803
804   rtcCommitGeometry(geom_id);
805   rtcAttachGeometryByID(scene, geom_id, i * 2 + 1);
806   rtcReleaseGeometry(geom_id);
807 }
808
809 void BVHEmbree::pack_nodes(const BVHNode *)
810 {
811   /* Quite a bit of this code is for compatibility with Cycles' native BVH. */
812   if (!params.top_level) {
813     return;
814   }
815
816   for (size_t i = 0; i < pack.prim_index.size(); ++i) {
817     if (pack.prim_index[i] != -1) {
818       if (pack.prim_type[i] & PRIMITIVE_ALL_CURVE)
819         pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->curve_offset;
820       else
821         pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->tri_offset;
822     }
823   }
824
825   size_t prim_offset = pack.prim_index.size();
826
827   /* reserve */
828   size_t prim_index_size = pack.prim_index.size();
829   size_t prim_tri_verts_size = pack.prim_tri_verts.size();
830
831   size_t pack_prim_index_offset = prim_index_size;
832   size_t pack_prim_tri_verts_offset = prim_tri_verts_size;
833   size_t object_offset = 0;
834
835   map<Mesh *, int> mesh_map;
836
837   foreach (Object *ob, objects) {
838     Mesh *mesh = ob->mesh;
839     BVH *bvh = mesh->bvh;
840
841     if (mesh->need_build_bvh()) {
842       if (mesh_map.find(mesh) == mesh_map.end()) {
843         prim_index_size += bvh->pack.prim_index.size();
844         prim_tri_verts_size += bvh->pack.prim_tri_verts.size();
845         mesh_map[mesh] = 1;
846       }
847     }
848   }
849
850   mesh_map.clear();
851
852   pack.prim_index.resize(prim_index_size);
853   pack.prim_type.resize(prim_index_size);
854   pack.prim_object.resize(prim_index_size);
855   pack.prim_visibility.clear();
856   pack.prim_tri_verts.resize(prim_tri_verts_size);
857   pack.prim_tri_index.resize(prim_index_size);
858   pack.object_node.resize(objects.size());
859
860   int *pack_prim_index = (pack.prim_index.size()) ? &pack.prim_index[0] : NULL;
861   int *pack_prim_type = (pack.prim_type.size()) ? &pack.prim_type[0] : NULL;
862   int *pack_prim_object = (pack.prim_object.size()) ? &pack.prim_object[0] : NULL;
863   float4 *pack_prim_tri_verts = (pack.prim_tri_verts.size()) ? &pack.prim_tri_verts[0] : NULL;
864   uint *pack_prim_tri_index = (pack.prim_tri_index.size()) ? &pack.prim_tri_index[0] : NULL;
865
866   /* merge */
867   foreach (Object *ob, objects) {
868     Mesh *mesh = ob->mesh;
869
870     /* We assume that if mesh doesn't need own BVH it was already included
871      * into a top-level BVH and no packing here is needed.
872      */
873     if (!mesh->need_build_bvh()) {
874       pack.object_node[object_offset++] = prim_offset;
875       continue;
876     }
877
878     /* if mesh already added once, don't add it again, but used set
879      * node offset for this object */
880     map<Mesh *, int>::iterator it = mesh_map.find(mesh);
881
882     if (mesh_map.find(mesh) != mesh_map.end()) {
883       int noffset = it->second;
884       pack.object_node[object_offset++] = noffset;
885       continue;
886     }
887
888     BVHEmbree *bvh = (BVHEmbree *)mesh->bvh;
889
890     rtc_memory_monitor_func(stats, unaccounted_mem, true);
891     unaccounted_mem = 0;
892
893     int mesh_tri_offset = mesh->tri_offset;
894     int mesh_curve_offset = mesh->curve_offset;
895
896     /* fill in node indexes for instances */
897     pack.object_node[object_offset++] = prim_offset;
898
899     mesh_map[mesh] = pack.object_node[object_offset - 1];
900
901     /* merge primitive, object and triangle indexes */
902     if (bvh->pack.prim_index.size()) {
903       size_t bvh_prim_index_size = bvh->pack.prim_index.size();
904       int *bvh_prim_index = &bvh->pack.prim_index[0];
905       int *bvh_prim_type = &bvh->pack.prim_type[0];
906       uint *bvh_prim_tri_index = &bvh->pack.prim_tri_index[0];
907
908       for (size_t i = 0; i < bvh_prim_index_size; ++i) {
909         if (bvh->pack.prim_type[i] & PRIMITIVE_ALL_CURVE) {
910           pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + mesh_curve_offset;
911           pack_prim_tri_index[pack_prim_index_offset] = -1;
912         }
913         else {
914           pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + mesh_tri_offset;
915           pack_prim_tri_index[pack_prim_index_offset] = bvh_prim_tri_index[i] +
916                                                         pack_prim_tri_verts_offset;
917         }
918
919         pack_prim_type[pack_prim_index_offset] = bvh_prim_type[i];
920         pack_prim_object[pack_prim_index_offset] = 0;
921
922         ++pack_prim_index_offset;
923       }
924     }
925
926     /* Merge triangle vertices data. */
927     if (bvh->pack.prim_tri_verts.size()) {
928       const size_t prim_tri_size = bvh->pack.prim_tri_verts.size();
929       memcpy(pack_prim_tri_verts + pack_prim_tri_verts_offset,
930              &bvh->pack.prim_tri_verts[0],
931              prim_tri_size * sizeof(float4));
932       pack_prim_tri_verts_offset += prim_tri_size;
933     }
934
935     prim_offset += bvh->pack.prim_index.size();
936   }
937 }
938
939 void BVHEmbree::refit_nodes()
940 {
941   /* Update all vertex buffers, then tell Embree to rebuild/-fit the BVHs. */
942   unsigned geom_id = 0;
943   foreach (Object *ob, objects) {
944     if (!params.top_level || (ob->is_traceable() && !ob->mesh->is_instanced())) {
945       if (params.primitive_mask & PRIMITIVE_ALL_TRIANGLE && ob->mesh->num_triangles() > 0) {
946         update_tri_vertex_buffer(rtcGetGeometry(scene, geom_id), ob->mesh);
947         rtcCommitGeometry(rtcGetGeometry(scene, geom_id));
948       }
949
950       if (params.primitive_mask & PRIMITIVE_ALL_CURVE && ob->mesh->num_curves() > 0) {
951         update_curve_vertex_buffer(rtcGetGeometry(scene, geom_id + 1), ob->mesh);
952         rtcCommitGeometry(rtcGetGeometry(scene, geom_id + 1));
953       }
954     }
955     geom_id += 2;
956   }
957   rtcCommitScene(scene);
958 }
959 CCL_NAMESPACE_END
960
961 #endif /* WITH_EMBREE */