From c983528862987d248c6dcf0db83ed08f3c8dae76 Mon Sep 17 00:00:00 2001 From: Hamish Milne Date: Sun, 19 Jan 2020 22:49:22 +0000 Subject: [PATCH] Reworked DSP serialization --- externals/boost | 2 +- src/audio_core/dsp_interface.h | 5 +++ src/audio_core/hle/hle.cpp | 37 +++++++++++++++++--- src/audio_core/hle/hle.h | 9 +++++ src/audio_core/hle/mixers.h | 12 +++++++ src/audio_core/hle/shared_memory.h | 7 ++++ src/audio_core/hle/source.h | 54 ++++++++++++++++++++++++++++-- src/core/core.cpp | 15 ++++++--- 8 files changed, 128 insertions(+), 13 deletions(-) diff --git a/externals/boost b/externals/boost index 6d7edc593..eb10fac1e 160000 --- a/externals/boost +++ b/externals/boost @@ -1 +1 @@ -Subproject commit 6d7edc593be8e47c8de7bc5f7d6b32971fad0c24 +Subproject commit eb10fac1e1dfa4881c273d87e23d41509017223a diff --git a/src/audio_core/dsp_interface.h b/src/audio_core/dsp_interface.h index fc3d7cab2..00adfa3ea 100644 --- a/src/audio_core/dsp_interface.h +++ b/src/audio_core/dsp_interface.h @@ -6,6 +6,7 @@ #include #include +#include #include "audio_core/audio_types.h" #include "audio_core/time_stretch.h" #include "common/common_types.h" @@ -113,6 +114,10 @@ private: Common::RingBuffer fifo; std::array last_frame{}; TimeStretcher time_stretcher; + + template + void serialize(Archive& ar, const unsigned int) {} + friend class boost::serialization::access; }; } // namespace AudioCore diff --git a/src/audio_core/hle/hle.cpp b/src/audio_core/hle/hle.cpp index 873d6a72e..f96e2b642 100644 --- a/src/audio_core/hle/hle.cpp +++ b/src/audio_core/hle/hle.cpp @@ -1,7 +1,13 @@ +#pragma optimize("", off) // Copyright 2017 Citra Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include +#include +#include +#include +#include #include "audio_core/audio_types.h" #ifdef HAVE_MF #include "audio_core/hle/wmf_decoder.h" @@ -22,11 +28,21 @@ #include "core/core.h" #include "core/core_timing.h" +SERIALIZE_EXPORT_IMPL(AudioCore::DspHle) + using InterruptType = Service::DSP::DSP_DSP::InterruptType; using Service::DSP::DSP_DSP; namespace AudioCore { +DspHle::DspHle() : DspHle(Core::System::GetInstance().Memory()) {} + +template +void DspHle::serialize(Archive& ar, const unsigned int) { + ar& boost::serialization::base_object(*this); + ar&* impl.get(); +} + static constexpr u64 audio_frame_ticks = 1310252ull; ///< Units: ARM11 cycles struct DspHle::Impl final { @@ -60,7 +76,7 @@ private: void AudioTickCallback(s64 cycles_late); DspState dsp_state = DspState::Off; - std::array, num_dsp_pipe> pipe_data; + std::array, num_dsp_pipe> pipe_data{}; HLE::DspMemory dsp_memory; std::array sources{{ @@ -70,14 +86,25 @@ private: HLE::Source(15), HLE::Source(16), HLE::Source(17), HLE::Source(18), HLE::Source(19), HLE::Source(20), HLE::Source(21), HLE::Source(22), HLE::Source(23), }}; - HLE::Mixers mixers; + HLE::Mixers mixers{}; DspHle& parent; - Core::TimingEventType* tick_event; + Core::TimingEventType* tick_event{}; - std::unique_ptr decoder; + std::unique_ptr decoder{}; - std::weak_ptr dsp_dsp; + std::weak_ptr dsp_dsp{}; + + template + void serialize(Archive& ar, const unsigned int) { + ar& dsp_state; + ar& pipe_data; + ar& dsp_memory.raw_memory; + ar& sources; + ar& mixers; + ar& dsp_dsp; + } + friend class boost::serialization::access; }; DspHle::Impl::Impl(DspHle& parent_, Memory::MemorySystem& memory) : parent(parent_) { diff --git a/src/audio_core/hle/hle.h b/src/audio_core/hle/hle.h index 4ab468331..11ec2820a 100644 --- a/src/audio_core/hle/hle.h +++ b/src/audio_core/hle/hle.h @@ -7,6 +7,7 @@ #include #include #include +#include #include "audio_core/audio_types.h" #include "audio_core/dsp_interface.h" #include "common/common_types.h" @@ -42,6 +43,14 @@ private: struct Impl; friend struct Impl; std::unique_ptr impl; + + DspHle(); + + template + void serialize(Archive& ar, const unsigned int); + friend class boost::serialization::access; }; } // namespace AudioCore + +BOOST_CLASS_EXPORT_KEY(AudioCore::DspHle) diff --git a/src/audio_core/hle/mixers.h b/src/audio_core/hle/mixers.h index c5bfd512f..5043be38c 100644 --- a/src/audio_core/hle/mixers.h +++ b/src/audio_core/hle/mixers.h @@ -5,6 +5,7 @@ #pragma once #include +#include #include "audio_core/audio_types.h" #include "audio_core/hle/shared_memory.h" @@ -54,6 +55,17 @@ private: void DownmixAndMixIntoCurrentFrame(float gain, const QuadFrame32& samples); /// INTERNAL: Generate DspStatus based on internal state. DspStatus GetCurrentStatus() const; + + template + void serialize(Archive& ar, const unsigned int) { + ar& current_frame; + ar& state.intermediate_mixer_volume; + ar& state.mixer1_enabled; + ar& state.mixer2_enabled; + ar& state.intermediate_mix_buffer; + ar& state.output_format; + } + friend class boost::serialization::access; }; } // namespace AudioCore::HLE diff --git a/src/audio_core/hle/shared_memory.h b/src/audio_core/hle/shared_memory.h index 8ab9aa88e..43bf1df69 100644 --- a/src/audio_core/hle/shared_memory.h +++ b/src/audio_core/hle/shared_memory.h @@ -8,6 +8,7 @@ #include #include #include +#include #include "audio_core/audio_types.h" #include "audio_core/hle/common.h" #include "common/bit_field.h" @@ -56,6 +57,12 @@ private: return (value << 16) | (value >> 16); } u32_le storage; + + template + void serialize(Archive& ar, const unsigned int) { + ar& storage; + } + friend class boost::serialization::access; }; static_assert(std::is_trivially_copyable::value, "u32_dsp isn't trivially copyable"); diff --git a/src/audio_core/hle/source.h b/src/audio_core/hle/source.h index b0db4a5d3..17c31672b 100644 --- a/src/audio_core/hle/source.h +++ b/src/audio_core/hle/source.h @@ -6,6 +6,10 @@ #include #include +#include +#include +#include +#include #include #include "audio_core/audio_types.h" #include "audio_core/codec.h" @@ -85,6 +89,24 @@ private: bool from_queue; u32_dsp play_position; // = 0; bool has_played; // = false; + + private: + template + void serialize(Archive& ar, const unsigned int) { + ar& physical_address; + ar& length; + ar& adpcm_ps; + ar& adpcm_yn; + ar& adpcm_dirty; + ar& is_looping; + ar& buffer_id; + ar& mono_or_stereo; + ar& format; + ar& from_queue; + ar& play_position; + ar& has_played; + } + friend class boost::serialization::access; }; struct BufferOrder { @@ -107,7 +129,7 @@ private: // Buffer queue - std::priority_queue, BufferOrder> input_queue; + std::priority_queue, BufferOrder> input_queue = {}; MonoOrStereo mono_or_stereo = MonoOrStereo::Mono; Format format = Format::ADPCM; @@ -115,7 +137,7 @@ private: u32 current_sample_number = 0; u32 next_sample_number = 0; - AudioInterp::StereoBuffer16 current_buffer; + AudioInterp::StereoBuffer16 current_buffer = {}; // buffer_id state @@ -135,7 +157,27 @@ private: // Filter state - SourceFilters filters; + SourceFilters filters = {}; + + private: + template + void serialize(Archive& ar, const unsigned int) { + ar& enabled; + ar& sync; + ar& gain; + ar& input_queue; + ar& mono_or_stereo; + ar& format; + ar& current_sample_number; + ar& next_sample_number; + ar& current_buffer; + ar& buffer_update; + ar& current_buffer_id; + ar& adpcm_coeffs; + ar& rate_multiplier; + ar& interpolation_mode; + } + friend class boost::serialization::access; } state; @@ -150,6 +192,12 @@ private: bool DequeueBuffer(); /// INTERNAL: Generates a SourceStatus::Status based on our internal state. SourceStatus::Status GetCurrentStatus(); + + template + void serialize(Archive& ar, const unsigned int) { + ar& state; + } + friend class boost::serialization::access; }; } // namespace AudioCore::HLE diff --git a/src/core/core.cpp b/src/core/core.cpp index aeab0d2b5..03b64b04e 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -1,3 +1,4 @@ +#pragma optimize("", off) // Copyright 2014 Citra Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -244,8 +245,8 @@ System::ResultStatus System::Init(Frontend::EmuWindow& emu_window, u32 system_mo timing = std::make_unique(); - kernel = std::make_unique(*memory, *timing, - [this] { PrepareReschedule(); }, system_mode); + kernel = std::make_unique( + *memory, *timing, [this] { PrepareReschedule(); }, system_mode); if (Settings::values.use_cpu_jit) { #ifdef ARCHITECTURE_x86_64 @@ -445,14 +446,20 @@ void System::serialize(Archive& ar, const unsigned int file_version) { ar&* service_manager.get(); ar& GPU::g_regs; ar& LCD::g_regs; - ar & dsp_core->GetDspMemory(); + if (Archive::is_loading::value) { + dsp_core.reset(); + } + ar& dsp_core; ar&* memory.get(); ar&* kernel.get(); // This needs to be set from somewhere - might as well be here! if (Archive::is_loading::value) { Service::GSP::SetGlobalModule(*this); - DSP().SetServiceToInterrupt(ServiceManager().GetService("dsp::DSP")); + + memory->SetDSP(*dsp_core); + dsp_core->SetSink(Settings::values.sink_id, Settings::values.audio_device_id); + dsp_core->EnableStretching(Settings::values.enable_audio_stretching); } }