From 54c3c8f411a8291bfd4f674537b4788cca6345ed Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Tue, 17 Jun 2025 16:06:05 +0200 Subject: [PATCH] Draw: Inline small functions to reduce overhead Some functions used at least once per object/instance when drawing are so trivial that function call overhead becomes significant. Allowing these functions to be inlined can remove that overhead and also give the compiler more information it can use for optimization. In the Erindale Flower Shop file, this change gives me a 10% improvement in playback FPS, from 8.77 to 9.65. Pull Request: https://projects.blender.org/blender/blender/pulls/140402 --- .../blender/blenkernel/BKE_subdiv_modifier.hh | 9 +++++- .../blenkernel/intern/subdiv_modifier.cc | 6 ---- .../engines/workbench/workbench_materials.cc | 30 ------------------- .../engines/workbench/workbench_private.hh | 27 +++++++++++++++-- source/blender/draw/intern/DRW_render.hh | 14 ++++++++- .../draw_cache_extract_mesh_render_data.cc | 11 ------- source/blender/draw/intern/draw_context.cc | 17 ----------- .../draw/intern/draw_context_private.hh | 5 +++- .../intern/mesh_extractors/extract_mesh.hh | 13 +++++++- 9 files changed, 61 insertions(+), 71 deletions(-) diff --git a/source/blender/blenkernel/BKE_subdiv_modifier.hh b/source/blender/blenkernel/BKE_subdiv_modifier.hh index ee0c474e93b..f25328a9b3c 100644 --- a/source/blender/blenkernel/BKE_subdiv_modifier.hh +++ b/source/blender/blenkernel/BKE_subdiv_modifier.hh @@ -8,8 +8,11 @@ #pragma once +#include "BKE_mesh_types.hh" #include "BKE_subdiv.hh" +#include "DNA_mesh_types.h" + /* Hardcoded for until GPU shaders are automatically generated, then we will have a more * programmatic way of detecting this. */ #define MAX_GPU_SUBDIV_SSBOS 12 @@ -74,7 +77,11 @@ bool BKE_subsurf_modifier_force_disable_gpu_evaluation_for_mesh(const SubsurfMod */ bool BKE_subsurf_modifier_can_do_gpu_subdiv(const SubsurfModifierData *smd, const Mesh *mesh); -bool BKE_subsurf_modifier_has_gpu_subdiv(const Mesh *mesh); +inline bool BKE_subsurf_modifier_has_gpu_subdiv(const Mesh *mesh) +{ + SubsurfRuntimeData *runtime_data = mesh->runtime->subsurf_runtime_data; + return runtime_data && runtime_data->has_gpu_subdiv; +} extern void (*BKE_subsurf_modifier_free_gpu_cache_cb)(blender::bke::subdiv::Subdiv *subdiv); diff --git a/source/blender/blenkernel/intern/subdiv_modifier.cc b/source/blender/blenkernel/intern/subdiv_modifier.cc index d628a70f265..569c45f9fb2 100644 --- a/source/blender/blenkernel/intern/subdiv_modifier.cc +++ b/source/blender/blenkernel/intern/subdiv_modifier.cc @@ -120,12 +120,6 @@ bool BKE_subsurf_modifier_can_do_gpu_subdiv(const SubsurfModifierData *smd, cons !BKE_subsurf_modifier_has_split_normals(smd, mesh); } -bool BKE_subsurf_modifier_has_gpu_subdiv(const Mesh *mesh) -{ - SubsurfRuntimeData *runtime_data = mesh->runtime->subsurf_runtime_data; - return runtime_data && runtime_data->has_gpu_subdiv; -} - void (*BKE_subsurf_modifier_free_gpu_cache_cb)(subdiv::Subdiv *subdiv) = nullptr; subdiv::Subdiv *BKE_subsurf_modifier_subdiv_descriptor_ensure(SubsurfRuntimeData *runtime_data, diff --git a/source/blender/draw/engines/workbench/workbench_materials.cc b/source/blender/draw/engines/workbench/workbench_materials.cc index 8909f9539bf..911c15a282b 100644 --- a/source/blender/draw/engines/workbench/workbench_materials.cc +++ b/source/blender/draw/engines/workbench/workbench_materials.cc @@ -16,14 +16,6 @@ namespace blender::workbench { -Material::Material() = default; - -Material::Material(float3 color) -{ - base_color = color; - packed_data = Material::pack_data(0.0f, 0.4f, 1.0f); -} - Material::Material(::Object &ob, bool random) { if (random) { @@ -40,28 +32,6 @@ Material::Material(::Object &ob, bool random) packed_data = Material::pack_data(0.0f, 0.4f, ob.color[3]); } -Material::Material(::Material &mat) -{ - base_color = &mat.r; - packed_data = Material::pack_data(mat.metallic, mat.roughness, mat.a); -} - -bool Material::is_transparent() -{ - uint32_t full_alpha_ref = 0x00ff0000; - return (packed_data & full_alpha_ref) != full_alpha_ref; -} - -uint32_t Material::pack_data(float metallic, float roughness, float alpha) -{ - /* Remap to Disney roughness. */ - roughness = sqrtf(roughness); - uint32_t packed_roughness = unit_float_to_uchar_clamp(roughness); - uint32_t packed_metallic = unit_float_to_uchar_clamp(metallic); - uint32_t packed_alpha = unit_float_to_uchar_clamp(alpha); - return (packed_alpha << 16u) | (packed_roughness << 8u) | packed_metallic; -} - MaterialTexture::MaterialTexture(Object *ob, int material_index) { const ::bNode *node = nullptr; diff --git a/source/blender/draw/engines/workbench/workbench_private.hh b/source/blender/draw/engines/workbench/workbench_private.hh index 11bbffe8eac..b97421ce8f4 100644 --- a/source/blender/draw/engines/workbench/workbench_private.hh +++ b/source/blender/draw/engines/workbench/workbench_private.hh @@ -5,6 +5,7 @@ #include "BKE_context.hh" #include "DNA_camera_types.h" +#include "DNA_material_types.h" #include "DRW_render.hh" #include "GPU_shader.hh" #include "draw_manager.hh" @@ -110,16 +111,36 @@ struct Material { /* Packed data into a int. Decoded in the shader. */ uint packed_data = 0; - Material(); - Material(float3 color); + Material() = default; + Material(float3 color) : base_color(color), packed_data(Material::pack_data(0.0f, 0.4f, 1.0f)) {} + Material(::Object &ob, bool random = false); - Material(::Material &mat); + Material(::Material &mat) + : base_color(&mat.r), packed_data(Material::pack_data(mat.metallic, mat.roughness, mat.a)) + { + } static uint32_t pack_data(float metallic, float roughness, float alpha); bool is_transparent(); }; +inline bool Material::is_transparent() +{ + uint32_t full_alpha_ref = 0x00ff0000; + return (packed_data & full_alpha_ref) != full_alpha_ref; +} + +inline uint32_t Material::pack_data(float metallic, float roughness, float alpha) +{ + /* Remap to Disney roughness. */ + roughness = sqrtf(roughness); + uint32_t packed_roughness = unit_float_to_uchar_clamp(roughness); + uint32_t packed_metallic = unit_float_to_uchar_clamp(metallic); + uint32_t packed_alpha = unit_float_to_uchar_clamp(alpha); + return (packed_alpha << 16u) | (packed_roughness << 8u) | packed_metallic; +} + ImageGPUTextures get_material_texture(GPUSamplerState &sampler_state); struct SceneState { diff --git a/source/blender/draw/intern/DRW_render.hh b/source/blender/draw/intern/DRW_render.hh index 7fe0327f621..1fe858f9cf8 100644 --- a/source/blender/draw/intern/DRW_render.hh +++ b/source/blender/draw/intern/DRW_render.hh @@ -12,6 +12,8 @@ #include +#include "BKE_mesh_wrapper.hh" +#include "BKE_subdiv_modifier.hh" #include "BLI_math_vector_types.hh" #include "DNA_object_enums.h" #include "DNA_object_types.h" @@ -192,7 +194,17 @@ template T &DRW_object_get_data_for_drawing(const Object &object) return *static_cast(object.data); } -template<> Mesh &DRW_object_get_data_for_drawing(const Object &object); +template<> inline Mesh &DRW_object_get_data_for_drawing(const Object &object) +{ + /* For drawing we want either the base mesh if GPU subdivision is enabled, or the + * tessellated mesh if GPU subdivision is disabled. */ + BLI_assert(object.type == OB_MESH); + Mesh &mesh = *static_cast(object.data); + if (BKE_subsurf_modifier_has_gpu_subdiv(&mesh)) { + return mesh; + } + return *BKE_mesh_wrapper_ensure_subdivision(&mesh); +} /** * Same as DRW_object_get_data_for_drawing, but for the editmesh cage, diff --git a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc index 1f2949e3401..8bb3d6f4202 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc +++ b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc @@ -358,17 +358,6 @@ const SortedFaceData &mesh_render_data_faces_sorted_ensure(const MeshRenderData /** \name Mesh/BMesh Interface (indirect, partially cached access to complex data). * \{ */ -const Mesh &editmesh_final_or_this(const Object &object, const Mesh &mesh) -{ - if (mesh.runtime->edit_mesh != nullptr) { - if (const Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(&object)) { - return *editmesh_eval_final; - } - } - - return mesh; -} - const CustomData &mesh_cd_ldata_get_from_mesh(const Mesh &mesh) { switch (mesh.runtime->wrapper_type) { diff --git a/source/blender/draw/intern/draw_context.cc b/source/blender/draw/intern/draw_context.cc index 2f7ba26c523..6c359f5dd79 100644 --- a/source/blender/draw/intern/draw_context.cc +++ b/source/blender/draw/intern/draw_context.cc @@ -106,11 +106,6 @@ thread_local DRWContext *DRWContext::g_context = nullptr; -DRWContext &drw_get() -{ - return DRWContext::get_active(); -} - DRWContext::DRWContext(Mode mode_, Depsgraph *depsgraph, const int2 size, @@ -370,18 +365,6 @@ bool DRW_object_is_visible_psys_in_active_context(const Object *object, const Pa return true; } -template<> Mesh &DRW_object_get_data_for_drawing(const Object &object) -{ - /* For drawing we want either the base mesh if GPU subdivision is enabled, or the - * tessellated mesh if GPU subdivision is disabled. */ - BLI_assert(object.type == OB_MESH); - Mesh &mesh = *static_cast(object.data); - if (BKE_subsurf_modifier_has_gpu_subdiv(&mesh)) { - return mesh; - } - return *BKE_mesh_wrapper_ensure_subdivision(&mesh); -} - const Mesh *DRW_object_get_editmesh_cage_for_drawing(const Object &object) { /* Same as DRW_object_get_data_for_drawing, but for the cage mesh. */ diff --git a/source/blender/draw/intern/draw_context_private.hh b/source/blender/draw/intern/draw_context_private.hh index a858dac4276..ff7e70e351a 100644 --- a/source/blender/draw/intern/draw_context_private.hh +++ b/source/blender/draw/intern/draw_context_private.hh @@ -74,7 +74,10 @@ struct DRWData { * \{ */ /* Get thread local draw context. */ -DRWContext &drw_get(); +inline DRWContext &drw_get() +{ + return DRWContext::get_active(); +} namespace blender::draw { diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh.hh b/source/blender/draw/intern/mesh_extractors/extract_mesh.hh index cbb0e2acbaa..8979da3c7be 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh.hh +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh.hh @@ -18,6 +18,7 @@ #include "DNA_scene_types.h" #include "BKE_mesh.hh" +#include "BKE_object.hh" #include "bmesh.hh" @@ -120,7 +121,17 @@ struct MeshRenderData { const char *default_color_name; }; -const Mesh &editmesh_final_or_this(const Object &object, const Mesh &mesh); +inline const Mesh &editmesh_final_or_this(const Object &object, const Mesh &mesh) +{ + if (mesh.runtime->edit_mesh != nullptr) { + if (const Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(&object)) { + return *editmesh_eval_final; + } + } + + return mesh; +} + const CustomData &mesh_cd_vdata_get_from_mesh(const Mesh &mesh); const CustomData &mesh_cd_edata_get_from_mesh(const Mesh &mesh); const CustomData &mesh_cd_pdata_get_from_mesh(const Mesh &mesh);