diff options
Diffstat (limited to 'intern/cycles')
-rw-r--r-- | intern/cycles/blender/addon/properties.py | 6 | ||||
-rw-r--r-- | intern/cycles/blender/addon/ui.py | 4 | ||||
-rw-r--r-- | intern/cycles/blender/blender_sync.cpp | 1 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh_build.cpp | 109 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh_params.h | 10 | ||||
-rw-r--r-- | intern/cycles/render/scene.h | 3 |
6 files changed, 113 insertions, 20 deletions
diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index 3616b13e751..802b9b76c5d 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -528,6 +528,12 @@ class CyclesRenderSettings(bpy.types.PropertyGroup): description="Use special type BVH optimized for hair (uses more ram but renders faster)", default=True, ) + cls.debug_bvh_time_steps = IntProperty( + name="BVH Time Steps", + description="Split BVH primitives by this number of time steps to speed up render time in cost of memory", + default=0, + min=0, max=16, + ) cls.tile_order = EnumProperty( name="Tile Order", description="Tile order for rendering", diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 53bd208c0e7..d26ab73fac3 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -432,6 +432,10 @@ class CyclesRender_PT_performance(CyclesButtonsPanel, Panel): col.prop(cscene, "debug_use_spatial_splits") col.prop(cscene, "debug_use_hair_bvh") + row = col.row() + row.active = not cscene.debug_use_spatial_splits + row.prop(cscene, "debug_bvh_time_steps") + class CyclesRender_PT_layer_options(CyclesButtonsPanel, Panel): bl_label = "Layer" diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index 38b2ce19e8a..a9b7d7d3583 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -498,6 +498,7 @@ SceneParams BlenderSync::get_scene_params(BL::Scene& b_scene, params.use_bvh_spatial_split = RNA_boolean_get(&cscene, "debug_use_spatial_splits"); params.use_bvh_unaligned_nodes = RNA_boolean_get(&cscene, "debug_use_hair_bvh"); + params.num_bvh_motion_curve_steps = RNA_int_get(&cscene, "debug_bvh_time_steps"); if(background && params.shadingsystem != SHADINGSYSTEM_OSL) params.persistent_data = r.use_persistent_data(); diff --git a/intern/cycles/bvh/bvh_build.cpp b/intern/cycles/bvh/bvh_build.cpp index a045481e50f..4d684e51c1b 100644 --- a/intern/cycles/bvh/bvh_build.cpp +++ b/intern/cycles/bvh/bvh_build.cpp @@ -158,32 +158,101 @@ void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh, size_t num_curves = mesh->num_curves(); for(uint j = 0; j < num_curves; j++) { const Mesh::Curve curve = mesh->get_curve(j); - PrimitiveType type = PRIMITIVE_CURVE; const float *curve_radius = &mesh->curve_radius[0]; - for(int k = 0; k < curve.num_keys - 1; k++) { - BoundBox bounds = BoundBox::empty; - curve.bounds_grow(k, &mesh->curve_keys[0], curve_radius, bounds); - - /* motion curve */ - if(curve_attr_mP) { + if(curve_attr_mP == NULL) { + /* Really simple logic for static hair. */ + BoundBox bounds = BoundBox::empty; + curve.bounds_grow(k, &mesh->curve_keys[0], curve_radius, bounds); + if(bounds.valid()) { + int packed_type = PRIMITIVE_PACK_SEGMENT(PRIMITIVE_CURVE, k); + references.push_back(BVHReference(bounds, j, i, packed_type)); + root.grow(bounds); + center.grow(bounds.center2()); + } + } + else if(params.num_motion_curve_steps == 0 || params.use_spatial_split) { + /* Simple case of motion curves: single node for the while + * shutter time. Lowest memory usage but less optimal + * rendering. + */ + /* TODO(sergey): Support motion steps for spatially split BVH. */ + BoundBox bounds = BoundBox::empty; + curve.bounds_grow(k, &mesh->curve_keys[0], curve_radius, bounds); const size_t num_keys = mesh->curve_keys.size(); - const size_t num_steps = mesh->motion_steps - 1; + const size_t num_steps = mesh->motion_steps; const float3 *key_steps = curve_attr_mP->data_float3(); - - for(size_t step = 0; step < num_steps; step++) { - curve.bounds_grow(k, key_steps + step*num_keys, curve_radius, bounds); + for(size_t step = 0; step < num_steps - 1; step++) { + curve.bounds_grow(k, + key_steps + step*num_keys, + curve_radius, + bounds); + } + if(bounds.valid()) { + int packed_type = PRIMITIVE_PACK_SEGMENT(PRIMITIVE_MOTION_CURVE, k); + references.push_back(BVHReference(bounds, + j, + i, + packed_type)); + root.grow(bounds); + center.grow(bounds.center2()); } - - type = PRIMITIVE_MOTION_CURVE; } - - if(bounds.valid()) { - int packed_type = PRIMITIVE_PACK_SEGMENT(type, k); - - references.push_back(BVHReference(bounds, j, i, packed_type)); - root.grow(bounds); - center.grow(bounds.center2()); + else { + /* Motion curves, trace optimized case: we split curve keys + * primitives into separate nodes for each of the time steps. + * This way we minimize overlap of neighbor curve primitives. + */ + const int num_bvh_steps = params.num_motion_curve_steps * 2 + 1; + const float num_bvh_steps_inv_1 = 1.0f / (num_bvh_steps - 1); + const size_t num_steps = mesh->motion_steps; + const float3 *curve_keys = &mesh->curve_keys[0]; + const float3 *key_steps = curve_attr_mP->data_float3(); + const size_t num_keys = mesh->curve_keys.size(); + /* Calculate bounding box of the previous time step. + * Will be reused later to avoid duplicated work on + * calculating BVH time step boundbox. + */ + float4 prev_keys[4]; + curve.cardinal_motion_keys(curve_keys, + curve_radius, + key_steps, + num_keys, + num_steps, + 0.0f, + k - 1, k, k + 1, k + 2, + prev_keys); + BoundBox prev_bounds = BoundBox::empty; + curve.bounds_grow(prev_keys, prev_bounds); + for(int bvh_step = 1; bvh_step < num_bvh_steps; ++bvh_step) { + const float curr_time = (float)(bvh_step) * num_bvh_steps_inv_1; + float4 curr_keys[4]; + curve.cardinal_motion_keys(curve_keys, + curve_radius, + key_steps, + num_keys, + num_steps, + curr_time, + k - 1, k, k + 1, k + 2, + curr_keys); + BoundBox curr_bounds = BoundBox::empty; + curve.bounds_grow(curr_keys, curr_bounds); + BoundBox bounds = prev_bounds; + bounds.grow(curr_bounds); + if(bounds.valid()) { + int packed_type = PRIMITIVE_PACK_SEGMENT(PRIMITIVE_MOTION_CURVE, k); + references.push_back(BVHReference(bounds, + j, + i, + packed_type)); + root.grow(bounds); + center.grow(bounds.center2()); + } + /* Current time boundbox becomes previous one for the + * next time step. + */ + prev_bounds = curr_bounds; + } } } } diff --git a/intern/cycles/bvh/bvh_params.h b/intern/cycles/bvh/bvh_params.h index 6d426475737..1521fe9b5e4 100644 --- a/intern/cycles/bvh/bvh_params.h +++ b/intern/cycles/bvh/bvh_params.h @@ -61,6 +61,14 @@ public: */ bool use_unaligned_nodes; + /* Split time range to this number of steps and create leaf node for each + * of this time steps. + * + * Speeds up rendering of motion curve primitives in the cost of higher + * memory usage. + */ + int num_motion_curve_steps; + /* fixed parameters */ enum { MAX_DEPTH = 64, @@ -91,6 +99,8 @@ public: use_unaligned_nodes = false; primitive_mask = PRIMITIVE_ALL; + + num_motion_curve_steps = 0; } /* SAH costs */ diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h index df9363cc768..948697dd136 100644 --- a/intern/cycles/render/scene.h +++ b/intern/cycles/render/scene.h @@ -143,6 +143,7 @@ public: } bvh_type; bool use_bvh_spatial_split; bool use_bvh_unaligned_nodes; + int num_bvh_motion_curve_steps; bool use_qbvh; bool persistent_data; int texture_limit; @@ -153,6 +154,7 @@ public: bvh_type = BVH_DYNAMIC; use_bvh_spatial_split = false; use_bvh_unaligned_nodes = true; + num_bvh_motion_curve_steps = 0; use_qbvh = false; persistent_data = false; texture_limit = 0; @@ -163,6 +165,7 @@ public: && bvh_type == params.bvh_type && use_bvh_spatial_split == params.use_bvh_spatial_split && use_bvh_unaligned_nodes == params.use_bvh_unaligned_nodes + && num_bvh_motion_curve_steps == params.num_bvh_motion_curve_steps && use_qbvh == params.use_qbvh && persistent_data == params.persistent_data && texture_limit == params.texture_limit); } |