Fix T53598: OpenGL Render Animation does not update shadows

General idea of the fix: skip the whole draw manager callback madness which
was used to tag object's engine specific data as dirty. Use generic recalc
flag in ObjectEngineData structure instead. This gives us the following
benefits;

- Sovles mentioned bug report.
- Avoids whole interface lookup for opened viewports for EVERY changed ID.
- Fixes missing updates when viewport is temporarily invisible.

Reviewers: dfelinto, fclem

Differential Revision: https://developer.blender.org/D3028
This commit is contained in:
Sergey Sharybin 2018-01-29 16:42:04 +01:00
parent 006c66b1ff
commit 9577ebde79
Notes: blender-bot 2023-02-14 06:19:33 +01:00
Referenced by commit bfe88006a3, Remove unused function
Referenced by issue #53598, OpenGL Render Animation does not update shadows
5 changed files with 50 additions and 60 deletions

View File

@ -36,6 +36,7 @@
#include <deque>
#include "BLI_utildefines.h"
#include "BLI_listbase.h"
#include "BLI_task.h"
#include "BLI_ghash.h"
@ -207,10 +208,21 @@ BLI_INLINE OperationDepsNode *flush_schedule_children(
return result;
}
void flush_engine_data_update(ID *id)
{
if (GS(id->name) != ID_OB) {
return;
}
Object *object = (Object *)id;
BLI_LISTBASE_FOREACH(ObjectEngineData *, engine_data, &object->drawdata) {
engine_data->recalc |= id->recalc;
}
}
/* NOTE: It will also accumulate flags from changed components. */
BLI_INLINE void flush_editors_id_update(Main *bmain,
Depsgraph *graph,
const DEGEditorUpdateContext *update_ctx)
void flush_editors_id_update(Main *bmain,
Depsgraph *graph,
const DEGEditorUpdateContext *update_ctx)
{
foreach (IDDepsNode *id_node, graph->id_nodes) {
if (id_node->done != ID_STATE_MODIFIED) {
@ -241,6 +253,8 @@ BLI_INLINE void flush_editors_id_update(Main *bmain,
/* Inform editors. */
if (deg_copy_on_write_is_expanded(id_cow)) {
deg_editors_id_update(update_ctx, id_cow);
/* Inform draw engines that something was changed. */
flush_engine_data_update(id_cow);
}
}
}

View File

@ -294,30 +294,38 @@ static void eevee_view_update(void *vedata)
}
}
static void eevee_id_update(void *UNUSED(vedata), ID *id)
static void eevee_id_object_update(void *UNUSED(vedata), Object *object)
{
/* This is a bit mask of components which update is to be ignored. */
const int ignore_updates = ID_RECALC_COLLECTIONS;
/* Check whether we have to do anything here. */
if ((id->recalc & ~ignore_updates) == 0) {
return;
const int allowed_updates = ~ignore_updates;
EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_get(object);
if (ped != NULL && (ped->engine_data.recalc & allowed_updates) != 0) {
ped->need_full_update = true;
ped->engine_data.recalc = 0;
}
EEVEE_LampEngineData *led = EEVEE_lamp_data_get(object);
if (led != NULL && (led->engine_data.recalc & allowed_updates) != 0) {
led->need_update = true;
led->engine_data.recalc = 0;
}
EEVEE_ObjectEngineData *oedata = EEVEE_object_data_get(object);
if (oedata != NULL && (oedata->engine_data.recalc & allowed_updates) != 0) {
oedata->need_update = true;
oedata->engine_data.recalc = 0;
}
}
static void eevee_id_update(void *vedata, ID *id)
{
/* Handle updates based on ID type. */
const ID_Type id_type = GS(id->name);
if (id_type == ID_OB) {
Object *object = (Object *)id;
EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_get(object);
if (ped != NULL) {
ped->need_full_update = true;
}
EEVEE_LampEngineData *led = EEVEE_lamp_data_get(object);
if (led != NULL) {
led->need_update = true;
}
EEVEE_ObjectEngineData *oedata = EEVEE_object_data_get(object);
if (oedata != NULL) {
oedata->need_update = true;
}
switch (GS(id->name)) {
case ID_OB:
eevee_id_object_update(vedata, (Object *)id);
break;
default:
/* pass */
break;
}
}

View File

@ -2868,6 +2868,10 @@ static void drw_engines_cache_populate(Object *ob)
DrawEngineType *engine = link->data;
ViewportEngineData *data = DRW_viewport_engine_data_ensure(engine);
if (engine->id_update) {
engine->id_update(data, &ob->id);
}
if (engine->cache_populate) {
engine->cache_populate(data, ob);
}

View File

@ -542,8 +542,6 @@ void ED_render_id_flush_update(const DEGEditorUpdateContext *update_ctx, ID *id)
return;
}
Main *bmain = update_ctx->bmain;
Scene *scene = update_ctx->scene;
ViewLayer *view_layer = update_ctx->view_layer;
/* Internal ID update handlers. */
switch (GS(id->name)) {
case ID_MA:
@ -570,42 +568,6 @@ void ED_render_id_flush_update(const DEGEditorUpdateContext *update_ctx, ID *id)
render_engine_flag_changed(bmain, RE_ENGINE_UPDATE_OTHER);
break;
}
/* Inform all draw managers about changes.
*
* TODO(sergey): This code is run for every updated ID, via flushing
* mechanism. How can we avoid iterating over the whole interface for
* every of those IDs? One of the ideas would be to call draw manager's
* ID update which is not bound to any of contexts.
*/
{
wmWindowManager *wm = bmain->wm.first;
for (wmWindow *win = wm->windows.first; win; win = win->next) {
bScreen *sc = WM_window_get_active_screen(win);
WorkSpace *workspace = BKE_workspace_active_get(win->workspace_hook);
ViewRender *view_render = BKE_viewrender_get(win->scene, workspace);
for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) {
if (sa->spacetype != SPACE_VIEW3D) {
continue;
}
for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) {
if (ar->regiontype != RGN_TYPE_WINDOW) {
continue;
}
RenderEngineType *engine_type = RE_engines_find(view_render->engine_id);
DRW_notify_id_update(
(&(DRWUpdateContext){
.bmain = bmain,
.scene = scene,
.view_layer = view_layer,
.ar = ar,
.v3d = (View3D *)sa->spacedata.first,
.engine_type = engine_type
}),
id);
}
}
}
}
}

View File

@ -86,6 +86,8 @@ typedef struct ObjectEngineData {
struct DrawEngineType *engine_type;
/* Only nested data, NOT the engine data itself. */
ObjectEngineDataFreeCb free;
/* Accumulated recalc flags, which corresponds to ID->recalc flags. */
int recalc;
} ObjectEngineData;
#define MAX_VGROUP_NAME 64