From 0f6c8ffea1fd64b43e50977f79aed9979357bd32 Mon Sep 17 00:00:00 2001 From: pineappleEA Date: Sat, 11 Feb 2023 18:11:06 +0100 Subject: [PATCH] early-access version 3384 --- README.md | 2 +- src/audio_core/device/audio_buffers.h | 20 ++--- src/audio_core/device/device_session.cpp | 16 ++-- src/audio_core/device/device_session.h | 2 +- src/audio_core/in/audio_in_system.cpp | 14 ++- src/audio_core/out/audio_out_system.cpp | 14 ++- .../renderer/command/command_generator.cpp | 2 +- .../renderer/command/data_source/decode.cpp | 14 ++- .../renderer/command/effect/aux_.cpp | 90 ++++++++----------- .../renderer/command/effect/compressor.cpp | 11 +-- .../renderer/command/effect/delay.cpp | 15 ++-- .../renderer/command/effect/i3dl2_reverb.cpp | 7 +- .../renderer/command/effect/light_limiter.cpp | 17 ++-- .../renderer/command/effect/reverb.cpp | 15 ++-- .../renderer/command/sink/circular_buffer.cpp | 5 +- .../renderer/command/sink/device.cpp | 3 +- src/audio_core/sink/null_sink.h | 3 +- src/audio_core/sink/sink_stream.cpp | 8 +- src/audio_core/sink/sink_stream.h | 3 +- src/common/scratch_buffer.h | 18 ---- src/video_core/buffer_cache/buffer_base.h | 5 ++ src/video_core/buffer_cache/buffer_cache.h | 33 +++---- .../renderer_opengl/gl_rasterizer.cpp | 16 ++-- .../renderer_vulkan/vk_rasterizer.cpp | 26 +++--- 24 files changed, 144 insertions(+), 215 deletions(-) diff --git a/README.md b/README.md index f503ef5c9..48cdd1564 100755 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ yuzu emulator early access ============= -This is the source code for early-access 3383. +This is the source code for early-access 3384. ## Legal Notice diff --git a/src/audio_core/device/audio_buffers.h b/src/audio_core/device/audio_buffers.h index e79abaf5b..1e1616f4e 100755 --- a/src/audio_core/device/audio_buffers.h +++ b/src/audio_core/device/audio_buffers.h @@ -48,7 +48,7 @@ public: * * @param out_buffers - The buffers which were registered. */ - void RegisterBuffers(std::span out_buffers, u32& out_size) { + void RegisterBuffers(std::vector& out_buffers) { std::scoped_lock l{lock}; const s32 to_register{std::min(std::min(appended_count, BufferAppendLimit), BufferAppendLimit - registered_count)}; @@ -59,7 +59,7 @@ public: index += N; } - out_buffers[out_size++] = buffers[index]; + out_buffers.push_back(buffers[index]); registered_count++; registered_index = (registered_index + 1) % append_limit; @@ -162,7 +162,7 @@ public: * @param max_buffers - Maximum number of buffers to released. * @return The number of buffers released. */ - u32 GetRegisteredAppendedBuffers(std::span out_buffers, u32 max_buffers) { + u32 GetRegisteredAppendedBuffers(std::vector& buffers_flushed, u32 max_buffers) { std::scoped_lock l{lock}; if (registered_count + appended_count == 0) { return 0; @@ -174,20 +174,19 @@ public: return 0; } - u32 buffers_flushed{0}; while (registered_count > 0) { auto index{registered_index - registered_count}; if (index < 0) { index += N; } - out_buffers[buffers_flushed++] = buffers[index]; + buffers_flushed.push_back(buffers[index]); registered_count--; released_count++; released_index = (released_index + 1) % append_limit; - if (buffers_flushed >= buffers_to_flush) { + if (buffers_flushed.size() >= buffers_to_flush) { break; } } @@ -198,18 +197,18 @@ public: index += N; } - out_buffers[buffers_flushed++] = buffers[index]; + buffers_flushed.push_back(buffers[index]); appended_count--; released_count++; released_index = (released_index + 1) % append_limit; - if (buffers_flushed >= buffers_to_flush) { + if (buffers_flushed.size() >= buffers_to_flush) { break; } } - return buffers_flushed; + return static_cast(buffers_flushed.size()); } /** @@ -271,9 +270,8 @@ public: */ bool FlushBuffers(u32& buffers_released) { std::scoped_lock l{lock}; + std::vector buffers_flushed{}; - static Common::ScratchBuffer buffers_flushed{}; - buffers_flushed.resize_destructive(append_limit); buffers_released = GetRegisteredAppendedBuffers(buffers_flushed, append_limit); if (registered_count > 0) { diff --git a/src/audio_core/device/device_session.cpp b/src/audio_core/device/device_session.cpp index fcf3d2b79..f60bd14e9 100755 --- a/src/audio_core/device/device_session.cpp +++ b/src/audio_core/device/device_session.cpp @@ -6,7 +6,6 @@ #include "audio_core/device/audio_buffer.h" #include "audio_core/device/device_session.h" #include "audio_core/sink/sink_stream.h" -#include "common/scratch_buffer.h" #include "core/core.h" #include "core/core_timing.h" #include "core/memory.h" @@ -80,22 +79,21 @@ void DeviceSession::ClearBuffers() { } } -void DeviceSession::AppendBuffers(std::span buffers, u32 out_size) const { - static Common::ScratchBuffer samples{}; - - for (u32 i = 0; i < out_size; i++) { +void DeviceSession::AppendBuffers(std::span buffers) const { + for (const auto& buffer : buffers) { Sink::SinkBuffer new_buffer{ - .frames = buffers[i].size / (channel_count * sizeof(s16)), + .frames = buffer.size / (channel_count * sizeof(s16)), .frames_played = 0, - .tag = buffers[i].tag, + .tag = buffer.tag, .consumed = false, }; if (type == Sink::StreamType::In) { + std::vector samples{}; stream->AppendBuffer(new_buffer, samples); } else { - samples.resize_destructive(buffers[i].size / sizeof(s16)); - system.Memory().ReadBlockUnsafe(buffers[i].samples, samples.data(), buffers[i].size); + std::vector samples(buffer.size / sizeof(s16)); + system.Memory().ReadBlockUnsafe(buffer.samples, samples.data(), buffer.size); stream->AppendBuffer(new_buffer, samples); } } diff --git a/src/audio_core/device/device_session.h b/src/audio_core/device/device_session.h index e79e1b1d0..f65c850bd 100755 --- a/src/audio_core/device/device_session.h +++ b/src/audio_core/device/device_session.h @@ -62,7 +62,7 @@ public: * * @param buffers - The buffers to play. */ - void AppendBuffers(std::span buffers, u32 out_size) const; + void AppendBuffers(std::span buffers) const; /** * (Audio In only) Pop samples from the backend, and write them back to this buffer's address. diff --git a/src/audio_core/in/audio_in_system.cpp b/src/audio_core/in/audio_in_system.cpp index 90c561291..45aade449 100755 --- a/src/audio_core/in/audio_in_system.cpp +++ b/src/audio_core/in/audio_in_system.cpp @@ -89,10 +89,9 @@ Result System::Start() { session->Start(); state = State::Started; - std::array buffers_to_flush{}; - u32 out_size{0}; - buffers.RegisterBuffers(buffers_to_flush, out_size); - session->AppendBuffers(buffers_to_flush, out_size); + std::vector buffers_to_flush{}; + buffers.RegisterBuffers(buffers_to_flush); + session->AppendBuffers(buffers_to_flush); session->SetRingSize(static_cast(buffers_to_flush.size())); return ResultSuccess; @@ -135,10 +134,9 @@ bool System::AppendBuffer(const AudioInBuffer& buffer, const u64 tag) { void System::RegisterBuffers() { if (state == State::Started) { - std::array registered_buffers{}; - u32 out_size{0}; - buffers.RegisterBuffers(registered_buffers, out_size); - session->AppendBuffers(registered_buffers, out_size); + std::vector registered_buffers{}; + buffers.RegisterBuffers(registered_buffers); + session->AppendBuffers(registered_buffers); } } diff --git a/src/audio_core/out/audio_out_system.cpp b/src/audio_core/out/audio_out_system.cpp index 83cbf8543..9f75cd1a8 100755 --- a/src/audio_core/out/audio_out_system.cpp +++ b/src/audio_core/out/audio_out_system.cpp @@ -89,10 +89,9 @@ Result System::Start() { session->Start(); state = State::Started; - std::array buffers_to_flush{}; - u32 out_size{0}; - buffers.RegisterBuffers(buffers_to_flush, out_size); - session->AppendBuffers(buffers_to_flush, out_size); + std::vector buffers_to_flush{}; + buffers.RegisterBuffers(buffers_to_flush); + session->AppendBuffers(buffers_to_flush); session->SetRingSize(static_cast(buffers_to_flush.size())); return ResultSuccess; @@ -135,10 +134,9 @@ bool System::AppendBuffer(const AudioOutBuffer& buffer, u64 tag) { void System::RegisterBuffers() { if (state == State::Started) { - std::array registered_buffers{}; - u32 out_size{0}; - buffers.RegisterBuffers(registered_buffers, out_size); - session->AppendBuffers(registered_buffers, out_size); + std::vector registered_buffers{}; + buffers.RegisterBuffers(registered_buffers); + session->AppendBuffers(registered_buffers); } } diff --git a/src/audio_core/renderer/command/command_generator.cpp b/src/audio_core/renderer/command/command_generator.cpp index d8ae99461..63cd3f888 100755 --- a/src/audio_core/renderer/command/command_generator.cpp +++ b/src/audio_core/renderer/command/command_generator.cpp @@ -46,7 +46,7 @@ void CommandGenerator::GenerateDataSourceCommand(VoiceInfo& voice_info, while (destination != nullptr) { if (destination->IsConfigured()) { auto mix_id{destination->GetMixId()}; - if (mix_id < mix_context.GetCount() && mix_id != -1) { + if (mix_id < mix_context.GetCount() && mix_id != UnusedSplitterId) { auto mix_info{mix_context.GetInfo(mix_id)}; command_buffer.GenerateDepopPrepareCommand( voice_info.node_id, voice_state, render_context.depop_buffer, diff --git a/src/audio_core/renderer/command/data_source/decode.cpp b/src/audio_core/renderer/command/data_source/decode.cpp index 1e85490dc..d391be35d 100755 --- a/src/audio_core/renderer/command/data_source/decode.cpp +++ b/src/audio_core/renderer/command/data_source/decode.cpp @@ -8,7 +8,6 @@ #include "audio_core/renderer/command/resample/resample.h" #include "common/fixed_point.h" #include "common/logging/log.h" -#include "common/scratch_buffer.h" #include "core/memory.h" namespace AudioCore::AudioRenderer { @@ -30,7 +29,6 @@ static u32 DecodePcm(Core::Memory::Memory& memory, std::span out_buffer, const DecodeArg& req) { constexpr s32 min{std::numeric_limits::min()}; constexpr s32 max{std::numeric_limits::max()}; - static Common::ScratchBuffer samples; if (req.buffer == 0 || req.buffer_size == 0) { return 0; @@ -51,7 +49,7 @@ static u32 DecodePcm(Core::Memory::Memory& memory, std::span out_buffer, const u64 size{channel_count * samples_to_decode}; const u64 size_bytes{size * sizeof(T)}; - samples.resize_destructive(size); + std::vector samples(size); memory.ReadBlockUnsafe(source, samples.data(), size_bytes); if constexpr (std::is_floating_point_v) { @@ -75,7 +73,7 @@ static u32 DecodePcm(Core::Memory::Memory& memory, std::span out_buffer, } const VAddr source{req.buffer + ((req.start_offset + req.offset) * sizeof(T))}; - samples.resize_destructive(samples_to_decode); + std::vector samples(samples_to_decode); memory.ReadBlockUnsafe(source, samples.data(), samples_to_decode * sizeof(T)); if constexpr (std::is_floating_point_v) { @@ -105,7 +103,6 @@ static u32 DecodeAdpcm(Core::Memory::Memory& memory, std::span out_buffer, const DecodeArg& req) { constexpr u32 SamplesPerFrame{14}; constexpr u32 NibblesPerFrame{16}; - static Common::ScratchBuffer wavebuffer; if (req.buffer == 0 || req.buffer_size == 0) { return 0; @@ -141,7 +138,7 @@ static u32 DecodeAdpcm(Core::Memory::Memory& memory, std::span out_buffer, } const auto size{std::max((samples_to_process / 8U) * SamplesPerFrame, 8U)}; - wavebuffer.resize_destructive(size); + std::vector wavebuffer(size); memory.ReadBlockUnsafe(req.buffer + position_in_frame / 2, wavebuffer.data(), wavebuffer.size()); @@ -230,8 +227,6 @@ static u32 DecodeAdpcm(Core::Memory::Memory& memory, std::span out_buffer, * @param args - The wavebuffer data, and information for how to decode it. */ void DecodeFromWaveBuffers(Core::Memory::Memory& memory, const DecodeFromWaveBuffersArgs& args) { - Common::ScratchBuffer temp_buffer(TempBufferSize); - auto& voice_state{*args.voice_state}; auto remaining_sample_count{args.sample_count}; auto fraction{voice_state.fraction}; @@ -261,8 +256,9 @@ void DecodeFromWaveBuffers(Core::Memory::Memory& memory, const DecodeFromWaveBuf bool is_buffer_starved{false}; u32 offset{voice_state.offset}; - std::memset(temp_buffer.data(), 0, temp_buffer.size() * sizeof(s16)); + auto output_buffer{args.output}; + std::vector temp_buffer(TempBufferSize, 0); while (remaining_sample_count > 0) { const auto samples_to_write{std::min(remaining_sample_count, max_remaining_sample_count)}; diff --git a/src/audio_core/renderer/command/effect/aux_.cpp b/src/audio_core/renderer/command/effect/aux_.cpp index eb4624fd7..32873ec49 100755 --- a/src/audio_core/renderer/command/effect/aux_.cpp +++ b/src/audio_core/renderer/command/effect/aux_.cpp @@ -41,11 +41,10 @@ static void ResetAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr aux_in * @param update_count - If non-zero, send_info_ will be updated. * @return Number of samples written. */ -static u32 WriteAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr send_info_, - [[maybe_unused]] u32 sample_count, const CpuAddr send_buffer, - const u32 count_max, std::span input, - const u32 write_count_, const u32 write_offset, - const u32 update_count) { +static u32 WriteAuxBufferDsp(Core::Memory::Memory& memory, CpuAddr send_info_, + [[maybe_unused]] u32 sample_count, CpuAddr send_buffer, u32 count_max, + std::span input, u32 write_count_, u32 write_offset, + u32 update_count) { if (write_count_ > count_max) { LOG_ERROR(Service_Audio, "write_count must be smaller than count_max! write_count {}, count_max {}", @@ -53,6 +52,11 @@ static u32 WriteAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr send_in return 0; } + if (send_info_ == 0) { + LOG_ERROR(Service_Audio, "send_info_ is 0!"); + return 0; + } + if (input.empty()) { LOG_ERROR(Service_Audio, "input buffer is empty!"); return 0; @@ -67,35 +71,30 @@ static u32 WriteAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr send_in return 0; } - AuxInfo::AuxInfoDsp send_info{}; - memory.ReadBlockUnsafe(send_info_, &send_info, sizeof(AuxInfo::AuxInfoDsp)); + auto send_info{reinterpret_cast(memory.GetPointer(send_info_))}; - u32 target_write_offset{send_info.write_offset + write_offset}; - if (target_write_offset > count_max || write_count_ == 0) { + u32 target_write_offset{send_info->write_offset + write_offset}; + if (target_write_offset > count_max) { return 0; } u32 write_count{write_count_}; - u32 write_pos{0}; + u32 read_pos{0}; while (write_count > 0) { u32 to_write{std::min(count_max - target_write_offset, write_count)}; - - if (to_write > 0) { + if (to_write) { memory.WriteBlockUnsafe(send_buffer + target_write_offset * sizeof(s32), - &input[write_pos], to_write * sizeof(s32)); + &input[read_pos], to_write * sizeof(s32)); } - target_write_offset = (target_write_offset + to_write) % count_max; write_count -= to_write; - write_pos += to_write; + read_pos += to_write; } if (update_count) { - send_info.write_offset = (send_info.write_offset + update_count) % count_max; + send_info->write_offset = (send_info->write_offset + update_count) % count_max; } - memory.WriteBlockUnsafe(send_info_, &send_info, sizeof(AuxInfo::AuxInfoDsp)); - return write_count_; } @@ -103,7 +102,7 @@ static u32 WriteAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr send_in * Read the given memory at return_buffer into the output mix buffer, and update return_info_ if * update_count is set, to notify the game that an update happened. * - * @param memory - Core memory for writing. + * @param memory - Core memory for reading. * @param return_info_ - Meta information for where to read the mix buffer. * @param return_buffer - Memory address to read the samples from. * @param count_max - Maximum number of samples in the receiving buffer. @@ -113,16 +112,21 @@ static u32 WriteAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr send_in * @param update_count - If non-zero, send_info_ will be updated. * @return Number of samples read. */ -static u32 ReadAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr return_info_, - const CpuAddr return_buffer, const u32 count_max, std::span output, - const u32 count_, const u32 read_offset, const u32 update_count) { +static u32 ReadAuxBufferDsp(Core::Memory::Memory& memory, CpuAddr return_info_, + CpuAddr return_buffer, u32 count_max, std::span output, + u32 read_count_, u32 read_offset, u32 update_count) { if (count_max == 0) { return 0; } - if (count_ > count_max) { + if (read_count_ > count_max) { LOG_ERROR(Service_Audio, "count must be smaller than count_max! count {}, count_max {}", - count_, count_max); + read_count_, count_max); + return 0; + } + + if (return_info_ == 0) { + LOG_ERROR(Service_Audio, "return_info_ is 0!"); return 0; } @@ -136,36 +140,31 @@ static u32 ReadAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr return_i return 0; } - AuxInfo::AuxInfoDsp return_info{}; - memory.ReadBlockUnsafe(return_info_, &return_info, sizeof(AuxInfo::AuxInfoDsp)); + auto return_info{reinterpret_cast(memory.GetPointer(return_info_))}; - u32 target_read_offset{return_info.read_offset + read_offset}; + u32 target_read_offset{return_info->read_offset + read_offset}; if (target_read_offset > count_max) { return 0; } - u32 read_count{count_}; - u32 read_pos{0}; + u32 read_count{read_count_}; + u32 write_pos{0}; while (read_count > 0) { u32 to_read{std::min(count_max - target_read_offset, read_count)}; - - if (to_read > 0) { + if (to_read) { memory.ReadBlockUnsafe(return_buffer + target_read_offset * sizeof(s32), - &output[read_pos], to_read * sizeof(s32)); + &output[write_pos], to_read * sizeof(s32)); } - target_read_offset = (target_read_offset + to_read) % count_max; read_count -= to_read; - read_pos += to_read; + write_pos += to_read; } if (update_count) { - return_info.read_offset = (return_info.read_offset + update_count) % count_max; + return_info->read_offset = (return_info->read_offset + update_count) % count_max; } - memory.WriteBlockUnsafe(return_info_, &return_info, sizeof(AuxInfo::AuxInfoDsp)); - - return count_; + return read_count_; } void AuxCommand::Dump([[maybe_unused]] const ADSP::CommandListProcessor& processor, @@ -175,19 +174,6 @@ void AuxCommand::Dump([[maybe_unused]] const ADSP::CommandListProcessor& process } void AuxCommand::Process(const ADSP::CommandListProcessor& processor) { - // HACK! - // Ignore aux for Super Mario Odyssey and Metroid Prime Remastered. - // For some reason these games receive output samples, and then send them back in as input - // again. Problem is the data being sent back in is slightly offset from the current output by - // 240 or 480 samples, leading to a very fast echoing effect, which should not be there. - // Timing issue or some bug in the code? - // We can't disable this unconditionally as some games rely on it for synchronisation and will - // softlock without it (Age of Calamity). - const auto program_id = processor.system->GetCurrentProcessProgramID(); - if (program_id == 0x0100000000010000ull || program_id == 0x010012101468C000ull) { - return; - } - auto input_buffer{ processor.mix_buffers.subspan(input * processor.sample_count, processor.sample_count)}; auto output_buffer{ @@ -203,7 +189,7 @@ void AuxCommand::Process(const ADSP::CommandListProcessor& processor) { update_count)}; if (read != processor.sample_count) { - std::memset(&output_buffer[read], 0, processor.sample_count - read); + std::memset(&output_buffer[read], 0, (processor.sample_count - read) * sizeof(s32)); } } else { ResetAuxBufferDsp(*processor.memory, send_buffer_info); diff --git a/src/audio_core/renderer/command/effect/compressor.cpp b/src/audio_core/renderer/command/effect/compressor.cpp index 0b183c334..6f4032615 100755 --- a/src/audio_core/renderer/command/effect/compressor.cpp +++ b/src/audio_core/renderer/command/effect/compressor.cpp @@ -8,7 +8,6 @@ #include "audio_core/renderer/adsp/command_list_processor.h" #include "audio_core/renderer/command/effect/compressor.h" #include "audio_core/renderer/effect/compressor.h" -#include "common/scratch_buffer.h" namespace AudioCore::AudioRenderer { @@ -45,8 +44,8 @@ static void InitializeCompressorEffect(const CompressorInfo::ParameterVersion2& static void ApplyCompressorEffect(const CompressorInfo::ParameterVersion2& params, CompressorInfo::State& state, bool enabled, - std::span> input_buffers, - std::span> output_buffers, u32 sample_count) { + std::vector> input_buffers, + std::vector> output_buffers, u32 sample_count) { if (enabled) { auto state_00{state.unk_00}; auto state_04{state.unk_04}; @@ -125,10 +124,8 @@ void CompressorCommand::Dump([[maybe_unused]] const ADSP::CommandListProcessor& } void CompressorCommand::Process(const ADSP::CommandListProcessor& processor) { - static Common::ScratchBuffer> input_buffers{}; - static Common::ScratchBuffer> output_buffers{}; - input_buffers.resize_destructive(parameter.channel_count); - output_buffers.resize_destructive(parameter.channel_count); + std::vector> input_buffers(parameter.channel_count); + std::vector> output_buffers(parameter.channel_count); for (s16 i = 0; i < parameter.channel_count; i++) { input_buffers[i] = processor.mix_buffers.subspan(inputs[i] * processor.sample_count, diff --git a/src/audio_core/renderer/command/effect/delay.cpp b/src/audio_core/renderer/command/effect/delay.cpp index 7ac6d4bfa..595667446 100755 --- a/src/audio_core/renderer/command/effect/delay.cpp +++ b/src/audio_core/renderer/command/effect/delay.cpp @@ -3,7 +3,6 @@ #include "audio_core/renderer/adsp/command_list_processor.h" #include "audio_core/renderer/command/effect/delay.h" -#include "common/scratch_buffer.h" namespace AudioCore::AudioRenderer { /** @@ -75,8 +74,8 @@ static void InitializeDelayEffect(const DelayInfo::ParameterVersion1& params, */ template static void ApplyDelay(const DelayInfo::ParameterVersion1& params, DelayInfo::State& state, - std::span> inputs, std::span> outputs, - const u32 sample_count) { + std::vector>& inputs, + std::vector>& outputs, const u32 sample_count) { for (u32 sample_index = 0; sample_index < sample_count; sample_index++) { std::array, NumChannels> input_samples{}; for (u32 channel = 0; channel < NumChannels; channel++) { @@ -154,8 +153,8 @@ static void ApplyDelay(const DelayInfo::ParameterVersion1& params, DelayInfo::St * @param sample_count - Number of samples to process. */ static void ApplyDelayEffect(const DelayInfo::ParameterVersion1& params, DelayInfo::State& state, - const bool enabled, std::span> inputs, - std::span> outputs, const u32 sample_count) { + const bool enabled, std::vector>& inputs, + std::vector>& outputs, const u32 sample_count) { if (!IsChannelCountValid(params.channel_count)) { LOG_ERROR(Service_Audio, "Invalid delay channels {}", params.channel_count); @@ -209,10 +208,8 @@ void DelayCommand::Dump([[maybe_unused]] const ADSP::CommandListProcessor& proce } void DelayCommand::Process(const ADSP::CommandListProcessor& processor) { - static Common::ScratchBuffer> input_buffers{}; - static Common::ScratchBuffer> output_buffers{}; - input_buffers.resize_destructive(parameter.channel_count); - output_buffers.resize_destructive(parameter.channel_count); + std::vector> input_buffers(parameter.channel_count); + std::vector> output_buffers(parameter.channel_count); for (s16 i = 0; i < parameter.channel_count; i++) { input_buffers[i] = processor.mix_buffers.subspan(inputs[i] * processor.sample_count, diff --git a/src/audio_core/renderer/command/effect/i3dl2_reverb.cpp b/src/audio_core/renderer/command/effect/i3dl2_reverb.cpp index d6651a7f7..5003b916b 100755 --- a/src/audio_core/renderer/command/effect/i3dl2_reverb.cpp +++ b/src/audio_core/renderer/command/effect/i3dl2_reverb.cpp @@ -6,7 +6,6 @@ #include "audio_core/renderer/adsp/command_list_processor.h" #include "audio_core/renderer/command/effect/i3dl2_reverb.h" #include "common/polyfill_ranges.h" -#include "common/scratch_buffer.h" namespace AudioCore::AudioRenderer { @@ -409,10 +408,8 @@ void I3dl2ReverbCommand::Dump([[maybe_unused]] const ADSP::CommandListProcessor& } void I3dl2ReverbCommand::Process(const ADSP::CommandListProcessor& processor) { - static Common::ScratchBuffer> input_buffers{}; - static Common::ScratchBuffer> output_buffers{}; - input_buffers.resize_destructive(parameter.channel_count); - output_buffers.resize_destructive(parameter.channel_count); + std::vector> input_buffers(parameter.channel_count); + std::vector> output_buffers(parameter.channel_count); for (u32 i = 0; i < parameter.channel_count; i++) { input_buffers[i] = processor.mix_buffers.subspan(inputs[i] * processor.sample_count, diff --git a/src/audio_core/renderer/command/effect/light_limiter.cpp b/src/audio_core/renderer/command/effect/light_limiter.cpp index d1a72f5cd..4c57350a9 100755 --- a/src/audio_core/renderer/command/effect/light_limiter.cpp +++ b/src/audio_core/renderer/command/effect/light_limiter.cpp @@ -3,7 +3,6 @@ #include "audio_core/renderer/adsp/command_list_processor.h" #include "audio_core/renderer/command/effect/light_limiter.h" -#include "common/scratch_buffer.h" namespace AudioCore::AudioRenderer { /** @@ -48,8 +47,8 @@ static void InitializeLightLimiterEffect(const LightLimiterInfo::ParameterVersio */ static void ApplyLightLimiterEffect(const LightLimiterInfo::ParameterVersion2& params, LightLimiterInfo::State& state, const bool enabled, - std::span> inputs, - std::span> outputs, const u32 sample_count, + std::vector>& inputs, + std::vector>& outputs, const u32 sample_count, LightLimiterInfo::StatisticsInternal* statistics) { constexpr s64 min{std::numeric_limits::min()}; constexpr s64 max{std::numeric_limits::max()}; @@ -148,10 +147,8 @@ void LightLimiterVersion1Command::Dump([[maybe_unused]] const ADSP::CommandListP } void LightLimiterVersion1Command::Process(const ADSP::CommandListProcessor& processor) { - static Common::ScratchBuffer> input_buffers{}; - static Common::ScratchBuffer> output_buffers{}; - input_buffers.resize_destructive(parameter.channel_count); - output_buffers.resize_destructive(parameter.channel_count); + std::vector> input_buffers(parameter.channel_count); + std::vector> output_buffers(parameter.channel_count); for (u32 i = 0; i < parameter.channel_count; i++) { input_buffers[i] = processor.mix_buffers.subspan(inputs[i] * processor.sample_count, @@ -193,10 +190,8 @@ void LightLimiterVersion2Command::Dump([[maybe_unused]] const ADSP::CommandListP } void LightLimiterVersion2Command::Process(const ADSP::CommandListProcessor& processor) { - static Common::ScratchBuffer> input_buffers{}; - static Common::ScratchBuffer> output_buffers{}; - input_buffers.resize_destructive(parameter.channel_count); - output_buffers.resize_destructive(parameter.channel_count); + std::vector> input_buffers(parameter.channel_count); + std::vector> output_buffers(parameter.channel_count); for (u32 i = 0; i < parameter.channel_count; i++) { input_buffers[i] = processor.mix_buffers.subspan(inputs[i] * processor.sample_count, diff --git a/src/audio_core/renderer/command/effect/reverb.cpp b/src/audio_core/renderer/command/effect/reverb.cpp index d9403f9dd..25c2910aa 100755 --- a/src/audio_core/renderer/command/effect/reverb.cpp +++ b/src/audio_core/renderer/command/effect/reverb.cpp @@ -7,7 +7,6 @@ #include "audio_core/renderer/adsp/command_list_processor.h" #include "audio_core/renderer/command/effect/reverb.h" #include "common/polyfill_ranges.h" -#include "common/scratch_buffer.h" namespace AudioCore::AudioRenderer { @@ -251,8 +250,8 @@ static Common::FixedPoint<50, 14> Axfx2AllPassTick(ReverbInfo::ReverbDelayLine& */ template static void ApplyReverbEffect(const ReverbInfo::ParameterVersion2& params, ReverbInfo::State& state, - std::span> inputs, - std::span> outputs, const u32 sample_count) { + std::vector>& inputs, + std::vector>& outputs, const u32 sample_count) { constexpr std::array OutTapIndexes1Ch{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; @@ -369,8 +368,8 @@ static void ApplyReverbEffect(const ReverbInfo::ParameterVersion2& params, Rever * @param sample_count - Number of samples to process. */ static void ApplyReverbEffect(const ReverbInfo::ParameterVersion2& params, ReverbInfo::State& state, - const bool enabled, std::span> inputs, - std::span> outputs, const u32 sample_count) { + const bool enabled, std::vector>& inputs, + std::vector>& outputs, const u32 sample_count) { if (enabled) { switch (params.channel_count) { case 0: @@ -412,10 +411,8 @@ void ReverbCommand::Dump([[maybe_unused]] const ADSP::CommandListProcessor& proc } void ReverbCommand::Process(const ADSP::CommandListProcessor& processor) { - static Common::ScratchBuffer> input_buffers{}; - static Common::ScratchBuffer> output_buffers{}; - input_buffers.resize_destructive(parameter.channel_count); - output_buffers.resize_destructive(parameter.channel_count); + std::vector> input_buffers(parameter.channel_count); + std::vector> output_buffers(parameter.channel_count); for (u32 i = 0; i < parameter.channel_count; i++) { input_buffers[i] = processor.mix_buffers.subspan(inputs[i] * processor.sample_count, diff --git a/src/audio_core/renderer/command/sink/circular_buffer.cpp b/src/audio_core/renderer/command/sink/circular_buffer.cpp index dacb8c66a..64cd1b0cb 100755 --- a/src/audio_core/renderer/command/sink/circular_buffer.cpp +++ b/src/audio_core/renderer/command/sink/circular_buffer.cpp @@ -5,7 +5,6 @@ #include "audio_core/renderer/adsp/command_list_processor.h" #include "audio_core/renderer/command/sink/circular_buffer.h" -#include "common/scratch_buffer.h" #include "core/memory.h" namespace AudioCore::AudioRenderer { @@ -25,9 +24,7 @@ void CircularBufferSinkCommand::Process(const ADSP::CommandListProcessor& proces constexpr s32 min{std::numeric_limits::min()}; constexpr s32 max{std::numeric_limits::max()}; - static Common::ScratchBuffer output{}; - output.resize_destructive(processor.sample_count); - + std::vector output(processor.sample_count); for (u32 channel = 0; channel < input_count; channel++) { auto input{processor.mix_buffers.subspan(inputs[channel] * processor.sample_count, processor.sample_count)}; diff --git a/src/audio_core/renderer/command/sink/device.cpp b/src/audio_core/renderer/command/sink/device.cpp index 846d0a0c0..22e2a8464 100755 --- a/src/audio_core/renderer/command/sink/device.cpp +++ b/src/audio_core/renderer/command/sink/device.cpp @@ -33,8 +33,7 @@ void DeviceSinkCommand::Process(const ADSP::CommandListProcessor& processor) { .consumed{false}, }; - static Common::ScratchBuffer samples{}; - samples.resize_destructive(out_buffer.frames * input_count); + std::vector samples(out_buffer.frames * input_count); for (u32 channel = 0; channel < input_count; channel++) { const auto offset{inputs[channel] * out_buffer.frames}; diff --git a/src/audio_core/sink/null_sink.h b/src/audio_core/sink/null_sink.h index 2ed81c4f6..319271c2b 100755 --- a/src/audio_core/sink/null_sink.h +++ b/src/audio_core/sink/null_sink.h @@ -9,7 +9,6 @@ #include "audio_core/sink/sink.h" #include "audio_core/sink/sink_stream.h" -#include "common/scratch_buffer.h" namespace Core { class System; @@ -21,7 +20,7 @@ public: explicit NullSinkStreamImpl(Core::System& system_, StreamType type_) : SinkStream{system_, type_} {} ~NullSinkStreamImpl() override {} - void AppendBuffer(SinkBuffer&, Common::ScratchBuffer&) override {} + void AppendBuffer(SinkBuffer&, std::vector&) override {} std::vector ReleaseBuffer(u64) override { return {}; } diff --git a/src/audio_core/sink/sink_stream.cpp b/src/audio_core/sink/sink_stream.cpp index 9d2bae2b0..8412983cc 100755 --- a/src/audio_core/sink/sink_stream.cpp +++ b/src/audio_core/sink/sink_stream.cpp @@ -17,7 +17,7 @@ namespace AudioCore::Sink { -void SinkStream::AppendBuffer(SinkBuffer& buffer, Common::ScratchBuffer& samples) { +void SinkStream::AppendBuffer(SinkBuffer& buffer, std::vector& samples) { if (type == StreamType::In) { queue.enqueue(buffer); queued_buffers++; @@ -71,9 +71,7 @@ void SinkStream::AppendBuffer(SinkBuffer& buffer, Common::ScratchBuffer& sa // We need moar samples! Not all games will provide 6 channel audio. // TODO: Implement some upmixing here. Currently just passthrough, with other // channels left as silence. - static Common::ScratchBuffer new_samples{}; - new_samples.resize_destructive(samples.size() / system_channels * device_channels); - std::memset(new_samples.data(), 0, new_samples.size() * sizeof(s16)); + std::vector new_samples(samples.size() / system_channels * device_channels, 0); for (u32 read_index = 0, write_index = 0; read_index < samples.size(); read_index += system_channels, write_index += device_channels) { @@ -102,7 +100,7 @@ void SinkStream::AppendBuffer(SinkBuffer& buffer, Common::ScratchBuffer& sa } } - samples_buffer.Push(samples.data(), samples.size()); + samples_buffer.Push(samples); queue.enqueue(buffer); queued_buffers++; } diff --git a/src/audio_core/sink/sink_stream.h b/src/audio_core/sink/sink_stream.h index ae867a5ef..39b1bc3ca 100755 --- a/src/audio_core/sink/sink_stream.h +++ b/src/audio_core/sink/sink_stream.h @@ -14,7 +14,6 @@ #include "common/common_types.h" #include "common/reader_writer_queue.h" #include "common/ring_buffer.h" -#include "common/scratch_buffer.h" namespace Core { class System; @@ -170,7 +169,7 @@ public: * @param buffer - Audio buffer information to be queued. * @param samples - The s16 samples to be queue for playback. */ - virtual void AppendBuffer(SinkBuffer& buffer, Common::ScratchBuffer& samples); + virtual void AppendBuffer(SinkBuffer& buffer, std::vector& samples); /** * Release a buffer. Audio In only, will fill a buffer with recorded samples. diff --git a/src/common/scratch_buffer.h b/src/common/scratch_buffer.h index 62fa9f609..1245a5086 100755 --- a/src/common/scratch_buffer.h +++ b/src/common/scratch_buffer.h @@ -24,24 +24,6 @@ public: ~ScratchBuffer() = default; - ScratchBuffer(ScratchBuffer&& rhs) { - last_requested_size = rhs.last_requested_size; - buffer_capacity = rhs.buffer_capacity; - buffer = std::move(rhs.buffer); - - rhs.last_requested_size = 0; - rhs.buffer_capacity = 0; - } - - void operator=(ScratchBuffer&& rhs) { - last_requested_size = rhs.last_requested_size; - buffer_capacity = rhs.buffer_capacity; - buffer = std::move(rhs.buffer); - - rhs.last_requested_size = 0; - rhs.buffer_capacity = 0; - } - /// This will only grow the buffer's capacity if size is greater than the current capacity. /// The previously held data will remain intact. void resize(size_t size) { diff --git a/src/video_core/buffer_cache/buffer_base.h b/src/video_core/buffer_cache/buffer_base.h index 0a44caa66..172e849b6 100755 --- a/src/video_core/buffer_cache/buffer_base.h +++ b/src/video_core/buffer_cache/buffer_base.h @@ -289,6 +289,11 @@ public: return cpu_addr; } + /// Update the base CPU address of the buffer + void UpdateCpuAddr(VAddr cpu_addr_) noexcept { + cpu_addr = cpu_addr_; + } + /// Returns the offset relative to the given CPU address /// @pre IsInBounds returns true [[nodiscard]] u32 Offset(VAddr other_cpu_addr) const noexcept { diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index b2b0c8ae6..e46e0f518 100755 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -205,9 +205,9 @@ public: current_draw_indirect = current_draw_indirect_; } - [[nodiscard]] std::pair GetDrawIndirectCount(); + [[nodiscard]] typename BufferCache

