Fix T78452 EEVEE: Motion Blur: Crash when using camera switching

This was caused by the ViewLayer being freed with all its
engine data.
This commit is contained in:
Clément Foucault 2020-08-06 19:58:35 +02:00
parent 3dcaca93a0
commit 4f59e4bddc
Notes: blender-bot 2023-02-14 05:25:44 +01:00
Referenced by commit 58909abc68, EEVEE: Render: Fix regression caused by previous Motion blur fix
Referenced by issue #79970, Camera Animation Breaks EEVEE Motion Blur (Two Steps or More)
Referenced by issue #79672, Motion blur steps value incorrectly changes shutter duration and affects AA quality
Referenced by issue #79630, Crop and transparent in render
Referenced by issue #79533, Crash when opening file
Referenced by issue #78452, crash while switching camera in animation rendering (only when motion blur is on in eevee render settings )
7 changed files with 70 additions and 52 deletions

View File

@ -237,6 +237,11 @@ EEVEE_ViewLayerData *EEVEE_view_layer_data_get(void)
return (EEVEE_ViewLayerData *)DRW_view_layer_engine_data_get(&draw_engine_eevee_type);
}
static void eevee_view_layer_init(EEVEE_ViewLayerData *sldata)
{
sldata->common_ubo = DRW_uniformbuffer_create(sizeof(sldata->common_data), NULL);
}
EEVEE_ViewLayerData *EEVEE_view_layer_data_ensure_ex(struct ViewLayer *view_layer)
{
EEVEE_ViewLayerData **sldata = (EEVEE_ViewLayerData **)DRW_view_layer_engine_data_ensure_ex(
@ -244,6 +249,7 @@ EEVEE_ViewLayerData *EEVEE_view_layer_data_ensure_ex(struct ViewLayer *view_laye
if (*sldata == NULL) {
*sldata = MEM_callocN(sizeof(**sldata), "EEVEE_ViewLayerData");
eevee_view_layer_init(*sldata);
}
return *sldata;
@ -256,6 +262,7 @@ EEVEE_ViewLayerData *EEVEE_view_layer_data_ensure(void)
if (*sldata == NULL) {
*sldata = MEM_callocN(sizeof(**sldata), "EEVEE_ViewLayerData");
eevee_view_layer_init(*sldata);
}
return *sldata;

View File

@ -79,11 +79,6 @@ static void eevee_engine_init(void *ved)
GPU_framebuffer_ensure_config(&fbl->main_color_fb,
{GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->color)});
if (sldata->common_ubo == NULL) {
sldata->common_ubo = DRW_uniformbuffer_create(sizeof(sldata->common_data),
&sldata->common_data);
}
/* `EEVEE_renderpasses_init` will set the active render passes used by `EEVEE_effects_init`.
* `EEVEE_effects_init` needs to go second for TAA. */
EEVEE_renderpasses_init(vedata);
@ -459,6 +454,8 @@ static void eevee_render_to_image(void *vedata,
}
EEVEE_PrivateData *g_data = ved->stl->g_data;
EEVEE_render_modules_init(vedata, engine, depsgraph);
int initial_frame = CFRA;
int steps = max_ii(1, scene->eevee.motion_blur_steps);
int time_steps_tot = (do_motion_blur) ? steps : 1;
@ -481,9 +478,10 @@ static void eevee_render_to_image(void *vedata,
}
else {
EEVEE_motion_blur_step_set(ved, MB_PREV);
RE_engine_frame_set(engine, floorf(time_prev), fractf(time_prev));
DRW_render_set_time(engine, depsgraph, floorf(time_prev), fractf(time_prev));
EEVEE_render_modules_init(vedata, engine, depsgraph);
sldata = EEVEE_view_layer_data_ensure();
EEVEE_render_view_sync(vedata, engine, depsgraph);
EEVEE_render_cache_init(sldata, vedata);
DRW_render_object_iter(vedata, engine, depsgraph, EEVEE_render_cache);
@ -497,9 +495,10 @@ static void eevee_render_to_image(void *vedata,
/* Next motion step. */
if (do_motion_blur_fx) {
EEVEE_motion_blur_step_set(ved, MB_NEXT);
RE_engine_frame_set(engine, floorf(time_next), fractf(time_next));
DRW_render_set_time(engine, depsgraph, floorf(time_next), fractf(time_next));
EEVEE_render_modules_init(vedata, engine, depsgraph);
sldata = EEVEE_view_layer_data_ensure();
EEVEE_render_view_sync(vedata, engine, depsgraph);
EEVEE_render_cache_init(sldata, vedata);
DRW_render_object_iter(vedata, engine, depsgraph, EEVEE_render_cache);
@ -513,10 +512,11 @@ static void eevee_render_to_image(void *vedata,
{
if (do_motion_blur) {
EEVEE_motion_blur_step_set(ved, MB_CURR);
RE_engine_frame_set(engine, floorf(time_curr), fractf(time_curr));
DRW_render_set_time(engine, depsgraph, floorf(time_curr), fractf(time_curr));
EEVEE_render_modules_init(vedata, engine, depsgraph);
sldata = EEVEE_view_layer_data_ensure();
}
EEVEE_render_view_sync(vedata, engine, depsgraph);
EEVEE_render_cache_init(sldata, vedata);
DRW_render_object_iter(vedata, engine, depsgraph, EEVEE_render_cache);

View File

@ -861,11 +861,6 @@ static void eevee_lightbake_cache_create(EEVEE_Data *vedata, EEVEE_LightBake *lb
DRW_view_set_active(view);
}
if (sldata->common_ubo == NULL) {
sldata->common_ubo = DRW_uniformbuffer_create(sizeof(sldata->common_data),
&sldata->common_data);
}
/* HACK: set txl->color but unset it before Draw Manager frees it. */
txl->color = lbake->rt_color;
int viewport_size[2] = {

View File

@ -1285,6 +1285,9 @@ bool EEVEE_render_init(EEVEE_Data *vedata,
void EEVEE_render_view_sync(EEVEE_Data *vedata,
struct RenderEngine *engine,
struct Depsgraph *depsgraph);
void EEVEE_render_modules_init(EEVEE_Data *vedata,
struct RenderEngine *engine,
struct Depsgraph *depsgraph);
void EEVEE_render_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_render_cache(void *vedata,
struct Object *ob,

View File

@ -47,17 +47,13 @@
#include "eevee_private.h"
/* Return true if init properly. */
bool EEVEE_render_init(EEVEE_Data *ved, RenderEngine *engine, struct Depsgraph *depsgraph)
bool EEVEE_render_init(EEVEE_Data *ved, RenderEngine *engine, struct Depsgraph *UNUSED(depsgraph))
{
EEVEE_Data *vedata = (EEVEE_Data *)ved;
EEVEE_StorageList *stl = vedata->stl;
EEVEE_TextureList *txl = vedata->txl;
EEVEE_FramebufferList *fbl = vedata->fbl;
EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure();
Scene *scene = DEG_get_evaluated_scene(depsgraph);
const float *size_orig = DRW_viewport_size_get();
float size_final[2];
float camtexcofac[4];
/* Init default FB and render targets:
* In render mode the default framebuffer is not generated
@ -75,25 +71,6 @@ bool EEVEE_render_init(EEVEE_Data *ved, RenderEngine *engine, struct Depsgraph *
g_data->valid_double_buffer = 0;
copy_v2_v2(g_data->size_orig, size_orig);
if (scene->eevee.flag & SCE_EEVEE_OVERSCAN) {
g_data->overscan = scene->eevee.overscan / 100.0f;
g_data->overscan_pixels = roundf(max_ff(size_orig[0], size_orig[1]) * g_data->overscan);
madd_v2_v2v2fl(size_final, size_orig, (float[2]){2.0f, 2.0f}, g_data->overscan_pixels);
camtexcofac[0] = size_final[0] / size_orig[0];
camtexcofac[1] = size_final[1] / size_orig[1];
camtexcofac[2] = -camtexcofac[0] * g_data->overscan_pixels / size_final[0];
camtexcofac[3] = -camtexcofac[1] * g_data->overscan_pixels / size_final[1];
}
else {
copy_v2_v2(size_final, size_orig);
g_data->overscan = 0.0f;
g_data->overscan_pixels = 0.0f;
copy_v4_fl4(camtexcofac, 1.0f, 1.0f, 0.0f, 0.0f);
}
int final_res[2] = {size_orig[0] + g_data->overscan_pixels * 2.0f,
size_orig[1] + g_data->overscan_pixels * 2.0f};
@ -125,19 +102,19 @@ bool EEVEE_render_init(EEVEE_Data *ved, RenderEngine *engine, struct Depsgraph *
GPU_framebuffer_ensure_config(&fbl->main_color_fb,
{GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->color)});
/* Alloc common ubo data. */
if (sldata->common_ubo == NULL) {
sldata->common_ubo = DRW_uniformbuffer_create(sizeof(sldata->common_data),
&sldata->common_data);
}
EEVEE_render_view_sync(vedata, engine, depsgraph);
return true;
}
void EEVEE_render_modules_init(EEVEE_Data *vedata,
RenderEngine *engine,
struct Depsgraph *depsgraph)
{
EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure();
EEVEE_StorageList *stl = vedata->stl;
EEVEE_FramebufferList *fbl = vedata->fbl;
/* TODO(sergey): Shall render hold pointer to an evaluated camera instead? */
struct Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, RE_GetCamera(engine->re));
DRWView *view = (DRWView *)DRW_view_default_get();
DRW_view_camtexco_set(view, camtexcofac);
EEVEE_render_view_sync(vedata, engine, depsgraph);
/* `EEVEE_renderpasses_init` will set the active render passes used by `EEVEE_effects_init`.
* `EEVEE_effects_init` needs to go second for TAA. */
@ -146,13 +123,14 @@ bool EEVEE_render_init(EEVEE_Data *ved, RenderEngine *engine, struct Depsgraph *
EEVEE_materials_init(sldata, vedata, stl, fbl);
EEVEE_shadows_init(sldata);
EEVEE_lightprobes_init(sldata, vedata);
return true;
}
void EEVEE_render_view_sync(EEVEE_Data *vedata, RenderEngine *engine, struct Depsgraph *depsgraph)
{
EEVEE_PrivateData *g_data = vedata->stl->g_data;
Scene *scene = DEG_get_evaluated_scene(depsgraph);
const float *size_orig = DRW_viewport_size_get();
float size_final[2];
/* Set the pers & view matrix. */
float winmat[4][4], viewmat[4][4], viewinv[4][4];
@ -169,10 +147,33 @@ void EEVEE_render_view_sync(EEVEE_Data *vedata, RenderEngine *engine, struct Dep
DRW_view_reset();
DRW_view_default_set(view);
DRW_view_set_active(view);
float camtexcofac[4];
if (scene->eevee.flag & SCE_EEVEE_OVERSCAN) {
g_data->overscan = scene->eevee.overscan / 100.0f;
g_data->overscan_pixels = roundf(max_ff(size_orig[0], size_orig[1]) * g_data->overscan);
madd_v2_v2v2fl(size_final, size_orig, (float[2]){2.0f, 2.0f}, g_data->overscan_pixels);
camtexcofac[0] = size_final[0] / size_orig[0];
camtexcofac[1] = size_final[1] / size_orig[1];
camtexcofac[2] = -camtexcofac[0] * g_data->overscan_pixels / size_final[0];
camtexcofac[3] = -camtexcofac[1] * g_data->overscan_pixels / size_final[1];
}
else {
copy_v2_v2(size_final, size_orig);
g_data->overscan = 0.0f;
g_data->overscan_pixels = 0.0f;
copy_v4_fl4(camtexcofac, 1.0f, 1.0f, 0.0f, 0.0f);
}
DRW_view_camtexco_set(view, camtexcofac);
}
void EEVEE_render_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
EEVEE_view_layer_data_ensure();
EEVEE_bloom_cache_init(sldata, vedata);
EEVEE_depth_of_field_cache_init(sldata, vedata);
EEVEE_effects_cache_init(sldata, vedata);

View File

@ -632,6 +632,10 @@ void DRW_render_object_iter(void *vedata,
struct RenderEngine *engine,
struct Depsgraph *depsgraph));
void DRW_render_instance_buffer_finish(void);
void DRW_render_set_time(struct RenderEngine *engine,
struct Depsgraph *depsgraph,
int frame,
float subframe);
void DRW_render_viewport_size_set(const int size[2]);
void DRW_custom_pipeline(DrawEngineType *draw_engine_type,

View File

@ -1953,6 +1953,14 @@ void DRW_render_instance_buffer_finish(void)
drw_resource_buffer_finish(DST.vmempool);
}
/* WARNING: Changing frame might free the ViewLayerEngineData */
void DRW_render_set_time(RenderEngine *engine, Depsgraph *depsgraph, int frame, float subframe)
{
RE_engine_frame_set(engine, frame, subframe);
DST.draw_ctx.scene = DEG_get_evaluated_scene(depsgraph);
DST.draw_ctx.view_layer = DEG_get_evaluated_view_layer(depsgraph);
}
/**
* object mode select-loop, see: ED_view3d_draw_select_loop (legacy drawing).
*/