Render: Use dependency graph for compositor/sequencer

This change makes it so a minimal dependency graph which only includes
compositor and sequencer is built for the render pipeline purposes.

Tricky part here is that it's only compositor itself and sequencer who
to use this dependency graph and IDs from it. Render engines are still
to be provided original IDs because:

- They will create dependency graph for the given scene, and currently
  it is not possible to create dependency graph from CoW scene.

- IDs from the compositor/sequencer dependency graph are "stripped",
  as in, they wouldn't have all view layers, collections or objects
	required for proper final render.

This creates annoying mess of mixing evaluated and original scene
access in various parts of the pipeline.

Fixes T63927: Compositing nodes - drivers don't really work

Reviewers: brecht

Maniphest Tasks: T63927

Differential Revision: https://developer.blender.org/D4911
This commit is contained in:
Sergey Sharybin 2019-05-20 15:14:10 +02:00
parent 0ec6fa782b
commit b432209f63
Notes: blender-bot 2023-06-12 00:52:52 +02:00
Referenced by issue #65062, Compositor doesn't update anymore
Referenced by issue #63927, Compositing nodes - drivers don't really work
Referenced by issue #60961, Camera DOF distance based on an object doesn't update on animations with compositing Defocus
16 changed files with 228 additions and 80 deletions

View File

