diff options
Diffstat (limited to 'intern/cycles/blender/blender_sync.cpp')
-rw-r--r-- | intern/cycles/blender/blender_sync.cpp | 336 |
1 files changed, 156 insertions, 180 deletions
diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index 841af87000f..063a2cd4d16 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -79,35 +79,17 @@ BlenderSync::~BlenderSync() /* Sync */ -bool BlenderSync::sync_recalc() +void BlenderSync::sync_recalc(BL::Depsgraph& b_depsgraph) { - /* sync recalc flags from blender to cycles. actual update is done separate, - * so we can do it later on if doing it immediate is not suitable */ - - BL::BlendData::materials_iterator b_mat; - bool has_updated_objects = b_data.objects.is_updated(); - for(b_data.materials.begin(b_mat); b_mat != b_data.materials.end(); ++b_mat) { - if(b_mat->is_updated() || (b_mat->node_tree() && b_mat->node_tree().is_updated())) { - shader_map.set_recalc(*b_mat); - } - else { - Shader *shader = shader_map.find(*b_mat); - if(has_updated_objects && shader != NULL && shader->has_object_dependency) { - shader_map.set_recalc(*b_mat); - } - } - } - - BL::BlendData::lamps_iterator b_lamp; + /* Sync recalc flags from blender to cycles. Actual update is done separate, + * so we can do it later on if doing it immediate is not suitable. */ - for(b_data.lamps.begin(b_lamp); b_lamp != b_data.lamps.end(); ++b_lamp) - if(b_lamp->is_updated() || (b_lamp->node_tree() && b_lamp->node_tree().is_updated())) - shader_map.set_recalc(*b_lamp); - - bool dicing_prop_changed = false; + bool has_updated_objects = b_depsgraph.id_type_updated(BL::DriverTarget::id_type_OBJECT); if(experimental) { + /* Mark all meshes as needing to be exported again if dicing changed. */ PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles"); + bool dicing_prop_changed = false; float updated_dicing_rate = preview ? RNA_float_get(&cscene, "preview_dicing_rate") : RNA_float_get(&cscene, "dicing_rate"); @@ -123,85 +105,103 @@ bool BlenderSync::sync_recalc() max_subdivisions = updated_max_subdivisions; dicing_prop_changed = true; } + + if(dicing_prop_changed) { + for(const pair<void*, Mesh*>& iter: mesh_map.key_to_scene_data()) { + Mesh *mesh = iter.second; + if(mesh->subdivision_type != Mesh::SUBDIVISION_NONE) { + mesh_map.set_recalc(iter.first); + } + } + } } - BL::BlendData::objects_iterator b_ob; + /* Iterate over all IDs in this depsgraph. */ + BL::Depsgraph::updates_iterator b_update; + for(b_depsgraph.updates.begin(b_update); b_update != b_depsgraph.updates.end(); ++b_update) { + BL::ID b_id(b_update->id()); - for(b_data.objects.begin(b_ob); b_ob != b_data.objects.end(); ++b_ob) { - if(b_ob->is_updated()) { - object_map.set_recalc(*b_ob); - light_map.set_recalc(*b_ob); + /* Material */ + if(b_id.is_a(&RNA_Material)) { + BL::Material b_mat(b_id); + shader_map.set_recalc(b_mat); + } + /* Light */ + else if(b_id.is_a(&RNA_Light)) { + BL::Light b_light(b_id); + shader_map.set_recalc(b_light); } + /* Object */ + else if(b_id.is_a(&RNA_Object)) { + BL::Object b_ob(b_id); + const bool updated_geometry = b_update->is_updated_geometry(); + + if(b_update->is_updated_transform()) { + object_map.set_recalc(b_ob); + light_map.set_recalc(b_ob); + } - if(object_is_mesh(*b_ob)) { - if(b_ob->is_updated_data() || b_ob->data().is_updated() || - (dicing_prop_changed && object_subdivision_type(*b_ob, preview, experimental) != Mesh::SUBDIVISION_NONE)) - { - BL::ID key = BKE_object_is_modified(*b_ob)? *b_ob: b_ob->data(); - mesh_map.set_recalc(key); + if(object_is_mesh(b_ob)) { + if(updated_geometry || + (object_subdivision_type(b_ob, preview, experimental) != Mesh::SUBDIVISION_NONE)) + { + BL::ID key = BKE_object_is_modified(b_ob)? b_ob: b_ob.data(); + mesh_map.set_recalc(key); + } + } + else if(object_is_light(b_ob)) { + if(updated_geometry) { + light_map.set_recalc(b_ob); + } + } + + if(updated_geometry) { + BL::Object::particle_systems_iterator b_psys; + for(b_ob.particle_systems.begin(b_psys); b_psys != b_ob.particle_systems.end(); ++b_psys) + particle_system_map.set_recalc(b_ob); } } - else if(object_is_light(*b_ob)) { - if(b_ob->is_updated_data() || b_ob->data().is_updated()) - light_map.set_recalc(*b_ob); + /* Mesh */ + else if(b_id.is_a(&RNA_Mesh)) { + BL::Mesh b_mesh(b_id); + mesh_map.set_recalc(b_mesh); } - - if(b_ob->is_updated_data()) { - BL::Object::particle_systems_iterator b_psys; - for(b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys) - particle_system_map.set_recalc(*b_ob); + /* World */ + else if(b_id.is_a(&RNA_World)) { + BL::World b_world(b_id); + if(world_map == b_world.ptr.data) { + world_recalc = true; + } } } - BL::BlendData::meshes_iterator b_mesh; - - for(b_data.meshes.begin(b_mesh); b_mesh != b_data.meshes.end(); ++b_mesh) { - if(b_mesh->is_updated()) { - mesh_map.set_recalc(*b_mesh); + /* Updates shader with object dependency if objects changed. */ + if(has_updated_objects) { + if(scene->default_background->has_object_dependency) { + world_recalc = true; } - } - - BL::BlendData::worlds_iterator b_world; - for(b_data.worlds.begin(b_world); b_world != b_data.worlds.end(); ++b_world) { - if(world_map == b_world->ptr.data) { - if(b_world->is_updated() || - (b_world->node_tree() && b_world->node_tree().is_updated())) - { - world_recalc = true; - } - else if(b_world->node_tree() && b_world->use_nodes()) { - Shader *shader = scene->default_background; - if(has_updated_objects && shader->has_object_dependency) { - world_recalc = true; - } + foreach(Shader *shader, scene->shaders) { + if(shader->has_object_dependency) { + shader->need_sync_object = true; } } } - - bool recalc = - shader_map.has_recalc() || - object_map.has_recalc() || - light_map.has_recalc() || - mesh_map.has_recalc() || - particle_system_map.has_recalc() || - BlendDataObjects_is_updated_get(&b_data.ptr) || - world_recalc; - - return recalc; } void BlenderSync::sync_data(BL::RenderSettings& b_render, + BL::Depsgraph& b_depsgraph, BL::SpaceView3D& b_v3d, BL::Object& b_override, int width, int height, - void **python_thread_state, - const char *layer) + void **python_thread_state) { - sync_render_layers(b_v3d, layer); + BL::ViewLayer b_view_layer = b_depsgraph.view_layer_eval(); + + sync_view_layer(b_v3d, b_view_layer); sync_integrator(); sync_film(); - sync_shaders(); + sync_shaders(b_depsgraph); sync_images(); sync_curve_settings(); @@ -211,14 +211,17 @@ void BlenderSync::sync_data(BL::RenderSettings& b_render, scene->need_motion() == Scene::MOTION_NONE || scene->camera->motion_position == Camera::MOTION_POSITION_CENTER) { - sync_objects(); + sync_objects(b_depsgraph); } sync_motion(b_render, + b_depsgraph, b_override, width, height, python_thread_state); mesh_synced.clear(); + + free_data_after_sync(b_depsgraph); } /* Integrator */ @@ -372,75 +375,33 @@ void BlenderSync::sync_film() /* Render Layer */ -void BlenderSync::sync_render_layers(BL::SpaceView3D& b_v3d, const char *layer) +void BlenderSync::sync_view_layer(BL::SpaceView3D& /*b_v3d*/, BL::ViewLayer& b_view_layer) { - PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles"); - string layername; - - /* 3d view */ - if(b_v3d) { - if(RNA_boolean_get(&cscene, "preview_active_layer")) { - BL::RenderLayers layers(b_scene.render().ptr); - layername = layers.active().name(); - layer = layername.c_str(); - } - else { - render_layer.scene_layer = get_layer(b_v3d.layers(), b_v3d.layers_local_view()); - render_layer.layer = render_layer.scene_layer; - render_layer.exclude_layer = 0; - render_layer.holdout_layer = 0; - render_layer.material_override = PointerRNA_NULL; - render_layer.use_background_shader = true; - render_layer.use_background_ao = true; - render_layer.use_hair = true; - render_layer.use_surfaces = true; - render_layer.use_viewport_visibility = true; - render_layer.samples = 0; - render_layer.bound_samples = false; - return; - } - } - /* render layer */ - BL::RenderSettings r = b_scene.render(); - BL::RenderSettings::layers_iterator b_rlay; + view_layer.name = b_view_layer.name(); + view_layer.use_background_shader = b_view_layer.use_sky(); + view_layer.use_background_ao = b_view_layer.use_ao(); + view_layer.use_surfaces = b_view_layer.use_solid(); + view_layer.use_hair = b_view_layer.use_strand(); + + /* Material override. */ + view_layer.material_override = b_view_layer.material_override(); + + /* Sample override. */ + PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles"); int use_layer_samples = get_enum(cscene, "use_layer_samples"); - bool first_layer = true; - uint layer_override = get_layer(b_engine.layer_override()); - uint scene_layers = layer_override ? layer_override : get_layer(b_scene.layers()); - - for(r.layers.begin(b_rlay); b_rlay != r.layers.end(); ++b_rlay) { - if((!layer && first_layer) || (layer && b_rlay->name() == layer)) { - render_layer.name = b_rlay->name(); - - render_layer.holdout_layer = get_layer(b_rlay->layers_zmask()); - render_layer.exclude_layer = get_layer(b_rlay->layers_exclude()); - - render_layer.scene_layer = scene_layers & ~render_layer.exclude_layer; - render_layer.scene_layer |= render_layer.exclude_layer & render_layer.holdout_layer; - - render_layer.layer = get_layer(b_rlay->layers()); - render_layer.layer |= render_layer.holdout_layer; - - render_layer.material_override = b_rlay->material_override(); - render_layer.use_background_shader = b_rlay->use_sky(); - render_layer.use_background_ao = b_rlay->use_ao(); - render_layer.use_surfaces = b_rlay->use_solid(); - render_layer.use_hair = b_rlay->use_strand(); - render_layer.use_viewport_visibility = false; - - render_layer.bound_samples = (use_layer_samples == 1); - if(use_layer_samples != 2) { - int samples = b_rlay->samples(); - if(get_boolean(cscene, "use_square_samples")) - render_layer.samples = samples * samples; - else - render_layer.samples = samples; - } - } - first_layer = false; + view_layer.bound_samples = (use_layer_samples == 1); + view_layer.samples = 0; + + if(use_layer_samples != 2) { + int samples = b_view_layer.samples(); + if(get_boolean(cscene, "use_square_samples")) + view_layer.samples = samples * samples; + else + view_layer.samples = samples; } + } /* Images */ @@ -553,7 +514,7 @@ int BlenderSync::get_denoising_pass(BL::RenderPass& b_pass) } vector<Pass> BlenderSync::sync_render_passes(BL::RenderLayer& b_rlay, - BL::SceneRenderLayer& b_srlay) + BL::ViewLayer& b_view_layer) { vector<Pass> passes; Pass::add(PASS_COMBINED, passes); @@ -571,7 +532,7 @@ vector<Pass> BlenderSync::sync_render_passes(BL::RenderLayer& b_rlay, Pass::add(pass_type, passes); } - PointerRNA crp = RNA_pointer_get(&b_srlay.ptr, "cycles"); + PointerRNA crp = RNA_pointer_get(&b_view_layer.ptr, "cycles"); bool full_denoising = get_boolean(crp, "use_denoising"); bool write_denoising_passes = get_boolean(crp, "denoising_store_passes"); @@ -587,49 +548,49 @@ vector<Pass> BlenderSync::sync_render_passes(BL::RenderLayer& b_rlay, MAP_OPTION("denoising_subsurface_direct", DENOISING_CLEAN_SUBSURFACE_DIR); MAP_OPTION("denoising_subsurface_indirect", DENOISING_CLEAN_SUBSURFACE_IND); #undef MAP_OPTION - b_engine.add_pass("Noisy Image", 4, "RGBA", b_srlay.name().c_str()); + b_engine.add_pass("Noisy Image", 4, "RGBA", b_view_layer.name().c_str()); } if(write_denoising_passes) { - b_engine.add_pass("Denoising Normal", 3, "XYZ", b_srlay.name().c_str()); - b_engine.add_pass("Denoising Albedo", 3, "RGB", b_srlay.name().c_str()); - b_engine.add_pass("Denoising Depth", 1, "Z", b_srlay.name().c_str()); - b_engine.add_pass("Denoising Shadowing", 1, "X", b_srlay.name().c_str()); - b_engine.add_pass("Denoising Variance", 3, "RGB", b_srlay.name().c_str()); - b_engine.add_pass("Denoising Intensity", 1, "X", b_srlay.name().c_str()); + b_engine.add_pass("Denoising Normal", 3, "XYZ", b_view_layer.name().c_str()); + b_engine.add_pass("Denoising Albedo", 3, "RGB", b_view_layer.name().c_str()); + b_engine.add_pass("Denoising Depth", 1, "Z", b_view_layer.name().c_str()); + b_engine.add_pass("Denoising Shadowing", 1, "X", b_view_layer.name().c_str()); + b_engine.add_pass("Denoising Variance", 3, "RGB", b_view_layer.name().c_str()); + b_engine.add_pass("Denoising Intensity", 1, "X", b_view_layer.name().c_str()); if(scene->film->denoising_flags & DENOISING_CLEAN_ALL_PASSES) { - b_engine.add_pass("Denoising Clean", 3, "RGB", b_srlay.name().c_str()); + b_engine.add_pass("Denoising Clean", 3, "RGB", b_view_layer.name().c_str()); } } #ifdef __KERNEL_DEBUG__ if(get_boolean(crp, "pass_debug_bvh_traversed_nodes")) { - b_engine.add_pass("Debug BVH Traversed Nodes", 1, "X", b_srlay.name().c_str()); + b_engine.add_pass("Debug BVH Traversed Nodes", 1, "X", b_view_layer.name().c_str()); Pass::add(PASS_BVH_TRAVERSED_NODES, passes); } if(get_boolean(crp, "pass_debug_bvh_traversed_instances")) { - b_engine.add_pass("Debug BVH Traversed Instances", 1, "X", b_srlay.name().c_str()); + b_engine.add_pass("Debug BVH Traversed Instances", 1, "X", b_view_layer.name().c_str()); Pass::add(PASS_BVH_TRAVERSED_INSTANCES, passes); } if(get_boolean(crp, "pass_debug_bvh_intersections")) { - b_engine.add_pass("Debug BVH Intersections", 1, "X", b_srlay.name().c_str()); + b_engine.add_pass("Debug BVH Intersections", 1, "X", b_view_layer.name().c_str()); Pass::add(PASS_BVH_INTERSECTIONS, passes); } if(get_boolean(crp, "pass_debug_ray_bounces")) { - b_engine.add_pass("Debug Ray Bounces", 1, "X", b_srlay.name().c_str()); + b_engine.add_pass("Debug Ray Bounces", 1, "X", b_view_layer.name().c_str()); Pass::add(PASS_RAY_BOUNCES, passes); } #endif if(get_boolean(crp, "pass_debug_render_time")) { - b_engine.add_pass("Debug Render Time", 1, "X", b_srlay.name().c_str()); + b_engine.add_pass("Debug Render Time", 1, "X", b_view_layer.name().c_str()); Pass::add(PASS_RENDER_TIME, passes); } if(get_boolean(crp, "use_pass_volume_direct")) { - b_engine.add_pass("VolumeDir", 3, "RGB", b_srlay.name().c_str()); + b_engine.add_pass("VolumeDir", 3, "RGB", b_view_layer.name().c_str()); Pass::add(PASS_VOLUME_DIRECT, passes); } if(get_boolean(crp, "use_pass_volume_indirect")) { - b_engine.add_pass("VolumeInd", 3, "RGB", b_srlay.name().c_str()); + b_engine.add_pass("VolumeInd", 3, "RGB", b_view_layer.name().c_str()); Pass::add(PASS_VOLUME_INDIRECT, passes); } @@ -641,7 +602,7 @@ vector<Pass> BlenderSync::sync_render_passes(BL::RenderLayer& b_rlay, if(get_boolean(crp, "use_pass_crypto_object")) { for(int i = 0; i < crypto_depth; ++i) { string passname = cryptomatte_prefix + string_printf("Object%02d", i); - b_engine.add_pass(passname.c_str(), 4, "RGBA", b_srlay.name().c_str()); + b_engine.add_pass(passname.c_str(), 4, "RGBA", b_view_layer.name().c_str()); Pass::add(PASS_CRYPTOMATTE, passes, passname.c_str()); } scene->film->cryptomatte_passes = (CryptomatteType)(scene->film->cryptomatte_passes | CRYPT_OBJECT); @@ -649,7 +610,7 @@ vector<Pass> BlenderSync::sync_render_passes(BL::RenderLayer& b_rlay, if(get_boolean(crp, "use_pass_crypto_material")) { for(int i = 0; i < crypto_depth; ++i) { string passname = cryptomatte_prefix + string_printf("Material%02d", i); - b_engine.add_pass(passname.c_str(), 4, "RGBA", b_srlay.name().c_str()); + b_engine.add_pass(passname.c_str(), 4, "RGBA", b_view_layer.name().c_str()); Pass::add(PASS_CRYPTOMATTE, passes, passname.c_str()); } scene->film->cryptomatte_passes = (CryptomatteType)(scene->film->cryptomatte_passes | CRYPT_MATERIAL); @@ -657,7 +618,7 @@ vector<Pass> BlenderSync::sync_render_passes(BL::RenderLayer& b_rlay, if(get_boolean(crp, "use_pass_crypto_asset")) { for(int i = 0; i < crypto_depth; ++i) { string passname = cryptomatte_prefix + string_printf("Asset%02d", i); - b_engine.add_pass(passname.c_str(), 4, "RGBA", b_srlay.name().c_str()); + b_engine.add_pass(passname.c_str(), 4, "RGBA", b_view_layer.name().c_str()); Pass::add(PASS_CRYPTOMATTE, passes, passname.c_str()); } scene->film->cryptomatte_passes = (CryptomatteType)(scene->film->cryptomatte_passes | CRYPT_ASSET); @@ -669,6 +630,30 @@ vector<Pass> BlenderSync::sync_render_passes(BL::RenderLayer& b_rlay, return passes; } +void BlenderSync::free_data_after_sync(BL::Depsgraph& b_depsgraph) +{ + /* When viewport display is not needed during render we can force some + * 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; + if(!can_free_caches) { + return; + } + /* TODO(sergey): We can actually remove the whole dependency graph, + * but that will need some API support first. + */ + BL::Depsgraph::objects_iterator b_ob; + for(b_depsgraph.objects.begin(b_ob); + b_ob != b_depsgraph.objects.end(); + ++b_ob) + { + b_ob->cache_release(); + } +} + /* Scene Parameters */ SceneParams BlenderSync::get_scene_params(BL::Scene& b_scene, @@ -737,7 +722,7 @@ bool BlenderSync::get_session_pause(BL::Scene& b_scene, bool background) } SessionParams BlenderSync::get_session_params(BL::RenderEngine& b_engine, - BL::UserPreferences& b_userpref, + BL::Preferences& b_preferences, BL::Scene& b_scene, bool background) { @@ -752,7 +737,7 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine& b_engine, /* Device */ params.threads = blender_device_threads(b_scene); - params.device = blender_device_info(b_userpref, b_scene, params.background); + params.device = blender_device_info(b_preferences, b_scene, params.background); /* samples */ int samples = get_int(cscene, "samples"); @@ -828,13 +813,14 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine& b_engine, /* progressive refine */ BL::RenderSettings b_r = b_scene.render(); - params.progressive_refine = get_boolean(cscene, "use_progressive_refine") && + params.progressive_refine = (b_engine.is_preview() || + get_boolean(cscene, "use_progressive_refine")) && !b_r.use_save_buffers(); if(params.progressive_refine) { - BL::RenderSettings::layers_iterator b_rlay; - for(b_r.layers.begin(b_rlay); b_rlay != b_r.layers.end(); ++b_rlay) { - PointerRNA crl = RNA_pointer_get(&b_rlay->ptr, "cycles"); + BL::Scene::view_layers_iterator b_view_layer; + for(b_scene.view_layers.begin(b_view_layer); b_view_layer != b_scene.view_layers.end(); ++b_view_layer) { + PointerRNA crl = RNA_pointer_get(&b_view_layer->ptr, "cycles"); if(get_boolean(crl, "use_denoising")) { params.progressive_refine = false; } @@ -862,17 +848,7 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine& b_engine, params.shadingsystem = SHADINGSYSTEM_OSL; /* color managagement */ -#ifdef GLEW_MX - /* When using GLEW MX we need to check whether we've got an OpenGL - * context for current window. This is because command line rendering - * doesn't have OpenGL context actually. - */ - if(glewGetContext() != NULL) -#endif - { - params.display_buffer_linear = GLEW_ARB_half_float_pixel && - b_engine.support_display_space_shader(b_scene); - } + params.display_buffer_linear = b_engine.support_display_space_shader(b_scene); if(b_engine.is_preview()) { /* For preview rendering we're using same timeout as |