Draw: Remove mode transfer overhead when inactive
Currently the mode transfer overlay has to check whether it should draw for every single object. For scenes with many instances even that small amount of work per object can be significant. I observed the overlay taking 1.8% of the samples in a profile. This commit removes the mode transfer timer and stores it in a global map instead. Besides the benefit of removing 8 bytes per object, the main improvement is that it's now trivial to check whether the overlay can be completely disabled. Pull Request: https://projects.blender.org/blender/blender/pulls/140374
This commit is contained in:
@@ -56,9 +56,6 @@ struct ObjectRuntime {
|
||||
*/
|
||||
char is_data_eval_owned = false;
|
||||
|
||||
/** Start time of the mode transfer overlay animation. */
|
||||
double overlay_mode_transfer_start_time = 0.0f;
|
||||
|
||||
/**
|
||||
* The bounding box of the object's evaluated geometry in the active dependency graph. The bounds
|
||||
* are copied back to the original object for the RNA API and for display in the interface.
|
||||
|
||||
@@ -146,6 +146,7 @@ set(SRC
|
||||
engines/overlay/overlay_armature.cc
|
||||
engines/overlay/overlay_engine.cc
|
||||
engines/overlay/overlay_instance.cc
|
||||
engines/overlay/overlay_mode_transfer.cc
|
||||
engines/overlay/overlay_shader.cc
|
||||
engines/overlay/overlay_shape.cc
|
||||
|
||||
|
||||
34
source/blender/draw/engines/overlay/overlay_mode_transfer.cc
Normal file
34
source/blender/draw/engines/overlay/overlay_mode_transfer.cc
Normal file
@@ -0,0 +1,34 @@
|
||||
/* SPDX-FileCopyrightText: 2025 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "ED_object.hh"
|
||||
|
||||
#include "overlay_mode_transfer.hh"
|
||||
|
||||
namespace blender::draw::overlay {
|
||||
|
||||
void ModeTransfer::begin_sync(Resources &res, const State &state)
|
||||
{
|
||||
object_factors_ = ed::object::mode_transfer_overlay_current_state();
|
||||
|
||||
enabled_ = state.is_space_v3d() && !res.is_selection() && !object_factors_.is_empty();
|
||||
|
||||
if (!enabled_) {
|
||||
/* Not used. But release the data. */
|
||||
ps_.init();
|
||||
return;
|
||||
}
|
||||
|
||||
UI_GetThemeColor3fv(TH_VERTEX_SELECT, flash_color_);
|
||||
srgb_to_linearrgb_v4(flash_color_, flash_color_);
|
||||
|
||||
ps_.init();
|
||||
ps_.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WRITE_DEPTH,
|
||||
state.clipping_plane_count);
|
||||
ps_.shader_set(res.shaders->uniform_color.get());
|
||||
ps_.bind_ubo(OVERLAY_GLOBALS_SLOT, &res.globals_buf);
|
||||
ps_.bind_ubo(DRW_CLIPPING_UBO_SLOT, &res.clip_planes_buf);
|
||||
}
|
||||
|
||||
} // namespace blender::draw::overlay
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BLI_time.h"
|
||||
#include "BLI_map.hh"
|
||||
|
||||
#include "BKE_paint.hh"
|
||||
|
||||
@@ -27,38 +27,12 @@ class ModeTransfer : Overlay {
|
||||
private:
|
||||
PassSimple ps_ = {"ModeTransfer"};
|
||||
|
||||
Map<std::string, float, 1> object_factors_;
|
||||
|
||||
float4 flash_color_;
|
||||
|
||||
double current_time_ = 0.0;
|
||||
|
||||
/* True if any object used was synced using this overlay. */
|
||||
bool any_animated_ = false;
|
||||
|
||||
public:
|
||||
void begin_sync(Resources &res, const State &state) final
|
||||
{
|
||||
enabled_ = state.is_space_v3d() && !res.is_selection();
|
||||
|
||||
if (!enabled_) {
|
||||
/* Not used. But release the data. */
|
||||
ps_.init();
|
||||
return;
|
||||
}
|
||||
|
||||
UI_GetThemeColor3fv(TH_VERTEX_SELECT, flash_color_);
|
||||
srgb_to_linearrgb_v4(flash_color_, flash_color_);
|
||||
|
||||
current_time_ = BLI_time_now_seconds();
|
||||
|
||||
ps_.init();
|
||||
ps_.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WRITE_DEPTH,
|
||||
state.clipping_plane_count);
|
||||
ps_.shader_set(res.shaders->uniform_color.get());
|
||||
ps_.bind_ubo(OVERLAY_GLOBALS_SLOT, &res.globals_buf);
|
||||
ps_.bind_ubo(DRW_CLIPPING_UBO_SLOT, &res.clip_planes_buf);
|
||||
|
||||
any_animated_ = false;
|
||||
}
|
||||
void begin_sync(Resources &res, const State &state) final;
|
||||
|
||||
void object_sync(Manager &manager,
|
||||
const ObjectRef &ob_ref,
|
||||
@@ -69,6 +43,11 @@ class ModeTransfer : Overlay {
|
||||
return;
|
||||
}
|
||||
|
||||
const std::optional<float> alpha_opt = object_factors_.lookup_try_as(ob_ref.object->id.name);
|
||||
if (!alpha_opt) {
|
||||
return;
|
||||
}
|
||||
|
||||
const bool renderable = DRW_object_is_renderable(ob_ref.object);
|
||||
const bool draw_surface = (ob_ref.object->dt >= OB_WIRE) &&
|
||||
(renderable || (ob_ref.object->dt == OB_WIRE));
|
||||
@@ -76,11 +55,8 @@ class ModeTransfer : Overlay {
|
||||
return;
|
||||
}
|
||||
|
||||
const float time = current_time_ - ob_ref.object->runtime->overlay_mode_transfer_start_time;
|
||||
const float alpha = alpha_from_time_get(time);
|
||||
if (alpha == 0.0f) {
|
||||
return;
|
||||
}
|
||||
constexpr float flash_alpha = 0.25f;
|
||||
const float alpha = *alpha_opt * flash_alpha;
|
||||
|
||||
ps_.push_constant("ucolor", float4(flash_color_.xyz() * alpha, alpha));
|
||||
|
||||
@@ -99,8 +75,6 @@ class ModeTransfer : Overlay {
|
||||
ps_.draw(geom, manager.unique_handle(ob_ref));
|
||||
}
|
||||
}
|
||||
|
||||
any_animated_ = true;
|
||||
}
|
||||
|
||||
void draw(Framebuffer &framebuffer, Manager &manager, View &view) final
|
||||
@@ -112,25 +86,8 @@ class ModeTransfer : Overlay {
|
||||
GPU_framebuffer_bind(framebuffer);
|
||||
manager.submit(ps_, view);
|
||||
|
||||
if (any_animated_) {
|
||||
/* Request redraws until the object fades out. */
|
||||
DRW_viewport_request_redraw();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr float flash_length = 0.55f;
|
||||
static constexpr float flash_alpha = 0.25f;
|
||||
|
||||
static float alpha_from_time_get(const float anim_time)
|
||||
{
|
||||
if (anim_time > flash_length) {
|
||||
return 0.0f;
|
||||
}
|
||||
if (anim_time < 0.0f) {
|
||||
return 0.0f;
|
||||
}
|
||||
return (1.0f - (anim_time / flash_length)) * flash_alpha;
|
||||
/* Request redraws until the object fades out (enabled_ will be reset to false). */
|
||||
DRW_viewport_request_redraw();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <string>
|
||||
|
||||
#include "BLI_compiler_attrs.h"
|
||||
#include "BLI_map.hh"
|
||||
#include "BLI_math_matrix_types.hh"
|
||||
#include "BLI_string_ref.hh"
|
||||
#include "BLI_vector.hh"
|
||||
@@ -457,6 +458,13 @@ Object *object_in_mode_from_index(const Scene *scene,
|
||||
eObjectMode mode,
|
||||
int index);
|
||||
|
||||
/**
|
||||
* Retrieve the alpha factors of the currently active mode transfer overlay animations. The key is
|
||||
* the object ID name to prevent possible storage of stale pointers and because the #session_uid
|
||||
* isn't available on evaluated objects.
|
||||
*/
|
||||
Map<std::string, float, 1> mode_transfer_overlay_current_state();
|
||||
|
||||
/* `object_modifier.cc` */
|
||||
|
||||
enum {
|
||||
|
||||
@@ -408,11 +408,50 @@ static void object_transfer_mode_reposition_view_pivot(ARegion *region,
|
||||
ups->last_stroke_valid = true;
|
||||
}
|
||||
|
||||
constexpr float mode_transfer_flash_length = 0.55f;
|
||||
|
||||
static auto &mode_transfer_overlay_start_times()
|
||||
{
|
||||
static Map<std::string, double> map;
|
||||
return map;
|
||||
}
|
||||
|
||||
static float alpha_from_time_get(const float anim_time)
|
||||
{
|
||||
if (anim_time < 0.0f) {
|
||||
return 0.0f;
|
||||
}
|
||||
return (1.0f - (anim_time / mode_transfer_flash_length));
|
||||
}
|
||||
|
||||
Map<std::string, float, 1> mode_transfer_overlay_current_state()
|
||||
{
|
||||
const double now = BLI_time_now_seconds();
|
||||
|
||||
/* Protect against possible concurrent access from multiple renderers or viewports. */
|
||||
static Mutex mutex;
|
||||
std::scoped_lock lock(mutex);
|
||||
|
||||
/* Remove finished animations form the global map. */
|
||||
Map<std::string, double> &start_times = mode_transfer_overlay_start_times();
|
||||
start_times.remove_if(
|
||||
[&](const auto &item) { return (now - item.value) > mode_transfer_flash_length; });
|
||||
|
||||
Map<std::string, float, 1> factors;
|
||||
for (const auto &item : start_times.items()) {
|
||||
const float alpha = alpha_from_time_get(now - item.value);
|
||||
if (alpha > 0.0f) {
|
||||
factors.add_new(item.key, alpha);
|
||||
}
|
||||
}
|
||||
return factors;
|
||||
}
|
||||
|
||||
static void object_overlay_mode_transfer_animation_start(bContext *C, Object *ob_dst)
|
||||
{
|
||||
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
|
||||
Object *ob_dst_eval = DEG_get_evaluated(depsgraph, ob_dst);
|
||||
ob_dst_eval->runtime->overlay_mode_transfer_start_time = BLI_time_now_seconds();
|
||||
mode_transfer_overlay_start_times().add_as(ob_dst_eval->id.name, BLI_time_now_seconds());
|
||||
}
|
||||
|
||||
static bool object_transfer_mode_to_base(bContext *C,
|
||||
|
||||
Reference in New Issue
Block a user