From 3dcaca93a050eebf68e9b86e2c110476b7b9979c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Thu, 6 Aug 2020 16:18:15 +0200 Subject: Fix T78160 EEVEE: Motion Blur: Bug with Follow Path animation Follow path seems to not be catched by `BKE_object_moves_in_time`. For this reason, we cache all transforms for all object and check ourselves if an animation occurs. This is almost what cycles does. We also fix the rigid body case if the rigid body use deformation. --- .../blender/draw/engines/eevee/eevee_motion_blur.c | 40 ++++++++++++++++------ 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/source/blender/draw/engines/eevee/eevee_motion_blur.c b/source/blender/draw/engines/eevee/eevee_motion_blur.c index 0d55d92ce6f..400b309de07 100644 --- a/source/blender/draw/engines/eevee/eevee_motion_blur.c +++ b/source/blender/draw/engines/eevee/eevee_motion_blur.c @@ -37,6 +37,7 @@ #include "DNA_mesh_types.h" #include "DNA_modifier_types.h" #include "DNA_particle_types.h" +#include "DNA_rigidbody_types.h" #include "DNA_screen_types.h" #include "ED_screen.h" @@ -329,10 +330,20 @@ void EEVEE_motion_blur_cache_populate(EEVEE_ViewLayerData *UNUSED(sldata), return; } - const bool is_dupli = (ob->base_flag & BASE_FROM_DUPLI) != 0; + RigidBodyOb *rbo = ob->rigidbody_object; + + /* active rigidbody objects only, as only those are affected by sim. */ + const bool has_rigidbody = (rbo && (rbo->type == RBO_TYPE_ACTIVE)); +#if 0 /* For now we assume dupli objects are moving. */ - const bool object_moves = is_dupli || BKE_object_moves_in_time(ob, true); - const bool is_deform = BKE_object_is_deform_modified(DRW_context_state_get()->scene, ob); + const bool is_dupli = (ob->base_flag & BASE_FROM_DUPLI) != 0; + const bool object_moves = is_dupli || has_rigidbody || BKE_object_moves_in_time(ob, true); +#else + /* BKE_object_moves_in_time does not work in some cases. Better */ + const bool object_moves = true; +#endif + const bool is_deform = BKE_object_is_deform_modified(DRW_context_state_get()->scene, ob) || + (has_rigidbody && (rbo->flag & RBO_FLAG_USE_DEFORM) != 0); if (!(object_moves || is_deform)) { return; @@ -363,14 +374,6 @@ void EEVEE_motion_blur_cache_populate(EEVEE_ViewLayerData *UNUSED(sldata), copy_m4_m4(mb_data->obmat[MB_NEXT], mb_data->obmat[MB_CURR]); } - grp = DRW_shgroup_create(e_data.motion_blur_object_sh, psl->velocity_object); - DRW_shgroup_uniform_mat4(grp, "prevModelMatrix", mb_data->obmat[MB_PREV]); - DRW_shgroup_uniform_mat4(grp, "currModelMatrix", mb_data->obmat[MB_CURR]); - DRW_shgroup_uniform_mat4(grp, "nextModelMatrix", mb_data->obmat[MB_NEXT]); - DRW_shgroup_uniform_bool(grp, "useDeform", &mb_geom->use_deform, 1); - - DRW_shgroup_call(grp, batch, ob); - if (mb_geom->use_deform) { EEVEE_ObjectEngineData *oedata = EEVEE_object_data_ensure(ob); if (!oedata->geom_update) { @@ -386,6 +389,21 @@ void EEVEE_motion_blur_cache_populate(EEVEE_ViewLayerData *UNUSED(sldata), /* Keep to modify later (after init). */ mb_geom->batch = batch; } + + /* Avoid drawing object that has no motions since object_moves is always true. */ + if (!mb_geom->use_deform && /* Object deformation can happen without transform. */ + equals_m4m4(mb_data->obmat[MB_PREV], mb_data->obmat[MB_CURR]) && + equals_m4m4(mb_data->obmat[MB_NEXT], mb_data->obmat[MB_CURR])) { + return; + } + + grp = DRW_shgroup_create(e_data.motion_blur_object_sh, psl->velocity_object); + DRW_shgroup_uniform_mat4(grp, "prevModelMatrix", mb_data->obmat[MB_PREV]); + DRW_shgroup_uniform_mat4(grp, "currModelMatrix", mb_data->obmat[MB_CURR]); + DRW_shgroup_uniform_mat4(grp, "nextModelMatrix", mb_data->obmat[MB_NEXT]); + DRW_shgroup_uniform_bool(grp, "useDeform", &mb_geom->use_deform, 1); + + DRW_shgroup_call(grp, batch, ob); } else if (is_deform) { /* Store vertex position buffer. */ -- cgit v1.2.3 From 4f59e4bddcb0c06e441adf68a5f252a4e5b4b260 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Thu, 6 Aug 2020 19:58:35 +0200 Subject: Fix T78452 EEVEE: Motion Blur: Crash when using camera switching This was caused by the ViewLayer being freed with all its engine data. --- source/blender/draw/engines/eevee/eevee_data.c | 7 +++ source/blender/draw/engines/eevee/eevee_engine.c | 22 +++---- .../blender/draw/engines/eevee/eevee_lightcache.c | 5 -- source/blender/draw/engines/eevee/eevee_private.h | 3 + source/blender/draw/engines/eevee/eevee_render.c | 73 +++++++++++----------- source/blender/draw/intern/DRW_render.h | 4 ++ source/blender/draw/intern/draw_manager.c | 8 +++ 7 files changed, 70 insertions(+), 52 deletions(-) diff --git a/source/blender/draw/engines/eevee/eevee_data.c b/source/blender/draw/engines/eevee/eevee_data.c index 55bbf7740e3..c475e5287c2 100644 --- a/source/blender/draw/engines/eevee/eevee_data.c +++ b/source/blender/draw/engines/eevee/eevee_data.c @@ -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; diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c index d49bb5a268c..a142648d08d 100644 --- a/source/blender/draw/engines/eevee/eevee_engine.c +++ b/source/blender/draw/engines/eevee/eevee_engine.c @@ -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); diff --git a/source/blender/draw/engines/eevee/eevee_lightcache.c b/source/blender/draw/engines/eevee/eevee_lightcache.c index e4922bd85ed..19325729114 100644 --- a/source/blender/draw/engines/eevee/eevee_lightcache.c +++ b/source/blender/draw/engines/eevee/eevee_lightcache.c @@ -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] = { diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index 2f54c839d80..14ee1915412 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -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, diff --git a/source/blender/draw/engines/eevee/eevee_render.c b/source/blender/draw/engines/eevee/eevee_render.c index e8619701365..195791d8dd4 100644 --- a/source/blender/draw/engines/eevee/eevee_render.c +++ b/source/blender/draw/engines/eevee/eevee_render.c @@ -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); diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h index 7a889d9399e..16e6269aad6 100644 --- a/source/blender/draw/intern/DRW_render.h +++ b/source/blender/draw/intern/DRW_render.h @@ -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, diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 43025d9fef4..2beab021cfb 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -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). */ -- cgit v1.2.3