EEVEE: Skip Forward Rendering Pipeline Stages When Empty

Increase performance when drawing scenes that don't have blended materials. This should
save some CPU and GPU cycles as parts (or the whole pipeline) can be skipped.

Mostly it ensures that the hiz isn't tagged dirty and has a chance that it is being reused
by other areas. Shadows and irradiance caches aren't forced to be updated.

Mac Studio M1 Ultra
 - space_raceship.blend went from 27 fps to 33 fps (10%-20% improvement).

This is a common scenario to optimize as by default materials are not blended and require
user action to set them up. When using compositing/renderpasses, blended materials aren't
supported and most likely not being used.

Pull Request: https://projects.blender.org/blender/blender/pulls/117269
This commit is contained in:
Jeroen Bakker
2024-01-18 11:10:03 +01:00
parent d875e5d4cb
commit 545f2c04fa
2 changed files with 21 additions and 4 deletions

View File

@@ -244,6 +244,8 @@ void ShadowPipeline::render(View &view)
void ForwardPipeline::sync()
{
camera_forward_ = inst_.camera.forward();
has_opaque_ = false;
has_transparent_ = false;
DRWState state_depth_only = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS;
DRWState state_depth_color = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS |
@@ -340,6 +342,7 @@ PassMain::Sub *ForwardPipeline::prepass_opaque_add(::Material *blender_mat,
/* TODO(fclem): To skip it, we need to know if the transparent BSDF is fully white AND if there
* is no mix shader (could do better constant folding but that's expensive). */
has_opaque_ = true;
return &pass->sub(GPU_material_get_name(gpumat));
}
@@ -350,6 +353,7 @@ PassMain::Sub *ForwardPipeline::material_opaque_add(::Material *blender_mat, GPU
"PipelineModule::material_add()");
PassMain::Sub *pass = (blender_mat->blend_flag & MA_BL_CULL_BACKFACE) ? opaque_single_sided_ps_ :
opaque_double_sided_ps_;
has_opaque_ = true;
return &pass->sub(GPU_material_get_name(gpumat));
}
@@ -364,6 +368,7 @@ PassMain::Sub *ForwardPipeline::prepass_transparent_add(const Object *ob,
if (blender_mat->blend_flag & MA_BL_CULL_BACKFACE) {
state |= DRW_STATE_CULL_BACK;
}
has_transparent_ = true;
float sorting_value = math::dot(float3(ob->object_to_world[3]), camera_forward_);
PassMain::Sub *pass = &transparent_ps_.sub(GPU_material_get_name(gpumat), sorting_value);
pass->state_set(state);
@@ -379,6 +384,7 @@ PassMain::Sub *ForwardPipeline::material_transparent_add(const Object *ob,
if (blender_mat->blend_flag & MA_BL_CULL_BACKFACE) {
state |= DRW_STATE_CULL_BACK;
}
has_transparent_ = true;
float sorting_value = math::dot(float3(ob->object_to_world[3]), camera_forward_);
PassMain::Sub *pass = &transparent_ps_.sub(GPU_material_get_name(gpumat), sorting_value);
pass->state_set(state);
@@ -388,6 +394,10 @@ PassMain::Sub *ForwardPipeline::material_transparent_add(const Object *ob,
void ForwardPipeline::render(View &view, Framebuffer &prepass_fb, Framebuffer &combined_fb)
{
if (!has_transparent_ && !has_opaque_) {
return;
}
DRW_stats_group_start("Forward.Opaque");
prepass_fb.bind();
@@ -398,15 +408,19 @@ void ForwardPipeline::render(View &view, Framebuffer &prepass_fb, Framebuffer &c
inst_.shadows.set_view(view, inst_.render_buffers.depth_tx);
inst_.irradiance_cache.set_view(view);
combined_fb.bind();
inst_.manager->submit(opaque_ps_, view);
if (has_opaque_) {
combined_fb.bind();
inst_.manager->submit(opaque_ps_, view);
}
DRW_stats_group_end();
inst_.volume.draw_resolve(view);
combined_fb.bind();
inst_.manager->submit(transparent_ps_, view);
if (has_transparent_) {
combined_fb.bind();
inst_.manager->submit(transparent_ps_, view);
}
}
/** \} */

View File

@@ -145,6 +145,9 @@ class ForwardPipeline {
PassSortable transparent_ps_ = {"Forward.Transparent"};
float3 camera_forward_;
bool has_opaque_ = false;
bool has_transparent_ = false;
public:
ForwardPipeline(Instance &inst) : inst_(inst){};