From 7c49fe739df2a9b83984c8c4e0db926dd5b6067d Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Sat, 22 May 2021 17:38:07 +0200 Subject: [PATCH] Use our new custom std::variant bitsery extension This prevents reinitializing `std::variant`s when the variant we want to deserialize is already active. We store audio buffers in variants, so reinitializing them results in a lot of unnecessary memory frees, allocations and writes during every processing cycle. --- CHANGELOG.md | 6 ++++++ src/common/serialization/vst2.h | 8 ++++---- src/common/serialization/vst3.h | 8 ++++---- src/common/serialization/vst3/event-list.h | 4 ++-- src/common/serialization/vst3/plugin-proxy.h | 7 ++++--- src/common/serialization/vst3/plugin/connection-point.h | 4 ++-- src/common/serialization/vst3/process-data.h | 4 ++-- 7 files changed, 24 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 10e5ab8e..a8640f46 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,12 @@ Versioning](https://semver.org/spec/v2.0.0.html). - Redesigned the VST3 audio socket handling to be able to reuse the process data objects on both sides. This greatly reduces the overhead of our VST3 bridging by getting rid of all memory allocations during audio processing. +- Considerably optimized both VST2 and VST3 audio processing by preventing + unnecessary memory operations. As it turns out, the underlying binary + serialization library used by yabridge would always reinitialize the type-safe + unions yabridge uses to differentiate between single and double precision + floating point audio buffers, undoing all of our efforts at reusing objects + and preventing memory allocations in the process. - Changed the way mutual recursion in VST3 plugins on the plugin side works to counter any potential GUI related timing issues with VST3 plugins. - The deserialization part of yabridge's communication is now slightly faster by diff --git a/src/common/serialization/vst2.h b/src/common/serialization/vst2.h index e01a8c0a..0b858ece 100644 --- a/src/common/serialization/vst2.h +++ b/src/common/serialization/vst2.h @@ -19,7 +19,7 @@ #include #include -#include +#include "../bitsery/ext/in-place-variant.h" #include #include #include @@ -402,7 +402,7 @@ struct Vst2Event { template void serialize(S& s, Vst2Event::Payload& payload) { s.ext(payload, - bitsery::ext::StdVariant{ + bitsery::ext::InPlaceVariant{ [](S&, std::nullptr_t&) {}, [](S& s, std::string& string) { s.text1b(string, max_string_length); @@ -486,7 +486,7 @@ struct Vst2EventResult { template void serialize(S& s, Vst2EventResult::Payload& payload) { s.ext(payload, - bitsery::ext::StdVariant{ + bitsery::ext::InPlaceVariant{ [](S&, std::nullptr_t&) {}, [](S& s, std::string& string) { s.text1b(string, max_string_length); @@ -585,7 +585,7 @@ struct AudioBuffers { void serialize(S& s) { s.ext( buffers, - bitsery::ext::StdVariant{ + bitsery::ext::InPlaceVariant{ [](S& s, std::vector>& buffer) { s.container(buffer, max_audio_channels, [](S& s, auto& v) { s.container4b(v, max_buffer_size); diff --git a/src/common/serialization/vst3.h b/src/common/serialization/vst3.h index 94d726d3..66d6a639 100644 --- a/src/common/serialization/vst3.h +++ b/src/common/serialization/vst3.h @@ -18,7 +18,7 @@ #include -#include +#include "../bitsery/ext/in-place-variant.h" #include "../bitsery/ext/message-reference.h" #include "../configuration.h" @@ -147,7 +147,7 @@ template void serialize(S& s, ControlRequest& payload) { // All of the objects in `ControlRequest` should have their own // serialization function. - s.ext(payload, bitsery::ext::StdVariant{}); + s.ext(payload, bitsery::ext::InPlaceVariant{}); } /** @@ -202,7 +202,7 @@ struct AudioProcessorRequest { void serialize(S& s) { s.ext( payload, - bitsery::ext::StdVariant{ + bitsery::ext::InPlaceVariant{ [&](S& s, MessageReference& request_ref) { // When serializing this reference we'll read the data @@ -268,7 +268,7 @@ template void serialize(S& s, CallbackRequest& payload) { // All of the objects in `CallbackRequest` should have their own // serialization function. - s.ext(payload, bitsery::ext::StdVariant{}); + s.ext(payload, bitsery::ext::InPlaceVariant{}); } /** diff --git a/src/common/serialization/vst3/event-list.h b/src/common/serialization/vst3/event-list.h index 7e1a2f06..c0eb8cfb 100644 --- a/src/common/serialization/vst3/event-list.h +++ b/src/common/serialization/vst3/event-list.h @@ -16,7 +16,7 @@ #pragma once -#include +#include "../../bitsery/ext/in-place-variant.h" #include #include "base.h" @@ -202,7 +202,7 @@ struct YaEvent { s.value4b(sample_offset); s.value8b(ppq_position); s.value2b(flags); - s.ext(payload, bitsery::ext::StdVariant{}); + s.ext(payload, bitsery::ext::InPlaceVariant{}); } }; diff --git a/src/common/serialization/vst3/plugin-proxy.h b/src/common/serialization/vst3/plugin-proxy.h index 84ac2512..0fc350bc 100644 --- a/src/common/serialization/vst3/plugin-proxy.h +++ b/src/common/serialization/vst3/plugin-proxy.h @@ -16,7 +16,7 @@ #pragma once -#include +#include "../../bitsery/ext/in-place-variant.h" #include "../common.h" #include "plugin/audio-presentation-latency.h" @@ -101,7 +101,8 @@ class Vst3PluginProxy : public YaAudioPresentationLatency, * Read from an existing object. We will try to mimic this object, so * we'll support any interfaces this object also supports. */ - ConstructArgs(Steinberg::IPtr object, size_t instance_id) noexcept; + ConstructArgs(Steinberg::IPtr object, + size_t instance_id) noexcept; /** * The unique identifier for this specific object instance. @@ -296,5 +297,5 @@ template void serialize( S& s, std::variant& result) { - s.ext(result, bitsery::ext::StdVariant{}); + s.ext(result, bitsery::ext::InPlaceVariant{}); } diff --git a/src/common/serialization/vst3/plugin/connection-point.h b/src/common/serialization/vst3/plugin/connection-point.h index d8e9153e..6e31109e 100644 --- a/src/common/serialization/vst3/plugin/connection-point.h +++ b/src/common/serialization/vst3/plugin/connection-point.h @@ -19,7 +19,7 @@ #include #include -#include +#include "../../../bitsery/ext/in-place-variant.h" #include #include "../../common.h" @@ -133,7 +133,7 @@ class YaConnectionPoint : public Steinberg::Vst::IConnectionPoint { void serialize(S& s) { s.value8b(instance_id); s.ext(other, - bitsery::ext::StdVariant{ + bitsery::ext::InPlaceVariant{ [](S& s, native_size_t& other_instance_id) { s.value8b(other_instance_id); }, diff --git a/src/common/serialization/vst3/process-data.h b/src/common/serialization/vst3/process-data.h index 4988369d..e4141079 100644 --- a/src/common/serialization/vst3/process-data.h +++ b/src/common/serialization/vst3/process-data.h @@ -19,8 +19,8 @@ #include #include -#include #include +#include "../../bitsery/ext/in-place-variant.h" #include "base.h" #include "event-list.h" @@ -89,7 +89,7 @@ class YaAudioBusBuffers { template void serialize(S& s) { s.value8b(silence_flags); - s.ext(buffers, bitsery::ext::StdVariant{ + s.ext(buffers, bitsery::ext::InPlaceVariant{ [](S& s, std::vector>& buffers) { s.container(buffers, max_num_speakers, [](S& s, auto& channel) {