Draw: Add default material fallback detection
Detect passes that are functionally equivalent to the default Material ones to skip their compilation. Pull Request: https://projects.blender.org/blender/blender/pulls/121137
This commit is contained in:
@@ -190,9 +190,7 @@ MaterialPass MaterialModule::material_pass_get(Object *ob,
|
|||||||
}
|
}
|
||||||
case GPU_MAT_QUEUED:
|
case GPU_MAT_QUEUED:
|
||||||
queued_shaders_count++;
|
queued_shaders_count++;
|
||||||
blender_mat = (is_volume) ? BKE_material_default_volume() : BKE_material_default_surface();
|
matpass.gpumat = inst_.shaders.material_default_shader_get(pipeline_type, geometry_type);
|
||||||
matpass.gpumat = inst_.shaders.material_shader_get(
|
|
||||||
blender_mat, blender_mat->nodetree, pipeline_type, geometry_type, false);
|
|
||||||
break;
|
break;
|
||||||
case GPU_MAT_FAILED:
|
case GPU_MAT_FAILED:
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -764,6 +764,59 @@ static void codegen_callback(void *thunk, GPUMaterial *mat, GPUCodegenOutput *co
|
|||||||
reinterpret_cast<ShaderModule *>(thunk)->material_create_info_ammend(mat, codegen);
|
reinterpret_cast<ShaderModule *>(thunk)->material_create_info_ammend(mat, codegen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool can_use_default_cb(GPUMaterial *mat)
|
||||||
|
{
|
||||||
|
using namespace blender::gpu::shader;
|
||||||
|
|
||||||
|
uint64_t shader_uuid = GPU_material_uuid_get(mat);
|
||||||
|
|
||||||
|
eMaterialPipeline pipeline_type;
|
||||||
|
eMaterialGeometry geometry_type;
|
||||||
|
eMaterialDisplacement displacement_type;
|
||||||
|
bool transparent_shadows;
|
||||||
|
material_type_from_shader_uuid(
|
||||||
|
shader_uuid, pipeline_type, geometry_type, displacement_type, transparent_shadows);
|
||||||
|
|
||||||
|
bool is_shadow_pass = pipeline_type == eMaterialPipeline::MAT_PIPE_SHADOW;
|
||||||
|
bool is_prepass = ELEM(pipeline_type,
|
||||||
|
eMaterialPipeline::MAT_PIPE_PREPASS_DEFERRED,
|
||||||
|
eMaterialPipeline::MAT_PIPE_PREPASS_DEFERRED_VELOCITY,
|
||||||
|
eMaterialPipeline::MAT_PIPE_PREPASS_OVERLAP,
|
||||||
|
eMaterialPipeline::MAT_PIPE_PREPASS_FORWARD,
|
||||||
|
eMaterialPipeline::MAT_PIPE_PREPASS_FORWARD_VELOCITY,
|
||||||
|
eMaterialPipeline::MAT_PIPE_PREPASS_PLANAR);
|
||||||
|
|
||||||
|
bool has_vertex_displacement = GPU_material_has_displacement_output(mat) &&
|
||||||
|
displacement_type != eMaterialDisplacement::MAT_DISPLACEMENT_BUMP;
|
||||||
|
bool has_transparency = GPU_material_flag_get(mat, GPU_MATFLAG_TRANSPARENT);
|
||||||
|
bool has_shadow_transparency = has_transparency && transparent_shadows;
|
||||||
|
|
||||||
|
return (is_shadow_pass && (!has_vertex_displacement && !has_shadow_transparency)) ||
|
||||||
|
(is_prepass && (!has_vertex_displacement && !has_transparency));
|
||||||
|
}
|
||||||
|
|
||||||
|
GPUMaterial *ShaderModule::material_default_shader_get(eMaterialPipeline pipeline_type,
|
||||||
|
eMaterialGeometry geometry_type)
|
||||||
|
{
|
||||||
|
bool is_volume = ELEM(pipeline_type, MAT_PIPE_VOLUME_MATERIAL, MAT_PIPE_VOLUME_OCCUPANCY);
|
||||||
|
::Material *blender_mat = (is_volume) ? BKE_material_default_volume() :
|
||||||
|
BKE_material_default_surface();
|
||||||
|
|
||||||
|
eMaterialDisplacement displacement_type = to_displacement_type(blender_mat->displacement_method);
|
||||||
|
|
||||||
|
uint64_t shader_uuid = shader_uuid_from_material_type(
|
||||||
|
pipeline_type, geometry_type, displacement_type, blender_mat->blend_flag);
|
||||||
|
|
||||||
|
return DRW_shader_from_material(blender_mat,
|
||||||
|
blender_mat->nodetree,
|
||||||
|
GPU_MAT_EEVEE,
|
||||||
|
shader_uuid,
|
||||||
|
is_volume,
|
||||||
|
false,
|
||||||
|
codegen_callback,
|
||||||
|
this);
|
||||||
|
}
|
||||||
|
|
||||||
GPUMaterial *ShaderModule::material_shader_get(::Material *blender_mat,
|
GPUMaterial *ShaderModule::material_shader_get(::Material *blender_mat,
|
||||||
bNodeTree *nodetree,
|
bNodeTree *nodetree,
|
||||||
eMaterialPipeline pipeline_type,
|
eMaterialPipeline pipeline_type,
|
||||||
@@ -777,14 +830,21 @@ GPUMaterial *ShaderModule::material_shader_get(::Material *blender_mat,
|
|||||||
uint64_t shader_uuid = shader_uuid_from_material_type(
|
uint64_t shader_uuid = shader_uuid_from_material_type(
|
||||||
pipeline_type, geometry_type, displacement_type, blender_mat->blend_flag);
|
pipeline_type, geometry_type, displacement_type, blender_mat->blend_flag);
|
||||||
|
|
||||||
return DRW_shader_from_material(blender_mat,
|
GPUMaterial *mat = DRW_shader_from_material(blender_mat,
|
||||||
nodetree,
|
nodetree,
|
||||||
GPU_MAT_EEVEE,
|
GPU_MAT_EEVEE,
|
||||||
shader_uuid,
|
shader_uuid,
|
||||||
is_volume,
|
is_volume,
|
||||||
deferred_compilation,
|
deferred_compilation,
|
||||||
codegen_callback,
|
codegen_callback,
|
||||||
this);
|
this,
|
||||||
|
can_use_default_cb);
|
||||||
|
|
||||||
|
if (GPU_material_status(mat) == GPU_MAT_USE_DEFAULT) {
|
||||||
|
mat = material_default_shader_get(pipeline_type, geometry_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
return mat;
|
||||||
}
|
}
|
||||||
|
|
||||||
GPUMaterial *ShaderModule::world_shader_get(::World *blender_world,
|
GPUMaterial *ShaderModule::world_shader_get(::World *blender_world,
|
||||||
|
|||||||
@@ -165,6 +165,8 @@ class ShaderModule {
|
|||||||
~ShaderModule();
|
~ShaderModule();
|
||||||
|
|
||||||
GPUShader *static_shader_get(eShaderType shader_type);
|
GPUShader *static_shader_get(eShaderType shader_type);
|
||||||
|
GPUMaterial *material_default_shader_get(eMaterialPipeline pipeline_type,
|
||||||
|
eMaterialGeometry geometry_type);
|
||||||
GPUMaterial *material_shader_get(::Material *blender_mat,
|
GPUMaterial *material_shader_get(::Material *blender_mat,
|
||||||
bNodeTree *nodetree,
|
bNodeTree *nodetree,
|
||||||
eMaterialPipeline pipeline_type,
|
eMaterialPipeline pipeline_type,
|
||||||
|
|||||||
@@ -306,14 +306,16 @@ GPUMaterial *DRW_shader_from_world(World *wo,
|
|||||||
bool deferred,
|
bool deferred,
|
||||||
GPUCodegenCallbackFn callback,
|
GPUCodegenCallbackFn callback,
|
||||||
void *thunk);
|
void *thunk);
|
||||||
GPUMaterial *DRW_shader_from_material(Material *ma,
|
GPUMaterial *DRW_shader_from_material(
|
||||||
bNodeTree *ntree,
|
Material *ma,
|
||||||
eGPUMaterialEngine engine,
|
bNodeTree *ntree,
|
||||||
const uint64_t shader_id,
|
eGPUMaterialEngine engine,
|
||||||
const bool is_volume_shader,
|
const uint64_t shader_id,
|
||||||
bool deferred,
|
const bool is_volume_shader,
|
||||||
GPUCodegenCallbackFn callback,
|
bool deferred,
|
||||||
void *thunk);
|
GPUCodegenCallbackFn callback,
|
||||||
|
void *thunk,
|
||||||
|
GPUMaterialCanUseDefaultCallbackFn can_use_default_cb = nullptr);
|
||||||
void DRW_shader_queue_optimize_material(GPUMaterial *mat);
|
void DRW_shader_queue_optimize_material(GPUMaterial *mat);
|
||||||
void DRW_shader_free(GPUShader *shader);
|
void DRW_shader_free(GPUShader *shader);
|
||||||
#define DRW_SHADER_FREE_SAFE(shader) \
|
#define DRW_SHADER_FREE_SAFE(shader) \
|
||||||
|
|||||||
@@ -258,6 +258,8 @@ static void drw_deferred_shader_add(GPUMaterial *mat, bool deferred)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BLI_assert(GPU_material_status(mat) != GPU_MAT_USE_DEFAULT);
|
||||||
|
|
||||||
/* Do not defer the compilation if we are rendering for image.
|
/* Do not defer the compilation if we are rendering for image.
|
||||||
* deferred rendering is only possible when `evil_C` is available */
|
* deferred rendering is only possible when `evil_C` is available */
|
||||||
if (DST.draw_ctx.evil_C == nullptr || DRW_state_is_image_render() || !USE_DEFERRED_COMPILATION) {
|
if (DST.draw_ctx.evil_C == nullptr || DRW_state_is_image_render() || !USE_DEFERRED_COMPILATION) {
|
||||||
@@ -294,6 +296,8 @@ static void drw_deferred_shader_add(GPUMaterial *mat, bool deferred)
|
|||||||
|
|
||||||
static void drw_register_shader_vlattrs(GPUMaterial *mat)
|
static void drw_register_shader_vlattrs(GPUMaterial *mat)
|
||||||
{
|
{
|
||||||
|
BLI_assert(GPU_material_status(mat) != GPU_MAT_USE_DEFAULT);
|
||||||
|
|
||||||
const ListBase *attrs = GPU_material_layer_attributes(mat);
|
const ListBase *attrs = GPU_material_layer_attributes(mat);
|
||||||
|
|
||||||
if (!attrs) {
|
if (!attrs) {
|
||||||
@@ -536,7 +540,8 @@ GPUMaterial *DRW_shader_from_material(Material *ma,
|
|||||||
const bool is_volume_shader,
|
const bool is_volume_shader,
|
||||||
bool deferred,
|
bool deferred,
|
||||||
GPUCodegenCallbackFn callback,
|
GPUCodegenCallbackFn callback,
|
||||||
void *thunk)
|
void *thunk,
|
||||||
|
GPUMaterialCanUseDefaultCallbackFn can_use_default_cb)
|
||||||
{
|
{
|
||||||
Scene *scene = (Scene *)DEG_get_original_id(&DST.draw_ctx.scene->id);
|
Scene *scene = (Scene *)DEG_get_original_id(&DST.draw_ctx.scene->id);
|
||||||
GPUMaterial *mat = GPU_material_from_nodetree(scene,
|
GPUMaterial *mat = GPU_material_from_nodetree(scene,
|
||||||
@@ -549,7 +554,12 @@ GPUMaterial *DRW_shader_from_material(Material *ma,
|
|||||||
is_volume_shader,
|
is_volume_shader,
|
||||||
false,
|
false,
|
||||||
callback,
|
callback,
|
||||||
thunk);
|
thunk,
|
||||||
|
can_use_default_cb);
|
||||||
|
|
||||||
|
if (GPU_material_status(mat) == GPU_MAT_USE_DEFAULT) {
|
||||||
|
return mat;
|
||||||
|
}
|
||||||
|
|
||||||
drw_register_shader_vlattrs(mat);
|
drw_register_shader_vlattrs(mat);
|
||||||
|
|
||||||
@@ -565,6 +575,8 @@ GPUMaterial *DRW_shader_from_material(Material *ma,
|
|||||||
|
|
||||||
void DRW_shader_queue_optimize_material(GPUMaterial *mat)
|
void DRW_shader_queue_optimize_material(GPUMaterial *mat)
|
||||||
{
|
{
|
||||||
|
BLI_assert(GPU_material_status(mat) != GPU_MAT_USE_DEFAULT);
|
||||||
|
|
||||||
/* Do not perform deferred optimization if performing render.
|
/* Do not perform deferred optimization if performing render.
|
||||||
* De-queue any queued optimization jobs. */
|
* De-queue any queued optimization jobs. */
|
||||||
if (DRW_state_is_image_render()) {
|
if (DRW_state_is_image_render()) {
|
||||||
|
|||||||
@@ -116,6 +116,7 @@ enum eGPUMaterialStatus {
|
|||||||
GPU_MAT_CREATED,
|
GPU_MAT_CREATED,
|
||||||
GPU_MAT_QUEUED,
|
GPU_MAT_QUEUED,
|
||||||
GPU_MAT_SUCCESS,
|
GPU_MAT_SUCCESS,
|
||||||
|
GPU_MAT_USE_DEFAULT,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* GPU_MAT_OPTIMIZATION_SKIP for cases where we do not
|
/* GPU_MAT_OPTIMIZATION_SKIP for cases where we do not
|
||||||
@@ -146,6 +147,8 @@ struct GPUCodegenOutput {
|
|||||||
};
|
};
|
||||||
|
|
||||||
using GPUCodegenCallbackFn = void (*)(void *thunk, GPUMaterial *mat, GPUCodegenOutput *codegen);
|
using GPUCodegenCallbackFn = void (*)(void *thunk, GPUMaterial *mat, GPUCodegenOutput *codegen);
|
||||||
|
/* Should return true if the pass is functionally equivalent to the default Material one. */
|
||||||
|
using GPUMaterialCanUseDefaultCallbackFn = bool (*)(GPUMaterial *mat);
|
||||||
|
|
||||||
GPUNodeLink *GPU_constant(const float *num);
|
GPUNodeLink *GPU_constant(const float *num);
|
||||||
GPUNodeLink *GPU_uniform(const float *num);
|
GPUNodeLink *GPU_uniform(const float *num);
|
||||||
@@ -237,17 +240,19 @@ enum eGPUMaterialEngine {
|
|||||||
GPU_MAT_COMPOSITOR,
|
GPU_MAT_COMPOSITOR,
|
||||||
};
|
};
|
||||||
|
|
||||||
GPUMaterial *GPU_material_from_nodetree(Scene *scene,
|
GPUMaterial *GPU_material_from_nodetree(
|
||||||
Material *ma,
|
Scene *scene,
|
||||||
bNodeTree *ntree,
|
Material *ma,
|
||||||
ListBase *gpumaterials,
|
bNodeTree *ntree,
|
||||||
const char *name,
|
ListBase *gpumaterials,
|
||||||
eGPUMaterialEngine engine,
|
const char *name,
|
||||||
uint64_t shader_uuid,
|
eGPUMaterialEngine engine,
|
||||||
bool is_volume_shader,
|
uint64_t shader_uuid,
|
||||||
bool is_lookdev,
|
bool is_volume_shader,
|
||||||
GPUCodegenCallbackFn callback,
|
bool is_lookdev,
|
||||||
void *thunk);
|
GPUCodegenCallbackFn callback,
|
||||||
|
void *thunk,
|
||||||
|
GPUMaterialCanUseDefaultCallbackFn can_use_default_cb = nullptr);
|
||||||
|
|
||||||
void GPU_material_compile(GPUMaterial *mat);
|
void GPU_material_compile(GPUMaterial *mat);
|
||||||
void GPU_material_free_single(GPUMaterial *material);
|
void GPU_material_free_single(GPUMaterial *material);
|
||||||
|
|||||||
@@ -831,7 +831,8 @@ GPUMaterial *GPU_material_from_nodetree(Scene *scene,
|
|||||||
bool is_volume_shader,
|
bool is_volume_shader,
|
||||||
bool is_lookdev,
|
bool is_lookdev,
|
||||||
GPUCodegenCallbackFn callback,
|
GPUCodegenCallbackFn callback,
|
||||||
void *thunk)
|
void *thunk,
|
||||||
|
GPUMaterialCanUseDefaultCallbackFn can_use_default_cb)
|
||||||
{
|
{
|
||||||
/* Search if this material is not already compiled. */
|
/* Search if this material is not already compiled. */
|
||||||
LISTBASE_FOREACH (LinkData *, link, gpumaterials) {
|
LISTBASE_FOREACH (LinkData *, link, gpumaterials) {
|
||||||
@@ -862,10 +863,13 @@ GPUMaterial *GPU_material_from_nodetree(Scene *scene,
|
|||||||
bNodeTree *localtree = ntreeLocalize(ntree);
|
bNodeTree *localtree = ntreeLocalize(ntree);
|
||||||
ntreeGPUMaterialNodes(localtree, mat);
|
ntreeGPUMaterialNodes(localtree, mat);
|
||||||
|
|
||||||
gpu_material_ramp_texture_build(mat);
|
if (can_use_default_cb && can_use_default_cb(mat)) {
|
||||||
gpu_material_sky_texture_build(mat);
|
mat->status = GPU_MAT_USE_DEFAULT;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
gpu_material_ramp_texture_build(mat);
|
||||||
|
gpu_material_sky_texture_build(mat);
|
||||||
|
|
||||||
{
|
|
||||||
/* Create source code and search pass cache for an already compiled version. */
|
/* Create source code and search pass cache for an already compiled version. */
|
||||||
mat->pass = GPU_generate_pass(mat, &mat->graph, engine, callback, thunk, false);
|
mat->pass = GPU_generate_pass(mat, &mat->graph, engine, callback, thunk, false);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user