Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2018-07-07 13:58:46 +0300
committerClément Foucault <foucault.clem@gmail.com>2018-07-07 13:58:46 +0300
commit6d0d237be37bfe36255f61ccd9817005148d4475 (patch)
treecd0f50106e824122594e56a5747cd88519c1f7c1 /source
parent5402529debef4d56322bad8b066a7a732efeb743 (diff)
Eevee: LightCache: Add auto update when lightprobe are being modified
One draw back is that there is a significant overhead caused by creating the batches for the new depsgraph. Caching the depsgraph between subsequent update is not possible right now because we cannot update it. This is to be adressed in the future. There is no option to disable auto update right now.
Diffstat (limited to 'source')
-rw-r--r--source/blender/draw/engines/eevee/eevee_data.c12
-rw-r--r--source/blender/draw/engines/eevee/eevee_engine.c3
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightcache.c219
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightcache.h4
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightprobes.c41
-rw-r--r--source/blender/draw/engines/eevee/eevee_private.h28
-rw-r--r--source/blender/draw/intern/draw_manager.c4
-rw-r--r--source/blender/editors/render/render_shading.c30
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c22
-rw-r--r--source/blender/windowmanager/WM_types.h1
10 files changed, 240 insertions, 124 deletions
diff --git a/source/blender/draw/engines/eevee/eevee_data.c b/source/blender/draw/engines/eevee/eevee_data.c
index 74bb7a17eb7..96e784b524c 100644
--- a/source/blender/draw/engines/eevee/eevee_data.c
+++ b/source/blender/draw/engines/eevee/eevee_data.c
@@ -131,15 +131,7 @@ EEVEE_ObjectEngineData *EEVEE_object_data_ensure(Object *ob)
static void eevee_lightprobe_data_init(DrawData *dd)
{
EEVEE_LightProbeEngineData *ped = (EEVEE_LightProbeEngineData *)dd;
- ped->need_full_update = true;
- ped->need_update = true;
-}
-
-static void eevee_lightprobe_data_free(DrawData *dd)
-{
- EEVEE_LightProbeEngineData *ped = (EEVEE_LightProbeEngineData *)dd;
-
- BLI_freelistN(&ped->captured_object_list);
+ ped->need_update = false;
}
EEVEE_LightProbeEngineData *EEVEE_lightprobe_data_get(Object *ob)
@@ -159,7 +151,7 @@ EEVEE_LightProbeEngineData *EEVEE_lightprobe_data_ensure(Object *ob)
&draw_engine_eevee_type,
sizeof(EEVEE_LightProbeEngineData),
eevee_lightprobe_data_init,
- eevee_lightprobe_data_free);
+ NULL);
}
/* Lamp data. */
diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c
index c4b673ddabf..6d68e609f03 100644
--- a/source/blender/draw/engines/eevee/eevee_engine.c
+++ b/source/blender/draw/engines/eevee/eevee_engine.c
@@ -367,10 +367,9 @@ static void eevee_view_update(void *vedata)
static void eevee_id_object_update(void *UNUSED(vedata), Object *object)
{
- /* This is a bit mask of components which update is to be ignored. */
EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_get(object);
if (ped != NULL && ped->dd.recalc != 0) {
- ped->need_full_update = true;
+ ped->need_update = (ped->dd.recalc & (ID_RECALC_TRANSFORM | ID_RECALC_COPY_ON_WRITE)) != 0;
ped->dd.recalc = 0;
}
EEVEE_LampEngineData *led = EEVEE_lamp_data_get(object);
diff --git a/source/blender/draw/engines/eevee/eevee_lightcache.c b/source/blender/draw/engines/eevee/eevee_lightcache.c
index 219297d6c83..89f21b02dcd 100644
--- a/source/blender/draw/engines/eevee/eevee_lightcache.c
+++ b/source/blender/draw/engines/eevee/eevee_lightcache.c
@@ -30,6 +30,8 @@
#include "BKE_global.h"
#include "BKE_blender.h"
+#include "BLI_threads.h"
+
#include "DEG_depsgraph_build.h"
#include "DEG_depsgraph_query.h"
@@ -44,6 +46,9 @@
#include "../../../intern/gawain/gawain/gwn_context.h"
#include "WM_api.h"
+#include "WM_types.h"
+
+#include "wm_window.h"
/* Rounded to nearest PowerOfTwo */
#if defined(IRRADIANCE_SH_L2)
@@ -82,6 +87,8 @@ extern void DRW_gawain_render_context_disable(void *re_gwn_context);
typedef struct EEVEE_LightBake {
Depsgraph *depsgraph;
ViewLayer *view_layer;
+ ViewLayer *view_layer_input;
+ LightCache *lcache;
Scene *scene;
struct Main *bmain;
@@ -105,7 +112,8 @@ typedef struct EEVEE_LightBake {
int irr_size[3]; /* Size of the irradiance texture. */
int total_irr_samples; /* Total for all grids */
int grid_sample; /* Nth sample of the current grid being rendered. */
- int bounce_curr, bounce_count; /* The current light bounce being evaluated. */
+ int grid_curr; /* Nth grid in the cache being rendered. */
+ int bounce_curr, bounce_len; /* The current light bounce being evaluated. */
float vis_range, vis_blur; /* Sample Visibility compression and bluring. */
float vis_res; /* Resolution of the Visibility shadowmap. */
GPUTexture *grid_prev; /* Result of previous light bounce. */
@@ -129,6 +137,8 @@ typedef struct EEVEE_LightBake {
float *progress;
bool resource_only; /* For only handling the resources. */
+ bool own_resources;
+ int delay; /* ms. delay the start of the baking to not slowdown interactions (TODO remove) */
void *gl_context, *gwn_context; /* If running in parallel (in a separate thread), use this context. */
} EEVEE_LightBake;
@@ -242,7 +252,6 @@ void EEVEE_lightcache_load(LightCache *lcache)
NULL);
GPU_texture_bind(lcache->cube_tx.tex, 0);
GPU_texture_mipmap_mode(lcache->cube_tx.tex, true, true);
- GPU_texture_generate_mipmap(lcache->cube_tx.tex);
for (int mip = 0; mip < lcache->mips_len; ++mip) {
GPU_texture_add_mipmap(lcache->cube_tx.tex, GPU_DATA_10_11_11_REV, mip + 1, lcache->cube_mips[mip].data);
}
@@ -378,10 +387,9 @@ static void eevee_lightbake_create_render_target(EEVEE_LightBake *lbake, int rt_
static void eevee_lightbake_create_resources(EEVEE_LightBake *lbake)
{
Scene *scene_eval = DEG_get_evaluated_scene(lbake->depsgraph);
- Scene *scene_orig = lbake->scene;
- const SceneEEVEE *eevee = &scene_eval->eevee;
+ SceneEEVEE *eevee = &scene_eval->eevee;
- lbake->bounce_count = eevee->gi_diffuse_bounces;
+ lbake->bounce_len = eevee->gi_diffuse_bounces;
lbake->vis_res = eevee->gi_visibility_resolution;
lbake->rt_res = eevee->gi_cubemap_resolution;
@@ -398,62 +406,98 @@ static void eevee_lightbake_create_resources(EEVEE_LightBake *lbake)
/* Ensure Light Cache is ready to accept new data. If not recreate one.
* WARNING: All the following must be threadsafe. It's currently protected
* by the DRW mutex. */
- LightCache *lcache = scene_orig->eevee.light_cache;
+ lbake->lcache = eevee->light_cache;
/* TODO validate irradiance and reflection cache independantly... */
- if (lcache != NULL &&
- !EEVEE_lightcache_validate(lcache, lbake->cube_len, lbake->ref_cube_res, lbake->irr_size))
+ if (lbake->lcache != NULL &&
+ !EEVEE_lightcache_validate(lbake->lcache, lbake->cube_len, lbake->ref_cube_res, lbake->irr_size))
{
- EEVEE_lightcache_free(lcache);
- scene_orig->eevee.light_cache = lcache = NULL;
+ eevee->light_cache = lbake->lcache = NULL;
}
- if (lcache == NULL) {
- lcache = EEVEE_lightcache_create(lbake->grid_len,
- lbake->cube_len,
- lbake->ref_cube_res,
- lbake->vis_res,
- lbake->irr_size);
- scene_orig->eevee.light_cache = lcache;
+ if (lbake->lcache == NULL) {
+ lbake->lcache = EEVEE_lightcache_create(lbake->grid_len,
+ lbake->cube_len,
+ lbake->ref_cube_res,
+ lbake->vis_res,
+ lbake->irr_size);
+ eevee->light_cache = lbake->lcache;
+ }
+
+ lbake->lcache->vis_res = lbake->vis_res;
+ lbake->lcache->flag = LIGHTCACHE_UPDATE_WORLD | LIGHTCACHE_UPDATE_CUBE | LIGHTCACHE_UPDATE_GRID | LIGHTCACHE_BAKING;
+}
+
+wmJob *EEVEE_lightbake_job_create(
+ struct wmWindowManager *wm, struct wmWindow *win, struct Main *bmain,
+ struct ViewLayer *view_layer, struct Scene *scene, int delay)
+{
+ EEVEE_LightBake *lbake = NULL;
+
+ /* only one render job at a time */
+ if (WM_jobs_test(wm, scene, WM_JOB_TYPE_RENDER))
+ return NULL;
+
+ wmJob *wm_job = WM_jobs_get(wm, win, scene, "Bake Lighting",
+ WM_JOB_EXCL_RENDER | WM_JOB_PRIORITY | WM_JOB_PROGRESS, WM_JOB_TYPE_LIGHT_BAKE);
+
+ /* If job exists do not recreate context and depsgraph. */
+ EEVEE_LightBake *old_lbake = (EEVEE_LightBake *)WM_jobs_customdata_get(wm_job);
+
+ if (old_lbake && (old_lbake->view_layer_input == view_layer) && (old_lbake->bmain == bmain)) {
+ lbake = MEM_callocN(sizeof(EEVEE_LightBake), "EEVEE_LightBake");
+ /* Cannot reuse depsgraph for now because we cannot get the update from the
+ * main database directly. TODO reuse depsgraph and only update positions. */
+ /* lbake->depsgraph = old_lbake->depsgraph; */
+ lbake->depsgraph = DEG_graph_new(scene, view_layer, DAG_EVAL_RENDER);
+
+ lbake->scene = scene;
+ lbake->bmain = bmain;
+ lbake->view_layer_input = view_layer;
+ lbake->gl_context = old_lbake->gl_context;
+ lbake->gwn_context = old_lbake->gwn_context;
+ lbake->own_resources = true;
+ lbake->delay = delay;
+
+ old_lbake->own_resources = false;
- DEG_id_tag_update(&scene_orig->id, DEG_TAG_COPY_ON_WRITE);
+ if (old_lbake->stop != NULL) {
+ *old_lbake->stop = 1;
+ }
+ }
+ else {
+ lbake = EEVEE_lightbake_job_data_alloc(bmain, view_layer, scene, true);
+ lbake->delay = delay;
}
- lcache->vis_res = lbake->vis_res;
+ WM_jobs_customdata_set(wm_job, lbake, EEVEE_lightbake_job_data_free);
+ WM_jobs_timer(wm_job, 0.4, NC_SCENE | NA_EDITED, 0);
+ WM_jobs_callbacks(wm_job, EEVEE_lightbake_job, NULL, EEVEE_lightbake_update, EEVEE_lightbake_update);
- lcache->flag = LIGHTCACHE_UPDATE_WORLD | LIGHTCACHE_UPDATE_CUBE | LIGHTCACHE_UPDATE_GRID | LIGHTCACHE_BAKING;
+ G.is_break = false;
- /* Share light cache with the evaluated (baking) layer and the original layer.
- * This avoid full scene re-evaluation by depsgraph. */
- scene_eval->eevee.light_cache = lcache;
+ return wm_job;
}
/* MUST run on the main thread. */
-void *EEVEE_lightbake_job_data_alloc(struct Main *bmain, struct ViewLayer *view_layer, struct Scene *scene, bool run_as_job)
+void *EEVEE_lightbake_job_data_alloc(
+ struct Main *bmain, struct ViewLayer *view_layer, struct Scene *scene, bool run_as_job)
{
+ BLI_assert(BLI_thread_is_main());
+
EEVEE_LightBake *lbake = MEM_callocN(sizeof(EEVEE_LightBake), "EEVEE_LightBake");
lbake->depsgraph = DEG_graph_new(scene, view_layer, DAG_EVAL_RENDER);
lbake->scene = scene;
lbake->bmain = bmain;
+ lbake->view_layer_input = view_layer;
+ lbake->own_resources = true;
if (run_as_job) {
lbake->gl_context = WM_opengl_context_create();
+ wm_window_reset_drawable();
}
- DEG_graph_relations_update(lbake->depsgraph, bmain, scene, view_layer);
-
- int frame = 0; /* TODO make it user param. */
- DEG_evaluate_on_framechange(lbake->bmain, lbake->depsgraph, frame);
-
- /* Count lightprobes */
- eevee_lightbake_count_probes(lbake);
-
- DRW_opengl_context_enable();
- /* This function needs to run on the main thread. */
- eevee_lightbake_create_resources(lbake);
- DRW_opengl_context_disable();
-
return lbake;
}
@@ -461,7 +505,10 @@ void EEVEE_lightbake_job_data_free(void *custom_data)
{
EEVEE_LightBake *lbake = (EEVEE_LightBake *)custom_data;
- DEG_graph_free(lbake->depsgraph);
+ /* TODO reuse depsgraph. */
+ /* if (lbake->own_resources) { */
+ DEG_graph_free(lbake->depsgraph);
+ /* } */
MEM_SAFE_FREE(lbake->cube_prb);
MEM_SAFE_FREE(lbake->grid_prb);
@@ -487,7 +534,7 @@ static void eevee_lightbake_delete_resources(EEVEE_LightBake *lbake)
GPU_FRAMEBUFFER_FREE_SAFE(lbake->rt_fb[i]);
}
- if (lbake->gl_context) {
+ if (lbake->gl_context && lbake->own_resources) {
/* Delete the baking context. */
DRW_gawain_render_context_disable(lbake->gwn_context);
DRW_gawain_render_context_enable(lbake->gwn_context);
@@ -497,6 +544,10 @@ static void eevee_lightbake_delete_resources(EEVEE_LightBake *lbake)
lbake->gwn_context = NULL;
lbake->gl_context = NULL;
}
+ else if (lbake->gl_context) {
+ DRW_gawain_render_context_disable(lbake->gwn_context);
+ DRW_opengl_render_context_disable(lbake->gl_context);
+ }
else if (!lbake->resource_only) {
DRW_opengl_context_disable();
}
@@ -724,6 +775,14 @@ static void eevee_lightbake_render_grid_sample(void *ved, void *user_data)
if (is_last_bounce_sample) {
eevee_lightbake_copy_irradiance(lbake, lcache);
}
+
+ /* If it is the last sample grid sample (and last bounce). */
+ if ((lbake->bounce_curr == lbake->bounce_len - 1) &&
+ (lbake->grid_curr == lbake->grid_len - 1) &&
+ (lbake->grid_sample == lbake->grid_sample - 1))
+ {
+ lcache->flag &= ~LIGHTCACHE_UPDATE_GRID;
+ }
}
static void eevee_lightbake_render_probe_sample(void *ved, void *user_data)
@@ -732,7 +791,8 @@ static void eevee_lightbake_render_probe_sample(void *ved, void *user_data)
EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure();
EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
EEVEE_LightBake *lbake = (EEVEE_LightBake *)user_data;
- LightCache *lcache = lbake->scene->eevee.light_cache;
+ Scene *scene_eval = DEG_get_evaluated_scene(lbake->depsgraph);
+ LightCache *lcache = scene_eval->eevee.light_cache;
EEVEE_LightProbe *eprobe = lbake->cube;
LightProbe *prb = *lbake->probe;
@@ -749,6 +809,11 @@ static void eevee_lightbake_render_probe_sample(void *ved, void *user_data)
EEVEE_lightbake_filter_glossy(sldata, vedata, lbake->rt_color, lbake->store_fb, lbake->cube_offset, prb->intensity, lcache->mips_len);
lcache->cube_len += 1;
+
+ /* If it's the last probe. */
+ if (lbake->cube_offset == lbake->cube_len - 1) {
+ lcache->flag &= ~LIGHTCACHE_UPDATE_CUBE;
+ }
}
static float eevee_lightbake_grid_influence_volume(EEVEE_LightGrid *grid)
@@ -792,7 +857,8 @@ static bool eevee_lightbake_cube_comp(EEVEE_LightProbe *prb_a, EEVEE_LightProbe
static void eevee_lightbake_gather_probes(EEVEE_LightBake *lbake)
{
Depsgraph *depsgraph = lbake->depsgraph;
- LightCache *lcache = lbake->scene->eevee.light_cache;
+ Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
+ LightCache *lcache = scene_eval->eevee.light_cache;
/* At least one for the world */
int grid_len = 1;
@@ -823,21 +889,29 @@ static void eevee_lightbake_gather_probes(EEVEE_LightBake *lbake)
SORT_PROBE(EEVEE_LightGrid, lcache->grid_data + 1, lbake->grid_len - 1, eevee_lightbake_grid_comp);
SORT_PROBE(EEVEE_LightProbe, lcache->cube_data + 1, lbake->cube_len - 1, eevee_lightbake_cube_comp);
- lbake->total = lbake->total_irr_samples * lbake->bounce_count + lbake->cube_len;
+ lbake->total = lbake->total_irr_samples * lbake->bounce_len + lbake->cube_len;
lbake->done = 0;
}
void EEVEE_lightbake_update(void *custom_data)
{
EEVEE_LightBake *lbake = (EEVEE_LightBake *)custom_data;
- Scene *scene = lbake->scene;
+ Scene *scene_orig = lbake->scene;
+
+ /* If a new lightcache was created, free the old one and reference the new. */
+ if (scene_orig->eevee.light_cache != lbake->lcache) {
+ if (scene_orig->eevee.light_cache != NULL) {
+ EEVEE_lightcache_free(scene_orig->eevee.light_cache);
+ }
+ scene_orig->eevee.light_cache = lbake->lcache;
+ }
- DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE);
+ DEG_id_tag_update(&scene_orig->id, DEG_TAG_COPY_ON_WRITE);
}
static bool lightbake_do_sample(EEVEE_LightBake *lbake, void (*render_callback)(void *ved, void *user_data))
{
- if (G.is_break == true) {
+ if (G.is_break == true || *lbake->stop) {
return false;
}
@@ -858,22 +932,38 @@ void EEVEE_lightbake_job(void *custom_data, short *stop, short *do_update, float
{
EEVEE_LightBake *lbake = (EEVEE_LightBake *)custom_data;
Depsgraph *depsgraph = lbake->depsgraph;
+ int frame = 0; /* TODO make it user param. */
+
+ DEG_graph_relations_update(depsgraph, lbake->bmain, lbake->scene, lbake->view_layer_input);
+ DEG_evaluate_on_framechange(lbake->bmain, depsgraph, frame);
lbake->view_layer = DEG_get_evaluated_view_layer(depsgraph);
lbake->stop = stop;
lbake->do_update = do_update;
lbake->progress = progress;
+ /* Count lightprobes */
+ eevee_lightbake_count_probes(lbake);
+
/* We need to create the FBOs in the right context.
* We cannot do it in the main thread. */
eevee_lightbake_context_enable(lbake);
+ eevee_lightbake_create_resources(lbake);
eevee_lightbake_create_render_target(lbake, lbake->rt_res);
eevee_lightbake_context_disable(lbake);
/* Gather all probes data */
eevee_lightbake_gather_probes(lbake);
- LightCache *lcache = lbake->scene->eevee.light_cache;
+ LightCache *lcache = lbake->lcache;
+
+ /* HACK: Sleep to delay the first rendering operation
+ * that causes a small freeze (caused by VBO generation)
+ * because this step is locking at this moment. */
+ /* TODO remove this. */
+ if (lbake->delay) {
+ PIL_sleep_ms(lbake->delay);
+ }
/* Render world irradiance and reflection first */
if (lcache->flag & LIGHTCACHE_UPDATE_WORLD) {
@@ -882,28 +972,39 @@ void EEVEE_lightbake_job(void *custom_data, short *stop, short *do_update, float
}
/* Render irradiance grids */
- for (lbake->bounce_curr = 0; lbake->bounce_curr < lbake->bounce_count; ++lbake->bounce_curr) {
- /* Bypass world, start at 1. */
- lbake->probe = lbake->grid_prb + 1;
- lbake->grid = lcache->grid_data + 1;
- for (int p = 1; p < lbake->grid_len; ++p, lbake->probe++, lbake->grid++) {
- LightProbe *prb = *lbake->probe;
- const int grid_sample_count = prb->grid_resolution_x *
- prb->grid_resolution_y *
- prb->grid_resolution_z;
- for (lbake->grid_sample = 0; lbake->grid_sample < grid_sample_count; ++lbake->grid_sample) {
- lightbake_do_sample(lbake, eevee_lightbake_render_grid_sample);
+ if (lcache->flag & LIGHTCACHE_UPDATE_GRID) {
+ for (lbake->bounce_curr = 0; lbake->bounce_curr < lbake->bounce_len; ++lbake->bounce_curr) {
+ /* Bypass world, start at 1. */
+ lbake->probe = lbake->grid_prb + 1;
+ lbake->grid = lcache->grid_data + 1;
+ for (lbake->grid_curr = 1;
+ lbake->grid_curr < lbake->grid_len;
+ ++lbake->grid_curr, ++lbake->probe, ++lbake->grid)
+ {
+ LightProbe *prb = *lbake->probe;
+ const int grid_sample_count = prb->grid_resolution_x *
+ prb->grid_resolution_y *
+ prb->grid_resolution_z;
+ for (lbake->grid_sample = 0;
+ lbake->grid_sample < grid_sample_count;
+ ++lbake->grid_sample)
+ {
+ lightbake_do_sample(lbake, eevee_lightbake_render_grid_sample);
+ }
}
}
}
/* Render reflections */
- {
+ if (lcache->flag & LIGHTCACHE_UPDATE_CUBE) {
lcache->cube_len = 1;
/* Bypass world, start at 1. */
lbake->probe = lbake->cube_prb + 1;
lbake->cube = lcache->cube_data + 1;
- for (lbake->cube_offset = 1; lbake->cube_offset < lbake->cube_len; ++lbake->cube_offset, lbake->probe++, lbake->cube++) {
+ for (lbake->cube_offset = 1;
+ lbake->cube_offset < lbake->cube_len;
+ ++lbake->cube_offset, ++lbake->probe, ++lbake->cube)
+ {
lightbake_do_sample(lbake, eevee_lightbake_render_probe_sample);
}
}
diff --git a/source/blender/draw/engines/eevee/eevee_lightcache.h b/source/blender/draw/engines/eevee/eevee_lightcache.h
index 1556c996df8..2400486a698 100644
--- a/source/blender/draw/engines/eevee/eevee_lightcache.h
+++ b/source/blender/draw/engines/eevee/eevee_lightcache.h
@@ -33,8 +33,12 @@ struct Scene;
struct LightCache;
struct EEVEE_ViewLayerData;
struct EEVEE_Data;
+struct EEVEE_LightBake;
/* Light Bake */
+struct wmJob *EEVEE_lightbake_job_create(
+ struct wmWindowManager *wm, struct wmWindow *win, struct Main *bmain,
+ struct ViewLayer *view_layer, struct Scene *scene, int delay);
void *EEVEE_lightbake_job_data_alloc(struct Main *bmain, struct ViewLayer *viewlayer, struct Scene *scene, bool run_as_job);
void EEVEE_lightbake_job_data_free(void *custom_data);
void EEVEE_lightbake_update(void *custom_data);
diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c
index 1e8daeaa958..92e61aa773a 100644
--- a/source/blender/draw/engines/eevee/eevee_lightprobes.c
+++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c
@@ -51,6 +51,9 @@
#include "ED_screen.h"
+#include "WM_api.h"
+#include "WM_types.h"
+
#define HAMMERSLEY_SIZE 1024
static struct {
@@ -437,6 +440,8 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
pinfo->num_planar = 0;
pinfo->vis_data.collection = NULL;
+ pinfo->do_grid_update = false;
+ pinfo->do_cube_update = false;
{
psl->probe_background = DRW_pass_create("World Probe Background Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL);
@@ -606,6 +611,18 @@ void EEVEE_lightprobes_cache_add(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata
pinfo->num_planar++;
}
+ else {
+ EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_ensure(ob);
+ if (ped->need_update) {
+ if (probe->type == LIGHTPROBE_TYPE_GRID) {
+ pinfo->do_grid_update = true;
+ }
+ else {
+ pinfo->do_cube_update = true;
+ }
+ ped->need_update = false;
+ }
+ }
}
void EEVEE_lightprobes_grid_data_from_object(Object *ob, EEVEE_LightGrid *egrid, int *offset)
@@ -798,7 +815,6 @@ void EEVEE_lightprobes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *ved
DRW_uniformbuffer_update(sldata->grid_ubo, &sldata->probes->grid_data);
/* For shading, save max level of the octahedron map */
- int mipsize = GPU_texture_width(light_cache->cube_tx.tex);
sldata->common_data.prb_lod_cube_max = (float)light_cache->mips_len - 1.0f;
sldata->common_data.prb_lod_planar_max = (float)MAX_PLANAR_LOD_LEVEL;
sldata->common_data.prb_irradiance_vis_size = light_cache->vis_res;
@@ -812,6 +828,29 @@ void EEVEE_lightprobes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *ved
pinfo->cache_num_planar = pinfo->num_planar;
}
planar_pool_ensure_alloc(vedata, pinfo->num_planar);
+
+ /* If lightcache auto-update is enable we tag the relevant part
+ * of the cache to update and fire up a baking job. */
+ if (!DRW_state_is_image_render() && !DRW_state_is_opengl_render() &&
+ (pinfo->do_grid_update || pinfo->do_cube_update))
+ {
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ BLI_assert(draw_ctx->evil_C);
+
+ Scene *scene_orig = DEG_get_input_scene(draw_ctx->depsgraph);
+
+ if (scene_orig->eevee.light_cache != NULL) {
+ if (pinfo->do_grid_update) {
+ scene_orig->eevee.light_cache->flag |= LIGHTCACHE_UPDATE_GRID;
+ }
+ /* If we update grid we need to update the cubemaps too.
+ * So always refresh cubemaps. */
+ scene_orig->eevee.light_cache->flag |= LIGHTCACHE_UPDATE_CUBE;
+ }
+
+ /* Use a notifier to trigger the operator after all */
+ WM_event_add_notifier(draw_ctx->evil_C, NC_LIGHTPROBE, scene_orig);
+ }
}
/* -------------------------------------------------------------------- */
diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h
index b71165fbd8c..c9149d3bcf8 100644
--- a/source/blender/draw/engines/eevee/eevee_private.h
+++ b/source/blender/draw/engines/eevee/eevee_private.h
@@ -443,10 +443,9 @@ typedef struct EEVEE_LightProbesInfo {
int updated_bounce;
int num_bounce;
int cubemap_res;
- int grid_initialized;
- struct World *prev_world;
+ /* Update */
bool do_cube_update;
- bool all_materials_updated;
+ bool do_grid_update;
/* For rendering probes */
float probemat[6][4][4];
int layer;
@@ -716,30 +715,7 @@ typedef struct EEVEE_LampEngineData {
typedef struct EEVEE_LightProbeEngineData {
DrawData dd;
- /* TODO Remove this struct if not needed anymore. */
- /* 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;
- int num_cell;
- int max_lvl;
- int probe_id; /* Only used for display data */
- float probe_size; /* Only used for display data */
- DRWMatrixState mats; /* For planar probes */
- float planer_eq_offset[4];
- struct ListBase captured_object_list;
} EEVEE_LightProbeEngineData;
typedef struct EEVEE_ObjectEngineData {
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index 5fabb856346..26e5365a6fd 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -755,10 +755,6 @@ DrawDataList *DRW_drawdatalist_from_id(ID *id)
DrawData *DRW_drawdata_get(ID *id, DrawEngineType *engine_type)
{
- if (!id_can_have_drawdata(id)) {
- return NULL;
- }
-
DrawDataList *drawdata = DRW_drawdatalist_from_id(id);
if (drawdata == NULL)
diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c
index 636900a2e29..23ac1dfd598 100644
--- a/source/blender/editors/render/render_shading.c
+++ b/source/blender/editors/render/render_shading.c
@@ -717,6 +717,7 @@ static int light_cache_bake_exec(bContext *C, wmOperator *UNUSED(op))
void *rj = EEVEE_lightbake_job_data_alloc(bmain, view_layer, scene, false);
short stop = 0, do_update; float progress; /* Not actually used. */
EEVEE_lightbake_job(rj, &stop, &do_update, &progress);
+ EEVEE_lightbake_update(rj);
EEVEE_lightbake_job_data_free(rj);
// no redraw needed, we leave state as we entered it
@@ -730,31 +731,18 @@ static int light_cache_bake_exec(bContext *C, wmOperator *UNUSED(op))
static int light_cache_bake_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
wmWindowManager *wm = CTX_wm_manager(C);
+ wmWindow *win = CTX_wm_window(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ int delay = RNA_int_get(op->ptr, "delay");
- /* only one render job at a time */
- if (WM_jobs_test(wm, scene, WM_JOB_TYPE_RENDER))
- return OPERATOR_CANCELLED;
-
- if (WM_jobs_test(wm, scene, WM_JOB_TYPE_LIGHT_BAKE))
- return OPERATOR_CANCELLED;
-
- /* TODO abort if selected engine is not eevee. */
- void *rj = EEVEE_lightbake_job_data_alloc(bmain, view_layer, scene, true);
+ wmJob *wm_job = EEVEE_lightbake_job_create(wm, win, bmain, view_layer, scene, delay);
- if (rj == NULL) {
- /* TODO display reason of faillure Blabla */
+ if (!wm_job) {
return OPERATOR_CANCELLED;
}
- wmJob *wm_job = WM_jobs_get(wm, CTX_wm_window(C), scene, "Bake Lighting",
- WM_JOB_EXCL_RENDER | WM_JOB_PRIORITY | WM_JOB_PROGRESS, WM_JOB_TYPE_LIGHT_BAKE);
- WM_jobs_customdata_set(wm_job, rj, EEVEE_lightbake_job_data_free);
- WM_jobs_timer(wm_job, 0.4, NC_OBJECT | ND_DRAW, 0);
- WM_jobs_callbacks(wm_job, EEVEE_lightbake_job, NULL, EEVEE_lightbake_update, NULL);
-
/* add modal handler for ESC */
WM_event_add_modal_handler(C, op);
@@ -764,9 +752,7 @@ static int light_cache_bake_invoke(bContext *C, wmOperator *op, const wmEvent *U
*/
op->customdata = scene;
- G.is_break = false;
-
- WM_jobs_start(CTX_wm_manager(C), wm_job);
+ WM_jobs_start(wm, wm_job);
WM_cursor_wait(0);
@@ -786,8 +772,8 @@ void SCENE_OT_light_cache_bake(wmOperatorType *ot)
ot->cancel = light_cache_bake_cancel;
ot->exec = light_cache_bake_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->prop = RNA_def_int(ot->srna, "delay", 0, 0, 2000, "Delay", "Delay in millisecond before baking start.", 0, 2000);
+ RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
}
/********************** render view operators *********************/
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index 15d241a88cc..5830b3fcd09 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -683,6 +683,17 @@ static void view3d_id_path_drop_copy(wmDrag *drag, wmDropBox *drop)
}
}
+static void view3d_lightcache_update(bContext *C)
+{
+ PointerRNA op_ptr;
+
+ WM_operator_properties_create(&op_ptr, "SCENE_OT_light_cache_bake");
+ RNA_int_set(&op_ptr, "delay", 200);
+
+ WM_operator_name_call(C, "SCENE_OT_light_cache_bake", WM_OP_INVOKE_DEFAULT, &op_ptr);
+
+ WM_operator_properties_free(&op_ptr);
+}
/* region dropbox definition */
static void view3d_dropboxes(void)
@@ -980,6 +991,9 @@ static void view3d_main_region_listener(
break;
}
break;
+ case NC_LIGHTPROBE:
+ ED_area_tag_refresh(sa);
+ break;
case NC_IMAGE:
/* this could be more fine grained checks if we had
* more context than just the region */
@@ -1409,6 +1423,13 @@ static void space_view3d_listener(
}
}
+static void space_view3d_refresh(const bContext *C, ScrArea *UNUSED(sa))
+{
+ /* This is only used by the auto lightprobe refresh for the moment.
+ * So we don't need to check anything to know what to do. */
+ view3d_lightcache_update((bContext *)C);
+}
+
const char *view3d_context_dir[] = {
"active_base", "active_object", NULL
};
@@ -1509,6 +1530,7 @@ void ED_spacetype_view3d(void)
st->free = view3d_free;
st->init = view3d_init;
st->listener = space_view3d_listener;
+ st->refresh = space_view3d_refresh;
st->duplicate = view3d_duplicate;
st->operatortypes = view3d_operatortypes;
st->keymap = view3d_keymap;
diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h
index 8e05822dd55..8b7633b635b 100644
--- a/source/blender/windowmanager/WM_types.h
+++ b/source/blender/windowmanager/WM_types.h
@@ -257,6 +257,7 @@ typedef struct wmNotifier {
#define NC_GPENCIL (22<<24)
#define NC_LINESTYLE (23<<24)
#define NC_CAMERA (24<<24)
+#define NC_LIGHTPROBE (25<<24)
/* data type, 256 entries is enough, it can overlap */
#define NOTE_DATA 0x00FF0000