From 9424c369936a730ed70db59e8f61b290fcd8d3ae Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Wed, 5 May 2021 19:44:44 +0200 Subject: [PATCH] Temporarily memoize IPlugView::canResize() This makes VST3 plugin resizing more responsive, because this function would otherwise be constantly running in lockstep from the GUI thread. --- CHANGELOG.md | 8 ++++++ src/common/logging/vst3.cpp | 11 +++++--- src/common/logging/vst3.h | 4 ++- .../bridges/vst3-impls/plug-view-proxy.cpp | 26 +++++++++++++++++-- .../bridges/vst3-impls/plug-view-proxy.h | 16 ++++++++++++ 5 files changed, 59 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 22a80803..1615f818 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] + +### Added + +- Added a timed cache for the `IPluginView::canResize()` VST3 function, so value + will be remembered during an active resize. This makes resizing VST3 plugin + editor windows more responsive. + ## [3.2.0] - 2021-05-03 ### Added diff --git a/src/common/logging/vst3.cpp b/src/common/logging/vst3.cpp index 1e852996..5fefe136 100644 --- a/src/common/logging/vst3.cpp +++ b/src/common/logging/vst3.cpp @@ -1400,9 +1400,14 @@ void Vst3Logger::log_response(bool is_host_vst, const Ack&) { } void Vst3Logger::log_response(bool is_host_vst, - const UniversalTResult& result) { - log_response_base(is_host_vst, - [&](auto& message) { message << result.string(); }); + const UniversalTResult& result, + bool from_cache) { + log_response_base(is_host_vst, [&](auto& message) { + message << result.string(); + if (from_cache) { + message << " (from cache)"; + } + }); } void Vst3Logger::log_response( diff --git a/src/common/logging/vst3.h b/src/common/logging/vst3.h index cf351ba8..ad167825 100644 --- a/src/common/logging/vst3.h +++ b/src/common/logging/vst3.h @@ -242,7 +242,9 @@ class Vst3Logger { const YaUnitHandler2::NotifyUnitByBusChange&); void log_response(bool is_host_vst, const Ack&); - void log_response(bool is_host_vst, const UniversalTResult&); + void log_response(bool is_host_vst, + const UniversalTResult&, + bool from_cache = false); void log_response(bool is_host_vst, const Vst3PluginFactoryProxy::ConstructArgs&); void log_response( diff --git a/src/plugin/bridges/vst3-impls/plug-view-proxy.cpp b/src/plugin/bridges/vst3-impls/plug-view-proxy.cpp index a84f1ed8..2162f196 100644 --- a/src/plugin/bridges/vst3-impls/plug-view-proxy.cpp +++ b/src/plugin/bridges/vst3-impls/plug-view-proxy.cpp @@ -244,8 +244,30 @@ Vst3PlugViewProxyImpl::setFrame(Steinberg::IPlugFrame* frame) { } tresult PLUGIN_API Vst3PlugViewProxyImpl::canResize() { - return send_mutually_recursive_message( - YaPlugView::CanResize{.owner_instance_id = owner_instance_id()}); + const auto request = + YaPlugView::CanResize{.owner_instance_id = owner_instance_id()}; + + { + std::lock_guard lock(can_resize_cache_mutex); + if (const tresult* result = can_resize_cache.get_and_keep_alive(5)) { + const bool log_response = bridge.logger.log_request(true, request); + if (log_response) { + bridge.logger.log_response( + true, YaPlugView::CanResize::Response(*result)); + } + + return *result; + } + } + + const UniversalTResult result = send_mutually_recursive_message(request); + + { + std::lock_guard lock(can_resize_cache_mutex); + can_resize_cache.set(result, 5); + } + + return result; } tresult PLUGIN_API diff --git a/src/plugin/bridges/vst3-impls/plug-view-proxy.h b/src/plugin/bridges/vst3-impls/plug-view-proxy.h index a6386e2e..77d33baf 100644 --- a/src/plugin/bridges/vst3-impls/plug-view-proxy.h +++ b/src/plugin/bridges/vst3-impls/plug-view-proxy.h @@ -301,4 +301,20 @@ class Vst3PlugViewProxyImpl : public Vst3PlugViewProxy { * This will be an `std::nullopt` if the hostdoes not support `IRunLoop`. */ std::optional run_loop_tasks; + + // Caches + + /** + * During resizing the host will likely constantly ask the plugin if it can + * be freely resized. Even if it is technically possible, I'm not aware of + * any plugins that change from not being able arbitrarily resizeable to + * being able to be resized like this. The reason why we might want to cache + * `IPlugView::canResize()` is because this function has to be run on the + * GUI thread, just like `IPlugView::onSize()` and + * `IPlugView::checkSizeConstraint`. Everything running in lockstep makes + * resizing a lot laggier than they would have to be, so as a compromise + * we'll remember this value for the duration of the resize. + */ + TimedValueCache can_resize_cache; + std::mutex can_resize_cache_mutex; };