diff options
Diffstat (limited to 'intern/cycles/blender/blender_session.cpp')
-rw-r--r-- | intern/cycles/blender/blender_session.cpp | 323 |
1 files changed, 174 insertions, 149 deletions
diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index 00d23b9095e..eec13d04d7d 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -52,21 +52,22 @@ int BlenderSession::end_resumable_chunk = 0; BlenderSession::BlenderSession(BL::RenderEngine& b_engine, BL::UserPreferences& b_userpref, BL::BlendData& b_data, - BL::Scene& b_scene) -: b_engine(b_engine), + bool preview_osl) +: session(NULL), + b_engine(b_engine), b_userpref(b_userpref), b_data(b_data), b_render(b_engine.render()), - b_scene(b_scene), + b_depsgraph(PointerRNA_NULL), + b_scene(PointerRNA_NULL), b_v3d(PointerRNA_NULL), b_rv3d(PointerRNA_NULL), + width(0), + height(0), + preview_osl(preview_osl), python_thread_state(NULL) { /* offline render */ - - width = render_resolution_x(b_render); - height = render_resolution_y(b_render); - background = true; last_redraw_time = 0.0; start_resize_time = 0.0; @@ -76,23 +77,24 @@ BlenderSession::BlenderSession(BL::RenderEngine& b_engine, BlenderSession::BlenderSession(BL::RenderEngine& b_engine, BL::UserPreferences& b_userpref, BL::BlendData& b_data, - BL::Scene& b_scene, BL::SpaceView3D& b_v3d, BL::RegionView3D& b_rv3d, int width, int height) -: b_engine(b_engine), +: session(NULL), + b_engine(b_engine), b_userpref(b_userpref), b_data(b_data), - b_render(b_scene.render()), - b_scene(b_scene), + b_render(b_engine.render()), + b_depsgraph(PointerRNA_NULL), + b_scene(PointerRNA_NULL), b_v3d(b_v3d), b_rv3d(b_rv3d), width(width), height(height), + preview_osl(false), python_thread_state(NULL) { /* 3d view render */ - background = false; last_redraw_time = 0.0; start_resize_time = 0.0; @@ -141,26 +143,19 @@ void BlenderSession::create_session() session->scene = scene; + /* There is no single depsgraph to use for the entire render. + * So we need to handle this differently. + * + * We could loop over the final render result render layers in pipeline and keep Cycles unaware of multiple layers, + * or perhaps move syncing further down in the pipeline. + */ /* create sync */ sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress); BL::Object b_camera_override(b_engine.camera_override()); if(b_v3d) { - if(session_pause == false) { - /* full data sync */ - sync->sync_view(b_v3d, b_rv3d, width, height); - sync->sync_data(b_render, - b_v3d, - b_camera_override, - width, height, - &python_thread_state, - b_rlay_name.c_str()); - } + sync->sync_view(b_v3d, b_rv3d, width, height); } else { - /* for final render we will do full data sync per render layer, only - * do some basic syncing here, no objects or materials for speed */ - sync->sync_render_layers(b_v3d, NULL); - sync->sync_integrator(); sync->sync_camera(b_render, b_camera_override, width, height, ""); } @@ -173,18 +168,40 @@ void BlenderSession::create_session() update_resumable_tile_manager(session_params.samples); } -void BlenderSession::reset_session(BL::BlendData& b_data_, BL::Scene& b_scene_) +void BlenderSession::reset_session(BL::BlendData& b_data, BL::Depsgraph& b_depsgraph) { - b_data = b_data_; - b_render = b_engine.render(); - b_scene = b_scene_; + this->b_data = b_data; + this->b_depsgraph = b_depsgraph; + this->b_scene = b_depsgraph.scene_eval(); + + if (preview_osl) { + PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles"); + RNA_boolean_set(&cscene, "shading_system", preview_osl); + } + + if (b_v3d) { + this->b_render = b_scene.render(); + } + else { + this->b_render = b_engine.render(); + width = render_resolution_x(b_render); + height = render_resolution_y(b_render); + } + + if (session == NULL) { + create(); + } + + if (b_v3d) { + /* NOTE: We need to create session, but all the code from below + * will make viewport render to stuck on initialization. + */ + return; + } SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background); SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background); - width = render_resolution_x(b_render); - height = render_resolution_y(b_render); - if(scene->params.modified(scene_params) || session->params.modified(session_params) || !scene_params.persistent_data) @@ -210,16 +227,12 @@ void BlenderSession::reset_session(BL::BlendData& b_data_, BL::Scene& b_scene_) */ session->stats.mem_peak = session->stats.mem_used; + /* There is no single depsgraph to use for the entire render. + * See note on create_session(). + */ /* sync object should be re-created */ sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress); - /* for final render we will do full data sync per render layer, only - * do some basic syncing here, no objects or materials for speed */ - BL::Object b_camera_override(b_engine.camera_override()); - sync->sync_render_layers(b_v3d, NULL); - sync->sync_integrator(); - sync->sync_camera(b_render, b_camera_override, width, height, ""); - BL::SpaceView3D b_null_space_view3d(PointerRNA_NULL); BL::RegionView3D b_null_region_view3d(PointerRNA_NULL); BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, @@ -368,8 +381,10 @@ void BlenderSession::update_render_tile(RenderTile& rtile, bool highlight) do_write_update_render_tile(rtile, false, false); } -void BlenderSession::render() +void BlenderSession::render(BL::Depsgraph& b_depsgraph_) { + b_depsgraph = b_depsgraph_; + /* set callback to write out render results */ session->write_render_tile_cb = function_bind(&BlenderSession::write_render_tile, this, _1); session->update_render_tile_cb = function_bind(&BlenderSession::update_render_tile, this, _1, _2); @@ -379,123 +394,110 @@ void BlenderSession::render() BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, b_v3d, b_rv3d, scene->camera, width, height); /* render each layer */ - BL::RenderSettings r = b_scene.render(); - BL::RenderSettings::layers_iterator b_layer_iter; - BL::RenderResult::views_iterator b_view_iter; + BL::ViewLayer b_view_layer = b_depsgraph.view_layer_eval(); /* We do some special meta attributes when we only have single layer. */ - const bool is_single_layer = (r.layers.length() == 1); - - for(r.layers.begin(b_layer_iter); b_layer_iter != r.layers.end(); ++b_layer_iter) { - b_rlay_name = b_layer_iter->name(); + const bool is_single_layer = (b_scene.view_layers.length() == 1); - /* temporary render result to find needed passes and views */ - BL::RenderResult b_rr = begin_render_result(b_engine, 0, 0, 1, 1, b_rlay_name.c_str(), NULL); - BL::RenderResult::layers_iterator b_single_rlay; - b_rr.layers.begin(b_single_rlay); + /* temporary render result to find needed passes and views */ + BL::RenderResult b_rr = begin_render_result(b_engine, 0, 0, 1, 1, b_view_layer.name().c_str(), NULL); + BL::RenderResult::layers_iterator b_single_rlay; + b_rr.layers.begin(b_single_rlay); + BL::RenderLayer b_rlay = *b_single_rlay; - /* layer will be missing if it was disabled in the UI */ - if(b_single_rlay == b_rr.layers.end()) { - end_render_result(b_engine, b_rr, true, true, false); - continue; - } + /* add passes */ + array<Pass> passes = sync->sync_render_passes(b_rlay, b_view_layer, session_params); + buffer_params.passes = passes; + + PointerRNA crl = RNA_pointer_get(&b_view_layer.ptr, "cycles"); + bool use_denoising = get_boolean(crl, "use_denoising"); + buffer_params.denoising_data_pass = use_denoising; + session->tile_manager.schedule_denoising = use_denoising; + session->params.use_denoising = use_denoising; + scene->film->denoising_data_pass = buffer_params.denoising_data_pass; + scene->film->denoising_flags = 0; + if(!get_boolean(crl, "denoising_diffuse_direct")) scene->film->denoising_flags |= DENOISING_CLEAN_DIFFUSE_DIR; + if(!get_boolean(crl, "denoising_diffuse_indirect")) scene->film->denoising_flags |= DENOISING_CLEAN_DIFFUSE_IND; + if(!get_boolean(crl, "denoising_glossy_direct")) scene->film->denoising_flags |= DENOISING_CLEAN_GLOSSY_DIR; + if(!get_boolean(crl, "denoising_glossy_indirect")) scene->film->denoising_flags |= DENOISING_CLEAN_GLOSSY_IND; + if(!get_boolean(crl, "denoising_transmission_direct")) scene->film->denoising_flags |= DENOISING_CLEAN_TRANSMISSION_DIR; + if(!get_boolean(crl, "denoising_transmission_indirect")) scene->film->denoising_flags |= DENOISING_CLEAN_TRANSMISSION_IND; + if(!get_boolean(crl, "denoising_subsurface_direct")) scene->film->denoising_flags |= DENOISING_CLEAN_SUBSURFACE_DIR; + if(!get_boolean(crl, "denoising_subsurface_indirect")) scene->film->denoising_flags |= DENOISING_CLEAN_SUBSURFACE_IND; + scene->film->denoising_clean_pass = (scene->film->denoising_flags & DENOISING_CLEAN_ALL_PASSES); + buffer_params.denoising_clean_pass = scene->film->denoising_clean_pass; + session->params.denoising_radius = get_int(crl, "denoising_radius"); + session->params.denoising_strength = get_float(crl, "denoising_strength"); + session->params.denoising_feature_strength = get_float(crl, "denoising_feature_strength"); + session->params.denoising_relative_pca = get_boolean(crl, "denoising_relative_pca"); + + scene->film->pass_alpha_threshold = b_view_layer.pass_alpha_threshold(); + scene->film->tag_passes_update(scene, passes); + scene->film->tag_update(scene); + scene->integrator->tag_update(scene); - BL::RenderLayer b_rlay = *b_single_rlay; - - /* add passes */ - array<Pass> passes = sync->sync_render_passes(b_rlay, *b_layer_iter, session_params); - buffer_params.passes = passes; - - PointerRNA crl = RNA_pointer_get(&b_layer_iter->ptr, "cycles"); - bool use_denoising = get_boolean(crl, "use_denoising"); - buffer_params.denoising_data_pass = use_denoising; - session->tile_manager.schedule_denoising = use_denoising; - session->params.use_denoising = use_denoising; - scene->film->denoising_data_pass = buffer_params.denoising_data_pass; - scene->film->denoising_flags = 0; - if(!get_boolean(crl, "denoising_diffuse_direct")) scene->film->denoising_flags |= DENOISING_CLEAN_DIFFUSE_DIR; - if(!get_boolean(crl, "denoising_diffuse_indirect")) scene->film->denoising_flags |= DENOISING_CLEAN_DIFFUSE_IND; - if(!get_boolean(crl, "denoising_glossy_direct")) scene->film->denoising_flags |= DENOISING_CLEAN_GLOSSY_DIR; - if(!get_boolean(crl, "denoising_glossy_indirect")) scene->film->denoising_flags |= DENOISING_CLEAN_GLOSSY_IND; - if(!get_boolean(crl, "denoising_transmission_direct")) scene->film->denoising_flags |= DENOISING_CLEAN_TRANSMISSION_DIR; - if(!get_boolean(crl, "denoising_transmission_indirect")) scene->film->denoising_flags |= DENOISING_CLEAN_TRANSMISSION_IND; - if(!get_boolean(crl, "denoising_subsurface_direct")) scene->film->denoising_flags |= DENOISING_CLEAN_SUBSURFACE_DIR; - if(!get_boolean(crl, "denoising_subsurface_indirect")) scene->film->denoising_flags |= DENOISING_CLEAN_SUBSURFACE_IND; - scene->film->denoising_clean_pass = (scene->film->denoising_flags & DENOISING_CLEAN_ALL_PASSES); - buffer_params.denoising_clean_pass = scene->film->denoising_clean_pass; - session->params.denoising_radius = get_int(crl, "denoising_radius"); - session->params.denoising_strength = get_float(crl, "denoising_strength"); - session->params.denoising_feature_strength = get_float(crl, "denoising_feature_strength"); - session->params.denoising_relative_pca = get_boolean(crl, "denoising_relative_pca"); - - scene->film->pass_alpha_threshold = b_layer_iter->pass_alpha_threshold(); - scene->film->tag_passes_update(scene, passes); - scene->film->tag_update(scene); - scene->integrator->tag_update(scene); - - int view_index = 0; - for(b_rr.views.begin(b_view_iter); b_view_iter != b_rr.views.end(); ++b_view_iter, ++view_index) { - b_rview_name = b_view_iter->name(); - - /* set the current view */ - b_engine.active_view_set(b_rview_name.c_str()); - - /* update scene */ - BL::Object b_camera_override(b_engine.camera_override()); - sync->sync_camera(b_render, b_camera_override, width, height, b_rview_name.c_str()); - sync->sync_data(b_render, - b_v3d, - b_camera_override, - width, height, - &python_thread_state, - b_rlay_name.c_str()); - - /* Make sure all views have different noise patterns. - hardcoded value just to make it random */ - if(view_index != 0) { - scene->integrator->seed += hash_int_2d(scene->integrator->seed, hash_int(view_index * 0xdeadbeef)); - scene->integrator->tag_update(scene); - } + BL::RenderResult::views_iterator b_view_iter; + int view_index = 0; + for(b_rr.views.begin(b_view_iter); b_view_iter != b_rr.views.end(); ++b_view_iter, ++view_index) { + b_rlay_name = b_view_layer.name(); + b_rview_name = b_view_iter->name(); - /* Update number of samples per layer. */ - int samples = sync->get_layer_samples(); - bool bound_samples = sync->get_layer_bound_samples(); - int effective_layer_samples; + /* set the current view */ + b_engine.active_view_set(b_rview_name.c_str()); - if(samples != 0 && (!bound_samples || (samples < session_params.samples))) - effective_layer_samples = samples; - else - effective_layer_samples = session_params.samples; + /* update scene */ + BL::Object b_camera_override(b_engine.camera_override()); + sync->sync_camera(b_render, b_camera_override, width, height, b_rview_name.c_str()); + sync->sync_data(b_render, + b_depsgraph, + b_v3d, + b_camera_override, + width, height, + &python_thread_state); + builtin_images_load(); - /* Update tile manager if we're doing resumable render. */ - update_resumable_tile_manager(effective_layer_samples); + /* Make sure all views have different noise patterns. - hardcoded value just to make it random */ + if(view_index != 0) { + scene->integrator->seed += hash_int_2d(scene->integrator->seed, hash_int(view_index * 0xdeadbeef)); + scene->integrator->tag_update(scene); + } - /* Update session itself. */ - session->reset(buffer_params, effective_layer_samples); + /* Update number of samples per layer. */ + int samples = sync->get_layer_samples(); + bool bound_samples = sync->get_layer_bound_samples(); + int effective_layer_samples; - /* render */ - session->start(); - session->wait(); + if(samples != 0 && (!bound_samples || (samples < session_params.samples))) + effective_layer_samples = samples; + else + effective_layer_samples = session_params.samples; - if(session->progress.get_cancel()) - break; - } + /* Update tile manager if we're doing resumable render. */ + update_resumable_tile_manager(effective_layer_samples); - if(is_single_layer) { - BL::RenderResult b_rr = b_engine.get_result(); - string num_aa_samples = string_printf("%d", session->params.samples); - b_rr.stamp_data_add_field("Cycles Samples", num_aa_samples.c_str()); - /* TODO(sergey): Report whether we're doing resumable render - * and also start/end sample if so. - */ - } + /* Update session itself. */ + session->reset(buffer_params, effective_layer_samples); - /* free result without merging */ - end_render_result(b_engine, b_rr, true, true, false); + /* render */ + session->start(); + session->wait(); if(session->progress.get_cancel()) break; } + if(is_single_layer) { + BL::RenderResult b_rr = b_engine.get_result(); + string num_aa_samples = string_printf("%d", session->params.samples); + b_rr.stamp_data_add_field("Cycles Samples", num_aa_samples.c_str()); + /* TODO(sergey): Report whether we're doing resumable render + * and also start/end sample if so. + */ + } + + /* free result without merging */ + end_render_result(b_engine, b_rr, true, true, false); + double total_time, render_time; session->progress.get_time(total_time, render_time); VLOG(1) << "Total render time: " << total_time; @@ -505,6 +507,8 @@ void BlenderSession::render() session->write_render_tile_cb = function_null; session->update_render_tile_cb = function_null; + /* TODO: find a way to clear this data for persistent data render */ +#if 0 /* free all memory used (host and device), so we wouldn't leave render * engine with extra memory allocated */ @@ -513,6 +517,7 @@ void BlenderSession::render() delete sync; sync = NULL; +#endif } static void populate_bake_data(BakeData *data, const @@ -561,7 +566,8 @@ static int bake_pass_filter_get(const int pass_filter) return flag; } -void BlenderSession::bake(BL::Object& b_object, +void BlenderSession::bake(BL::Depsgraph& b_depsgraph_, + BL::Object& b_object, const string& pass_type, const int pass_filter, const int object_id, @@ -570,6 +576,8 @@ void BlenderSession::bake(BL::Object& b_object, const int /*depth*/, float result[]) { + b_depsgraph = b_depsgraph_; + ShaderEvalType shader_type = get_shader_type(pass_type); /* Set baking flag in advance, so kernel loading can check if we need @@ -602,11 +610,12 @@ void BlenderSession::bake(BL::Object& b_object, BL::Object b_camera_override(b_engine.camera_override()); sync->sync_camera(b_render, b_camera_override, width, height, ""); sync->sync_data(b_render, + b_depsgraph, b_v3d, b_camera_override, width, height, - &python_thread_state, - b_rlay_name.c_str()); + &python_thread_state); + builtin_images_load(); } BakeData *bake_data = NULL; @@ -740,7 +749,7 @@ void BlenderSession::update_render_result(BL::RenderResult& b_rr, do_write_update_render_result(b_rr, b_rlay, rtile, true); } -void BlenderSession::synchronize() +void BlenderSession::synchronize(BL::Depsgraph& b_depsgraph_) { /* only used for viewport render */ if(!b_v3d) @@ -766,7 +775,7 @@ void BlenderSession::synchronize() /* copy recalc flags, outside of mutex so we can decide to do the real * synchronization at a later time to not block on running updates */ - sync->sync_recalc(); + sync->sync_recalc(b_depsgraph_); /* don't do synchronization if on pause */ if(session_pause) { @@ -781,19 +790,23 @@ void BlenderSession::synchronize() } /* data and camera synchronize */ + b_depsgraph = b_depsgraph_; + BL::Object b_camera_override(b_engine.camera_override()); sync->sync_data(b_render, + b_depsgraph, b_v3d, b_camera_override, width, height, - &python_thread_state, - b_rlay_name.c_str()); + &python_thread_state); if(b_rv3d) sync->sync_view(b_v3d, b_rv3d, width, height); else sync->sync_camera(b_render, b_camera_override, width, height, ""); + builtin_images_load(); + /* unlock */ session->scene->mutex.unlock(); @@ -1301,6 +1314,9 @@ bool BlenderSession::builtin_image_float_pixels(const string &builtin_name, fprintf(stderr, "Cycles error: unexpected smoke volume resolution, skipping\n"); } else { + /* We originally were passing view_layer here but in reality we need a + * a depsgraph to pass to the RE_point_density_minmax() function. + */ /* TODO(sergey): Check we're indeed in shader node tree. */ PointerRNA ptr; RNA_pointer_create(NULL, &RNA_Node, builtin_data, &ptr); @@ -1308,14 +1324,23 @@ bool BlenderSession::builtin_image_float_pixels(const string &builtin_name, if(b_node.is_a(&RNA_ShaderNodeTexPointDensity)) { BL::ShaderNodeTexPointDensity b_point_density_node(b_node); int length; - int settings = background ? 1 : 0; /* 1 - render settings, 0 - vewport settings. */ - b_point_density_node.calc_point_density(b_scene, settings, &length, &pixels); + b_point_density_node.calc_point_density(b_depsgraph, &length, &pixels); } } return false; } +void BlenderSession::builtin_images_load() +{ + /* Force builtin images to be loaded along with Blender data sync. This + * is needed because we may be reading from depsgraph evaluated data which + * can be freed by Blender before Cycles reads it. */ + ImageManager *manager = session->scene->image_manager; + Device *device = session->device; + manager->device_load_builtin(device, session->scene, session->progress); +} + void BlenderSession::update_resumable_tile_manager(int num_samples) { const int num_resumable_chunks = BlenderSession::num_resumable_chunks, |