@ -52,14 +52,19 @@ extern "C" {
/* Graph Building -------------------------------- */
/* Build depsgraph for the given scene, and dump results in given
* graph container.
*/
/* Build depsgraph for the given scene, and dump results in given graph container. */
void DEG_graph_build_from_view_layer(struct Depsgraph *graph,
struct Main *bmain,
struct Scene *scene,
struct ViewLayer *view_layer);
/* Special version of builder which produces dependency graph suitable for the render pipeline.
* It will contain sequencer and compositor (if needed) and all their dependencies. */
void DEG_graph_build_for_render_pipeline(struct Depsgraph *graph,
struct Main *bmain,
struct Scene *scene,
struct ViewLayer *view_layer);
/* Tag relations from the given graph for update. */
void DEG_graph_tag_relations_update(struct Depsgraph *graph);

View File

@ -38,8 +38,12 @@ class BuilderMap {
TAG_TRANSFORM = (1 << 2),
TAG_GEOMETRY = (1 << 3),
TAG_SCENE_COMPOSITOR = (1 << 4),
TAG_SCENE_SEQUENCER = (1 << 5),
/* All ID components has been built. */
TAG_COMPLETE = (TAG_ANIMATION | TAG_PARAMETERS | TAG_TRANSFORM | TAG_GEOMETRY),
TAG_COMPLETE = (TAG_ANIMATION | TAG_PARAMETERS | TAG_TRANSFORM | TAG_GEOMETRY |
TAG_SCENE_COMPOSITOR | TAG_SCENE_SEQUENCER),
};
BuilderMap();

View File

@ -543,7 +543,10 @@ void DepsgraphNodeBuilder::build_object(int base_index,
IDNode *id_node = add_id_node(&object->id);
Object *object_cow = get_cow_datablock(object);
id_node->linked_state = linked_state;
if (object == scene_->camera) {
/* NOTE: Scene is NULL when building dependency graph for render pipeline.
* Probably need to assign that to something non-NULL, but then the logic here will still be
* somewhat weird. */
if (scene_ != NULL && object == scene_->camera) {
id_node->is_directly_visible = true;
}
else {
@ -1366,8 +1369,16 @@ void DepsgraphNodeBuilder::build_nodetree(bNodeTree *ntree)
build_object(-1, (Object *)id, DEG_ID_LINKED_INDIRECTLY, true);
}
else if (id_type == ID_SCE) {
/* Scenes are used by compositor trees, and handled by render
* pipeline. No need to build dependencies for them here. */
Scene *node_scene = (Scene *)id;
build_scene_parameters(node_scene);
/* Camera is used by defocus node.
*
* On the one hand it's annoying to always pull it in, but on another hand it's also annoying
* to have hardcoded node-type exception here. */
if (node_scene->camera != NULL) {
/* TODO(sergey): Use visibility of owner of the node tree. */
build_object(-1, node_scene->camera, DEG_ID_LINKED_INDIRECTLY, true);
}
}
else if (id_type == ID_TXT) {
/* Ignore script nodes. */
@ -1442,19 +1453,6 @@ void DepsgraphNodeBuilder::build_image(Image *image)
&image->id, NodeType::GENERIC_DATABLOCK, OperationCode::GENERIC_DATABLOCK_UPDATE);
}
void DepsgraphNodeBuilder::build_compositor(Scene *scene)
{
/* For now, just a plain wrapper? */
// TODO: create compositing component?
// XXX: component type undefined!
// graph->get_node(&scene->id, NULL, NodeType::COMPOSITING, NULL);
/* for now, nodetrees are just parameters; compositing occurs in internals
* of renderer... */
add_component_node(&scene->id, NodeType::PARAMETERS);
build_nodetree(scene->nodetree);
}
void DepsgraphNodeBuilder::build_gpencil(bGPdata *gpd)
{
if (built_map_.checkIsBuiltAndTag(gpd)) {

View File

@ -153,7 +153,9 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder {
void build_id(ID *id);
void build_scene_render(Scene *scene);
void build_scene_parameters(Scene *scene);
void build_scene_compositor(Scene *scene);
void build_layer_collections(ListBase *lb);
void build_view_layer(Scene *scene,
@ -203,7 +205,6 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder {
void build_texture(Tex *tex);
void build_image(Image *image);
void build_world(World *world);
void build_compositor(Scene *scene);
void build_gpencil(bGPdata *gpd);
void build_cachefile(CacheFile *cache_file);
void build_mask(Mask *mask);

View File

@ -27,6 +27,18 @@
namespace DEG {
void DepsgraphNodeBuilder::build_scene_render(Scene *scene)
{
const bool build_compositor = (scene->r.scemode & R_DOCOMP);
IDNode *id_node = add_id_node(&scene->id);
id_node->linked_state = DEG_ID_LINKED_DIRECTLY;
add_time_source();
build_scene_parameters(scene);
if (build_compositor) {
build_scene_compositor(scene);
}
}
void DepsgraphNodeBuilder::build_scene_parameters(Scene *scene)
{
if (built_map_.checkIsBuiltAndTag(scene, BuilderMap::TAG_PARAMETERS)) {
@ -36,4 +48,15 @@ void DepsgraphNodeBuilder::build_scene_parameters(Scene *scene)
add_operation_node(&scene->id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EVAL);
}
void DepsgraphNodeBuilder::build_scene_compositor(Scene *scene)
{
if (built_map_.checkIsBuiltAndTag(scene, BuilderMap::TAG_SCENE_COMPOSITOR)) {
return;
}
if (scene->nodetree == NULL) {
return;
}
build_nodetree(scene->nodetree);
}
} // namespace DEG

View File

@ -125,9 +125,7 @@ void DepsgraphNodeBuilder::build_view_layer(Scene *scene,
build_world(scene->world);
}
/* Compositor nodes */
if (scene->nodetree != NULL) {
build_compositor(scene);
}
build_scene_compositor(scene);
/* Cache file. */
LISTBASE_FOREACH (CacheFile *, cachefile, &bmain_->cachefiles) {
build_cachefile(cachefile);

View File

@ -2131,8 +2131,15 @@ void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree)
build_object(NULL, (Object *)id);
}
else if (id_type == ID_SCE) {
/* Scenes are used by compositor trees, and handled by render
* pipeline. No need to build dependencies for them here. */
Scene *node_scene = (Scene *)id;
build_scene_parameters(node_scene);
/* Camera is used by defocus node.
*
* On the one hand it's annoying to always pull it in, but on another hand it's also annoying
* to have hardcoded node-type exception here. */
if (node_scene->camera != NULL) {
build_object(NULL, node_scene->camera);
}
}
else if (id_type == ID_TXT) {
/* Ignore script nodes. */
@ -2220,12 +2227,6 @@ void DepsgraphRelationBuilder::build_image(Image *image)
build_parameters(&image->id);
}
void DepsgraphRelationBuilder::build_compositor(Scene *scene)
{
/* For now, just a plain wrapper? */
build_nodetree(scene->nodetree);
}
void DepsgraphRelationBuilder::build_gpencil(bGPdata *gpd)
{
if (built_map_.checkIsBuiltAndTag(gpd)) {

View File

@ -195,7 +195,9 @@ class DepsgraphRelationBuilder : public DepsgraphBuilder {
void build_id(ID *id);
void build_scene_render(Scene *scene);
void build_scene_parameters(Scene *scene);
void build_scene_compositor(Scene *scene);
void build_layer_collections(ListBase *lb);
void build_view_layer(Scene *scene, ViewLayer *view_layer);
@ -261,7 +263,6 @@ class DepsgraphRelationBuilder : public DepsgraphBuilder {
void build_material(Material *ma);
void build_texture(Tex *tex);
void build_image(Image *image);
void build_compositor(Scene *scene);
void build_gpencil(bGPdata *gpd);
void build_cachefile(CacheFile *cache_file);
void build_mask(Mask *mask);

View File

@ -27,6 +27,15 @@
namespace DEG {
void DepsgraphRelationBuilder::build_scene_render(Scene *scene)
{
const bool build_compositor = (scene->r.scemode & R_DOCOMP);
build_scene_parameters(scene);
if (build_compositor) {
build_scene_compositor(scene);
}
}
void DepsgraphRelationBuilder::build_scene_parameters(Scene *scene)
{
if (built_map_.checkIsBuiltAndTag(scene, BuilderMap::TAG_PARAMETERS)) {
@ -38,4 +47,15 @@ void DepsgraphRelationBuilder::build_scene_parameters(Scene *scene)
add_relation(parameters_eval_key, scene_eval_key, "Parameters -> Scene Eval");
}
void DepsgraphRelationBuilder::build_scene_compositor(Scene *scene)
{
if (built_map_.checkIsBuiltAndTag(scene, BuilderMap::TAG_SCENE_COMPOSITOR)) {
return;
}
if (scene->nodetree == NULL) {
return;
}
build_nodetree(scene->nodetree);
}
} // namespace DEG

View File

@ -106,10 +106,6 @@ void DepsgraphRelationBuilder::build_view_layer(Scene *scene, ViewLayer *view_la
if (scene->world != NULL) {
build_world(scene->world);
}
/* Compositor nodes. */
if (scene->nodetree != NULL) {
build_compositor(scene);
}
/* Masks. */
LISTBASE_FOREACH (Mask *, mask, &bmain_->masks) {
build_mask(mask);
@ -128,7 +124,8 @@ void DepsgraphRelationBuilder::build_view_layer(Scene *scene, ViewLayer *view_la
build_collection(NULL, NULL, fls->group);
}
}
/* Scene parameters. */
/* Scene parameters, compositor and such. */
build_scene_compositor(scene);
build_scene_parameters(scene);
/* Build all set scenes. */
if (scene->set != NULL) {

View File

@ -73,7 +73,8 @@ Depsgraph::Depsgraph(Scene *scene, ViewLayer *view_layer, eEvaluationMode mode)
ctime(BKE_scene_frame_get(scene)),
scene_cow(NULL),
is_active(false),
debug_is_evaluating(false)
debug_is_evaluating(false),
is_render_pipeline_depsgraph(false)
{
BLI_spin_init(&lock);
id_hash = BLI_ghash_ptr_new("Depsgraph id hash");

View File

@ -194,6 +194,12 @@ struct Depsgraph {
bool debug_is_evaluating;
/* Is set to truth for dependency graph which are used for post-processing (compositor and
* sequencer).
* Such dependency graph needs all view layers (so render pipeline can access names), but it
* does not need any bases. */
bool is_render_pipeline_depsgraph;
/* Cached list of colliders/effectors for collections and the scene
* created along with relations, for fast lookup during evaluation. */
GHash *physics_relations[DEG_PHYSICS_RELATIONS_NUM];

View File

@ -222,9 +222,33 @@ struct Depsgraph *DEG_get_graph_from_handle(struct DepsNodeHandle *node_handle)
/* ******************** */
/* Graph Building API's */
/* Build depsgraph for the given scene layer, and dump results in given
* graph container.
*/
static void graph_build_finalize_common(DEG::Depsgraph *deg_graph, Main *bmain)
{
/* Detect and solve cycles. */
DEG::deg_graph_detect_cycles(deg_graph);
/* Simplify the graph by removing redundant relations (to optimize
* traversal later). */
/* TODO: it would be useful to have an option to disable this in cases where
* it is causing trouble. */
if (G.debug_value == 799) {
DEG::deg_graph_transitive_reduction(deg_graph);
}
/* Store pointers to commonly used valuated datablocks. */
deg_graph->scene_cow = (Scene *)deg_graph->get_cow_id(&deg_graph->scene->id);
/* Flush visibility layer and re-schedule nodes for update. */
DEG::deg_graph_build_finalize(bmain, deg_graph);
DEG_graph_on_visible_update(bmain, reinterpret_cast<::Depsgraph *>(deg_graph));
#if 0
if (!DEG_debug_consistency_check(deg_graph)) {
printf("Consistency validation failed, ABORTING!\n");
abort();
}
#endif
/* Relations are up to date. */
deg_graph->need_update = false;
}
/* Build depsgraph for the given scene layer, and dump results in given graph container. */
void DEG_graph_build_from_view_layer(Depsgraph *graph,
Main *bmain,
Scene *scene,
@ -245,34 +269,46 @@ void DEG_graph_build_from_view_layer(Depsgraph *graph,
node_builder.begin_build();
node_builder.build_view_layer(scene, view_layer, DEG::DEG_ID_LINKED_DIRECTLY);
node_builder.end_build();
/* Hook up relationships between operations - to determine evaluation
* order. */
/* Hook up relationships between operations - to determine evaluation order. */
DEG::DepsgraphRelationBuilder relation_builder(bmain, deg_graph, &builder_cache);
relation_builder.begin_build();
relation_builder.build_view_layer(scene, view_layer);
relation_builder.build_copy_on_write_relations();
/* Detect and solve cycles. */
DEG::deg_graph_detect_cycles(deg_graph);
/* Simplify the graph by removing redundant relations (to optimize
* traversal later). */
/* TODO: it would be useful to have an option to disable this in cases where
* it is causing trouble. */
if (G.debug_value == 799) {
DEG::deg_graph_transitive_reduction(deg_graph);
/* Finalize building. */
graph_build_finalize_common(deg_graph, bmain);
/* Finish statistics. */
if (G.debug & (G_DEBUG_DEPSGRAPH_BUILD | G_DEBUG_DEPSGRAPH_TIME)) {
printf("Depsgraph built in %f seconds.\n", PIL_check_seconds_timer() - start_time);
}
/* Store pointers to commonly used valuated datablocks. */
deg_graph->scene_cow = (Scene *)deg_graph->get_cow_id(&deg_graph->scene->id);
/* Flush visibility layer and re-schedule nodes for update. */
DEG::deg_graph_build_finalize(bmain, deg_graph);
DEG_graph_on_visible_update(bmain, graph);
#if 0
if (!DEG_debug_consistency_check(deg_graph)) {
printf("Consistency validation failed, ABORTING!\n");
abort();
}
void DEG_graph_build_for_render_pipeline(Depsgraph *graph,
Main *bmain,
Scene *scene,
ViewLayer * /*view_layer*/)
{
double start_time = 0.0;
if (G.debug & (G_DEBUG_DEPSGRAPH_BUILD | G_DEBUG_DEPSGRAPH_TIME)) {
start_time = PIL_check_seconds_timer();
}
#endif
/* Relations are up to date. */
deg_graph->need_update = false;
DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph);
/* Perform sanity checks. */
BLI_assert(deg_graph->scene == scene);
deg_graph->is_render_pipeline_depsgraph = true;
DEG::DepsgraphBuilderCache builder_cache;
/* Generate all the nodes in the graph first */
DEG::DepsgraphNodeBuilder node_builder(bmain, deg_graph, &builder_cache);
node_builder.begin_build();
node_builder.build_scene_render(scene);
node_builder.end_build();
/* Hook up relationships between operations - to determine evaluation
* order. */
DEG::DepsgraphRelationBuilder relation_builder(bmain, deg_graph, &builder_cache);
relation_builder.begin_build();
relation_builder.build_scene_render(scene);
relation_builder.build_copy_on_write_relations();
/* Finalize building. */
graph_build_finalize_common(deg_graph, bmain);
/* Finish statistics. */
if (G.debug & (G_DEBUG_DEPSGRAPH_BUILD | G_DEBUG_DEPSGRAPH_TIME)) {
printf("Depsgraph built in %f seconds.\n", PIL_check_seconds_timer() - start_time);

View File

@ -327,7 +327,7 @@ ViewLayer *get_original_view_layer(const Depsgraph *depsgraph, const IDNode *id_
return BKE_view_layer_default_render(scene_orig);
}
/* Is possible to have scene linked indirectly (i.e. via the driver) which
* we need to support. Currently there aer issues somewhere else, which
* we need to support. Currently there are issues somewhere else, which
* makes testing hard. This is a reported problem, so will eventually be
* properly fixed.
*
@ -341,11 +341,17 @@ void scene_remove_unused_view_layers(const Depsgraph *depsgraph,
Scene *scene_cow)
{
const ViewLayer *view_layer_input;
/* Indirectly linked scenes means it's not an input scene and not a set scene, and is pulled via
* some driver. Such scenes should not have view layers after copy. */
if (id_node->linked_state == DEG_ID_LINKED_INDIRECTLY) {
/* Indirectly linked scenes means it's not an input scene and not a set scene, and is pulled
* via some driver. Such scenes should not have view layers after copy. */
view_layer_input = NULL;
}
else if (depsgraph->is_render_pipeline_depsgraph) {
/* If the dependency graph is used for post-processing (such as compositor) we do need to
* have access to its view layer names so can not remove any view layers.
* On a more positive side we can remove all the bases from all the view layers. */
return;
}
else {
view_layer_input = get_original_view_layer(depsgraph, id_node);
}
@ -372,6 +378,13 @@ void scene_remove_unused_view_layers(const Depsgraph *depsgraph,
scene_cow->view_layers.last = view_layer_eval;
}
void scene_remove_all_bases(Scene *scene_cow)
{
LISTBASE_FOREACH (ViewLayer *, view_layer, &scene_cow->view_layers) {
BLI_freelistN(&view_layer->object_bases);
}
}
/* Makes it so given view layer only has bases corresponding to enabled
* objects. */
void view_layer_remove_disabled_bases(const Depsgraph *depsgraph, ViewLayer *view_layer)
@ -425,6 +438,11 @@ void scene_setup_view_layers_before_remap(const Depsgraph *depsgraph,
Scene *scene_cow)
{
scene_remove_unused_view_layers(depsgraph, id_node, scene_cow);
/* If dependency graph is used for post-processing we don't need any bases and can free of them.
* Do it before re-mapping to make that process faster. */
if (depsgraph->is_render_pipeline_depsgraph) {
scene_remove_all_bases(scene_cow);
}
}
void scene_setup_view_layers_after_remap(const Depsgraph *depsgraph,

View File

@ -118,6 +118,11 @@ struct Render {
/* render engine */
struct RenderEngine *engine;
/* NOTE: This is a minimal dependency graph and evaluated scene which is enough to access view
* layer visibility and use for post-precessing (compositor and sequencer). */
Depsgraph *pipeline_depsgraph;
Scene *pipeline_scene_eval;
#ifdef WITH_FREESTYLE
struct Main *freestyle_bmain;
ListBase freestyle_renders;

View File

@ -74,6 +74,7 @@
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
#include "DEG_depsgraph_debug.h"
#include "DEG_depsgraph_query.h"
#include "PIL_time.h"
@ -1430,10 +1431,10 @@ static void free_all_freestyle_renders(void)
/* returns fully composited render-result on given time step (in RenderData) */
static void do_render_composite(Render *re)
{
bNodeTree *ntree = re->scene->nodetree;
bNodeTree *ntree = re->pipeline_scene_eval->nodetree;
int update_newframe = 0;
if (composite_needs_render(re->scene, 1)) {
if (composite_needs_render(re->pipeline_scene_eval, 1)) {
/* save memory... free all cached images */
ntreeFreeCache(ntree);
@ -1471,7 +1472,7 @@ static void do_render_composite(Render *re)
if (!re->test_break(re->tbh)) {
if (ntree) {
ntreeCompositTagRender(re->scene);
ntreeCompositTagRender(re->pipeline_scene_eval);
}
if (ntree && re->scene->use_nodes && re->r.scemode & R_DOCOMP) {
@ -1494,7 +1495,7 @@ static void do_render_composite(Render *re)
RenderView *rv;
for (rv = re->result->views.first; rv; rv = rv->next) {
ntreeCompositExecTree(re->scene,
ntreeCompositExecTree(re->pipeline_scene_eval,
ntree,
&re->r,
true,
@ -1595,12 +1596,8 @@ static void do_render_seq(Render *re)
tot_views = BKE_scene_multiview_num_views_get(&re->r);
ibuf_arr = MEM_mallocN(sizeof(ImBuf *) * tot_views, "Sequencer Views ImBufs");
/* TODO(sergey): Currently depsgraph is only used to check whether it is an active
* edit window or not to deal with unkeyed changes. We don't have depsgraph here yet,
* but we also dont' deal with unkeyed changes. But still nice to get proper depsgraph
* within tjhe render pipeline, somehow.
*/
BKE_sequencer_new_render_data(re->main, NULL, re->scene, re_x, re_y, 100, true, &context);
BKE_sequencer_new_render_data(
re->main, re->pipeline_depsgraph, re->scene, re_x, re_y, 100, true, &context);
/* the renderresult gets destroyed during the rendering, so we first collect all ibufs
* and then we populate the final renderesult */
@ -1613,7 +1610,7 @@ static void do_render_seq(Render *re)
ibuf_arr[view_id] = IMB_dupImBuf(out);
IMB_metadata_copy(ibuf_arr[view_id], out);
IMB_freeImBuf(out);
BKE_sequencer_imbuf_from_sequencer_space(re->scene, ibuf_arr[view_id]);
BKE_sequencer_imbuf_from_sequencer_space(re->pipeline_scene_eval, ibuf_arr[view_id]);
}
else {
ibuf_arr[view_id] = NULL;
@ -1641,9 +1638,9 @@ static void do_render_seq(Render *re)
}
if (recurs_depth == 0) { /* with nested scenes, only free on toplevel... */
Editing *ed = re->scene->ed;
Editing *ed = re->pipeline_scene_eval->ed;
if (ed) {
BKE_sequencer_free_imbuf(re->scene, &ed->seqbase, true);
BKE_sequencer_free_imbuf(re->pipeline_scene_eval, &ed->seqbase, true);
}
}
IMB_freeImBuf(ibuf_arr[view_id]);
@ -2071,6 +2068,32 @@ void RE_SetReports(Render *re, ReportList *reports)
re->reports = reports;
}
static void render_update_depsgraph(Render *re)
{
Scene *scene = re->scene;
/* TODO(sergey): This doesn't run any callbacks and doesn't do sound update. But we can not use
* BKE_scene_graph_update_for_newframe() because that one builds dependency graph for view layer
* and not for the render pipeline. */
DEG_evaluate_on_framechange(re->main, re->pipeline_depsgraph, CFRA);
}
static void render_init_depsgraph(Render *re)
{
Scene *scene = re->scene;
ViewLayer *view_layer = BKE_view_layer_default_render(re->scene);
re->pipeline_depsgraph = DEG_graph_new(scene, view_layer, DAG_EVAL_RENDER);
DEG_debug_name_set(re->pipeline_depsgraph, "RENDER PIPELINE");
/* Make sure there is a correct evaluated scene pointer. */
DEG_graph_build_for_render_pipeline(re->pipeline_depsgraph, re->main, scene, view_layer);
/* Update immediately so we have proper evaluated scene. */
render_update_depsgraph(re);
re->pipeline_scene_eval = DEG_get_evaluated_scene(re->pipeline_depsgraph);
}
/* general Blender frame render call */
void RE_RenderFrame(Render *re,
Main *bmain,
@ -2093,6 +2116,8 @@ void RE_RenderFrame(Render *re,
const RenderData rd = scene->r;
MEM_reset_peak_memory();
render_init_depsgraph(re);
BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_PRE);
do_render_all_options(re);
@ -2490,6 +2515,8 @@ void RE_RenderAnim(Render *re,
return;
}
render_init_depsgraph(re);
if (is_movie) {
size_t width, height;
int i;
@ -2556,6 +2583,8 @@ void RE_RenderAnim(Render *re,
BKE_animsys_evaluate_animdata(NULL, scene, &scene->id, adt, ctime, ADT_RECALC_ALL);
}
render_update_depsgraph(re);
/* only border now, todo: camera lens. (ton) */
render_initialize_from_main(re, &rd, bmain, scene, single_layer, camera_override, 1, 0);
@ -2746,6 +2775,11 @@ void RE_CleanAfterRender(Render *re)
{
/* Destroy the opengl context in the correct thread. */
RE_gl_context_destroy(re);
if (re->pipeline_depsgraph != NULL) {
DEG_graph_free(re->pipeline_depsgraph);
}
re->pipeline_depsgraph = NULL;
re->pipeline_scene_eval = NULL;
}
/* note; repeated win/disprect calc... solve that nicer, also in compo */