From 545f2c04fa72b72ec6939fe9cb8e139a1a89263a Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Thu, 18 Jan 2024 11:10:03 +0100 Subject: [PATCH] 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 --- .../draw/engines/eevee_next/eevee_pipeline.cc | 22 +++++++++++++++---- .../draw/engines/eevee_next/eevee_pipeline.hh | 3 +++ 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/source/blender/draw/engines/eevee_next/eevee_pipeline.cc b/source/blender/draw/engines/eevee_next/eevee_pipeline.cc index 4af72171c22..b13d1e8ce1e 100644 --- a/source/blender/draw/engines/eevee_next/eevee_pipeline.cc +++ b/source/blender/draw/engines/eevee_next/eevee_pipeline.cc @@ -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); + } } /** \} */ diff --git a/source/blender/draw/engines/eevee_next/eevee_pipeline.hh b/source/blender/draw/engines/eevee_next/eevee_pipeline.hh index 29be0861c47..dcbab759b26 100644 --- a/source/blender/draw/engines/eevee_next/eevee_pipeline.hh +++ b/source/blender/draw/engines/eevee_next/eevee_pipeline.hh @@ -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){};