DRW: Deferred compilation initial implementation.
This commit is contained in:
parent
f14cbc0d07
commit
3a209c2857
|
@ -46,6 +46,7 @@ struct ViewContext;
|
|||
struct ViewportEngineData;
|
||||
struct View3D;
|
||||
struct rcti;
|
||||
struct GPUMaterial;
|
||||
struct GPUOffScreen;
|
||||
struct GPUViewport;
|
||||
struct RenderEngine;
|
||||
|
@ -136,4 +137,6 @@ void DRW_opengl_context_destroy(void);
|
|||
void DRW_opengl_context_enable(void);
|
||||
void DRW_opengl_context_disable(void);
|
||||
|
||||
void DRW_deferred_shader_remove(struct GPUMaterial *mat);
|
||||
|
||||
#endif /* __DRW_ENGINE_H__ */
|
||||
|
|
|
@ -630,8 +630,8 @@ struct GPUMaterial *EEVEE_material_world_lightprobe_get(struct Scene *scene, Wor
|
|||
if (mat != NULL) {
|
||||
return mat;
|
||||
}
|
||||
return GPU_material_from_nodetree(
|
||||
scene, wo->nodetree, &wo->gpumaterial, engine, options,
|
||||
return DRW_shader_create_from_world(
|
||||
scene, wo, engine, options,
|
||||
datatoc_background_vert_glsl, NULL, e_data.frag_shader_lib,
|
||||
SHADER_DEFINES "#define PROBE_CAPTURE\n");
|
||||
}
|
||||
|
@ -645,8 +645,8 @@ struct GPUMaterial *EEVEE_material_world_background_get(struct Scene *scene, Wor
|
|||
if (mat != NULL) {
|
||||
return mat;
|
||||
}
|
||||
return GPU_material_from_nodetree(
|
||||
scene, wo->nodetree, &wo->gpumaterial, engine, options,
|
||||
return DRW_shader_create_from_world(
|
||||
scene, wo, engine, options,
|
||||
datatoc_background_vert_glsl, NULL, e_data.frag_shader_lib,
|
||||
SHADER_DEFINES "#define WORLD_BACKGROUND\n");
|
||||
}
|
||||
|
@ -663,8 +663,8 @@ struct GPUMaterial *EEVEE_material_world_volume_get(struct Scene *scene, World *
|
|||
|
||||
char *defines = eevee_get_volume_defines(options);
|
||||
|
||||
mat = GPU_material_from_nodetree(
|
||||
scene, wo->nodetree, &wo->gpumaterial, engine, options,
|
||||
mat = DRW_shader_create_from_world(
|
||||
scene, wo, engine, options,
|
||||
datatoc_volumetric_vert_glsl, datatoc_volumetric_geom_glsl, e_data.volume_shader_lib,
|
||||
defines);
|
||||
|
||||
|
@ -698,8 +698,8 @@ struct GPUMaterial *EEVEE_material_mesh_get(
|
|||
|
||||
char *defines = eevee_get_defines(options);
|
||||
|
||||
mat = GPU_material_from_nodetree(
|
||||
scene, ma->nodetree, &ma->gpumaterial, engine, options,
|
||||
mat = DRW_shader_create_from_material(
|
||||
scene, ma, engine, options,
|
||||
datatoc_lit_surface_vert_glsl, NULL, e_data.frag_shader_lib,
|
||||
defines);
|
||||
|
||||
|
@ -720,8 +720,8 @@ struct GPUMaterial *EEVEE_material_mesh_volume_get(struct Scene *scene, Material
|
|||
|
||||
char *defines = eevee_get_volume_defines(options);
|
||||
|
||||
mat = GPU_material_from_nodetree(
|
||||
scene, ma->nodetree, &ma->gpumaterial, engine, options,
|
||||
mat = DRW_shader_create_from_material(
|
||||
scene, ma, engine, options,
|
||||
datatoc_volumetric_vert_glsl, datatoc_volumetric_geom_glsl, e_data.volume_shader_lib,
|
||||
defines);
|
||||
|
||||
|
@ -758,8 +758,8 @@ struct GPUMaterial *EEVEE_material_mesh_depth_get(
|
|||
e_data.frag_shader_lib,
|
||||
datatoc_prepass_frag_glsl);
|
||||
|
||||
mat = GPU_material_from_nodetree(
|
||||
scene, ma->nodetree, &ma->gpumaterial, engine, options,
|
||||
mat = DRW_shader_create_from_material(
|
||||
scene, ma, engine, options,
|
||||
(is_shadow) ? datatoc_shadow_vert_glsl : datatoc_lit_surface_vert_glsl,
|
||||
(is_shadow) ? datatoc_shadow_geom_glsl : NULL,
|
||||
frag_str,
|
||||
|
@ -786,8 +786,8 @@ struct GPUMaterial *EEVEE_material_hair_get(
|
|||
|
||||
char *defines = eevee_get_defines(options);
|
||||
|
||||
mat = GPU_material_from_nodetree(
|
||||
scene, ma->nodetree, &ma->gpumaterial, engine, options,
|
||||
mat = DRW_shader_create_from_material(
|
||||
scene, ma, engine, options,
|
||||
datatoc_lit_surface_vert_glsl, NULL, e_data.frag_shader_lib,
|
||||
defines);
|
||||
|
||||
|
@ -883,17 +883,24 @@ void EEVEE_materials_cache_init(EEVEE_Data *vedata)
|
|||
col = &wo->horr;
|
||||
|
||||
if (wo->use_nodes && wo->nodetree) {
|
||||
static float error_col[3] = {1.0f, 0.0f, 1.0f};
|
||||
static float compile_col[3] = {0.5f, 0.5f, 0.5f};
|
||||
struct GPUMaterial *gpumat = EEVEE_material_world_background_get(scene, wo);
|
||||
grp = DRW_shgroup_material_create(gpumat, psl->background_pass);
|
||||
|
||||
if (grp) {
|
||||
DRW_shgroup_uniform_float(grp, "backgroundAlpha", &stl->g_data->background_alpha, 1);
|
||||
DRW_shgroup_call_add(grp, geom, NULL);
|
||||
}
|
||||
else {
|
||||
/* Shader failed : pink background */
|
||||
static float pink[3] = {1.0f, 0.0f, 1.0f};
|
||||
col = pink;
|
||||
switch (GPU_material_status(gpumat)) {
|
||||
case GPU_MAT_SUCCESS:
|
||||
grp = DRW_shgroup_material_create(gpumat, psl->background_pass);
|
||||
DRW_shgroup_uniform_float(grp, "backgroundAlpha", &stl->g_data->background_alpha, 1);
|
||||
DRW_shgroup_call_add(grp, geom, NULL);
|
||||
break;
|
||||
case GPU_MAT_QUEUED:
|
||||
/* TODO Bypass probe compilation. */
|
||||
col = compile_col;
|
||||
break;
|
||||
case GPU_MAT_FAILED:
|
||||
default:
|
||||
col = error_col;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -268,6 +268,12 @@ struct GPUShader *DRW_shader_create_2D(const char *frag, const char *defines);
|
|||
struct GPUShader *DRW_shader_create_3D(const char *frag, const char *defines);
|
||||
struct GPUShader *DRW_shader_create_fullscreen(const char *frag, const char *defines);
|
||||
struct GPUShader *DRW_shader_create_3D_depth_only(void);
|
||||
struct GPUMaterial *DRW_shader_create_from_world(
|
||||
struct Scene *scene, struct World *wo, const void *engine_type, int options,
|
||||
const char *vert, const char *geom, const char *frag_lib, const char *defines);
|
||||
struct GPUMaterial *DRW_shader_create_from_material(
|
||||
struct Scene *scene, struct Material *ma, const void *engine_type, int options,
|
||||
const char *vert, const char *geom, const char *frag_lib, const char *defines);
|
||||
void DRW_shader_free(struct GPUShader *shader);
|
||||
#define DRW_SHADER_FREE_SAFE(shader) do { \
|
||||
if (shader != NULL) { \
|
||||
|
|
|
@ -1957,6 +1957,7 @@ void DRW_opengl_context_create(void)
|
|||
|
||||
immDeactivate();
|
||||
/* This changes the active context. */
|
||||
DRW_deferred_compiler_init();
|
||||
DST.ogl_context = WM_opengl_context_create();
|
||||
/* Be sure to create gawain.context too. */
|
||||
DST.gwn_context = GWN_context_create();
|
||||
|
@ -1971,6 +1972,7 @@ void DRW_opengl_context_destroy(void)
|
|||
{
|
||||
BLI_assert(BLI_thread_is_main());
|
||||
if (DST.ogl_context != NULL) {
|
||||
DRW_deferred_compiler_exit();
|
||||
WM_opengl_context_activate(DST.ogl_context);
|
||||
GWN_context_active_set(DST.gwn_context);
|
||||
GWN_context_discard(DST.gwn_context);
|
||||
|
|
|
@ -356,4 +356,7 @@ void *drw_viewport_engine_data_ensure(void *engine_type);
|
|||
|
||||
void drw_state_set(DRWState state);
|
||||
|
||||
void DRW_deferred_compiler_init(void);
|
||||
void DRW_deferred_compiler_exit(void);
|
||||
|
||||
#endif /* __DRAW_MANAGER_H__ */
|
||||
|
|
|
@ -25,15 +25,181 @@
|
|||
|
||||
#include "draw_manager.h"
|
||||
|
||||
#include "DNA_world_types.h"
|
||||
#include "DNA_material_types.h"
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_string_utils.h"
|
||||
#include "BLI_threads.h"
|
||||
#include "BLI_task.h"
|
||||
|
||||
#include "GPU_shader.h"
|
||||
#include "GPU_material.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
|
||||
extern char datatoc_gpu_shader_2D_vert_glsl[];
|
||||
extern char datatoc_gpu_shader_3D_vert_glsl[];
|
||||
extern char datatoc_gpu_shader_fullscreen_vert_glsl[];
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
/** \name Deferred Compilation (DRW_deferred)
|
||||
*
|
||||
* Since compiling shader can take a long time, we do it in a non blocking
|
||||
* manner in another thread.
|
||||
*
|
||||
* \{ */
|
||||
|
||||
typedef struct DRWDeferredShader {
|
||||
struct DRWDeferredShader *prev, *next;
|
||||
|
||||
GPUMaterial *mat;
|
||||
char *vert, *geom, *frag, *defs;
|
||||
|
||||
ThreadMutex compilation_mutex;
|
||||
} DRWDeferredShader;
|
||||
|
||||
typedef struct DRWShaderCompiler {
|
||||
ListBase queue; /* DRWDeferredShader */
|
||||
ThreadMutex list_mutex;
|
||||
|
||||
DRWDeferredShader *mat_compiling;
|
||||
ThreadMutex compilation_mutex;
|
||||
|
||||
TaskScheduler *task_scheduler; /* NULL if nothing is running. */
|
||||
TaskPool *task_pool;
|
||||
|
||||
void *ogl_context;
|
||||
} DRWShaderCompiler;
|
||||
|
||||
static DRWShaderCompiler DSC = {{NULL}};
|
||||
|
||||
static void drw_deferred_shader_free(DRWDeferredShader *dsh)
|
||||
{
|
||||
/* Make sure it is not queued before freeing. */
|
||||
BLI_assert(BLI_findindex(&DSC.queue, dsh) == -1);
|
||||
|
||||
MEM_SAFE_FREE(dsh->vert);
|
||||
MEM_SAFE_FREE(dsh->geom);
|
||||
MEM_SAFE_FREE(dsh->frag);
|
||||
MEM_SAFE_FREE(dsh->defs);
|
||||
|
||||
MEM_freeN(dsh);
|
||||
}
|
||||
|
||||
static void drw_deferred_shader_compilation_exec(TaskPool * __restrict UNUSED(pool), void *UNUSED(taskdata), int UNUSED(threadid))
|
||||
{
|
||||
WM_opengl_context_activate(DSC.ogl_context);
|
||||
|
||||
while (true) {
|
||||
BLI_mutex_lock(&DSC.list_mutex);
|
||||
DSC.mat_compiling = BLI_pophead(&DSC.queue);
|
||||
if (DSC.mat_compiling == NULL) {
|
||||
break;
|
||||
}
|
||||
BLI_mutex_lock(&DSC.compilation_mutex);
|
||||
BLI_mutex_unlock(&DSC.list_mutex);
|
||||
|
||||
/* Do the compilation. */
|
||||
GPU_material_generate_pass(
|
||||
DSC.mat_compiling->mat,
|
||||
DSC.mat_compiling->vert,
|
||||
DSC.mat_compiling->geom,
|
||||
DSC.mat_compiling->frag,
|
||||
DSC.mat_compiling->defs);
|
||||
|
||||
BLI_mutex_unlock(&DSC.compilation_mutex);
|
||||
|
||||
drw_deferred_shader_free(DSC.mat_compiling);
|
||||
}
|
||||
|
||||
WM_opengl_context_release(DSC.ogl_context);
|
||||
BLI_mutex_unlock(&DSC.list_mutex);
|
||||
}
|
||||
|
||||
static void drw_deferred_shader_add(
|
||||
GPUMaterial *mat, const char *vert, const char *geom, const char *frag_lib, const char *defines)
|
||||
{
|
||||
if (DRW_state_is_image_render()) {
|
||||
/* Do not deferre the compilation if we are rendering for image. */
|
||||
GPU_material_generate_pass(mat, vert, geom, frag_lib, defines);
|
||||
return;
|
||||
}
|
||||
|
||||
DRWDeferredShader *dsh = MEM_callocN(sizeof(DRWDeferredShader), "Deferred Shader");
|
||||
|
||||
dsh->mat = mat;
|
||||
if (vert) dsh->vert = BLI_strdup(vert);
|
||||
if (geom) dsh->geom = BLI_strdup(geom);
|
||||
if (frag_lib) dsh->frag = BLI_strdup(frag_lib);
|
||||
if (defines) dsh->defs = BLI_strdup(defines);
|
||||
|
||||
BLI_mutex_lock(&DSC.list_mutex);
|
||||
BLI_addtail(&DSC.queue, dsh);
|
||||
if (DSC.mat_compiling == NULL) {
|
||||
/* Set value so that other threads do not start a new task. */
|
||||
DSC.mat_compiling = (void *)1;
|
||||
|
||||
if (DSC.task_scheduler == NULL) {
|
||||
DSC.task_scheduler = BLI_task_scheduler_create(1);
|
||||
DSC.task_pool = BLI_task_pool_create_background(DSC.task_scheduler, NULL);
|
||||
}
|
||||
BLI_task_pool_push(DSC.task_pool, drw_deferred_shader_compilation_exec, NULL, false, TASK_PRIORITY_LOW);
|
||||
}
|
||||
BLI_mutex_unlock(&DSC.list_mutex);
|
||||
}
|
||||
|
||||
void DRW_deferred_shader_remove(GPUMaterial *mat)
|
||||
{
|
||||
BLI_mutex_lock(&DSC.list_mutex);
|
||||
DRWDeferredShader *dsh = (DRWDeferredShader *)BLI_findptr(&DSC.queue, mat, offsetof(DRWDeferredShader, mat));
|
||||
if (dsh) {
|
||||
BLI_remlink(&DSC.queue, dsh);
|
||||
}
|
||||
if (DSC.mat_compiling != NULL) {
|
||||
if (DSC.mat_compiling->mat == mat) {
|
||||
/* Wait for compilation to finish */
|
||||
BLI_mutex_lock(&DSC.compilation_mutex);
|
||||
BLI_mutex_unlock(&DSC.compilation_mutex);
|
||||
}
|
||||
}
|
||||
BLI_mutex_unlock(&DSC.list_mutex);
|
||||
if (dsh) {
|
||||
drw_deferred_shader_free(dsh);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void drw_deferred_compiler_finish(void)
|
||||
{
|
||||
if (DSC.task_scheduler != NULL) {
|
||||
BLI_task_pool_work_and_wait(DSC.task_pool);
|
||||
BLI_task_pool_free(DSC.task_pool);
|
||||
BLI_task_scheduler_free(DSC.task_scheduler);
|
||||
DSC.task_scheduler = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void DRW_deferred_compiler_init(void)
|
||||
{
|
||||
BLI_mutex_init(&DSC.list_mutex);
|
||||
BLI_mutex_init(&DSC.compilation_mutex);
|
||||
DSC.ogl_context = WM_opengl_context_create();
|
||||
}
|
||||
|
||||
void DRW_deferred_compiler_exit(void)
|
||||
{
|
||||
drw_deferred_compiler_finish();
|
||||
WM_opengl_context_dispose(DSC.ogl_context);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
GPUShader *DRW_shader_create(const char *vert, const char *geom, const char *frag, const char *defines)
|
||||
{
|
||||
return GPU_shader_create(vert, frag, geom, NULL, defines);
|
||||
|
@ -84,6 +250,32 @@ GPUShader *DRW_shader_create_3D_depth_only(void)
|
|||
return GPU_shader_get_builtin_shader(GPU_SHADER_3D_DEPTH_ONLY);
|
||||
}
|
||||
|
||||
GPUMaterial *DRW_shader_create_from_world(
|
||||
struct Scene *scene, World *wo, const void *engine_type, int options,
|
||||
const char *vert, const char *geom, const char *frag_lib, const char *defines)
|
||||
{
|
||||
GPUMaterial *mat = GPU_material_from_nodetree(
|
||||
scene, wo->nodetree, &wo->gpumaterial, engine_type, options,
|
||||
vert, geom, frag_lib, defines, true);
|
||||
|
||||
drw_deferred_shader_add(mat, vert, geom, frag_lib, defines);
|
||||
|
||||
return mat;
|
||||
}
|
||||
|
||||
GPUMaterial *DRW_shader_create_from_material(
|
||||
struct Scene *scene, Material *ma, const void *engine_type, int options,
|
||||
const char *vert, const char *geom, const char *frag_lib, const char *defines)
|
||||
{
|
||||
GPUMaterial *mat = GPU_material_from_nodetree(
|
||||
scene, ma->nodetree, &ma->gpumaterial, engine_type, options,
|
||||
vert, geom, frag_lib, defines, true);
|
||||
|
||||
drw_deferred_shader_add(mat, vert, geom, frag_lib, defines);
|
||||
|
||||
return mat;
|
||||
}
|
||||
|
||||
void DRW_shader_free(GPUShader *shader)
|
||||
{
|
||||
GPU_shader_free(shader);
|
||||
|
|
|
@ -144,6 +144,11 @@ typedef struct GPUNodeStack {
|
|||
bool end;
|
||||
} GPUNodeStack;
|
||||
|
||||
typedef enum GPUMaterialSatus {
|
||||
GPU_MAT_FAILED = 0,
|
||||
GPU_MAT_QUEUED,
|
||||
GPU_MAT_SUCCESS,
|
||||
} GPUMaterialSatus;
|
||||
|
||||
#define GPU_DYNAMIC_GROUP_FROM_TYPE(f) ((f) & 0xFFFF0000)
|
||||
|
||||
|
@ -245,9 +250,11 @@ GPUMaterial *GPU_material_from_nodetree_find(
|
|||
struct ListBase *gpumaterials, const void *engine_type, int options);
|
||||
GPUMaterial *GPU_material_from_nodetree(
|
||||
struct Scene *scene, struct bNodeTree *ntree, struct ListBase *gpumaterials, const void *engine_type, int options,
|
||||
const char *vert_code, const char *geom_code, const char *frag_lib, const char *defines);
|
||||
const char *vert_code, const char *geom_code, const char *frag_lib, const char *defines, bool deferred);
|
||||
GPUMaterial *GPU_material_from_blender(struct Scene *scene, struct Material *ma, bool use_opensubdiv);
|
||||
GPUMaterial *GPU_material_matcap(struct Scene *scene, struct Material *ma, bool use_opensubdiv);
|
||||
void GPU_material_generate_pass(
|
||||
GPUMaterial *mat, const char *vert_code, const char *geom_code, const char *frag_lib, const char *defines);
|
||||
void GPU_material_free(struct ListBase *gpumaterial);
|
||||
|
||||
void GPU_materials_free(void);
|
||||
|
@ -263,6 +270,7 @@ bool GPU_material_bound(GPUMaterial *material);
|
|||
struct Scene *GPU_material_scene(GPUMaterial *material);
|
||||
GPUMatType GPU_Material_get_type(GPUMaterial *material);
|
||||
struct GPUPass *GPU_material_get_pass(GPUMaterial *material);
|
||||
GPUMaterialSatus GPU_material_status(GPUMaterial *mat);
|
||||
|
||||
struct GPUUniformBuffer *GPU_material_get_uniform_buffer(GPUMaterial *material);
|
||||
void GPU_material_create_uniform_buffer(GPUMaterial *material, struct ListBase *inputs);
|
||||
|
|
|
@ -1720,7 +1720,7 @@ static void gpu_nodes_free(ListBase *nodes)
|
|||
|
||||
/* vertex attributes */
|
||||
|
||||
static void gpu_nodes_get_vertex_attributes(ListBase *nodes, GPUVertexAttribs *attribs)
|
||||
void GPU_nodes_get_vertex_attributes(ListBase *nodes, GPUVertexAttribs *attribs)
|
||||
{
|
||||
GPUNode *node;
|
||||
GPUInput *input;
|
||||
|
@ -2052,7 +2052,7 @@ static void gpu_nodes_tag(GPUNodeLink *link)
|
|||
gpu_nodes_tag(input->link);
|
||||
}
|
||||
|
||||
static void gpu_nodes_prune(ListBase *nodes, GPUNodeLink *outlink)
|
||||
void GPU_nodes_prune(ListBase *nodes, GPUNodeLink *outlink)
|
||||
{
|
||||
GPUNode *node, *next;
|
||||
|
||||
|
@ -2084,9 +2084,9 @@ GPUPass *GPU_generate_pass_new(
|
|||
char *vertexcode, *geometrycode, *fragmentcode;
|
||||
|
||||
/* prune unused nodes */
|
||||
gpu_nodes_prune(nodes, frag_outlink);
|
||||
GPU_nodes_prune(nodes, frag_outlink);
|
||||
|
||||
gpu_nodes_get_vertex_attributes(nodes, attribs);
|
||||
GPU_nodes_get_vertex_attributes(nodes, attribs);
|
||||
|
||||
/* generate code and compile with opengl */
|
||||
fragmentgen = code_generate_fragment(material, nodes, frag_outlink->output, true);
|
||||
|
@ -2135,7 +2135,6 @@ GPUPass *GPU_generate_pass_new(
|
|||
|
||||
/* extract dynamic inputs and throw away nodes */
|
||||
gpu_nodes_extract_dynamic_inputs_new(pass, nodes);
|
||||
gpu_nodes_free(nodes);
|
||||
|
||||
MEM_freeN(fragmentgen);
|
||||
MEM_freeN(vertexgen);
|
||||
|
@ -2162,9 +2161,9 @@ GPUPass *GPU_generate_pass(
|
|||
#endif
|
||||
|
||||
/* prune unused nodes */
|
||||
gpu_nodes_prune(nodes, outlink);
|
||||
GPU_nodes_prune(nodes, outlink);
|
||||
|
||||
gpu_nodes_get_vertex_attributes(nodes, attribs);
|
||||
GPU_nodes_get_vertex_attributes(nodes, attribs);
|
||||
gpu_nodes_get_builtin_flag(nodes, builtins);
|
||||
|
||||
/* generate code and compile with opengl */
|
||||
|
|
|
@ -183,6 +183,9 @@ GPUPass *GPU_generate_pass(
|
|||
|
||||
struct GPUShader *GPU_pass_shader(GPUPass *pass);
|
||||
|
||||
void GPU_nodes_get_vertex_attributes(ListBase *nodes, struct GPUVertexAttribs *attribs);
|
||||
void GPU_nodes_prune(ListBase *nodes, struct GPUNodeLink *outlink);
|
||||
|
||||
void GPU_pass_bind(GPUPass *pass, double time, int mipmap);
|
||||
void GPU_pass_update_uniforms(GPUPass *pass);
|
||||
void GPU_pass_unbind(GPUPass *pass);
|
||||
|
|
|
@ -68,6 +68,8 @@
|
|||
#include "GPU_texture.h"
|
||||
#include "GPU_uniformbuffer.h"
|
||||
|
||||
#include "DRW_engine.h"
|
||||
|
||||
#include "gpu_codegen.h"
|
||||
#include "gpu_lamp_private.h"
|
||||
|
||||
|
@ -103,6 +105,7 @@ struct GPUMaterial {
|
|||
/* material for mesh surface, worlds or something else.
|
||||
* some code generation is done differently depending on the use case */
|
||||
int type; /* DEPRECATED */
|
||||
GPUMaterialSatus status;
|
||||
|
||||
const void *engine_type; /* attached engine type */
|
||||
int options; /* to identify shader variations (shadow, probe, world background...) */
|
||||
|
@ -142,7 +145,10 @@ struct GPUMaterial {
|
|||
*/
|
||||
int domain;
|
||||
|
||||
/* Used by 2.8 pipeline */
|
||||
GPUUniformBuffer *ubo; /* UBOs for shader uniforms. */
|
||||
|
||||
/* Eevee SSS */
|
||||
GPUUniformBuffer *sss_profile; /* UBO containing SSS profile. */
|
||||
GPUTexture *sss_tex_profile; /* Texture containing SSS profile. */
|
||||
float *sss_radii; /* UBO containing SSS profile. */
|
||||
|
@ -221,6 +227,8 @@ static int gpu_material_construct_end(GPUMaterial *material, const char *passnam
|
|||
material->is_opensubdiv,
|
||||
GPU_material_use_new_shading_nodes(material));
|
||||
|
||||
material->status = (material->pass) ? GPU_MAT_SUCCESS : GPU_MAT_FAILED;
|
||||
|
||||
if (!material->pass)
|
||||
return 0;
|
||||
|
||||
|
@ -270,6 +278,11 @@ void GPU_material_free(ListBase *gpumaterial)
|
|||
for (LinkData *link = gpumaterial->first; link; link = link->next) {
|
||||
GPUMaterial *material = link->data;
|
||||
|
||||
/* Cancel / wait any pending lazy compilation. */
|
||||
DRW_deferred_shader_remove(material);
|
||||
|
||||
GPU_pass_free_nodes(&material->nodes);
|
||||
|
||||
if (material->pass)
|
||||
GPU_pass_free(material->pass);
|
||||
|
||||
|
@ -829,6 +842,12 @@ void gpu_material_add_node(GPUMaterial *material, GPUNode *node)
|
|||
BLI_addtail(&material->nodes, node);
|
||||
}
|
||||
|
||||
/* Return true if the material compilation has not yet begin or begin. */
|
||||
GPUMaterialSatus GPU_material_status(GPUMaterial *mat)
|
||||
{
|
||||
return mat->status;
|
||||
}
|
||||
|
||||
/* Code generation */
|
||||
|
||||
bool GPU_material_do_color_management(GPUMaterial *mat)
|
||||
|
@ -2490,10 +2509,8 @@ GPUMaterial *GPU_material_from_nodetree_find(
|
|||
*/
|
||||
GPUMaterial *GPU_material_from_nodetree(
|
||||
Scene *scene, struct bNodeTree *ntree, ListBase *gpumaterials, const void *engine_type, int options,
|
||||
const char *vert_code, const char *geom_code, const char *frag_lib, const char *defines)
|
||||
const char *vert_code, const char *geom_code, const char *frag_lib, const char *defines, bool deferred)
|
||||
{
|
||||
GPUMaterial *mat;
|
||||
GPUNodeLink *outlink;
|
||||
LinkData *link;
|
||||
bool has_volume_output, has_surface_output;
|
||||
|
||||
|
@ -2501,7 +2518,7 @@ GPUMaterial *GPU_material_from_nodetree(
|
|||
BLI_assert(GPU_material_from_nodetree_find(gpumaterials, engine_type, options) == NULL);
|
||||
|
||||
/* allocate material */
|
||||
mat = GPU_material_construct_begin(NULL); /* TODO remove GPU_material_construct_begin */
|
||||
GPUMaterial *mat = MEM_callocN(sizeof(GPUMaterial), "GPUMaterial");;
|
||||
mat->scene = scene;
|
||||
mat->engine_type = engine_type;
|
||||
mat->options = options;
|
||||
|
@ -2516,11 +2533,15 @@ GPUMaterial *GPU_material_from_nodetree(
|
|||
mat->domain |= GPU_DOMAIN_VOLUME;
|
||||
}
|
||||
|
||||
/* Let Draw manager finish the construction. */
|
||||
if (mat->outlink) {
|
||||
outlink = mat->outlink;
|
||||
mat->pass = GPU_generate_pass_new(
|
||||
mat, &mat->nodes, outlink, &mat->attribs, vert_code, geom_code, frag_lib, defines);
|
||||
if (!deferred) {
|
||||
GPU_material_generate_pass(mat, vert_code, geom_code, frag_lib, defines);
|
||||
}
|
||||
else if (mat->outlink) {
|
||||
/* Prune the unused nodes and extract attribs before compiling so the
|
||||
* generated VBOs are ready to accept the future shader. */
|
||||
GPU_nodes_prune(&mat->nodes, mat->outlink);
|
||||
GPU_nodes_get_vertex_attributes(&mat->nodes, &mat->attribs);
|
||||
mat->status = GPU_MAT_QUEUED;
|
||||
}
|
||||
|
||||
/* note that even if building the shader fails in some way, we still keep
|
||||
|
@ -2534,6 +2555,18 @@ GPUMaterial *GPU_material_from_nodetree(
|
|||
return mat;
|
||||
}
|
||||
|
||||
/* Calls this function if /a mat was created with deferred compilation. */
|
||||
void GPU_material_generate_pass(
|
||||
GPUMaterial *mat, const char *vert_code, const char *geom_code, const char *frag_lib, const char *defines)
|
||||
{
|
||||
BLI_assert(mat->pass == NULL); /* Only run once! */
|
||||
if (mat->outlink) {
|
||||
mat->pass = GPU_generate_pass_new(
|
||||
mat, &mat->nodes, mat->outlink, &mat->attribs, vert_code, geom_code, frag_lib, defines);
|
||||
mat->status = (mat->pass) ? GPU_MAT_SUCCESS : GPU_MAT_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma, bool use_opensubdiv)
|
||||
{
|
||||
GPUMaterial *mat;
|
||||
|
|
Loading…
Reference in New Issue