WIP: eevee-next-world-irradiance #108304
|
@ -570,6 +570,34 @@ class RENDER_PT_eevee_indirect_lighting(RenderButtonsPanel, Panel):
|
||||||
col.prop(props, "gi_filter_quality")
|
col.prop(props, "gi_filter_quality")
|
||||||
|
|
||||||
|
|
||||||
|
class RENDER_PT_eevee_next_indirect_lighting(RenderButtonsPanel, Panel):
|
||||||
|
bl_label = "Indirect Lighting"
|
||||||
|
bl_options = {'DEFAULT_CLOSED'}
|
||||||
|
COMPAT_ENGINES = {'BLENDER_EEVEE_NEXT'}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def poll(cls, context):
|
||||||
|
return (context.engine in cls.COMPAT_ENGINES)
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
layout = self.layout
|
||||||
|
layout.use_property_split = True
|
||||||
|
layout.use_property_decorate = False # No animation.
|
||||||
|
|
||||||
|
scene = context.scene
|
||||||
|
props = scene.eevee
|
||||||
|
|
||||||
|
col = layout.column()
|
||||||
|
col.operator("scene.light_cache_bake", text="Bake Indirect Lighting", icon='RENDER_STILL')
|
||||||
|
col.operator("scene.light_cache_free", text="Delete Lighting Cache")
|
||||||
|
|
||||||
|
cache_info = scene.eevee.gi_cache_info
|
||||||
|
if cache_info:
|
||||||
|
col.label(text=cache_info)
|
||||||
|
|
||||||
|
col.prop(props, "gi_auto_bake")
|
||||||
|
|
||||||
|
|
||||||
class RENDER_PT_eevee_indirect_lighting_display(RenderButtonsPanel, Panel):
|
class RENDER_PT_eevee_indirect_lighting_display(RenderButtonsPanel, Panel):
|
||||||
bl_label = "Display"
|
bl_label = "Display"
|
||||||
bl_parent_id = "RENDER_PT_eevee_indirect_lighting"
|
bl_parent_id = "RENDER_PT_eevee_indirect_lighting"
|
||||||
|
@ -905,6 +933,7 @@ classes = (
|
||||||
RENDER_PT_eevee_next_shadows,
|
RENDER_PT_eevee_next_shadows,
|
||||||
RENDER_PT_eevee_indirect_lighting,
|
RENDER_PT_eevee_indirect_lighting,
|
||||||
RENDER_PT_eevee_indirect_lighting_display,
|
RENDER_PT_eevee_indirect_lighting_display,
|
||||||
|
RENDER_PT_eevee_next_indirect_lighting,
|
||||||
RENDER_PT_eevee_film,
|
RENDER_PT_eevee_film,
|
||||||
RENDER_PT_eevee_next_film,
|
RENDER_PT_eevee_next_film,
|
||||||
|
|
||||||
|
|
|
@ -146,6 +146,7 @@ set(SRC
|
||||||
engines/eevee_next/eevee_instance.cc
|
engines/eevee_next/eevee_instance.cc
|
||||||
engines/eevee_next/eevee_irradiance_cache.cc
|
engines/eevee_next/eevee_irradiance_cache.cc
|
||||||
engines/eevee_next/eevee_light.cc
|
engines/eevee_next/eevee_light.cc
|
||||||
|
engines/eevee_next/eevee_lightcache.cc
|
||||||
engines/eevee_next/eevee_material.cc
|
engines/eevee_next/eevee_material.cc
|
||||||
engines/eevee_next/eevee_motion_blur.cc
|
engines/eevee_next/eevee_motion_blur.cc
|
||||||
engines/eevee_next/eevee_pipeline.cc
|
engines/eevee_next/eevee_pipeline.cc
|
||||||
|
|
|
@ -0,0 +1,218 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
|
||||||
|
/** \file
|
||||||
|
* \ingroup eevee
|
||||||
|
*
|
||||||
|
* Contains everything about light baking.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "DRW_render.h"
|
||||||
|
|
||||||
|
#include "BKE_global.h"
|
||||||
|
|
||||||
|
#include "BLI_endian_switch.h"
|
||||||
|
#include "BLI_threads.h"
|
||||||
|
|
||||||
|
#include "DEG_depsgraph_build.h"
|
||||||
|
#include "DEG_depsgraph_query.h"
|
||||||
|
|
||||||
|
#include "BKE_object.h"
|
||||||
|
|
||||||
|
#include "DNA_collection_types.h"
|
||||||
|
#include "DNA_lightprobe_types.h"
|
||||||
|
|
||||||
|
#include "PIL_time.h"
|
||||||
|
|
||||||
|
#include "eevee_lightcache.h"
|
||||||
|
|
||||||
|
#include "GPU_capabilities.h"
|
||||||
|
#include "GPU_context.h"
|
||||||
|
|
||||||
|
#include "WM_api.h"
|
||||||
|
#include "WM_types.h"
|
||||||
|
|
||||||
|
#include "BLO_read_write.h"
|
||||||
|
|
||||||
|
#include "wm_window.h"
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------- */
|
||||||
|
/** \name Light Probe Baking
|
||||||
|
* \{ */
|
||||||
|
|
||||||
|
/* TODO: should be replace by a more elegant alternative. */
|
||||||
|
extern void DRW_opengl_context_enable(void);
|
||||||
|
extern void DRW_opengl_context_disable(void);
|
||||||
|
|
||||||
|
extern void DRW_opengl_render_context_enable(void *re_gl_context);
|
||||||
|
extern void DRW_opengl_render_context_disable(void *re_gl_context);
|
||||||
|
extern void DRW_gpu_render_context_enable(void *re_gpu_context);
|
||||||
|
extern void DRW_gpu_render_context_disable(void *re_gpu_context);
|
||||||
|
|
||||||
|
namespace blender::eevee {
|
||||||
|
|
||||||
|
class LightBake {
|
||||||
|
private:
|
||||||
|
Depsgraph *depsgraph_;
|
||||||
|
|
||||||
|
/** Scene frame to evaluate the depsgraph at. */
|
||||||
|
int frame_;
|
||||||
|
/** Milliseconds. Delay the start of the baking to not slowdown interactions (TODO: remove). */
|
||||||
|
int delay_ms_;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If running in parallel (in a separate thread), use this context.
|
||||||
|
* Created on main thread but first bound in worker thread.
|
||||||
|
*/
|
||||||
|
void *gl_context_ = nullptr;
|
||||||
|
/** GPUContext associated to `gl_context_`. Created in the worker thread. */
|
||||||
|
void *gpu_context_ = nullptr;
|
||||||
|
|
||||||
|
public:
|
||||||
|
LightBake(struct Main *bmain,
|
||||||
|
struct ViewLayer *view_layer,
|
||||||
|
struct Scene *scene,
|
||||||
|
bool run_as_job,
|
||||||
|
int frame,
|
||||||
|
int delay_ms = 0)
|
||||||
|
: depsgraph_(DEG_graph_new(bmain, scene, view_layer, DAG_EVAL_RENDER)),
|
||||||
|
frame_(frame),
|
||||||
|
delay_ms_(delay_ms)
|
||||||
|
{
|
||||||
|
BLI_assert(BLI_thread_is_main());
|
||||||
|
if (run_as_job && !GPU_use_main_context_workaround()) {
|
||||||
|
/* This needs to happen in main thread. */
|
||||||
|
gl_context_ = WM_opengl_context_create();
|
||||||
|
wm_window_reset_drawable();
|
||||||
|
}
|
||||||
|
std::cout << "Create" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
~LightBake()
|
||||||
|
{
|
||||||
|
BLI_assert(BLI_thread_is_main());
|
||||||
|
std::cout << "Delete" << std::endl;
|
||||||
|
DEG_graph_free(depsgraph_);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called from main thread.
|
||||||
|
* Copy result to original scene data.
|
||||||
|
* Note that since this is in the main thread, the viewport cannot be using the light cache.
|
||||||
|
* So there is no race condition here.
|
||||||
|
*/
|
||||||
|
void update()
|
||||||
|
{
|
||||||
|
BLI_assert(BLI_thread_is_main());
|
||||||
|
std::cout << "update" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called from worker thread.
|
||||||
|
*/
|
||||||
|
void run(bool *stop = nullptr, bool *do_update = nullptr, float *progress = nullptr)
|
||||||
|
{
|
||||||
|
UNUSED_VARS(stop, do_update, progress);
|
||||||
|
|
||||||
|
DEG_graph_relations_update(depsgraph_);
|
||||||
|
DEG_evaluate_on_framechange(depsgraph_, frame_);
|
||||||
|
|
||||||
|
PIL_sleep_ms(1000);
|
||||||
|
std::cout << "run" << std::endl;
|
||||||
|
|
||||||
|
delete_resources();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void context_enable()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void context_disable()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete the engine instance and the optional contexts.
|
||||||
|
* This needs to run on the worker thread because the OpenGL context can only be ever bound to a
|
||||||
|
* single thread (because of some driver implementation), and the resources (textures,
|
||||||
|
* buffers,...) need to be freed with the right context bound.
|
||||||
|
*/
|
||||||
|
void delete_resources()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace blender::eevee
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
using namespace blender::eevee;
|
||||||
|
|
||||||
|
wmJob *EEVEE_NEXT_lightbake_job_create(struct wmWindowManager *wm,
|
||||||
|
struct wmWindow *win,
|
||||||
|
struct Main *bmain,
|
||||||
|
struct ViewLayer *view_layer,
|
||||||
|
struct Scene *scene,
|
||||||
|
int delay_ms,
|
||||||
|
int frame)
|
||||||
|
{
|
||||||
|
/* Do not bake if there is a render going on. */
|
||||||
|
if (WM_jobs_test(wm, scene, WM_JOB_TYPE_RENDER)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stop existing baking job. */
|
||||||
|
WM_jobs_stop(wm, nullptr, (void *)EEVEE_NEXT_lightbake_job);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
LightBake *bake = new LightBake(bmain, view_layer, scene, true, frame, delay_ms);
|
||||||
|
|
||||||
|
WM_jobs_customdata_set(wm_job, bake, EEVEE_NEXT_lightbake_job_data_free);
|
||||||
|
WM_jobs_timer(wm_job, 0.4, NC_SCENE | NA_EDITED, 0);
|
||||||
|
WM_jobs_callbacks(wm_job,
|
||||||
|
EEVEE_NEXT_lightbake_job,
|
||||||
|
nullptr,
|
||||||
|
EEVEE_NEXT_lightbake_update,
|
||||||
|
EEVEE_NEXT_lightbake_update);
|
||||||
|
|
||||||
|
G.is_break = false;
|
||||||
|
|
||||||
|
return wm_job;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *EEVEE_NEXT_lightbake_job_data_alloc(struct Main *bmain,
|
||||||
|
struct ViewLayer *view_layer,
|
||||||
|
struct Scene *scene,
|
||||||
|
bool run_as_job,
|
||||||
|
int frame)
|
||||||
|
{
|
||||||
|
/* This should only be used for exec job. Eventually, remove `run_as_job` parameter later. */
|
||||||
|
BLI_assert(run_as_job == false);
|
||||||
|
LightBake *bake = new LightBake(bmain, view_layer, scene, run_as_job, frame);
|
||||||
|
/* TODO(fclem): Can remove this cast once we remove the previous EEVEE light cache. */
|
||||||
|
return reinterpret_cast<void *>(bake);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EEVEE_NEXT_lightbake_job_data_free(void *job_data)
|
||||||
|
{
|
||||||
|
delete reinterpret_cast<LightBake *>(job_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EEVEE_NEXT_lightbake_update(void *job_data)
|
||||||
|
{
|
||||||
|
reinterpret_cast<LightBake *>(job_data)->update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EEVEE_NEXT_lightbake_job(void *job_data, bool *stop, bool *do_update, float *progress)
|
||||||
|
{
|
||||||
|
reinterpret_cast<LightBake *>(job_data)->run(stop, do_update, progress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \} */
|
|
@ -0,0 +1,70 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
|
||||||
|
/** \file
|
||||||
|
* \ingroup eevee
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** Opaque type hiding eevee::LightBake. */
|
||||||
|
typedef struct EEVEE_NEXT_LightBake EEVEE_NEXT_LightBake;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the job description.
|
||||||
|
* This is called for async (modal) bake operator.
|
||||||
|
* The actual work will be done by `EEVEE_NEXT_lightbake_job()`.
|
||||||
|
* Will internally call `EEVEE_NEXT_lightbake_job_data_alloc()` or reuse data from an already
|
||||||
|
* existing baking job.
|
||||||
|
* IMPORTANT: Must run on the main thread because of potential GPUContext creation.
|
||||||
|
*/
|
||||||
|
struct wmJob *EEVEE_NEXT_lightbake_job_create(struct wmWindowManager *wm,
|
||||||
|
struct wmWindow *win,
|
||||||
|
struct Main *bmain,
|
||||||
|
struct ViewLayer *view_layer,
|
||||||
|
struct Scene *scene,
|
||||||
|
int delay_ms,
|
||||||
|
int frame);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate dependency graph and job description (EEVEE_NEXT_LightBake).
|
||||||
|
* Dependency graph evaluation does *not* happen here. It is delayed until
|
||||||
|
* `EEVEE_NEXT_lightbake_job` runs.
|
||||||
|
* IMPORTANT: Must run on the main thread because of potential GPUContext creation.
|
||||||
|
* Return `EEVEE_NEXT_LightBake *` but cast to `void *` because of compatibility with existing
|
||||||
|
* EEVEE function.
|
||||||
|
*/
|
||||||
|
void *EEVEE_NEXT_lightbake_job_data_alloc(struct Main *bmain,
|
||||||
|
struct ViewLayer *view_layer,
|
||||||
|
struct Scene *scene,
|
||||||
|
bool run_as_job,
|
||||||
|
int frame);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free the job data.
|
||||||
|
* NOTE: Does not free the GPUContext. This is the responsibility of `EEVEE_NEXT_lightbake_job()`
|
||||||
|
*/
|
||||||
|
void EEVEE_NEXT_lightbake_job_data_free(void *job_data /* EEVEE_NEXT_LightBake */);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback for updating original scene light cache with bake result.
|
||||||
|
* Run by the job system for each update step and the finish step.
|
||||||
|
* This is called manually by `EEVEE_NEXT_lightbake_job()` if not run from a job.
|
||||||
|
*/
|
||||||
|
void EEVEE_NEXT_lightbake_update(void *job_data /* EEVEE_NEXT_LightBake */);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do the full light baking for all samples.
|
||||||
|
* Will call `EEVEE_NEXT_lightbake_update()` on finish.
|
||||||
|
*/
|
||||||
|
void EEVEE_NEXT_lightbake_job(void *job_data /* EEVEE_NEXT_LightBake */,
|
||||||
|
bool *stop,
|
||||||
|
bool *do_update,
|
||||||
|
float *progress);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -83,6 +83,7 @@
|
||||||
#include "RE_pipeline.h"
|
#include "RE_pipeline.h"
|
||||||
|
|
||||||
#include "engines/eevee/eevee_lightcache.h"
|
#include "engines/eevee/eevee_lightcache.h"
|
||||||
|
#include "engines/eevee_next/eevee_lightcache.h"
|
||||||
|
|
||||||
#include "render_intern.hh" /* own include */
|
#include "render_intern.hh" /* own include */
|
||||||
|
|
||||||
|
@ -1393,15 +1394,23 @@ static int light_cache_bake_exec(bContext *C, wmOperator *op)
|
||||||
|
|
||||||
G.is_break = false;
|
G.is_break = false;
|
||||||
|
|
||||||
|
RenderEngineType *engine_type = RE_engines_find(scene->r.engine);
|
||||||
|
bool use_eevee_next = STREQ(engine_type->idname, "BLENDER_EEVEE_NEXT");
|
||||||
|
|
||||||
/* TODO: abort if selected engine is not eevee. */
|
/* TODO: abort if selected engine is not eevee. */
|
||||||
void *rj = EEVEE_lightbake_job_data_alloc(bmain, view_layer, scene, false, scene->r.cfra);
|
void *rj = ((use_eevee_next) ?
|
||||||
|
EEVEE_NEXT_lightbake_job_data_alloc :
|
||||||
|
EEVEE_lightbake_job_data_alloc)(bmain, view_layer, scene, false, scene->r.cfra);
|
||||||
|
|
||||||
light_cache_bake_tag_cache(scene, op);
|
light_cache_bake_tag_cache(scene, op);
|
||||||
|
|
||||||
bool stop = false, do_update;
|
bool stop = false, do_update;
|
||||||
float progress; /* Not actually used. */
|
float progress; /* Not actually used. */
|
||||||
EEVEE_lightbake_job(rj, &stop, &do_update, &progress);
|
/* Do the job. */
|
||||||
EEVEE_lightbake_job_data_free(rj);
|
((use_eevee_next) ? EEVEE_NEXT_lightbake_job :
|
||||||
|
EEVEE_lightbake_job)(rj, &stop, &do_update, &progress);
|
||||||
|
/* Free baking data. Result is already stored in the scene data. */
|
||||||
|
((use_eevee_next) ? EEVEE_NEXT_lightbake_job_data_free : EEVEE_lightbake_job_data_free)(rj);
|
||||||
|
|
||||||
/* No redraw needed, we leave state as we entered it. */
|
/* No redraw needed, we leave state as we entered it. */
|
||||||
ED_update_for_newframe(bmain, CTX_data_depsgraph_pointer(C));
|
ED_update_for_newframe(bmain, CTX_data_depsgraph_pointer(C));
|
||||||
|
@ -1420,7 +1429,11 @@ static int light_cache_bake_invoke(bContext *C, wmOperator *op, const wmEvent *
|
||||||
Scene *scene = CTX_data_scene(C);
|
Scene *scene = CTX_data_scene(C);
|
||||||
int delay = RNA_int_get(op->ptr, "delay");
|
int delay = RNA_int_get(op->ptr, "delay");
|
||||||
|
|
||||||
wmJob *wm_job = EEVEE_lightbake_job_create(
|
RenderEngineType *engine_type = RE_engines_find(scene->r.engine);
|
||||||
|
bool use_eevee_next = STREQ(engine_type->idname, "BLENDER_EEVEE_NEXT");
|
||||||
|
|
||||||
|
wmJob *wm_job = ((use_eevee_next) ? EEVEE_NEXT_lightbake_job_create :
|
||||||
|
EEVEE_lightbake_job_create)(
|
||||||
wm, win, bmain, view_layer, scene, delay, scene->r.cfra);
|
wm, win, bmain, view_layer, scene, delay, scene->r.cfra);
|
||||||
|
|
||||||
if (!wm_job) {
|
if (!wm_job) {
|
||||||
|
|
Loading…
Reference in New Issue