diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index 19f49acddd7..3c41c831723 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -96,7 +96,49 @@ bool BlenderSync::object_is_light(BL::Object &b_ob) return (b_ob_data && b_ob_data.is_a(&RNA_Light)); } -/* Object */ +void BlenderSync::sync_object_motion_init(BL::Object &b_parent, BL::Object &b_ob, Object *object) +{ + /* Initialize motion blur for object, detecting if it's enabled and creating motion + * steps array if so. */ + array motion; + object->set_motion(motion); + + Scene::MotionType need_motion = scene->need_motion(); + if (need_motion == Scene::MOTION_NONE || !object->get_geometry()) { + return; + } + + Geometry *geom = object->get_geometry(); + geom->set_use_motion_blur(false); + geom->set_motion_steps(0); + + uint motion_steps; + + if (need_motion == Scene::MOTION_BLUR) { + motion_steps = object_motion_steps(b_parent, b_ob, Object::MAX_MOTION_STEPS); + geom->set_motion_steps(motion_steps); + if (motion_steps && object_use_deform_motion(b_parent, b_ob)) { + geom->set_use_motion_blur(true); + } + } + else { + motion_steps = 3; + geom->set_motion_steps(motion_steps); + } + + motion.resize(motion_steps, transform_empty()); + + if (motion_steps) { + motion[motion_steps / 2] = object->get_tfm(); + + /* update motion socket before trying to access object->motion_time */ + object->set_motion(motion); + + for (size_t step = 0; step < motion_steps; step++) { + motion_times.insert(object->motion_time(step)); + } + } +} Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph, BL::ViewLayer &b_view_layer, @@ -277,43 +319,6 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph, object->set_pass_id(b_ob.pass_index()); object->set_color(get_float3(b_ob.color())); object->set_tfm(tfm); - array motion; - object->set_motion(motion); - - /* motion blur */ - Scene::MotionType need_motion = scene->need_motion(); - if (need_motion != Scene::MOTION_NONE && object->get_geometry()) { - Geometry *geom = object->get_geometry(); - geom->set_use_motion_blur(false); - geom->set_motion_steps(0); - - uint motion_steps; - - if (need_motion == Scene::MOTION_BLUR) { - motion_steps = object_motion_steps(b_parent, b_ob, Object::MAX_MOTION_STEPS); - geom->set_motion_steps(motion_steps); - if (motion_steps && object_use_deform_motion(b_parent, b_ob)) { - geom->set_use_motion_blur(true); - } - } - else { - motion_steps = 3; - geom->set_motion_steps(motion_steps); - } - - motion.resize(motion_steps, transform_empty()); - - if (motion_steps) { - motion[motion_steps / 2] = tfm; - - /* update motion socket before trying to access object->motion_time */ - object->set_motion(motion); - - for (size_t step = 0; step < motion_steps; step++) { - motion_times.insert(object->motion_time(step)); - } - } - } /* dupli texture coordinates and random_id */ if (is_instance) { @@ -331,6 +336,8 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph, object->tag_update(scene); } + sync_object_motion_init(b_parent, b_ob, object); + if (is_instance) { /* Sync possible particle data. */ sync_dupli_particle(b_parent, b_instance, object); @@ -613,7 +620,7 @@ void BlenderSync::sync_motion(BL::RenderSettings &b_render, if (b_cam) { sync_camera_motion(b_render, b_cam, width, height, 0.0f); } - sync_objects(b_depsgraph, b_v3d, 0.0f); + sync_objects(b_depsgraph, b_v3d); } /* Insert motion times from camera. Motion times from other objects diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index aa87ac1dd81..4ec0477c585 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -739,12 +739,18 @@ void BlenderSync::free_data_after_sync(BL::Depsgraph &b_depsgraph) * caches to be releases from blender side in order to reduce peak memory * footprint during synchronization process. */ + const bool is_interface_locked = b_engine.render() && b_engine.render().use_lock_interface(); - const bool can_free_caches = (BlenderSession::headless || is_interface_locked) && - /* Baking re-uses the depsgraph multiple times, clearing crashes - * reading un-evaluated mesh data which isn't aligned with the - * geometry we're baking, see T71012. */ - !scene->bake_manager->get_baking(); + const bool is_persistent_data = b_engine.render() && b_engine.render().use_persistent_data(); + const bool can_free_caches = + (BlenderSession::headless || is_interface_locked) && + /* Baking re-uses the depsgraph multiple times, clearing crashes + * reading un-evaluated mesh data which isn't aligned with the + * geometry we're baking, see T71012. */ + !scene->bake_manager->get_baking() && + /* Persistent data must main caches for performance and correctness. */ + !is_persistent_data; + if (!can_free_caches) { return; } diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h index 787189da182..a222c5e490e 100644 --- a/intern/cycles/blender/blender_sync.h +++ b/intern/cycles/blender/blender_sync.h @@ -150,6 +150,7 @@ class BlenderSync { BlenderObjectCulling &culling, bool *use_portal, TaskPool *geom_task_pool); + void sync_object_motion_init(BL::Object &b_parent, BL::Object &b_ob, Object *object); bool sync_object_attributes(BL::DepsgraphObjectInstance &b_instance, Object *object); diff --git a/intern/cycles/kernel/kernel_subsurface.h b/intern/cycles/kernel/kernel_subsurface.h index b70df747a73..dd922b86722 100644 --- a/intern/cycles/kernel/kernel_subsurface.h +++ b/intern/cycles/kernel/kernel_subsurface.h @@ -25,8 +25,9 @@ CCL_NAMESPACE_BEGIN ccl_device_inline float3 subsurface_scatter_eval(ShaderData *sd, const ShaderClosure *sc, float disk_r, float r, bool all) { - /* this is the veach one-sample model with balance heuristic, some pdf - * factors drop out when using balance heuristic weighting */ + /* This is the Veach one-sample model with balance heuristic, some pdf + * factors drop out when using balance heuristic weighting. For branched + * path tracing (all) we sample all closure and don't use MIS. */ float3 eval_sum = zero_float3(); float pdf_sum = 0.0f; float sample_weight_inv = 0.0f; @@ -65,6 +66,30 @@ subsurface_scatter_eval(ShaderData *sd, const ShaderClosure *sc, float disk_r, f return (pdf_sum > 0.0f) ? eval_sum / pdf_sum : zero_float3(); } +ccl_device_inline float3 subsurface_scatter_walk_eval(ShaderData *sd, + const ShaderClosure *sc, + float3 throughput, + bool all) +{ + /* This is the Veach one-sample model with balance heuristic, some pdf + * factors drop out when using balance heuristic weighting. For branched + * path tracing (all) we sample all closure and don't use MIS. */ + if (!all) { + float bssrdf_weight = 0.0f; + float weight = sc->sample_weight; + + for (int i = 0; i < sd->num_closure; i++) { + sc = &sd->closure[i]; + + if (CLOSURE_IS_BSSRDF(sc->type)) { + bssrdf_weight += sc->sample_weight; + } + } + throughput *= bssrdf_weight / weight; + } + return throughput; +} + /* replace closures with a single diffuse bsdf closure after scatter step */ ccl_device void subsurface_scatter_setup_diffuse_bsdf( KernelGlobals *kg, ShaderData *sd, ClosureType type, float roughness, float3 weight, float3 N) @@ -437,7 +462,8 @@ ccl_device_noinline ccl_addr_space PathState *state, const ShaderClosure *sc, const float bssrdf_u, - const float bssrdf_v) + const float bssrdf_v, + bool all) { /* Sample diffuse surface scatter into the object. */ float3 D; @@ -669,7 +695,7 @@ ccl_device_noinline /* TODO: gain back performance lost from merging with disk BSSRDF. We * only need to return on hit so this indirect ray push/pop overhead * is not actually needed, but it does keep the code simpler. */ - ss_isect->weight[0] = throughput; + ss_isect->weight[0] = subsurface_scatter_walk_eval(sd, sc, throughput, all); #ifdef __SPLIT_KERNEL__ ss_isect->ray = *ray; #endif @@ -691,7 +717,7 @@ ccl_device_inline int subsurface_scatter_multi_intersect(KernelGlobals *kg, return subsurface_scatter_disk(kg, ss_isect, sd, sc, lcg_state, bssrdf_u, bssrdf_v, all); } else { - return subsurface_random_walk(kg, ss_isect, sd, state, sc, bssrdf_u, bssrdf_v); + return subsurface_random_walk(kg, ss_isect, sd, state, sc, bssrdf_u, bssrdf_v, all); } }