diff options
author | bunnei <bunneidev@gmail.com> | 2023-02-16 21:26:23 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-02-16 21:26:23 +0100 |
commit | 744434de3855641c41c3e0efdeb193a4a28d8787 (patch) | |
tree | 37df9b5a627c2cba0984408e1fdc3a494c2d274f /src/audio_core/renderer/command/effect | |
parent | Merge pull request #9796 from liamwhite/current (diff) | |
parent | Add fallback for memory read/write in case the address goes over a 4K page (diff) | |
download | yuzu-744434de3855641c41c3e0efdeb193a4a28d8787.tar yuzu-744434de3855641c41c3e0efdeb193a4a28d8787.tar.gz yuzu-744434de3855641c41c3e0efdeb193a4a28d8787.tar.bz2 yuzu-744434de3855641c41c3e0efdeb193a4a28d8787.tar.lz yuzu-744434de3855641c41c3e0efdeb193a4a28d8787.tar.xz yuzu-744434de3855641c41c3e0efdeb193a4a28d8787.tar.zst yuzu-744434de3855641c41c3e0efdeb193a4a28d8787.zip |
Diffstat (limited to 'src/audio_core/renderer/command/effect')
-rw-r--r-- | src/audio_core/renderer/command/effect/aux_.cpp | 130 |
1 files changed, 91 insertions, 39 deletions
diff --git a/src/audio_core/renderer/command/effect/aux_.cpp b/src/audio_core/renderer/command/effect/aux_.cpp index e76db893f..c5650effa 100644 --- a/src/audio_core/renderer/command/effect/aux_.cpp +++ b/src/audio_core/renderer/command/effect/aux_.cpp @@ -4,6 +4,7 @@ #include "audio_core/renderer/adsp/command_list_processor.h" #include "audio_core/renderer/command/effect/aux_.h" #include "audio_core/renderer/effect/aux_.h" +#include "core/core.h" #include "core/memory.h" namespace AudioCore::AudioRenderer { @@ -19,10 +20,24 @@ static void ResetAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr aux_in return; } - auto info{reinterpret_cast<AuxInfo::AuxInfoDsp*>(memory.GetPointer(aux_info))}; - info->read_offset = 0; - info->write_offset = 0; - info->total_sample_count = 0; + AuxInfo::AuxInfoDsp info{}; + auto info_ptr{&info}; + bool host_safe{(aux_info & Core::Memory::YUZU_PAGEMASK) <= + (Core::Memory::YUZU_PAGESIZE - sizeof(AuxInfo::AuxInfoDsp))}; + + if (host_safe) [[likely]] { + info_ptr = memory.GetPointer<AuxInfo::AuxInfoDsp>(aux_info); + } else { + memory.ReadBlockUnsafe(aux_info, info_ptr, sizeof(AuxInfo::AuxInfoDsp)); + } + + info_ptr->read_offset = 0; + info_ptr->write_offset = 0; + info_ptr->total_sample_count = 0; + + if (!host_safe) [[unlikely]] { + memory.WriteBlockUnsafe(aux_info, info_ptr, sizeof(AuxInfo::AuxInfoDsp)); + } } /** @@ -40,11 +55,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<const s32> 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<const s32> 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 {}", @@ -52,6 +66,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,33 +86,47 @@ static u32 WriteAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr send_in } AuxInfo::AuxInfoDsp send_info{}; - memory.ReadBlockUnsafe(send_info_, &send_info, sizeof(AuxInfo::AuxInfoDsp)); + auto send_ptr = &send_info; + bool host_safe = (send_info_ & Core::Memory::YUZU_PAGEMASK) <= + (Core::Memory::YUZU_PAGESIZE - sizeof(AuxInfo::AuxInfoDsp)); - u32 target_write_offset{send_info.write_offset + write_offset}; - if (target_write_offset > count_max || write_count_ == 0) { + if (host_safe) [[likely]] { + send_ptr = memory.GetPointer<AuxInfo::AuxInfoDsp>(send_info_); + } else { + memory.ReadBlockUnsafe(send_info_, send_ptr, sizeof(AuxInfo::AuxInfoDsp)); + } + + u32 target_write_offset{send_ptr->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) { + const auto write_addr = send_buffer + target_write_offset * sizeof(s32); + bool write_safe{(write_addr & Core::Memory::YUZU_PAGEMASK) <= + (Core::Memory::YUZU_PAGESIZE - (write_addr + to_write * sizeof(s32)))}; + if (write_safe) [[likely]] { + auto ptr = memory.GetPointer(write_addr); + std::memcpy(ptr, &input[read_pos], to_write * sizeof(s32)); + } else { 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_ptr->write_offset = (send_ptr->write_offset + update_count) % count_max; } - memory.WriteBlockUnsafe(send_info_, &send_info, sizeof(AuxInfo::AuxInfoDsp)); + if (!host_safe) [[unlikely]] { + memory.WriteBlockUnsafe(send_info_, send_ptr, sizeof(AuxInfo::AuxInfoDsp)); + } return write_count_; } @@ -102,7 +135,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. @@ -112,16 +145,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<s32> 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<s32> 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,35 +174,49 @@ static u32 ReadAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr return_i } AuxInfo::AuxInfoDsp return_info{}; - memory.ReadBlockUnsafe(return_info_, &return_info, sizeof(AuxInfo::AuxInfoDsp)); + auto return_ptr = &return_info; + bool host_safe = (return_info_ & Core::Memory::YUZU_PAGEMASK) <= + (Core::Memory::YUZU_PAGESIZE - sizeof(AuxInfo::AuxInfoDsp)); + + if (host_safe) [[likely]] { + return_ptr = memory.GetPointer<AuxInfo::AuxInfoDsp>(return_info_); + } else { + memory.ReadBlockUnsafe(return_info_, return_ptr, sizeof(AuxInfo::AuxInfoDsp)); + } - u32 target_read_offset{return_info.read_offset + read_offset}; + u32 target_read_offset{return_ptr->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) { + const auto read_addr = return_buffer + target_read_offset * sizeof(s32); + bool read_safe{(read_addr & Core::Memory::YUZU_PAGEMASK) <= + (Core::Memory::YUZU_PAGESIZE - (read_addr + to_read * sizeof(s32)))}; + if (read_safe) [[likely]] { + auto ptr = memory.GetPointer(read_addr); + std::memcpy(&output[write_pos], ptr, to_read * sizeof(s32)); + } else { 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_ptr->read_offset = (return_ptr->read_offset + update_count) % count_max; } - memory.WriteBlockUnsafe(return_info_, &return_info, sizeof(AuxInfo::AuxInfoDsp)); + if (!host_safe) [[unlikely]] { + memory.WriteBlockUnsafe(return_info_, return_ptr, sizeof(AuxInfo::AuxInfoDsp)); + } - return count_; + return read_count_; } void AuxCommand::Dump([[maybe_unused]] const ADSP::CommandListProcessor& processor, @@ -189,7 +241,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); |