diff options
| author | 2023-02-16 12:26:23 -0800 | |
|---|---|---|
| committer | 2023-02-16 12:26:23 -0800 | |
| commit | 744434de3855641c41c3e0efdeb193a4a28d8787 (patch) | |
| tree | 37df9b5a627c2cba0984408e1fdc3a494c2d274f /src/audio_core/renderer | |
| 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.gz yuzu-744434de3855641c41c3e0efdeb193a4a28d8787.tar.xz yuzu-744434de3855641c41c3e0efdeb193a4a28d8787.zip | |
Merge pull request #9769 from Kelebek1/audio_oob
[audio_core] Fix depop prepare
Diffstat (limited to 'src/audio_core/renderer')
| -rw-r--r-- | src/audio_core/renderer/command/command_generator.cpp | 2 | ||||
| -rw-r--r-- | src/audio_core/renderer/command/effect/aux_.cpp | 130 |
2 files changed, 92 insertions, 40 deletions
diff --git a/src/audio_core/renderer/command/command_generator.cpp b/src/audio_core/renderer/command/command_generator.cpp index 2ea50d128..fba84c7bd 100644 --- 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, | |||
| 46 | while (destination != nullptr) { | 46 | while (destination != nullptr) { |
| 47 | if (destination->IsConfigured()) { | 47 | if (destination->IsConfigured()) { |
| 48 | auto mix_id{destination->GetMixId()}; | 48 | auto mix_id{destination->GetMixId()}; |
| 49 | if (mix_id < mix_context.GetCount()) { | 49 | if (mix_id < mix_context.GetCount() && mix_id != UnusedSplitterId) { |
| 50 | auto mix_info{mix_context.GetInfo(mix_id)}; | 50 | auto mix_info{mix_context.GetInfo(mix_id)}; |
| 51 | command_buffer.GenerateDepopPrepareCommand( | 51 | command_buffer.GenerateDepopPrepareCommand( |
| 52 | voice_info.node_id, voice_state, render_context.depop_buffer, | 52 | voice_info.node_id, voice_state, render_context.depop_buffer, |
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 @@ | |||
| 4 | #include "audio_core/renderer/adsp/command_list_processor.h" | 4 | #include "audio_core/renderer/adsp/command_list_processor.h" |
| 5 | #include "audio_core/renderer/command/effect/aux_.h" | 5 | #include "audio_core/renderer/command/effect/aux_.h" |
| 6 | #include "audio_core/renderer/effect/aux_.h" | 6 | #include "audio_core/renderer/effect/aux_.h" |
| 7 | #include "core/core.h" | ||
| 7 | #include "core/memory.h" | 8 | #include "core/memory.h" |
| 8 | 9 | ||
| 9 | namespace AudioCore::AudioRenderer { | 10 | namespace AudioCore::AudioRenderer { |
| @@ -19,10 +20,24 @@ static void ResetAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr aux_in | |||
| 19 | return; | 20 | return; |
| 20 | } | 21 | } |
| 21 | 22 | ||
| 22 | auto info{reinterpret_cast<AuxInfo::AuxInfoDsp*>(memory.GetPointer(aux_info))}; | 23 | AuxInfo::AuxInfoDsp info{}; |
| 23 | info->read_offset = 0; | 24 | auto info_ptr{&info}; |
| 24 | info->write_offset = 0; | 25 | bool host_safe{(aux_info & Core::Memory::YUZU_PAGEMASK) <= |
| 25 | info->total_sample_count = 0; | 26 | (Core::Memory::YUZU_PAGESIZE - sizeof(AuxInfo::AuxInfoDsp))}; |
| 27 | |||
| 28 | if (host_safe) [[likely]] { | ||
| 29 | info_ptr = memory.GetPointer<AuxInfo::AuxInfoDsp>(aux_info); | ||
| 30 | } else { | ||
| 31 | memory.ReadBlockUnsafe(aux_info, info_ptr, sizeof(AuxInfo::AuxInfoDsp)); | ||
| 32 | } | ||
| 33 | |||
| 34 | info_ptr->read_offset = 0; | ||
| 35 | info_ptr->write_offset = 0; | ||
| 36 | info_ptr->total_sample_count = 0; | ||
| 37 | |||
| 38 | if (!host_safe) [[unlikely]] { | ||
| 39 | memory.WriteBlockUnsafe(aux_info, info_ptr, sizeof(AuxInfo::AuxInfoDsp)); | ||
| 40 | } | ||
| 26 | } | 41 | } |
| 27 | 42 | ||
| 28 | /** | 43 | /** |
| @@ -40,11 +55,10 @@ static void ResetAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr aux_in | |||
| 40 | * @param update_count - If non-zero, send_info_ will be updated. | 55 | * @param update_count - If non-zero, send_info_ will be updated. |
| 41 | * @return Number of samples written. | 56 | * @return Number of samples written. |
| 42 | */ | 57 | */ |
| 43 | static u32 WriteAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr send_info_, | 58 | static u32 WriteAuxBufferDsp(Core::Memory::Memory& memory, CpuAddr send_info_, |
| 44 | [[maybe_unused]] u32 sample_count, const CpuAddr send_buffer, | 59 | [[maybe_unused]] u32 sample_count, CpuAddr send_buffer, u32 count_max, |
| 45 | const u32 count_max, std::span<const s32> input, | 60 | std::span<const s32> input, u32 write_count_, u32 write_offset, |
| 46 | const u32 write_count_, const u32 write_offset, | 61 | u32 update_count) { |
| 47 | const u32 update_count) { | ||
| 48 | if (write_count_ > count_max) { | 62 | if (write_count_ > count_max) { |
| 49 | LOG_ERROR(Service_Audio, | 63 | LOG_ERROR(Service_Audio, |
| 50 | "write_count must be smaller than count_max! write_count {}, count_max {}", | 64 | "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 | |||
| 52 | return 0; | 66 | return 0; |
| 53 | } | 67 | } |
| 54 | 68 | ||
| 69 | if (send_info_ == 0) { | ||
| 70 | LOG_ERROR(Service_Audio, "send_info_ is 0!"); | ||
| 71 | return 0; | ||
| 72 | } | ||
| 73 | |||
| 55 | if (input.empty()) { | 74 | if (input.empty()) { |
| 56 | LOG_ERROR(Service_Audio, "input buffer is empty!"); | 75 | LOG_ERROR(Service_Audio, "input buffer is empty!"); |
| 57 | return 0; | 76 | return 0; |
| @@ -67,33 +86,47 @@ static u32 WriteAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr send_in | |||
| 67 | } | 86 | } |
| 68 | 87 | ||
| 69 | AuxInfo::AuxInfoDsp send_info{}; | 88 | AuxInfo::AuxInfoDsp send_info{}; |
| 70 | memory.ReadBlockUnsafe(send_info_, &send_info, sizeof(AuxInfo::AuxInfoDsp)); | 89 | auto send_ptr = &send_info; |
| 90 | bool host_safe = (send_info_ & Core::Memory::YUZU_PAGEMASK) <= | ||
| 91 | (Core::Memory::YUZU_PAGESIZE - sizeof(AuxInfo::AuxInfoDsp)); | ||
| 71 | 92 | ||
| 72 | u32 target_write_offset{send_info.write_offset + write_offset}; | 93 | if (host_safe) [[likely]] { |
| 73 | if (target_write_offset > count_max || write_count_ == 0) { | 94 | send_ptr = memory.GetPointer<AuxInfo::AuxInfoDsp>(send_info_); |
| 95 | } else { | ||
| 96 | memory.ReadBlockUnsafe(send_info_, send_ptr, sizeof(AuxInfo::AuxInfoDsp)); | ||
| 97 | } | ||
| 98 | |||
| 99 | u32 target_write_offset{send_ptr->write_offset + write_offset}; | ||
| 100 | if (target_write_offset > count_max) { | ||
| 74 | return 0; | 101 | return 0; |
| 75 | } | 102 | } |
| 76 | 103 | ||
| 77 | u32 write_count{write_count_}; | 104 | u32 write_count{write_count_}; |
| 78 | u32 write_pos{0}; | 105 | u32 read_pos{0}; |
| 79 | while (write_count > 0) { | 106 | while (write_count > 0) { |
| 80 | u32 to_write{std::min(count_max - target_write_offset, write_count)}; | 107 | u32 to_write{std::min(count_max - target_write_offset, write_count)}; |
| 81 | 108 | const auto write_addr = send_buffer + target_write_offset * sizeof(s32); | |
| 82 | if (to_write > 0) { | 109 | bool write_safe{(write_addr & Core::Memory::YUZU_PAGEMASK) <= |
| 110 | (Core::Memory::YUZU_PAGESIZE - (write_addr + to_write * sizeof(s32)))}; | ||
| 111 | if (write_safe) [[likely]] { | ||
| 112 | auto ptr = memory.GetPointer(write_addr); | ||
| 113 | std::memcpy(ptr, &input[read_pos], to_write * sizeof(s32)); | ||
| 114 | } else { | ||
| 83 | memory.WriteBlockUnsafe(send_buffer + target_write_offset * sizeof(s32), | 115 | memory.WriteBlockUnsafe(send_buffer + target_write_offset * sizeof(s32), |
| 84 | &input[write_pos], to_write * sizeof(s32)); | 116 | &input[read_pos], to_write * sizeof(s32)); |
| 85 | } | 117 | } |
| 86 | |||
| 87 | target_write_offset = (target_write_offset + to_write) % count_max; | 118 | target_write_offset = (target_write_offset + to_write) % count_max; |
| 88 | write_count -= to_write; | 119 | write_count -= to_write; |
| 89 | write_pos += to_write; | 120 | read_pos += to_write; |
| 90 | } | 121 | } |
| 91 | 122 | ||
| 92 | if (update_count) { | 123 | if (update_count) { |
| 93 | send_info.write_offset = (send_info.write_offset + update_count) % count_max; | 124 | send_ptr->write_offset = (send_ptr->write_offset + update_count) % count_max; |
| 94 | } | 125 | } |
| 95 | 126 | ||
| 96 | memory.WriteBlockUnsafe(send_info_, &send_info, sizeof(AuxInfo::AuxInfoDsp)); | 127 | if (!host_safe) [[unlikely]] { |
| 128 | memory.WriteBlockUnsafe(send_info_, send_ptr, sizeof(AuxInfo::AuxInfoDsp)); | ||
| 129 | } | ||
| 97 | 130 | ||
| 98 | return write_count_; | 131 | return write_count_; |
| 99 | } | 132 | } |
| @@ -102,7 +135,7 @@ static u32 WriteAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr send_in | |||
| 102 | * Read the given memory at return_buffer into the output mix buffer, and update return_info_ if | 135 | * Read the given memory at return_buffer into the output mix buffer, and update return_info_ if |
| 103 | * update_count is set, to notify the game that an update happened. | 136 | * update_count is set, to notify the game that an update happened. |
| 104 | * | 137 | * |
| 105 | * @param memory - Core memory for writing. | 138 | * @param memory - Core memory for reading. |
| 106 | * @param return_info_ - Meta information for where to read the mix buffer. | 139 | * @param return_info_ - Meta information for where to read the mix buffer. |
| 107 | * @param return_buffer - Memory address to read the samples from. | 140 | * @param return_buffer - Memory address to read the samples from. |
| 108 | * @param count_max - Maximum number of samples in the receiving buffer. | 141 | * @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 | |||
| 112 | * @param update_count - If non-zero, send_info_ will be updated. | 145 | * @param update_count - If non-zero, send_info_ will be updated. |
| 113 | * @return Number of samples read. | 146 | * @return Number of samples read. |
| 114 | */ | 147 | */ |
| 115 | static u32 ReadAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr return_info_, | 148 | static u32 ReadAuxBufferDsp(Core::Memory::Memory& memory, CpuAddr return_info_, |
| 116 | const CpuAddr return_buffer, const u32 count_max, std::span<s32> output, | 149 | CpuAddr return_buffer, u32 count_max, std::span<s32> output, |
| 117 | const u32 count_, const u32 read_offset, const u32 update_count) { | 150 | u32 read_count_, u32 read_offset, u32 update_count) { |
| 118 | if (count_max == 0) { | 151 | if (count_max == 0) { |
| 119 | return 0; | 152 | return 0; |
| 120 | } | 153 | } |
| 121 | 154 | ||
| 122 | if (count_ > count_max) { | 155 | if (read_count_ > count_max) { |
| 123 | LOG_ERROR(Service_Audio, "count must be smaller than count_max! count {}, count_max {}", | 156 | LOG_ERROR(Service_Audio, "count must be smaller than count_max! count {}, count_max {}", |
| 124 | count_, count_max); | 157 | read_count_, count_max); |
| 158 | return 0; | ||
| 159 | } | ||
| 160 | |||
| 161 | if (return_info_ == 0) { | ||
| 162 | LOG_ERROR(Service_Audio, "return_info_ is 0!"); | ||
| 125 | return 0; | 163 | return 0; |
| 126 | } | 164 | } |
| 127 | 165 | ||
| @@ -136,35 +174,49 @@ static u32 ReadAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr return_i | |||
| 136 | } | 174 | } |
| 137 | 175 | ||
| 138 | AuxInfo::AuxInfoDsp return_info{}; | 176 | AuxInfo::AuxInfoDsp return_info{}; |
| 139 | memory.ReadBlockUnsafe(return_info_, &return_info, sizeof(AuxInfo::AuxInfoDsp)); | 177 | auto return_ptr = &return_info; |
| 178 | bool host_safe = (return_info_ & Core::Memory::YUZU_PAGEMASK) <= | ||
| 179 | (Core::Memory::YUZU_PAGESIZE - sizeof(AuxInfo::AuxInfoDsp)); | ||
| 180 | |||
| 181 | if (host_safe) [[likely]] { | ||
| 182 | return_ptr = memory.GetPointer<AuxInfo::AuxInfoDsp>(return_info_); | ||
| 183 | } else { | ||
| 184 | memory.ReadBlockUnsafe(return_info_, return_ptr, sizeof(AuxInfo::AuxInfoDsp)); | ||
| 185 | } | ||
| 140 | 186 | ||
| 141 | u32 target_read_offset{return_info.read_offset + read_offset}; | 187 | u32 target_read_offset{return_ptr->read_offset + read_offset}; |
| 142 | if (target_read_offset > count_max) { | 188 | if (target_read_offset > count_max) { |
| 143 | return 0; | 189 | return 0; |
| 144 | } | 190 | } |
| 145 | 191 | ||
| 146 | u32 read_count{count_}; | 192 | u32 read_count{read_count_}; |
| 147 | u32 read_pos{0}; | 193 | u32 write_pos{0}; |
| 148 | while (read_count > 0) { | 194 | while (read_count > 0) { |
| 149 | u32 to_read{std::min(count_max - target_read_offset, read_count)}; | 195 | u32 to_read{std::min(count_max - target_read_offset, read_count)}; |
| 150 | 196 | const auto read_addr = return_buffer + target_read_offset * sizeof(s32); | |
| 151 | if (to_read > 0) { | 197 | bool read_safe{(read_addr & Core::Memory::YUZU_PAGEMASK) <= |
| 198 | (Core::Memory::YUZU_PAGESIZE - (read_addr + to_read * sizeof(s32)))}; | ||
| 199 | if (read_safe) [[likely]] { | ||
| 200 | auto ptr = memory.GetPointer(read_addr); | ||
| 201 | std::memcpy(&output[write_pos], ptr, to_read * sizeof(s32)); | ||
| 202 | } else { | ||
| 152 | memory.ReadBlockUnsafe(return_buffer + target_read_offset * sizeof(s32), | 203 | memory.ReadBlockUnsafe(return_buffer + target_read_offset * sizeof(s32), |
| 153 | &output[read_pos], to_read * sizeof(s32)); | 204 | &output[write_pos], to_read * sizeof(s32)); |
| 154 | } | 205 | } |
| 155 | |||
| 156 | target_read_offset = (target_read_offset + to_read) % count_max; | 206 | target_read_offset = (target_read_offset + to_read) % count_max; |
| 157 | read_count -= to_read; | 207 | read_count -= to_read; |
| 158 | read_pos += to_read; | 208 | write_pos += to_read; |
| 159 | } | 209 | } |
| 160 | 210 | ||
| 161 | if (update_count) { | 211 | if (update_count) { |
| 162 | return_info.read_offset = (return_info.read_offset + update_count) % count_max; | 212 | return_ptr->read_offset = (return_ptr->read_offset + update_count) % count_max; |
| 163 | } | 213 | } |
| 164 | 214 | ||
| 165 | memory.WriteBlockUnsafe(return_info_, &return_info, sizeof(AuxInfo::AuxInfoDsp)); | 215 | if (!host_safe) [[unlikely]] { |
| 216 | memory.WriteBlockUnsafe(return_info_, return_ptr, sizeof(AuxInfo::AuxInfoDsp)); | ||
| 217 | } | ||
| 166 | 218 | ||
| 167 | return count_; | 219 | return read_count_; |
| 168 | } | 220 | } |
| 169 | 221 | ||
| 170 | void AuxCommand::Dump([[maybe_unused]] const ADSP::CommandListProcessor& processor, | 222 | void AuxCommand::Dump([[maybe_unused]] const ADSP::CommandListProcessor& processor, |
| @@ -189,7 +241,7 @@ void AuxCommand::Process(const ADSP::CommandListProcessor& processor) { | |||
| 189 | update_count)}; | 241 | update_count)}; |
| 190 | 242 | ||
| 191 | if (read != processor.sample_count) { | 243 | if (read != processor.sample_count) { |
| 192 | std::memset(&output_buffer[read], 0, processor.sample_count - read); | 244 | std::memset(&output_buffer[read], 0, (processor.sample_count - read) * sizeof(s32)); |
| 193 | } | 245 | } |
| 194 | } else { | 246 | } else { |
| 195 | ResetAuxBufferDsp(*processor.memory, send_buffer_info); | 247 | ResetAuxBufferDsp(*processor.memory, send_buffer_info); |