diff --git a/src/plugin/bridges/vst3-impls/plugin-proxy.cpp b/src/plugin/bridges/vst3-impls/plugin-proxy.cpp index 2f5de79b..3438299b 100644 --- a/src/plugin/bridges/vst3-impls/plugin-proxy.cpp +++ b/src/plugin/bridges/vst3-impls/plugin-proxy.cpp @@ -82,7 +82,9 @@ bool Vst3PluginProxyImpl::unregister_context_menu(size_t context_menu_id) { void Vst3PluginProxyImpl::clear_caches() { clear_bus_cache(); - clear_parameter_cache(); + + std::lock_guard lock(function_result_cache_mutex); + function_result_cache = FunctionResultCache{}; } tresult PLUGIN_API Vst3PluginProxyImpl::setAudioPresentationLatencySamples( @@ -552,26 +554,26 @@ int32 PLUGIN_API Vst3PluginProxyImpl::getParameterCount() { YaEditController::GetParameterCount{.instance_id = instance_id()}; { - std::lock_guard lock(parameter_info_cache_mutex); - if (parameter_info_cache.parameter_count) { + std::lock_guard lock(function_result_cache_mutex); + if (function_result_cache.parameter_count) { const bool log_response = bridge.logger.log_request(true, request); if (log_response) { bridge.logger.log_response( true, YaEditController::GetParameterCount::Response( - *parameter_info_cache.parameter_count), + *function_result_cache.parameter_count), true); } - return *parameter_info_cache.parameter_count; + return *function_result_cache.parameter_count; } } const int32 result = bridge.send_message(request); { - std::lock_guard lock(parameter_info_cache_mutex); - parameter_info_cache.parameter_count = result; + std::lock_guard lock(function_result_cache_mutex); + function_result_cache.parameter_count = result; } return result; @@ -584,9 +586,9 @@ tresult PLUGIN_API Vst3PluginProxyImpl::getParameterInfo( .instance_id = instance_id(), .param_index = paramIndex}; { - std::lock_guard lock(parameter_info_cache_mutex); - if (auto it = parameter_info_cache.parameter_info.find(paramIndex); - it != parameter_info_cache.parameter_info.end()) { + std::lock_guard lock(function_result_cache_mutex); + if (auto it = function_result_cache.parameter_info.find(paramIndex); + it != function_result_cache.parameter_info.end()) { const bool log_response = bridge.logger.log_request(true, request); if (log_response) { bridge.logger.log_response( @@ -607,8 +609,8 @@ tresult PLUGIN_API Vst3PluginProxyImpl::getParameterInfo( info = response.info; { - std::lock_guard lock(parameter_info_cache_mutex); - parameter_info_cache.parameter_info[paramIndex] = response.info; + std::lock_guard lock(function_result_cache_mutex); + function_result_cache.parameter_info[paramIndex] = response.info; } return response.result; @@ -1286,8 +1288,3 @@ void Vst3PluginProxyImpl::clear_bus_cache() { processing_bus_cache.emplace(); } } - -void Vst3PluginProxyImpl::clear_parameter_cache() { - std::lock_guard lock(parameter_info_cache_mutex); - parameter_info_cache = ParameterInfoCache{}; -} diff --git a/src/plugin/bridges/vst3-impls/plugin-proxy.h b/src/plugin/bridges/vst3-impls/plugin-proxy.h index c8b228b4..df9dbc8a 100644 --- a/src/plugin/bridges/vst3-impls/plugin-proxy.h +++ b/src/plugin/bridges/vst3-impls/plugin-proxy.h @@ -62,17 +62,15 @@ class Vst3PluginProxyImpl : public Vst3PluginProxy { bool unregister_context_menu(size_t context_menu_id); /** - * Clear the bus and parameter caches. We'll call this on - * `IComponentHandler::restartComponent`. These caching layers are necessary - * to get decent performance in REAPER as REAPER repeatedly calls these - * functions many times per second, even though their values will never - * change. + * Clear our function call caches. We'll do this when the plugin calls + * `IComponentHandler::restartComponent()`. These caching layers are + * necessary to get decent performance in certain hosts because they will + * call these functions repeatedly even when their values cannot change. * - * HACK: See the doc comment on this class for more information on these - * caches + * See the bottom of this class for more information on what we're caching. * * @see clear_bus_cache - * @see clear_parameter_cache + * @see function_result_cache */ void clear_caches(); @@ -301,7 +299,7 @@ class Vst3PluginProxyImpl : public Vst3PluginProxy { // From `IXmlRepresentationController` tresult PLUGIN_API getXmlRepresentationStream(Steinberg::Vst::RepresentationInfo& info /*in*/, - Steinberg::IBStream* stream /*out*/); + Steinberg::IBStream* stream /*out*/) override; /** * The component handler the host passed to us during @@ -419,17 +417,6 @@ class Vst3PluginProxyImpl : public Vst3PluginProxy { */ void clear_bus_cache(); - /** - * Clears the parameter information cache. Normally hosts only have to - * request this once, since the information never changes. REAPER however in - * some situations asks for this information four times per second. This - * extra back and forth can really add up once plugins start having - * thousands of parameters. - * - * @see parameter_info_cache - */ - void clear_parameter_cache(); - /** * If we have an active `IPlugView` instance, try to use the mutual * recursion mechanism so that callbacks made by the plugin can be handled @@ -536,29 +523,38 @@ class Vst3PluginProxyImpl : public Vst3PluginProxy { std::mutex processing_bus_cache_mutex; /** - * A cache for `IEditController::getParameterCount()` and - * `IEditController::getParameterInfo()`. We'll memoize these function calls - * until the plugin tells the host that parameter information has changed. + * A cache for several function calls that should be safe to cache since + * their values shouldn't change at run time. We'll memoize these function + * calls until the plugin tells the host that parameter information has + * changed. * - * @see parameter_cache + * @see function_result_cache */ - struct ParameterInfoCache { + struct FunctionResultCache { + /** + * Memoizes `IEditController::getParameterCount()`. + */ std::optional parameter_count; + /** + * Memoizes `IEditController::getParameterInfo()`. + */ std::map parameter_info; }; /** - * A cache for the parameter count and infos. This used to be necessary - * because in some situations REAPER would query this information many times - * times per second even though it cannot change unless the plugin tells the - * host that it has. This issue has since been fixed, but we'll keep it in - * because some other hosts also query this information more than once. + * A cache for several frequently called functions that should not change + * values unless the plugin calls `IComponentHandler::restartComponent()`. + * This used to be necessary because in some situations REAPER would query + * this information many times times per second even though it cannot change + * unless the plugin tells the host that it has. This issue has since been + * fixed, but we'll keep it in because some other hosts also query this + * information more than once. * * The cache will be cleared when the plugin tells the host that some of its * parameter values have changed. * - * @see clear_parameter_cache + * @see clear_caches */ - ParameterInfoCache parameter_info_cache; - std::mutex parameter_info_cache_mutex; + FunctionResultCache function_result_cache; + std::mutex function_result_cache_mutex; };