Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--intern/cycles/blender/addon/ui.py2
-rw-r--r--intern/cycles/blender/blender_session.cpp36
-rw-r--r--intern/cycles/blender/blender_sync.cpp14
-rw-r--r--intern/cycles/render/scene.cpp2
-rw-r--r--intern/cycles/render/scene.h6
-rw-r--r--source/blender/blenkernel/intern/scene.c15
-rw-r--r--source/blender/depsgraph/DEG_depsgraph.h24
-rw-r--r--source/blender/depsgraph/intern/depsgraph.cc7
-rw-r--r--source/blender/depsgraph/intern/depsgraph.h3
-rw-r--r--source/blender/depsgraph/intern/depsgraph_tag.cc17
-rw-r--r--source/blender/editors/render/render_update.c2
-rw-r--r--source/blender/makesrna/intern/rna_render.c6
-rw-r--r--source/blender/makesrna/intern/rna_scene.c12
-rw-r--r--source/blender/render/RE_engine.h2
-rw-r--r--source/blender/render/RE_pipeline.h14
-rw-r--r--source/blender/render/intern/engine.c131
-rw-r--r--source/blender/render/intern/pipeline.c61
17 files changed, 229 insertions, 125 deletions
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index 28fc48f33d3..73bc114893a 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -775,7 +775,7 @@ class CYCLES_RENDER_PT_performance_final_render(CyclesButtonsPanel, Panel):
col = layout.column()
col.prop(rd, "use_save_buffers")
- col.prop(rd, "use_persistent_data", text="Persistent Images")
+ col.prop(rd, "use_persistent_data", text="Persistent Data")
class CYCLES_RENDER_PT_performance_viewport(CyclesButtonsPanel, Panel):
diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp
index ae13310789e..bf4d80ce51b 100644
--- a/intern/cycles/blender/blender_session.cpp
+++ b/intern/cycles/blender/blender_session.cpp
@@ -143,12 +143,6 @@ 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());
@@ -213,7 +207,7 @@ void BlenderSession::reset_session(BL::BlendData &b_data, BL::Depsgraph &b_depsg
SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background);
if (scene->params.modified(scene_params) || session->params.modified(session_params) ||
- !scene_params.persistent_data) {
+ !this->b_render.use_persistent_data()) {
/* if scene or session parameters changed, it's easier to simply re-create
* them rather than trying to distinguish which settings need to be updated
*/
@@ -225,7 +219,6 @@ void BlenderSession::reset_session(BL::BlendData &b_data, BL::Depsgraph &b_depsg
}
session->progress.reset();
- scene->reset();
session->tile_manager.set_tile_order(session_params.tile_order);
@@ -234,12 +227,15 @@ void BlenderSession::reset_session(BL::BlendData &b_data, BL::Depsgraph &b_depsg
*/
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 */
- delete sync;
- sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress);
+ if (is_new_session) {
+ /* Sync object should be re-created for new scene. */
+ delete sync;
+ sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress);
+ }
+ else {
+ /* Sync recalculations to do just the required updates. */
+ sync->sync_recalc(b_depsgraph, b_v3d);
+ }
BL::SpaceView3D b_null_space_view3d(PointerRNA_NULL);
BL::RegionView3D b_null_region_view3d(PointerRNA_NULL);
@@ -598,18 +594,6 @@ void BlenderSession::render(BL::Depsgraph &b_depsgraph_)
/* clear callback */
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
- */
-
- session->device_free();
-
- delete sync;
- sync = NULL;
-#endif
}
static int bake_pass_filter_get(const int pass_filter)
diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp
index bbeb6858b76..09bc329041f 100644
--- a/intern/cycles/blender/blender_sync.cpp
+++ b/intern/cycles/blender/blender_sync.cpp
@@ -211,9 +211,11 @@ void BlenderSync::sync_recalc(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d
}
}
- BlenderViewportParameters new_viewport_parameters(b_v3d);
- if (viewport_parameters.modified(new_viewport_parameters)) {
- world_recalc = true;
+ if (b_v3d) {
+ BlenderViewportParameters new_viewport_parameters(b_v3d);
+ if (viewport_parameters.modified(new_viewport_parameters)) {
+ world_recalc = true;
+ }
}
}
@@ -757,7 +759,6 @@ void BlenderSync::free_data_after_sync(BL::Depsgraph &b_depsgraph)
SceneParams BlenderSync::get_scene_params(BL::Scene &b_scene, bool background)
{
- BL::RenderSettings r = b_scene.render();
SceneParams params;
PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
const bool shadingsystem = RNA_boolean_get(&cscene, "shading_system");
@@ -781,11 +782,6 @@ SceneParams BlenderSync::get_scene_params(BL::Scene &b_scene, bool background)
params.hair_shape = (CurveShapeType)get_enum(
csscene, "shape", CURVE_NUM_SHAPE_TYPES, CURVE_THICK);
- if (background && params.shadingsystem != SHADINGSYSTEM_OSL)
- params.persistent_data = r.use_persistent_data();
- else
- params.persistent_data = false;
-
int texture_limit;
if (background) {
texture_limit = RNA_enum_get(&cscene, "texture_limit_render");
diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp
index d3dfe1c5be6..38e8d9145dc 100644
--- a/intern/cycles/render/scene.cpp
+++ b/intern/cycles/render/scene.cpp
@@ -179,7 +179,7 @@ void Scene::free_memory(bool final)
bake_manager->device_free(device, &dscene);
- if (!params.persistent_data || final)
+ if (final)
image_manager->device_free(device);
else
image_manager->device_free_builtin(device);
diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h
index 61c753e411c..3e7de203c54 100644
--- a/intern/cycles/render/scene.h
+++ b/intern/cycles/render/scene.h
@@ -178,7 +178,6 @@ class SceneParams {
int num_bvh_time_steps;
int hair_subdivisions;
CurveShapeType hair_shape;
- bool persistent_data;
int texture_limit;
bool background;
@@ -193,7 +192,6 @@ class SceneParams {
num_bvh_time_steps = 0;
hair_subdivisions = 3;
hair_shape = CURVE_RIBBON;
- persistent_data = false;
texture_limit = 0;
background = true;
}
@@ -206,7 +204,7 @@ class SceneParams {
use_bvh_unaligned_nodes == params.use_bvh_unaligned_nodes &&
num_bvh_time_steps == params.num_bvh_time_steps &&
hair_subdivisions == params.hair_subdivisions && hair_shape == params.hair_shape &&
- persistent_data == params.persistent_data && texture_limit == params.texture_limit);
+ texture_limit == params.texture_limit);
}
int curve_subdivisions()
@@ -301,7 +299,7 @@ class Scene : public NodeOwner {
* node array (e.g. Scene::geometry for Geometry nodes) and tag the appropriate
* manager for an update.
*/
- template<typename T, typename... Args> T *create_node(Args &&... args)
+ template<typename T, typename... Args> T *create_node(Args &&...args)
{
T *node = new T(args...);
node->set_owner(this);
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index e0ff0b0268a..44c0fd5144b 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -2660,7 +2660,7 @@ static void scene_graph_update_tagged(Depsgraph *depsgraph, Main *bmain, bool on
bmain, &scene->id, depsgraph, BKE_CB_EVT_DEPSGRAPH_UPDATE_POST);
/* It is possible that the custom callback modified scene and removed some IDs from the main
- * database. In this case DEG_ids_clear_recalc() will crash because it iterates over all IDs
+ * database. In this case DEG_editors_update() will crash because it iterates over all IDs
* which depsgraph was built for.
*
* The solution is to update relations prior to this call, avoiding access to freed IDs.
@@ -2673,9 +2673,7 @@ static void scene_graph_update_tagged(Depsgraph *depsgraph, Main *bmain, bool on
DEG_graph_relations_update(depsgraph);
}
/* Inform editors about possible changes. */
- DEG_ids_check_recalc(bmain, depsgraph, scene, view_layer, false);
- /* Clear recalc flags. */
- DEG_ids_clear_recalc(bmain, depsgraph);
+ DEG_editors_update(bmain, depsgraph, scene, view_layer, false);
/* If user callback did not tag anything for update we can skip second iteration.
* Otherwise we update scene once again, but without running callbacks to bring
@@ -2736,14 +2734,12 @@ void BKE_scene_graph_update_for_newframe(Depsgraph *depsgraph)
BKE_callback_exec_id_depsgraph(bmain, &scene->id, depsgraph, BKE_CB_EVT_FRAME_CHANGE_POST);
/* NOTE: Similar to this case in scene_graph_update_tagged(). Need to ensure that
- * DEG_ids_clear_recalc() doesn't access freed memory of possibly removed ID. */
+ * DEG_editors_update() doesn't access freed memory of possibly removed ID. */
DEG_graph_relations_update(depsgraph);
}
/* Inform editors about possible changes. */
- DEG_ids_check_recalc(bmain, depsgraph, scene, view_layer, true);
- /* clear recalc flags */
- DEG_ids_clear_recalc(bmain, depsgraph);
+ DEG_editors_update(bmain, depsgraph, scene, view_layer, true);
/* If user callback did not tag anything for update we can skip second iteration.
* Otherwise we update scene once again, but without running callbacks to bring
@@ -3462,6 +3458,9 @@ static Depsgraph **scene_ensure_depsgraph_p(Main *bmain, Scene *scene, ViewLayer
BLI_snprintf(name, sizeof(name), "%s :: %s", scene->id.name, view_layer->name);
DEG_debug_name_set(*depsgraph_ptr, name);
+ /* These viewport depsgraphs communicate changes to the editors. */
+ DEG_enable_editors_update(*depsgraph_ptr);
+
return depsgraph_ptr;
}
diff --git a/source/blender/depsgraph/DEG_depsgraph.h b/source/blender/depsgraph/DEG_depsgraph.h
index 567916fdebe..f7aeca7e75f 100644
--- a/source/blender/depsgraph/DEG_depsgraph.h
+++ b/source/blender/depsgraph/DEG_depsgraph.h
@@ -139,16 +139,20 @@ void DEG_graph_time_tag_update(struct Depsgraph *depsgraph);
void DEG_graph_id_type_tag(struct Depsgraph *depsgraph, short id_type);
void DEG_id_type_tag(struct Main *bmain, short id_type);
-void DEG_ids_clear_recalc(struct Main *bmain, Depsgraph *depsgraph);
-
-/* Check if something was changed in the database and inform
- * editors about this.
- */
-void DEG_ids_check_recalc(struct Main *bmain,
- struct Depsgraph *depsgraph,
- struct Scene *scene,
- struct ViewLayer *view_layer,
- bool time);
+/* Set a depsgraph to flush updates to editors. This would be done
+ * for viewport depsgraphs, but not render or export depsgraph for example. */
+void DEG_enable_editors_update(struct Depsgraph *depsgraph);
+
+/* Check if something was changed in the database and inform editors about this,
+ * then clear recalc flags. */
+void DEG_editors_update(struct Main *bmain,
+ struct Depsgraph *depsgraph,
+ struct Scene *scene,
+ struct ViewLayer *view_layer,
+ bool time);
+
+/* Clear recalc flags after editors or renderers have handled updates. */
+void DEG_ids_clear_recalc(Depsgraph *depsgraph);
/* ************************************************ */
/* Evaluation Engine API */
diff --git a/source/blender/depsgraph/intern/depsgraph.cc b/source/blender/depsgraph/intern/depsgraph.cc
index 3d30e7e79b9..8e1ab23fae0 100644
--- a/source/blender/depsgraph/intern/depsgraph.cc
+++ b/source/blender/depsgraph/intern/depsgraph.cc
@@ -70,7 +70,8 @@ Depsgraph::Depsgraph(Main *bmain, Scene *scene, ViewLayer *view_layer, eEvaluati
scene_cow(nullptr),
is_active(false),
is_evaluating(false),
- is_render_pipeline_depsgraph(false)
+ is_render_pipeline_depsgraph(false),
+ use_editors_update(false)
{
BLI_spin_init(&lock);
memset(id_type_updated, 0, sizeof(id_type_updated));
@@ -285,7 +286,9 @@ Depsgraph *DEG_graph_new(Main *bmain, Scene *scene, ViewLayer *view_layer, eEval
}
/* Replace the "owner" pointers (currently Main/Scene/ViewLayer) of this depsgraph.
- * Used during undo steps when we do want to re-use the old depsgraph data as much as possible. */
+ * Used for:
+ * - Undo steps when we do want to re-use the old depsgraph data as much as possible.
+ * - Rendering where we want to re-use objects between different view layers. */
void DEG_graph_replace_owners(struct Depsgraph *depsgraph,
Main *bmain,
Scene *scene,
diff --git a/source/blender/depsgraph/intern/depsgraph.h b/source/blender/depsgraph/intern/depsgraph.h
index df8c8215d2f..d54aba8e25d 100644
--- a/source/blender/depsgraph/intern/depsgraph.h
+++ b/source/blender/depsgraph/intern/depsgraph.h
@@ -161,6 +161,9 @@ struct Depsgraph {
* does not need any bases. */
bool is_render_pipeline_depsgraph;
+ /* Notify editors about changes to IDs in this depsgrpah. */
+ bool use_editors_update;
+
/* Cached list of colliders/effectors for collections and the scene
* created along with relations, for fast lookup during evaluation. */
Map<const ID *, ListBase *> *physics_relations[DEG_PHYSICS_RELATIONS_NUM];
diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc
index 2051ee3657a..504c3956d03 100644
--- a/source/blender/depsgraph/intern/depsgraph_tag.cc
+++ b/source/blender/depsgraph/intern/depsgraph_tag.cc
@@ -816,11 +816,22 @@ void DEG_on_visible_update(Main *bmain, const bool do_time)
}
}
+void DEG_enable_editors_update(Depsgraph *depsgraph)
+{
+ deg::Depsgraph *graph = (deg::Depsgraph *)depsgraph;
+ graph->use_editors_update = true;
+}
+
/* Check if something was changed in the database and inform
* editors about this. */
-void DEG_ids_check_recalc(
+void DEG_editors_update(
Main *bmain, Depsgraph *depsgraph, Scene *scene, ViewLayer *view_layer, bool time)
{
+ deg::Depsgraph *graph = (deg::Depsgraph *)depsgraph;
+ if (!graph->use_editors_update) {
+ return;
+ }
+
bool updated = time || DEG_id_type_any_updated(depsgraph);
DEGEditorUpdateContext update_ctx = {nullptr};
@@ -829,6 +840,8 @@ void DEG_ids_check_recalc(
update_ctx.scene = scene;
update_ctx.view_layer = view_layer;
deg::deg_editors_scene_update(&update_ctx, updated);
+
+ DEG_ids_clear_recalc(depsgraph);
}
static void deg_graph_clear_id_recalc_flags(ID *id)
@@ -842,7 +855,7 @@ static void deg_graph_clear_id_recalc_flags(ID *id)
/* XXX And what about scene's master collection here? */
}
-void DEG_ids_clear_recalc(Main *UNUSED(bmain), Depsgraph *depsgraph)
+void DEG_ids_clear_recalc(Depsgraph *depsgraph)
{
deg::Depsgraph *deg_graph = reinterpret_cast<deg::Depsgraph *>(depsgraph);
/* TODO(sergey): Re-implement POST_UPDATE_HANDLER_WORKAROUND using entry_tags
diff --git a/source/blender/editors/render/render_update.c b/source/blender/editors/render/render_update.c
index 4ed1cbd60a5..3e8a1bda2f0 100644
--- a/source/blender/editors/render/render_update.c
+++ b/source/blender/editors/render/render_update.c
@@ -188,7 +188,7 @@ void ED_render_engine_changed(Main *bmain, const bool update_scene_data)
ED_render_engine_area_exit(bmain, area);
}
}
- RE_FreePersistentData();
+ RE_FreePersistentData(NULL);
/* Inform all render engines and draw managers. */
DEGEditorUpdateContext update_ctx = {NULL};
update_ctx.bmain = bmain;
diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c
index 0411ef6d6ee..dd91a5509f5 100644
--- a/source/blender/makesrna/intern/rna_render.c
+++ b/source/blender/makesrna/intern/rna_render.c
@@ -298,13 +298,13 @@ static void rna_RenderEngine_unregister(Main *bmain, StructRNA *type)
return;
}
+ /* Stop all renders in case we were using this one. */
+ ED_render_engine_changed(bmain, false);
RE_FreeAllPersistentData();
+
RNA_struct_free_extension(type, &et->rna_ext);
RNA_struct_free(&BLENDER_RNA, type);
BLI_freelinkN(&R_engines, et);
-
- /* Stop all renders in case we were using this one. */
- ED_render_engine_changed(bmain, false);
}
static StructRNA *rna_RenderEngine_register(Main *bmain,
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 65643aa92d7..cc7747959a4 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -1896,10 +1896,10 @@ static void rna_Scene_use_persistent_data_update(Main *UNUSED(bmain),
Scene *UNUSED(scene),
PointerRNA *ptr)
{
- Scene *sce = (Scene *)ptr->owner_id;
+ Scene *scene = (Scene *)ptr->owner_id;
- if (!(sce->r.mode & R_PERSISTENT_DATA)) {
- RE_FreePersistentData();
+ if (!(scene->r.mode & R_PERSISTENT_DATA)) {
+ RE_FreePersistentData(scene);
}
}
@@ -6606,8 +6606,10 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
/* persistent data */
prop = RNA_def_property(srna, "use_persistent_data", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "mode", R_PERSISTENT_DATA);
- RNA_def_property_ui_text(
- prop, "Persistent Data", "Keep render data around for faster re-renders");
+ RNA_def_property_ui_text(prop,
+ "Persistent Data",
+ "Keep render data around for faster re-renders and animation renders, "
+ "at the cost of increased memory usage");
RNA_def_property_update(prop, 0, "rna_Scene_use_persistent_data_update");
/* Freestyle line thickness options */
diff --git a/source/blender/render/RE_engine.h b/source/blender/render/RE_engine.h
index c31a41f66d5..f6ab7fd9d3c 100644
--- a/source/blender/render/RE_engine.h
+++ b/source/blender/render/RE_engine.h
@@ -224,6 +224,8 @@ void RE_engine_register_pass(struct RenderEngine *engine,
const char *chanid,
eNodeSocketDatatype type);
+bool RE_engine_use_persistent_data(struct RenderEngine *engine);
+
/* Engine Types */
void RE_engines_init(void);
diff --git a/source/blender/render/RE_pipeline.h b/source/blender/render/RE_pipeline.h
index 27dcd9e70ed..7420ee64a81 100644
--- a/source/blender/render/RE_pipeline.h
+++ b/source/blender/render/RE_pipeline.h
@@ -184,14 +184,14 @@ void RE_InitRenderCB(struct Render *re);
void RE_FreeRender(struct Render *re);
/* only called on exit */
void RE_FreeAllRender(void);
-/* Free memory used by persistent data.
- * Invoked when loading new file.
- */
-void RE_FreeAllPersistentData(void);
-/* only call on file load */
+
+/* On file load, free render results. */
void RE_FreeAllRenderResults(void);
-/* for external render engines that can keep persistent data */
-void RE_FreePersistentData(void);
+/* On file load or changes engines, free persistent render data.
+ * Assumes no engines are currently rendering. */
+void RE_FreeAllPersistentData(void);
+/* Free persistent render data, optionally only for the given scene. */
+void RE_FreePersistentData(const Scene *scene);
/* get results and statistics */
void RE_FreeRenderResult(struct RenderResult *rr);
diff --git a/source/blender/render/intern/engine.c b/source/blender/render/intern/engine.c
index a43a78f5d3d..ccb9996a143 100644
--- a/source/blender/render/intern/engine.c
+++ b/source/blender/render/intern/engine.c
@@ -140,6 +140,27 @@ RenderEngine *RE_engine_create(RenderEngineType *type)
return engine;
}
+static void engine_depsgraph_free(RenderEngine *engine)
+{
+ if (engine->depsgraph) {
+ /* Need GPU context since this might free GPU buffers. This function can
+ * only be called from a render thread. We do not currently support
+ * persistent data with GPU contexts for that reason. */
+ const bool use_gpu_context = (engine->type->flag & RE_USE_GPU_CONTEXT);
+ if (use_gpu_context) {
+ BLI_assert(!BLI_thread_is_main());
+ DRW_render_context_enable(engine->re);
+ }
+
+ DEG_graph_free(engine->depsgraph);
+ engine->depsgraph = NULL;
+
+ if (use_gpu_context) {
+ DRW_render_context_disable(engine->re);
+ }
+ }
+}
+
void RE_engine_free(RenderEngine *engine)
{
#ifdef WITH_PYTHON
@@ -148,6 +169,8 @@ void RE_engine_free(RenderEngine *engine)
}
#endif
+ engine_depsgraph_free(engine);
+
BLI_mutex_end(&engine->update_render_passes_mutex);
MEM_freeN(engine);
@@ -598,34 +621,94 @@ RenderData *RE_engine_get_render_data(Render *re)
return &re->r;
}
+bool RE_engine_use_persistent_data(RenderEngine *engine)
+{
+ /* See engine_depsgraph_free() for why preserving the depsgraph for
+ * re-renders is not supported with GPU contexts. */
+ return (engine->re->r.mode & R_PERSISTENT_DATA) && !(engine->type->flag & RE_USE_GPU_CONTEXT);
+}
+
+static bool engine_keep_depsgraph(RenderEngine *engine)
+{
+ /* For persistent data or GPU engines like Eevee, reuse the depsgraph between
+ * view layers and animation frames. For renderers like Cycles that create
+ * their own copy of the scene, persistent data must be explicitly enabled to
+ * keep memory usage low by default. */
+ return (engine->re->r.mode & R_PERSISTENT_DATA) || (engine->type->flag & RE_USE_GPU_CONTEXT);
+}
+
/* Depsgraph */
static void engine_depsgraph_init(RenderEngine *engine, ViewLayer *view_layer)
{
Main *bmain = engine->re->main;
Scene *scene = engine->re->scene;
+ bool reuse_depsgraph = false;
+
+ /* Reuse depsgraph from persistent data if possible. */
+ if (engine->depsgraph) {
+ if (DEG_get_bmain(engine->depsgraph) != bmain ||
+ DEG_get_input_scene(engine->depsgraph) != scene) {
+ /* If bmain or scene changes, we need a completely new graph. */
+ engine_depsgraph_free(engine);
+ }
+ else if (DEG_get_input_view_layer(engine->depsgraph) != view_layer) {
+ /* If only view layer changed, reuse depsgraph in the hope of reusing
+ * objects shared between view layers. */
+ DEG_graph_replace_owners(engine->depsgraph, bmain, scene, view_layer);
+ DEG_graph_tag_relations_update(engine->depsgraph);
+ }
- engine->depsgraph = DEG_graph_new(bmain, scene, view_layer, DAG_EVAL_RENDER);
- DEG_debug_name_set(engine->depsgraph, "RENDER");
+ reuse_depsgraph = true;
+ }
+
+ if (!engine->depsgraph) {
+ /* Ensure we only use persistent data for one scene / view layer at a time,
+ * to avoid excessive memory usage. */
+ RE_FreePersistentData(NULL);
+
+ /* Create new depsgraph if not cached with persistent data. */
+ engine->depsgraph = DEG_graph_new(bmain, scene, view_layer, DAG_EVAL_RENDER);
+ DEG_debug_name_set(engine->depsgraph, "RENDER");
+ }
if (engine->re->r.scemode & R_BUTS_PREVIEW) {
+ /* Update for preview render. */
Depsgraph *depsgraph = engine->depsgraph;
DEG_graph_relations_update(depsgraph);
+
+ /* Need GPU context since this might free GPU buffers. */
+ const bool use_gpu_context = (engine->type->flag & RE_USE_GPU_CONTEXT) && reuse_depsgraph;
+ if (use_gpu_context) {
+ DRW_render_context_enable(engine->re);
+ }
+
DEG_evaluate_on_framechange(depsgraph, CFRA);
- DEG_ids_check_recalc(bmain, depsgraph, scene, view_layer, true);
- DEG_ids_clear_recalc(bmain, depsgraph);
+
+ if (use_gpu_context) {
+ DRW_render_context_disable(engine->re);
+ }
}
else {
+ /* Go through update with full Python callbacks for regular render. */
BKE_scene_graph_update_for_newframe(engine->depsgraph);
}
engine->has_grease_pencil = DRW_render_check_grease_pencil(engine->depsgraph);
}
-static void engine_depsgraph_free(RenderEngine *engine)
+static void engine_depsgraph_exit(RenderEngine *engine)
{
- DEG_graph_free(engine->depsgraph);
-
- engine->depsgraph = NULL;
+ if (engine->depsgraph) {
+ if (engine_keep_depsgraph(engine)) {
+ /* Clear recalc flags since the engine should have handled the updates for the currently
+ * rendered framed by now. */
+ DEG_ids_clear_recalc(engine->depsgraph);
+ }
+ else {
+ /* Free immediately to save memory. */
+ engine_depsgraph_free(engine);
+ }
+ }
}
void RE_engine_frame_set(RenderEngine *engine, int frame, float subframe)
@@ -670,7 +753,6 @@ bool RE_bake_engine(Render *re,
{
RenderEngineType *type = RE_engines_find(re->r.engine);
RenderEngine *engine;
- bool persistent_data = (re->r.mode & R_PERSISTENT_DATA) != 0;
/* set render info */
re->i.cfra = re->scene->r.cfra;
@@ -729,13 +811,13 @@ bool RE_bake_engine(Render *re,
engine->tile_y = 0;
engine->flag &= ~RE_ENGINE_RENDERING;
+ /* Free depsgraph outside of parts mutex lock, since this locks OpenGL context
+ * while the the UI drawing might also lock the OpenGL context and parts mutex. */
+ engine_depsgraph_free(engine);
BLI_rw_mutex_lock(&re->partsmutex, THREAD_LOCK_WRITE);
- /* re->engine becomes zero if user changed active render engine during render */
- if (!persistent_data || !re->engine) {
- RE_engine_free(engine);
- re->engine = NULL;
- }
+ RE_engine_free(engine);
+ re->engine = NULL;
RE_parts_free(re);
BLI_rw_mutex_unlock(&re->partsmutex);
@@ -778,13 +860,14 @@ static void engine_render_view_layer(Render *re,
/* Perform render with engine. */
if (use_engine) {
- if (engine->type->flag & RE_USE_GPU_CONTEXT) {
+ const bool use_gpu_context = (engine->type->flag & RE_USE_GPU_CONTEXT);
+ if (use_gpu_context) {
DRW_render_context_enable(engine->re);
}
engine->type->render(engine, engine->depsgraph);
- if (engine->type->flag & RE_USE_GPU_CONTEXT) {
+ if (use_gpu_context) {
DRW_render_context_disable(engine->re);
}
}
@@ -800,13 +883,12 @@ static void engine_render_view_layer(Render *re,
}
/* Free dependency graph, if engine has not done it already. */
- engine_depsgraph_free(engine);
+ engine_depsgraph_exit(engine);
}
bool RE_engine_render(Render *re, bool do_all)
{
RenderEngineType *type = RE_engines_find(re->r.engine);
- bool persistent_data = (re->r.mode & R_PERSISTENT_DATA) != 0;
/* verify if we can render */
if (!type->render) {
@@ -953,7 +1035,13 @@ bool RE_engine_render(Render *re, bool do_all)
}
/* re->engine becomes zero if user changed active render engine during render */
- if (!persistent_data || !re->engine) {
+ if (!engine_keep_depsgraph(engine) || !re->engine) {
+ /* Free depsgraph outside of parts mutex lock, since this locks OpenGL context
+ * while the the UI drawing might also lock the OpenGL context and parts mutex. */
+ BLI_rw_mutex_unlock(&re->partsmutex);
+ engine_depsgraph_free(engine);
+ BLI_rw_mutex_lock(&re->partsmutex, THREAD_LOCK_WRITE);
+
RE_engine_free(engine);
re->engine = NULL;
}
@@ -1023,9 +1111,8 @@ void RE_engine_free_blender_memory(RenderEngine *engine)
*
* TODO(sergey): Find better solution for this.
*/
- if (engine->has_grease_pencil) {
+ if (engine->has_grease_pencil || engine_keep_depsgraph(engine)) {
return;
}
- DEG_graph_free(engine->depsgraph);
- engine->depsgraph = NULL;
+ engine_depsgraph_free(engine);
}
diff --git a/source/blender/render/intern/pipeline.c b/source/blender/render/intern/pipeline.c
index 92bec9c6fd4..5a2ac6ed348 100644
--- a/source/blender/render/intern/pipeline.c
+++ b/source/blender/render/intern/pipeline.c
@@ -662,17 +662,6 @@ void RE_FreeAllRender(void)
#endif
}
-void RE_FreeAllPersistentData(void)
-{
- Render *re;
- for (re = RenderGlobal.renderlist.first; re != NULL; re = re->next) {
- if ((re->r.mode & R_PERSISTENT_DATA) != 0 && re->engine != NULL) {
- RE_engine_free(re->engine);
- re->engine = NULL;
- }
- }
-}
-
/* on file load, free all re */
void RE_FreeAllRenderResults(void)
{
@@ -687,19 +676,39 @@ void RE_FreeAllRenderResults(void)
}
}
-void RE_FreePersistentData(void)
+void RE_FreeAllPersistentData(void)
{
Render *re;
+ for (re = RenderGlobal.renderlist.first; re != NULL; re = re->next) {
+ if (re->engine != NULL) {
+ BLI_assert(!(re->engine->flag & RE_ENGINE_RENDERING));
+ RE_engine_free(re->engine);
+ re->engine = NULL;
+ }
+ }
+}
- /* render engines can be kept around for quick re-render, this clears all */
- for (re = RenderGlobal.renderlist.first; re; re = re->next) {
- if (re->engine) {
- /* if engine is currently rendering, just tag it to be freed when render is finished */
- if (!(re->engine->flag & RE_ENGINE_RENDERING)) {
- RE_engine_free(re->engine);
- }
+static void re_free_persistent_data(Render *re)
+{
+ /* If engine is currently rendering, just wait for it to be freed when it finishes rendering. */
+ if (re->engine && !(re->engine->flag & RE_ENGINE_RENDERING)) {
+ RE_engine_free(re->engine);
+ re->engine = NULL;
+ }
+}
- re->engine = NULL;
+void RE_FreePersistentData(const Scene *scene)
+{
+ /* Render engines can be kept around for quick re-render, this clears all or one scene. */
+ if (scene) {
+ Render *re = RE_GetSceneRender(scene);
+ if (re) {
+ re_free_persistent_data(re);
+ }
+ }
+ else {
+ for (Render *re = RenderGlobal.renderlist.first; re; re = re->next) {
+ re_free_persistent_data(re);
}
}
}
@@ -2669,13 +2678,17 @@ void RE_PreviewRender(Render *re, Main *bmain, Scene *sce)
void RE_CleanAfterRender(Render *re)
{
- /* Destroy the opengl context in the correct thread. */
- RE_gl_context_destroy(re);
+ if (re->engine && !RE_engine_use_persistent_data(re->engine)) {
+ RE_engine_free(re->engine);
+ re->engine = NULL;
+ }
if (re->pipeline_depsgraph != NULL) {
DEG_graph_free(re->pipeline_depsgraph);
+ re->pipeline_depsgraph = NULL;
+ re->pipeline_scene_eval = NULL;
}
- re->pipeline_depsgraph = NULL;
- re->pipeline_scene_eval = NULL;
+ /* Destroy the opengl context in the correct thread. */
+ RE_gl_context_destroy(re);
}
/* note; repeated win/disprect calc... solve that nicer, also in compo */