Draw manager: Listen to depsgraph's ID update callbacks
This replaces dedicated flag which wasn't clean who sets it and who clears it, and which was also trying to re-implement existing functionality in a way. Flushing is not currently very efficient but there are ways to speed this up a lot, but needs more investigation.
This commit is contained in:
parent
6208ce2e0a
commit
a6b6689c0a
|
@ -34,6 +34,7 @@ struct Main;
|
|||
struct Material;
|
||||
struct Scene;
|
||||
struct DrawEngineType;
|
||||
struct ID;
|
||||
struct IDProperty;
|
||||
struct bContext;
|
||||
struct Object;
|
||||
|
@ -78,6 +79,7 @@ typedef struct DRWUpdateContext {
|
|||
struct RenderEngineType *engine_type;
|
||||
} DRWUpdateContext;
|
||||
void DRW_notify_view_update(const DRWUpdateContext *update_ctx);
|
||||
void DRW_notify_id_update(const DRWUpdateContext *update_ctx, struct ID *id);
|
||||
|
||||
void DRW_draw_view(const struct bContext *C);
|
||||
|
||||
|
|
|
@ -263,6 +263,7 @@ DrawEngineType draw_engine_basic_type = {
|
|||
NULL,
|
||||
&BASIC_draw_scene,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
/* Note: currently unused, we may want to register so we can see this when debugging the view. */
|
||||
|
|
|
@ -916,6 +916,7 @@ DrawEngineType draw_engine_clay_type = {
|
|||
NULL,
|
||||
&CLAY_draw_scene,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
RenderEngineType DRW_engine_viewport_clay_type = {
|
||||
|
|
|
@ -109,6 +109,7 @@ EEVEE_LightProbeEngineData *EEVEE_lightprobe_data_get(Object *ob)
|
|||
|
||||
if (*pedata == NULL) {
|
||||
*pedata = MEM_callocN(sizeof(**pedata), "EEVEE_LightProbeEngineData");
|
||||
(*pedata)->need_full_update = true;
|
||||
(*pedata)->need_update = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -128,8 +128,6 @@ static void EEVEE_cache_populate(void *vedata, Object *ob)
|
|||
}
|
||||
else {
|
||||
BLI_addtail(&sldata->shadow_casters, BLI_genericNodeN(ob));
|
||||
EEVEE_ObjectEngineData *oedata = EEVEE_object_data_get(ob);
|
||||
oedata->need_update = ((ob->deg_update_flag & DEG_RUNTIME_DATA_UPDATE) != 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -287,6 +285,26 @@ static void EEVEE_view_update(void *vedata)
|
|||
}
|
||||
}
|
||||
|
||||
static void EEVEE_id_update(void *UNUSED(vedata), ID *id)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void EEVEE_engine_free(void)
|
||||
{
|
||||
EEVEE_bloom_free();
|
||||
|
@ -395,6 +413,7 @@ DrawEngineType draw_engine_eevee_type = {
|
|||
&EEVEE_draw_scene,
|
||||
NULL, //&EEVEE_draw_scene
|
||||
&EEVEE_view_update,
|
||||
&EEVEE_id_update,
|
||||
};
|
||||
|
||||
RenderEngineType DRW_engine_viewport_eevee_type = {
|
||||
|
|
|
@ -490,7 +490,9 @@ void EEVEE_lightprobes_cache_add(EEVEE_ViewLayerData *sldata, Object *ob)
|
|||
|
||||
ped->num_cell = probe->grid_resolution_x * probe->grid_resolution_y * probe->grid_resolution_z;
|
||||
|
||||
if ((ob->deg_update_flag & DEG_RUNTIME_DATA_UPDATE) != 0) {
|
||||
if (ped->need_full_update) {
|
||||
ped->need_full_update = false;
|
||||
|
||||
ped->need_update = true;
|
||||
ped->probe_id = 0;
|
||||
|
||||
|
|
|
@ -257,10 +257,6 @@ void EEVEE_lights_cache_add(EEVEE_ViewLayerData *sldata, Object *ob)
|
|||
Lamp *la = (Lamp *)ob->data;
|
||||
EEVEE_LampEngineData *led = EEVEE_lamp_data_get(ob);
|
||||
|
||||
if ((ob->deg_update_flag & DEG_RUNTIME_DATA_UPDATE) != 0) {
|
||||
led->need_update = true;
|
||||
}
|
||||
|
||||
MEM_SAFE_FREE(led->storage);
|
||||
|
||||
if (la->mode & (LA_SHAD_BUF | LA_SHAD_RAY)) {
|
||||
|
|
|
@ -568,7 +568,19 @@ typedef struct EEVEE_LampEngineData {
|
|||
} EEVEE_LampEngineData;
|
||||
|
||||
typedef struct EEVEE_LightProbeEngineData {
|
||||
/* NOTE: need_full_update is set by dependency graph when the probe or it's
|
||||
* object is updated. This triggers full probe update, including it's
|
||||
* "progressive" GI refresh.
|
||||
*
|
||||
* need_update is always set to truth when need_full_update is tagged, but
|
||||
* might also be forced to be kept truth during GI refresh stages.
|
||||
*
|
||||
* TODO(sergey): Is there a way to avoid two flags here, or at least make
|
||||
* it more clear what's going on here?
|
||||
*/
|
||||
bool need_full_update;
|
||||
bool need_update;
|
||||
|
||||
bool ready_to_shade;
|
||||
int updated_cells;
|
||||
int updated_lvl;
|
||||
|
|
|
@ -217,6 +217,7 @@ DrawEngineType draw_engine_external_type = {
|
|||
NULL,
|
||||
&EXTERNAL_draw_scene,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
/* Note: currently unused, we should not register unless we want to see this when debugging the view. */
|
||||
|
|
|
@ -138,6 +138,7 @@ typedef struct DrawEngineType {
|
|||
void (*draw_scene)(void *vedata);
|
||||
|
||||
void (*view_update)(void *vedata);
|
||||
void (*id_update)(void *vedata, struct ID *id);
|
||||
} DrawEngineType;
|
||||
|
||||
#ifndef __DRW_ENGINE_H__
|
||||
|
|
|
@ -3259,6 +3259,46 @@ void DRW_notify_view_update(const DRWUpdateContext *update_ctx)
|
|||
|
||||
/** \} */
|
||||
|
||||
/** \name ID Update
|
||||
* \{ */
|
||||
|
||||
/* TODO(sergey): This code is run for each changed ID (including the ones which
|
||||
* are changed indirectly via update flush. Need to find a way to make this to
|
||||
* run really fast, hopefully without any memory allocations on a heap
|
||||
* Idea here could be to run every known engine's id_update() and make them
|
||||
* do nothing if there is no engine-specific data yet.
|
||||
*/
|
||||
void DRW_notify_id_update(const DRWUpdateContext *update_ctx, ID *id)
|
||||
{
|
||||
RenderEngineType *engine_type = update_ctx->engine_type;
|
||||
ARegion *ar = update_ctx->ar;
|
||||
View3D *v3d = update_ctx->v3d;
|
||||
RegionView3D *rv3d = ar->regiondata;
|
||||
Scene *scene = update_ctx->scene;
|
||||
ViewLayer *view_layer = update_ctx->view_layer;
|
||||
if (rv3d->viewport == NULL) {
|
||||
return;
|
||||
}
|
||||
/* Reset before using it. */
|
||||
memset(&DST, 0x0, sizeof(DST));
|
||||
DST.viewport = rv3d->viewport;
|
||||
DST.draw_ctx = (DRWContextState){
|
||||
ar, rv3d, v3d, scene, view_layer, OBACT(view_layer), engine_type, NULL,
|
||||
};
|
||||
DRW_engines_enable(scene, view_layer, engine_type);
|
||||
for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
|
||||
DrawEngineType *draw_engine = link->data;
|
||||
ViewportEngineData *data = DRW_viewport_engine_data_get(draw_engine);
|
||||
if (draw_engine->id_update) {
|
||||
draw_engine->id_update(data, id);
|
||||
}
|
||||
}
|
||||
DST.viewport = NULL;
|
||||
DRW_engines_disable();
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
/** \name Main Draw Loops (DRW_draw)
|
||||
|
@ -3329,8 +3369,6 @@ void DRW_draw_render_loop_ex(
|
|||
DEG_OBJECT_ITER(graph, ob, DEG_OBJECT_ITER_FLAG_ALL);
|
||||
{
|
||||
DRW_engines_cache_populate(ob);
|
||||
/* XXX find a better place for this. maybe Depsgraph? */
|
||||
ob->deg_update_flag = 0;
|
||||
}
|
||||
DEG_OBJECT_ITER_END
|
||||
|
||||
|
|
|
@ -539,7 +539,9 @@ 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:
|
||||
material_changed(bmain, (Material *)id);
|
||||
|
@ -565,7 +567,42 @@ 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue