summaryrefslogtreecommitdiff
path: root/src/audio_core/renderer
diff options
context:
space:
mode:
authorGravatar bunnei2023-02-16 12:26:23 -0800
committerGravatar GitHub2023-02-16 12:26:23 -0800
commit744434de3855641c41c3e0efdeb193a4a28d8787 (patch)
tree37df9b5a627c2cba0984408e1fdc3a494c2d274f /src/audio_core/renderer
parentMerge pull request #9796 from liamwhite/current (diff)
parentAdd fallback for memory read/write in case the address goes over a 4K page (diff)
downloadyuzu-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.cpp2
-rw-r--r--src/audio_core/renderer/command/effect/aux_.cpp130
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
9namespace AudioCore::AudioRenderer { 10namespace 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 */
43static u32 WriteAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr send_info_, 58static 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 */
115static u32 ReadAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr return_info_, 148static 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
170void AuxCommand::Dump([[maybe_unused]] const ADSP::CommandListProcessor& processor, 222void 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);