::Buffer* GetDrawIndirectCount(); - [[nodiscard]] std::pair GetDrawIndirectBuffer(); + [[nodiscard]] typename BufferCache

::Buffer* GetDrawIndirectBuffer(); std::recursive_mutex mutex; Runtime& runtime; @@ -385,6 +385,9 @@ private: SlotVector slot_buffers; DelayedDestructionRing delayed_destruction_ring; + Buffer indirect_buffer; + Buffer indirect_count_buffer; + const Tegra::Engines::DrawManager::IndirectParams* current_draw_indirect{}; u32 last_index_count = 0; @@ -458,7 +461,9 @@ private: template BufferCache

::BufferCache(VideoCore::RasterizerInterface& rasterizer_, Core::Memory::Memory& cpu_memory_, Runtime& runtime_) - : runtime{runtime_}, rasterizer{rasterizer_}, cpu_memory{cpu_memory_} { + : runtime{runtime_}, rasterizer{rasterizer_}, cpu_memory{cpu_memory_}, + indirect_buffer(runtime, rasterizer, 0, 0x1000), + indirect_count_buffer(runtime, rasterizer, 0, 0x1000) { // Ensure the first slot is used for the null buffer void(slot_buffers.insert(runtime, NullBufferParams{})); common_ranges.clear(); @@ -1064,15 +1069,13 @@ void BufferCache

::BindHostVertexBuffers() { template void BufferCache

::BindHostDrawIndirectBuffers() { - const auto bind_buffer = [this](const Binding& binding) { - Buffer& buffer = slot_buffers[binding.buffer_id]; - TouchBuffer(buffer, binding.buffer_id); + const auto bind_buffer = [this](const Binding& binding, Buffer& buffer) { SynchronizeBuffer(buffer, binding.cpu_addr, binding.size); }; if (current_draw_indirect->include_count) { - bind_buffer(count_buffer_binding); + bind_buffer(count_buffer_binding, indirect_count_buffer); } - bind_buffer(indirect_buffer_binding); + bind_buffer(indirect_buffer_binding, indirect_buffer); } template @@ -1409,14 +1412,16 @@ void BufferCache

::UpdateDrawIndirect() { binding = Binding{ .cpu_addr = *cpu_addr, .size = static_cast(size), - .buffer_id = FindBuffer(*cpu_addr, static_cast(size)), + .buffer_id = NULL_BUFFER_ID, }; }; if (current_draw_indirect->include_count) { update(current_draw_indirect->count_start_address, sizeof(u32), count_buffer_binding); + indirect_count_buffer.UpdateCpuAddr(count_buffer_binding.cpu_addr); } update(current_draw_indirect->indirect_start_address, current_draw_indirect->buffer_size, indirect_buffer_binding); + indirect_buffer.UpdateCpuAddr(indirect_buffer_binding.cpu_addr); } template @@ -2000,15 +2005,13 @@ bool BufferCache

::HasFastUniformBufferBound(size_t stage, u32 binding_index) } template -std::pair::Buffer*, u32> BufferCache

::GetDrawIndirectCount() { - auto& buffer = slot_buffers[count_buffer_binding.buffer_id]; - return std::make_pair(&buffer, buffer.Offset(count_buffer_binding.cpu_addr)); +typename BufferCache

::Buffer* BufferCache

::GetDrawIndirectCount() { + return &indirect_count_buffer; } template -std::pair::Buffer*, u32> BufferCache

::GetDrawIndirectBuffer() { - auto& buffer = slot_buffers[indirect_buffer_binding.buffer_id]; - return std::make_pair(&buffer, buffer.Offset(indirect_buffer_binding.cpu_addr)); +typename BufferCache

::Buffer* BufferCache

::GetDrawIndirectBuffer() { + return &indirect_buffer; } } // namespace VideoCommon diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 5bea7e66c..3461b3bae 100755 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -285,23 +285,19 @@ void RasterizerOpenGL::DrawIndirect() { const auto& params = maxwell3d->draw_manager->GetIndirectParams(); buffer_cache.SetDrawIndirect(¶ms); PrepareDraw(params.is_indexed, [this, ¶ms](GLenum primitive_mode) { - const auto [buffer, offset] = buffer_cache.GetDrawIndirectBuffer(); - const GLvoid* const gl_offset = - reinterpret_cast(static_cast(offset)); + const auto buffer = buffer_cache.GetDrawIndirectBuffer(); glBindBuffer(GL_DRAW_INDIRECT_BUFFER, buffer->Handle()); if (params.include_count) { - const auto [draw_buffer, offset_base] = buffer_cache.GetDrawIndirectCount(); + const auto draw_buffer = buffer_cache.GetDrawIndirectCount(); glBindBuffer(GL_PARAMETER_BUFFER, draw_buffer->Handle()); if (params.is_indexed) { const GLenum format = MaxwellToGL::IndexFormat(maxwell3d->regs.index_buffer.format); - glMultiDrawElementsIndirectCount(primitive_mode, format, gl_offset, - static_cast(offset_base), + glMultiDrawElementsIndirectCount(primitive_mode, format, nullptr, 0, static_cast(params.max_draw_counts), static_cast(params.stride)); } else { - glMultiDrawArraysIndirectCount(primitive_mode, gl_offset, - static_cast(offset_base), + glMultiDrawArraysIndirectCount(primitive_mode, nullptr, 0, static_cast(params.max_draw_counts), static_cast(params.stride)); } @@ -309,11 +305,11 @@ void RasterizerOpenGL::DrawIndirect() { } if (params.is_indexed) { const GLenum format = MaxwellToGL::IndexFormat(maxwell3d->regs.index_buffer.format); - glMultiDrawElementsIndirect(primitive_mode, format, gl_offset, + glMultiDrawElementsIndirect(primitive_mode, format, nullptr, static_cast(params.max_draw_counts), static_cast(params.stride)); } else { - glMultiDrawArraysIndirect(primitive_mode, gl_offset, + glMultiDrawArraysIndirect(primitive_mode, nullptr, static_cast(params.max_draw_counts), static_cast(params.stride)); } diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 4d64a62f8..e1dccfadd 100755 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -230,35 +230,29 @@ void RasterizerVulkan::DrawIndirect() { const auto& params = maxwell3d->draw_manager->GetIndirectParams(); buffer_cache.SetDrawIndirect(¶ms); PrepareDraw(params.is_indexed, [this, ¶ms] { - const auto indirect_buffer = buffer_cache.GetDrawIndirectBuffer(); - const auto& buffer = indirect_buffer.first; - const auto& offset = indirect_buffer.second; + const auto buffer = buffer_cache.GetDrawIndirectBuffer(); if (params.include_count) { - const auto count = buffer_cache.GetDrawIndirectCount(); - const auto& draw_buffer = count.first; - const auto& offset_base = count.second; + const auto draw_buffer = buffer_cache.GetDrawIndirectCount(); scheduler.Record([draw_buffer_obj = draw_buffer->Handle(), - buffer_obj = buffer->Handle(), offset_base, offset, - params](vk::CommandBuffer cmdbuf) { + buffer_obj = buffer->Handle(), params](vk::CommandBuffer cmdbuf) { if (params.is_indexed) { - cmdbuf.DrawIndexedIndirectCount( - buffer_obj, offset, draw_buffer_obj, offset_base, - static_cast(params.max_draw_counts), static_cast(params.stride)); + cmdbuf.DrawIndexedIndirectCount(buffer_obj, 0, draw_buffer_obj, 0, + static_cast(params.max_draw_counts), + static_cast(params.stride)); } else { - cmdbuf.DrawIndirectCount(buffer_obj, offset, draw_buffer_obj, offset_base, + cmdbuf.DrawIndirectCount(buffer_obj, 0, draw_buffer_obj, 0, static_cast(params.max_draw_counts), static_cast(params.stride)); } }); return; } - scheduler.Record([buffer_obj = buffer->Handle(), offset, params](vk::CommandBuffer cmdbuf) { + scheduler.Record([buffer_obj = buffer->Handle(), params](vk::CommandBuffer cmdbuf) { if (params.is_indexed) { - cmdbuf.DrawIndexedIndirect(buffer_obj, offset, - static_cast(params.max_draw_counts), + cmdbuf.DrawIndexedIndirect(buffer_obj, 0, static_cast(params.max_draw_counts), static_cast(params.stride)); } else { - cmdbuf.DrawIndirect(buffer_obj, offset, static_cast(params.max_draw_counts), + cmdbuf.DrawIndirect(buffer_obj, 0, static_cast(params.max_draw_counts), static_cast(params.stride)); } });