From 31746e1baa14fd3a64053aec82a40ffc07f95973 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 1 Nov 2022 21:00:56 +0100 Subject: Fix memory leak with Freestyle renders after recent changes Render stored a shallow copy of the scene view layers and views for thread safety, without proper functions to free it. But with the CoW depsgraph this scene is already a copy of the original and an additional copy is not needed. Refactor to use the scene view layers and some other settings directly instead of making a copy. --- .../intern/blender_interface/FRS_freestyle.cpp | 6 +- source/blender/render/intern/engine.cc | 6 -- source/blender/render/intern/pipeline.cc | 77 +++++++--------------- source/blender/render/intern/pipeline.h | 9 +-- source/blender/render/intern/render_result.cc | 6 +- source/blender/render/intern/render_result.h | 5 +- source/blender/render/intern/render_types.h | 3 +- 7 files changed, 33 insertions(+), 79 deletions(-) (limited to 'source/blender') diff --git a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp index 06365c3799f..af9ef7f352e 100644 --- a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp +++ b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp @@ -131,9 +131,9 @@ static void init_view(Render *re) int ymax = re->disprect.ymax; float thickness = 1.0f; - switch (re->r.line_thickness_mode) { + switch (re->scene->r.line_thickness_mode) { case R_LINE_THICKNESS_ABSOLUTE: - thickness = re->r.unit_line_thickness * (re->r.size / 100.0f); + thickness = re->scene->r.unit_line_thickness * (re->r.size / 100.0f); break; case R_LINE_THICKNESS_RELATIVE: thickness = height / 480.0f; @@ -485,7 +485,7 @@ void FRS_composite_result(Render *re, ViewLayer *view_layer, Render *freestyle_r return; } - rl = render_get_active_layer(freestyle_render, freestyle_render->result); + rl = render_get_single_layer(freestyle_render, freestyle_render->result); if (!rl) { if (G.debug & G_DEBUG_FREESTYLE) { cout << "No source render layer to composite" << endl; diff --git a/source/blender/render/intern/engine.cc b/source/blender/render/intern/engine.cc index b8757d33580..acca657f7dc 100644 --- a/source/blender/render/intern/engine.cc +++ b/source/blender/render/intern/engine.cc @@ -1036,12 +1036,6 @@ bool RE_engine_render(Render *re, bool do_all) return true; } - /* update animation here so any render layer animation is applied before - * creating the render result */ - if ((re->r.scemode & (R_NO_FRAME_UPDATE | R_BUTS_PREVIEW)) == 0) { - render_update_anim_renderdata(re, &re->scene->r, &re->scene->view_layers); - } - /* Create engine. */ RenderEngine *engine = re->engine; diff --git a/source/blender/render/intern/pipeline.cc b/source/blender/render/intern/pipeline.cc index d2929a7f6ea..e71ad1e26c1 100644 --- a/source/blender/render/intern/pipeline.cc +++ b/source/blender/render/intern/pipeline.cc @@ -261,13 +261,10 @@ RenderResult *RE_MultilayerConvert( return render_result_new_from_exr(exrhandle, colorspace, predivide, rectx, recty); } -RenderLayer *render_get_active_layer(Render *re, RenderResult *rr) +RenderLayer *render_get_single_layer(Render *re, RenderResult *rr) { - ViewLayer *view_layer = static_cast( - BLI_findlink(&re->view_layers, re->active_view_layer)); - - if (view_layer) { - RenderLayer *rl = RE_GetRenderLayer(rr, view_layer->name); + if (re->single_view_layer[0]) { + RenderLayer *rl = RE_GetRenderLayer(rr, re->single_view_layer); if (rl) { return rl; @@ -385,8 +382,8 @@ void RE_AcquireResultImageViews(Render *re, RenderResult *rr) RenderView *rv = static_cast(rr->views.first); rr->have_combined = (rv->rectf != nullptr); - /* active layer */ - RenderLayer *rl = render_get_active_layer(re, re->result); + /* single layer */ + RenderLayer *rl = render_get_single_layer(re, re->result); if (rl) { if (rv->rectf == nullptr) { @@ -443,7 +440,7 @@ void RE_AcquireResultImage(Render *re, RenderResult *rr, const int view_id) rr->rect32 = rv->rect32; /* active layer */ - rl = render_get_active_layer(re, re->result); + rl = render_get_single_layer(re, re->result); if (rl) { if (rv->rectf == nullptr) { @@ -583,9 +580,6 @@ void RE_FreeRender(Render *re) BLI_mutex_end(&re->engine_draw_mutex); BLI_mutex_end(&re->highlighted_tiles_mutex); - BLI_freelistN(&re->view_layers); - BLI_freelistN(&re->r.views); - BKE_curvemapping_free_data(&re->r.mblur_shutter_curve); if (re->highlighted_tiles != nullptr) { @@ -705,12 +699,11 @@ static void re_init_resolution(Render *re, Render *source, int winx, int winy, r void render_copy_renderdata(RenderData *to, RenderData *from) { - BLI_freelistN(&to->views); + /* Mostly shallow copy referencing pointers in scene renderdata. */ BKE_curvemapping_free_data(&to->mblur_shutter_curve); memcpy(to, from, sizeof(*to)); - BLI_duplicatelist(&to->views, &from->views); BKE_curvemapping_copy_data(&to->mblur_shutter_curve, &from->mblur_shutter_curve); } @@ -731,9 +724,7 @@ void RE_InitState(Render *re, /* copy render data and render layers for thread safety */ render_copy_renderdata(&re->r, rd); - BLI_freelistN(&re->view_layers); - BLI_duplicatelist(&re->view_layers, render_layers); - re->active_view_layer = 0; + re->single_view_layer[0] = '\0'; if (source) { /* reuse border flags from source renderer */ @@ -762,11 +753,8 @@ void RE_InitState(Render *re, } if (single_layer) { - int index = BLI_findindex(render_layers, single_layer); - if (index != -1) { - re->active_view_layer = index; - re->r.scemode |= R_SINGLE_LAYER; - } + STRNCPY(re->single_view_layer, single_layer->name); + re->r.scemode |= R_SINGLE_LAYER; } /* if preview render, we try to keep old result */ @@ -779,13 +767,16 @@ void RE_InitState(Render *re, re->result = nullptr; } else if (re->result) { - ViewLayer *active_render_layer = static_cast( - BLI_findlink(&re->view_layers, re->active_view_layer)); bool have_layer = false; - LISTBASE_FOREACH (RenderLayer *, rl, &re->result->layers) { - if (STREQ(rl->name, active_render_layer->name)) { - have_layer = true; + if (re->single_view_layer[0] == '\0' && re->result->layers.first) { + have_layer = true; + } + else { + LISTBASE_FOREACH (RenderLayer *, rl, &re->result->layers) { + if (STREQ(rl->name, re->single_view_layer)) { + have_layer = true; + } } } @@ -817,27 +808,6 @@ void RE_InitState(Render *re, RE_point_density_fix_linking(); } -void render_update_anim_renderdata(Render *re, RenderData *rd, ListBase *render_layers) -{ - /* filter */ - re->r.gauss = rd->gauss; - - /* motion blur */ - re->r.blurfac = rd->blurfac; - - /* freestyle */ - re->r.line_thickness_mode = rd->line_thickness_mode; - re->r.unit_line_thickness = rd->unit_line_thickness; - - /* render layers */ - BLI_freelistN(&re->view_layers); - BLI_duplicatelist(&re->view_layers, render_layers); - - /* render views */ - BLI_freelistN(&re->r.views); - BLI_duplicatelist(&re->r.views, &rd->views); -} - void RE_display_init_cb(Render *re, void *handle, void (*f)(void *handle, RenderResult *rr)) { re->display_init = f; @@ -979,7 +949,7 @@ static void render_result_uncrop(Render *re) re->result = rres; /* Weak, the display callback wants an active render-layer pointer. */ - re->result->renlay = render_get_active_layer(re, re->result); + re->result->renlay = render_get_single_layer(re, re->result); BLI_rw_mutex_unlock(&re->resultmutex); @@ -1217,7 +1187,7 @@ static void do_render_compositor(Render *re) /* Weak: the display callback wants an active render-layer pointer. */ if (re->result != nullptr) { - re->result->renlay = render_get_active_layer(re, re->result); + re->result->renlay = render_get_single_layer(re, re->result); re->display_update(re->duh, re->result, nullptr); } } @@ -1676,7 +1646,6 @@ static int render_init_from_main(Render *re, /* not too nice, but it survives anim-border render */ if (anim) { - render_update_anim_renderdata(re, &scene->r, &scene->view_layers); re->disprect = disprect; return 1; } @@ -1890,12 +1859,10 @@ void RE_RenderFreestyleExternal(Render *re) LISTBASE_FOREACH (RenderView *, rv, &re->result->views) { RE_SetActiveRenderView(re, rv->name); - ViewLayer *active_view_layer = static_cast( - BLI_findlink(&re->view_layers, re->active_view_layer)); FRS_begin_stroke_rendering(re); - LISTBASE_FOREACH (ViewLayer *, view_layer, &re->view_layers) { - if ((re->r.scemode & R_SINGLE_LAYER) && view_layer != active_view_layer) { + LISTBASE_FOREACH (ViewLayer *, view_layer, &re->scene->view_layers) { + if ((re->r.scemode & R_SINGLE_LAYER) && !STREQ(view_layer->name, re->single_view_layer)) { continue; } diff --git a/source/blender/render/intern/pipeline.h b/source/blender/render/intern/pipeline.h index 689e4509da3..e5da3cb8830 100644 --- a/source/blender/render/intern/pipeline.h +++ b/source/blender/render/intern/pipeline.h @@ -17,14 +17,7 @@ struct RenderResult; extern "C" { #endif -struct RenderLayer *render_get_active_layer(struct Render *re, struct RenderResult *rr); -/** - * Update some variables that can be animated, and otherwise wouldn't be due to - * #RenderData getting copied once at the start of animation render. - */ -void render_update_anim_renderdata(struct Render *re, - struct RenderData *rd, - struct ListBase *render_layers); +struct RenderLayer *render_get_single_layer(struct Render *re, struct RenderResult *rr); void render_copy_renderdata(struct RenderData *to, struct RenderData *from); #ifdef __cplusplus diff --git a/source/blender/render/intern/render_result.cc b/source/blender/render/intern/render_result.cc index 94f6e2f1509..1cd95831ddf 100644 --- a/source/blender/render/intern/render_result.cc +++ b/source/blender/render/intern/render_result.cc @@ -321,7 +321,7 @@ RenderResult *render_result_new(Render *re, rl->layflag = SCE_LAY_FLAG_DEFAULT; rl->passflag = SCE_PASS_COMBINED; - re->active_view_layer = 0; + re->single_view_layer[0] = '\0'; } /* Border render; calculate offset for use in compositor. compo is centralized coords. */ @@ -768,8 +768,8 @@ void render_result_single_layer_end(Render *re) /* reconstruct render result layers */ int nr = 0; - LISTBASE_FOREACH (ViewLayer *, view_layer, &re->view_layers) { - if (nr == re->active_view_layer) { + LISTBASE_FOREACH (ViewLayer *, view_layer, &re->scene->view_layers) { + if (STREQ(view_layer->name, re->single_view_layer)) { BLI_addtail(&re->result->layers, rl); } else { diff --git a/source/blender/render/intern/render_result.h b/source/blender/render/intern/render_result.h index 2e76efba8a3..6e971d45d31 100644 --- a/source/blender/render/intern/render_result.h +++ b/source/blender/render/intern/render_result.h @@ -136,10 +136,11 @@ void render_result_views_shallowdelete(struct RenderResult *rr); { \ int nr_; \ ViewLayer *iter_; \ - for (nr_ = 0, iter_ = static_cast((re_)->view_layers.first); iter_ != NULL; \ + for (nr_ = 0, iter_ = static_cast((re_)->scene->view_layers.first); \ + iter_ != NULL; \ iter_ = iter_->next, nr_++) { \ if (!G.background && (re_)->r.scemode & R_SINGLE_LAYER) { \ - if (nr_ != re->active_view_layer) { \ + if (!STREQ(iter_->name, re->single_view_layer)) { \ continue; \ } \ } \ diff --git a/source/blender/render/intern/render_types.h b/source/blender/render/intern/render_types.h index 29bac6e2766..ad58f081388 100644 --- a/source/blender/render/intern/render_types.h +++ b/source/blender/render/intern/render_types.h @@ -76,8 +76,7 @@ struct Render { struct Main *main; Scene *scene; RenderData r; - ListBase view_layers; - int active_view_layer; + char single_view_layer[MAX_NAME]; struct Object *camera_override; ThreadMutex highlighted_tiles_mutex; -- cgit v1.2.3