Blender V5.0
eevee_lightcache.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
10
11#include "DRW_engine.hh"
12#include "DRW_render.hh"
13
14#include "BKE_global.hh"
15#include "BKE_lightprobe.h"
16
18
19#include "BLI_mutex.hh"
20#include "BLI_threads.h"
21#include "BLI_time.h"
22
25
26#include "GPU_capabilities.hh"
27#include "GPU_context.hh"
28
29#include "WM_api.hh"
30#include "WM_types.hh"
31
32#include "wm_window.hh"
33
34#include "eevee_instance.hh"
35
36#include "eevee_lightcache.hh"
37
38/* -------------------------------------------------------------------- */
41
42namespace blender::eevee {
43
44class LightBake {
45 private:
46 Depsgraph *depsgraph_;
47
49 int frame_;
51 int delay_ms_;
57 std::string &report_;
58
63 void *gl_context_ = nullptr;
65 GPUContext *gpu_context_ = nullptr;
66
68 Instance *instance_ = nullptr;
70 draw::Manager *manager_ = nullptr;
71
73 Vector<Object *> original_probes_;
76 Mutex result_mutex_;
77
78 public:
80 ViewLayer *view_layer,
81 Scene *scene,
82 Span<Object *> probes,
83 bool run_as_job,
84 std::string &report,
85 int frame,
86 int delay_ms = 0)
87 : depsgraph_(DEG_graph_new(bmain, scene, view_layer, DAG_EVAL_RENDER)),
88 frame_(frame),
89 delay_ms_(delay_ms),
90 report_(report),
91 original_probes_(probes)
92 {
94 bake_result_.resize(probes.size());
95 bake_result_.fill(nullptr);
96
97 if (run_as_job && !GPU_use_main_context_workaround()) {
98 /* This needs to happen in main thread. */
99 gl_context_ = WM_system_gpu_context_create();
101 }
102 }
103
105 {
107 DEG_graph_free(depsgraph_);
108 }
109
116 void update()
117 {
119
120 for (auto i : bake_result_.index_range()) {
121 if (bake_result_[i] == nullptr) {
122 continue;
123 }
124 Object *orig_ob = original_probes_[i];
125
126 {
127 std::scoped_lock lock(result_mutex_);
128
129 LightProbeObjectCache *cache = orig_ob->lightprobe_cache;
130 /* Delete any existing cache. */
131 if (cache->grid_static_cache != nullptr) {
133 }
134 /* Pass ownership to original object. */
135 cache->grid_static_cache = bake_result_[i];
136 bake_result_[i] = nullptr;
137 }
138 /* Propagate the cache to evaluated object. */
140 }
141 }
142
146 void run(const bool *stop = nullptr, bool *do_update = nullptr, float *progress = nullptr)
147 {
148 DEG_graph_relations_update(depsgraph_);
149 DEG_evaluate_on_framechange(depsgraph_, frame_);
150
151 if (delay_ms_ > 0) {
152 BLI_time_sleep_ms(delay_ms_);
153 }
154
155 context_enable();
156 manager_ = new draw::Manager();
157 instance_ = new eevee::Instance();
158 instance_->init_light_bake(depsgraph_, manager_);
159 context_disable();
160
161 for (auto i : original_probes_.index_range()) {
162 Object *eval_ob = DEG_get_evaluated(depsgraph_, original_probes_[i]);
163
164 instance_->light_bake_irradiance(
165 *eval_ob,
166 [this]() { context_enable(); },
167 [this]() { context_disable(); },
168 [&]() { return (G.is_break == true) || ((stop != nullptr) ? *stop : false); },
169 [&](LightProbeGridCacheFrame *cache_frame, float grid_progress) {
170 {
171 std::scoped_lock lock(result_mutex_);
172 /* Delete any existing cache that wasn't transferred to the original object. */
173 if (bake_result_[i] != nullptr) {
175 }
176 bake_result_[i] = cache_frame;
177 }
178
179 if (do_update) {
180 *do_update = true;
181 }
182
183 if (progress) {
184 *progress = (i + grid_progress) / original_probes_.size();
185 }
186 });
187
188 if (StringRefNull(instance_->info_get()) != "") {
189 /* Pipe report to operator. */
190 report_ = instance_->info_get();
191 }
192
193 if ((G.is_break == true) || (stop != nullptr && *stop == true)) {
194 break;
195 }
196 }
197
198 delete_resources();
199 }
200
201 private:
202 void context_enable(bool render_begin = true)
203 {
205 /* Reuse main draw context. */
208 }
209 else if (gl_context_ == nullptr) {
210 /* Main thread case. */
212 }
213 else {
214 /* Worker thread case. */
216 if (gpu_context_ == nullptr) {
217 /* Create GPUContext in worker thread as it needs the correct gl context bound (which can
218 * only be bound in worker thread because of some GL driver requirements). */
219 gpu_context_ = GPU_context_create(nullptr, gl_context_);
220 }
222 }
223
224 if (render_begin) {
226 }
227 }
228
229 void context_disable()
230 {
232 /* Reuse main draw context. */
236 }
237 else if (gl_context_ == nullptr) {
238 /* Main thread case. */
241 }
242 else {
243 /* Worker thread case. */
247 }
248 }
249
256 void delete_resources()
257 {
258 /* Bind context without GPU_render_begin(). */
259 context_enable(false);
260
261 /* Free GPU data (Textures, Frame-buffers, etc...). */
262 delete instance_;
263 delete manager_;
264
265 /* Delete / unbind the GL & GPU context. Assumes it is currently bound. */
267 /* Reuse main draw context. */
270 }
271 else if (gl_context_ == nullptr) {
272 /* Main thread case. */
274 }
275 else {
276 /* Worker thread case. */
277 if (gpu_context_ != nullptr) {
278 GPU_context_discard(gpu_context_);
279 }
282 }
283 }
284};
285
286} // namespace blender::eevee
287
289
290/* -------------------------------------------------------------------- */
293
294using namespace blender::eevee;
295
297 wmWindow *win,
298 Main *bmain,
299 ViewLayer *view_layer,
300 Scene *scene,
301 blender::Vector<Object *> original_probes,
302 std::string &report,
303 int delay_ms,
304 int frame)
305{
306 /* Do not bake if there is a render going on. */
307 if (WM_jobs_test(wm, scene, WM_JOB_TYPE_RENDER)) {
308 return nullptr;
309 }
310
311 /* Stop existing baking job. */
313
314 wmJob *wm_job = WM_jobs_get(wm,
315 win,
316 scene,
317 "Baking lighting...",
320
321 LightBake *bake = new LightBake(
322 bmain, view_layer, scene, std::move(original_probes), true, report, frame, delay_ms);
323
325 WM_jobs_timer(wm_job, 0.4, NC_SCENE | NA_EDITED, 0);
328
329 G.is_break = false;
330
331 return wm_job;
332}
333
335 ViewLayer *view_layer,
336 Scene *scene,
337 blender::Vector<Object *> original_probes,
338 std::string &report,
339 int frame)
340{
341 LightBake *bake = new LightBake(
342 bmain, view_layer, scene, std::move(original_probes), false, report, frame);
343 /* TODO(fclem): Can remove this cast once we remove the previous EEVEE light cache. */
344 return reinterpret_cast<void *>(bake);
345}
346
348{
349 delete static_cast<LightBake *>(job_data);
350}
351
352void EEVEE_lightbake_update(void *job_data)
353{
354 static_cast<LightBake *>(job_data)->update();
355}
356
357void EEVEE_lightbake_job(void *job_data, wmJobWorkerStatus *worker_status)
358{
359 static_cast<LightBake *>(job_data)->run(
360 &worker_status->stop, &worker_status->do_update, &worker_status->progress);
361}
362
General operations for probes.
void BKE_lightprobe_grid_cache_frame_free(struct LightProbeGridCacheFrame *cache)
#define BLI_assert(a)
Definition BLI_assert.h:46
int BLI_thread_is_main(void)
Definition threads.cc:179
Platform independent time functions.
void BLI_time_sleep_ms(int ms)
Definition time.cc:133
void DEG_id_tag_update(ID *id, unsigned int flags)
@ DAG_EVAL_RENDER
Depsgraph * DEG_graph_new(Main *bmain, Scene *scene, ViewLayer *view_layer, eEvaluationMode mode)
Definition depsgraph.cc:278
void DEG_graph_free(Depsgraph *graph)
Definition depsgraph.cc:306
void DEG_evaluate_on_framechange(Depsgraph *graph, float frame, DepsgraphEvaluateSyncWriteback sync_writeback=DEG_EVALUATE_SYNC_WRITEBACK_NO)
void DEG_graph_relations_update(Depsgraph *graph)
T * DEG_get_evaluated(const Depsgraph *depsgraph, T *id)
@ ID_RECALC_SHADING
Definition DNA_ID.h:1094
@ ID_RECALC_SYNC_TO_EVAL
Definition DNA_ID.h:1118
void DRW_blender_gpu_render_context_disable(void *re_gpu_context)
void DRW_gpu_context_disable()
void DRW_system_gpu_render_context_enable(void *re_system_gpu_context)
void DRW_gpu_context_enable()
void DRW_system_gpu_render_context_disable(void *re_system_gpu_context)
void DRW_blender_gpu_render_context_enable(void *re_gpu_context)
bool GPU_use_main_context_workaround()
void GPU_render_end()
GPUContext * GPU_context_create(void *ghost_window, void *ghost_context)
void GPU_context_main_lock()
void GPU_render_begin()
void GPU_context_main_unlock()
void GPU_context_discard(GPUContext *)
@ WM_JOB_TYPE_LIGHT_BAKE
Definition WM_api.hh:1802
@ WM_JOB_TYPE_RENDER
Definition WM_api.hh:1778
@ WM_JOB_EXCL_RENDER
Definition WM_api.hh:1765
@ WM_JOB_PROGRESS
Definition WM_api.hh:1766
@ WM_JOB_PRIORITY
Definition WM_api.hh:1760
#define NC_SCENE
Definition WM_types.hh:378
#define NA_EDITED
Definition WM_types.hh:584
volatile int lock
constexpr int64_t size() const
Definition BLI_span.hh:252
A running instance of the engine.
void run(const bool *stop=nullptr, bool *do_update=nullptr, float *progress=nullptr)
LightBake(Main *bmain, ViewLayer *view_layer, Scene *scene, Span< Object * > probes, bool run_as_job, std::string &report, int frame, int delay_ms=0)
void * EEVEE_lightbake_job_data_alloc(Main *bmain, ViewLayer *view_layer, Scene *scene, blender::Vector< Object * > original_probes, std::string &report, int frame)
void EEVEE_lightbake_job(void *job_data, wmJobWorkerStatus *worker_status)
void EEVEE_lightbake_job_data_free(void *job_data)
wmJob * EEVEE_lightbake_job_create(wmWindowManager *wm, wmWindow *win, Main *bmain, ViewLayer *view_layer, Scene *scene, blender::Vector< Object * > original_probes, std::string &report, int delay_ms, int frame)
void EEVEE_lightbake_update(void *job_data)
#define G(x, y, z)
std::mutex Mutex
Definition BLI_mutex.hh:47
static void update(bNodeTree *ntree)
struct LightProbeGridCacheFrame * grid_static_cache
struct LightProbeObjectCache * lightprobe_cache
i
Definition text_draw.cc:230
void WM_jobs_stop_type(wmWindowManager *wm, const void *owner, eWM_JobType job_type)
Definition wm_jobs.cc:647
void WM_jobs_timer(wmJob *wm_job, double time_step, uint note, uint endnote)
Definition wm_jobs.cc:376
wmJob * WM_jobs_get(wmWindowManager *wm, wmWindow *win, const void *owner, const char *name, const eWM_JobFlag flag, const eWM_JobType job_type)
Definition wm_jobs.cc:211
void WM_jobs_callbacks(wmJob *wm_job, wm_jobs_start_callback startjob, void(*initjob)(void *), void(*update)(void *), void(*endjob)(void *))
Definition wm_jobs.cc:388
bool WM_jobs_test(const wmWindowManager *wm, const void *owner, int job_type)
Definition wm_jobs.cc:247
void WM_jobs_customdata_set(wmJob *wm_job, void *customdata, void(*free)(void *customdata))
Definition wm_jobs.cc:360
void * WM_system_gpu_context_create()
void wm_window_reset_drawable()
void WM_system_gpu_context_dispose(void *context)