diff options
| author | 2018-06-23 12:22:33 +1000 | |
|---|---|---|
| committer | 2018-06-22 22:22:33 -0400 | |
| commit | 81f24f568519ce7b035e3631b12a816e2a1c8579 (patch) | |
| tree | 9a2c55f0d5cc2091627111cfa742dfd98aa915ea /src | |
| parent | Merge pull request #526 from janisozaur/appveyor-ninja (diff) | |
| download | yuzu-81f24f568519ce7b035e3631b12a816e2a1c8579.tar.gz yuzu-81f24f568519ce7b035e3631b12a816e2a1c8579.tar.xz yuzu-81f24f568519ce7b035e3631b12a816e2a1c8579.zip | |
Fixed RequestUpdateAudioRenderer deadlocks and calculated section sizes properly (#580)
* Fixed RequestUpdateAudioRenderer deadlocks and calculated section sizes properly
This fixes RequestUpdateAudioRenderer deadlocks in games like Puyo Puyo Tetris and games which require a proper section size in games such as Retro City Rampage. This fixes causes various games to start rendering or trying to render
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/service/audio/audren_u.cpp | 83 | ||||
| -rw-r--r-- | src/core/hle/service/audio/audren_u.h | 37 |
2 files changed, 76 insertions, 44 deletions
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp index 44b7ef216..653ded8e9 100644 --- a/src/core/hle/service/audio/audren_u.cpp +++ b/src/core/hle/service/audio/audren_u.cpp | |||
| @@ -17,7 +17,8 @@ constexpr u64 audio_ticks{static_cast<u64>(CoreTiming::BASE_CLOCK_RATE / 200)}; | |||
| 17 | 17 | ||
| 18 | class IAudioRenderer final : public ServiceFramework<IAudioRenderer> { | 18 | class IAudioRenderer final : public ServiceFramework<IAudioRenderer> { |
| 19 | public: | 19 | public: |
| 20 | IAudioRenderer() : ServiceFramework("IAudioRenderer") { | 20 | IAudioRenderer(AudioRendererParameters audren_params) |
| 21 | : ServiceFramework("IAudioRenderer"), worker_params(audren_params) { | ||
| 21 | static const FunctionInfo functions[] = { | 22 | static const FunctionInfo functions[] = { |
| 22 | {0, nullptr, "GetAudioRendererSampleRate"}, | 23 | {0, nullptr, "GetAudioRendererSampleRate"}, |
| 23 | {1, nullptr, "GetAudioRendererSampleCount"}, | 24 | {1, nullptr, "GetAudioRendererSampleCount"}, |
| @@ -60,16 +61,27 @@ private: | |||
| 60 | AudioRendererConfig config; | 61 | AudioRendererConfig config; |
| 61 | auto buf = ctx.ReadBuffer(); | 62 | auto buf = ctx.ReadBuffer(); |
| 62 | std::memcpy(&config, buf.data(), sizeof(AudioRendererConfig)); | 63 | std::memcpy(&config, buf.data(), sizeof(AudioRendererConfig)); |
| 64 | u32 memory_pool_count = worker_params.effect_count + (worker_params.voice_count * 4); | ||
| 63 | 65 | ||
| 64 | AudioRendererResponse response_data{config}; | 66 | std::vector<MemoryPoolInfo> mem_pool_info(memory_pool_count); |
| 67 | std::memcpy(mem_pool_info.data(), | ||
| 68 | buf.data() + sizeof(AudioRendererConfig) + config.behavior_size, | ||
| 69 | memory_pool_count * sizeof(MemoryPoolInfo)); | ||
| 70 | |||
| 71 | AudioRendererResponse response_data{worker_params}; | ||
| 65 | 72 | ||
| 66 | ASSERT(ctx.GetWriteBufferSize() == response_data.total_size); | 73 | ASSERT(ctx.GetWriteBufferSize() == response_data.total_size); |
| 67 | 74 | ||
| 68 | std::vector<u8> output(response_data.total_size); | 75 | std::vector<u8> output(response_data.total_size); |
| 69 | std::memcpy(output.data(), &response_data, sizeof(AudioRendererResponse)); | 76 | std::memcpy(output.data(), &response_data, sizeof(AudioRendererResponse)); |
| 70 | std::vector<MemoryPoolEntry> memory_pool(config.memory_pools_size / 0x20); | 77 | std::vector<MemoryPoolEntry> memory_pool(memory_pool_count); |
| 71 | for (auto& entry : memory_pool) { | 78 | for (unsigned i = 0; i < memory_pool.size(); i++) { |
| 72 | entry.state = 5; | 79 | if (mem_pool_info[i].pool_state == MemoryPoolStates::RequestAttach) |
| 80 | memory_pool[i].state = MemoryPoolStates::Attached; | ||
| 81 | else if (mem_pool_info[i].pool_state == MemoryPoolStates::RequestDetach) | ||
| 82 | memory_pool[i].state = MemoryPoolStates::Detached; | ||
| 83 | else | ||
| 84 | memory_pool[i].state = mem_pool_info[i].pool_state; | ||
| 73 | } | 85 | } |
| 74 | std::memcpy(output.data() + sizeof(AudioRendererResponse), memory_pool.data(), | 86 | std::memcpy(output.data() + sizeof(AudioRendererResponse), memory_pool.data(), |
| 75 | response_data.memory_pools_size); | 87 | response_data.memory_pools_size); |
| @@ -108,14 +120,32 @@ private: | |||
| 108 | NGLOG_WARNING(Service_Audio, "(STUBBED) called"); | 120 | NGLOG_WARNING(Service_Audio, "(STUBBED) called"); |
| 109 | } | 121 | } |
| 110 | 122 | ||
| 123 | enum class MemoryPoolStates : u32 { // Should be LE | ||
| 124 | Invalid = 0x0, | ||
| 125 | Unknown = 0x1, | ||
| 126 | RequestDetach = 0x2, | ||
| 127 | Detached = 0x3, | ||
| 128 | RequestAttach = 0x4, | ||
| 129 | Attached = 0x5, | ||
| 130 | Released = 0x6, | ||
| 131 | }; | ||
| 132 | |||
| 111 | struct MemoryPoolEntry { | 133 | struct MemoryPoolEntry { |
| 112 | u32_le state; | 134 | MemoryPoolStates state; |
| 113 | u32_le unknown_4; | 135 | u32_le unknown_4; |
| 114 | u32_le unknown_8; | 136 | u32_le unknown_8; |
| 115 | u32_le unknown_c; | 137 | u32_le unknown_c; |
| 116 | }; | 138 | }; |
| 117 | static_assert(sizeof(MemoryPoolEntry) == 0x10, "MemoryPoolEntry has wrong size"); | 139 | static_assert(sizeof(MemoryPoolEntry) == 0x10, "MemoryPoolEntry has wrong size"); |
| 118 | 140 | ||
| 141 | struct MemoryPoolInfo { | ||
| 142 | u64_le pool_address; | ||
| 143 | u64_le pool_size; | ||
| 144 | MemoryPoolStates pool_state; | ||
| 145 | INSERT_PADDING_WORDS(3); // Unknown | ||
| 146 | }; | ||
| 147 | static_assert(sizeof(MemoryPoolInfo) == 0x20, "MemoryPoolInfo has wrong size"); | ||
| 148 | |||
| 119 | struct AudioRendererConfig { | 149 | struct AudioRendererConfig { |
| 120 | u32 revision; | 150 | u32 revision; |
| 121 | u32 behavior_size; | 151 | u32 behavior_size; |
| @@ -132,13 +162,13 @@ private: | |||
| 132 | static_assert(sizeof(AudioRendererConfig) == 0x40, "AudioRendererConfig has wrong size"); | 162 | static_assert(sizeof(AudioRendererConfig) == 0x40, "AudioRendererConfig has wrong size"); |
| 133 | 163 | ||
| 134 | struct AudioRendererResponse { | 164 | struct AudioRendererResponse { |
| 135 | AudioRendererResponse(const AudioRendererConfig& config) { | 165 | AudioRendererResponse(const AudioRendererParameters& config) { |
| 136 | revision = config.revision; | 166 | revision = config.revision; |
| 137 | error_info_size = 0xb0; | 167 | error_info_size = 0xb0; |
| 138 | memory_pools_size = (config.memory_pools_size / 0x20) * 0x10; | 168 | memory_pools_size = (config.effect_count + (config.voice_count * 4)) * 0x10; |
| 139 | voices_size = (config.voices_size / 0x170) * 0x10; | 169 | voices_size = config.voice_count * 0x10; |
| 140 | effects_size = (config.effects_size / 0xC0) * 0x10; | 170 | effects_size = config.effect_count * 0x10; |
| 141 | sinks_size = (config.sinks_size / 0x140) * 0x20; | 171 | sinks_size = config.sink_count * 0x20; |
| 142 | performance_manager_size = 0x10; | 172 | performance_manager_size = 0x10; |
| 143 | total_size = sizeof(AudioRendererResponse) + error_info_size + memory_pools_size + | 173 | total_size = sizeof(AudioRendererResponse) + error_info_size + memory_pools_size + |
| 144 | voices_size + effects_size + sinks_size + performance_manager_size; | 174 | voices_size + effects_size + sinks_size + performance_manager_size; |
| @@ -162,6 +192,7 @@ private: | |||
| 162 | CoreTiming::EventType* audio_event; | 192 | CoreTiming::EventType* audio_event; |
| 163 | 193 | ||
| 164 | Kernel::SharedPtr<Kernel::Event> system_event; | 194 | Kernel::SharedPtr<Kernel::Event> system_event; |
| 195 | AudioRendererParameters worker_params; | ||
| 165 | }; | 196 | }; |
| 166 | 197 | ||
| 167 | class IAudioDevice final : public ServiceFramework<IAudioDevice> { | 198 | class IAudioDevice final : public ServiceFramework<IAudioDevice> { |
| @@ -259,10 +290,12 @@ AudRenU::AudRenU() : ServiceFramework("audren:u") { | |||
| 259 | } | 290 | } |
| 260 | 291 | ||
| 261 | void AudRenU::OpenAudioRenderer(Kernel::HLERequestContext& ctx) { | 292 | void AudRenU::OpenAudioRenderer(Kernel::HLERequestContext& ctx) { |
| 293 | IPC::RequestParser rp{ctx}; | ||
| 294 | auto params = rp.PopRaw<AudioRendererParameters>(); | ||
| 262 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 295 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 263 | 296 | ||
| 264 | rb.Push(RESULT_SUCCESS); | 297 | rb.Push(RESULT_SUCCESS); |
| 265 | rb.PushIpcInterface<Audio::IAudioRenderer>(); | 298 | rb.PushIpcInterface<Audio::IAudioRenderer>(std::move(params)); |
| 266 | 299 | ||
| 267 | NGLOG_DEBUG(Service_Audio, "called"); | 300 | NGLOG_DEBUG(Service_Audio, "called"); |
| 268 | } | 301 | } |
| @@ -271,19 +304,19 @@ void AudRenU::GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx) { | |||
| 271 | IPC::RequestParser rp{ctx}; | 304 | IPC::RequestParser rp{ctx}; |
| 272 | auto params = rp.PopRaw<AudioRendererParameters>(); | 305 | auto params = rp.PopRaw<AudioRendererParameters>(); |
| 273 | 306 | ||
| 274 | u64 buffer_sz = Common::AlignUp(4 * params.unknown8, 0x40); | 307 | u64 buffer_sz = Common::AlignUp(4 * params.unknown_8, 0x40); |
| 275 | buffer_sz += params.unknownC * 1024; | 308 | buffer_sz += params.unknown_c * 1024; |
| 276 | buffer_sz += 0x940 * (params.unknownC + 1); | 309 | buffer_sz += 0x940 * (params.unknown_c + 1); |
| 277 | buffer_sz += 0x3F0 * params.voice_count; | 310 | buffer_sz += 0x3F0 * params.voice_count; |
| 278 | buffer_sz += Common::AlignUp(8 * (params.unknownC + 1), 0x10); | 311 | buffer_sz += Common::AlignUp(8 * (params.unknown_c + 1), 0x10); |
| 279 | buffer_sz += Common::AlignUp(8 * params.voice_count, 0x10); | 312 | buffer_sz += Common::AlignUp(8 * params.voice_count, 0x10); |
| 280 | buffer_sz += | 313 | buffer_sz += |
| 281 | Common::AlignUp((0x3C0 * (params.sink_count + params.unknownC) + 4 * params.sample_count) * | 314 | Common::AlignUp((0x3C0 * (params.sink_count + params.unknown_c) + 4 * params.sample_count) * |
| 282 | (params.unknown8 + 6), | 315 | (params.unknown_8 + 6), |
| 283 | 0x40); | 316 | 0x40); |
| 284 | 317 | ||
| 285 | if (IsFeatureSupported(AudioFeatures::Splitter, params.magic)) { | 318 | if (IsFeatureSupported(AudioFeatures::Splitter, params.revision)) { |
| 286 | u32 count = params.unknownC + 1; | 319 | u32 count = params.unknown_c + 1; |
| 287 | u64 node_count = Common::AlignUp(count, 0x40); | 320 | u64 node_count = Common::AlignUp(count, 0x40); |
| 288 | u64 node_state_buffer_sz = | 321 | u64 node_state_buffer_sz = |
| 289 | 4 * (node_count * node_count) + 0xC * node_count + 2 * (node_count / 8); | 322 | 4 * (node_count * node_count) + 0xC * node_count + 2 * (node_count / 8); |
| @@ -298,20 +331,20 @@ void AudRenU::GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx) { | |||
| 298 | } | 331 | } |
| 299 | 332 | ||
| 300 | buffer_sz += 0x20 * (params.effect_count + 4 * params.voice_count) + 0x50; | 333 | buffer_sz += 0x20 * (params.effect_count + 4 * params.voice_count) + 0x50; |
| 301 | if (IsFeatureSupported(AudioFeatures::Splitter, params.magic)) { | 334 | if (IsFeatureSupported(AudioFeatures::Splitter, params.revision)) { |
| 302 | buffer_sz += 0xE0 * params.unknown2c; | 335 | buffer_sz += 0xE0 * params.unknown_2c; |
| 303 | buffer_sz += 0x20 * params.splitter_count; | 336 | buffer_sz += 0x20 * params.splitter_count; |
| 304 | buffer_sz += Common::AlignUp(4 * params.unknown2c, 0x10); | 337 | buffer_sz += Common::AlignUp(4 * params.unknown_2c, 0x10); |
| 305 | } | 338 | } |
| 306 | buffer_sz = Common::AlignUp(buffer_sz, 0x40) + 0x170 * params.sink_count; | 339 | buffer_sz = Common::AlignUp(buffer_sz, 0x40) + 0x170 * params.sink_count; |
| 307 | u64 output_sz = buffer_sz + 0x280 * params.sink_count + 0x4B0 * params.effect_count + | 340 | u64 output_sz = buffer_sz + 0x280 * params.sink_count + 0x4B0 * params.effect_count + |
| 308 | ((params.voice_count * 256) | 0x40); | 341 | ((params.voice_count * 256) | 0x40); |
| 309 | 342 | ||
| 310 | if (params.unknown1c >= 1) { | 343 | if (params.unknown_1c >= 1) { |
| 311 | output_sz = Common::AlignUp(((16 * params.sink_count + 16 * params.effect_count + | 344 | output_sz = Common::AlignUp(((16 * params.sink_count + 16 * params.effect_count + |
| 312 | 16 * params.voice_count + 16) + | 345 | 16 * params.voice_count + 16) + |
| 313 | 0x658) * | 346 | 0x658) * |
| 314 | (params.unknown1c + 1) + | 347 | (params.unknown_1c + 1) + |
| 315 | 0xc0, | 348 | 0xc0, |
| 316 | 0x40) + | 349 | 0x40) + |
| 317 | output_sz; | 350 | output_sz; |
diff --git a/src/core/hle/service/audio/audren_u.h b/src/core/hle/service/audio/audren_u.h index 7dbd9b74d..e8baf99ee 100644 --- a/src/core/hle/service/audio/audren_u.h +++ b/src/core/hle/service/audio/audren_u.h | |||
| @@ -12,6 +12,24 @@ class HLERequestContext; | |||
| 12 | 12 | ||
| 13 | namespace Service::Audio { | 13 | namespace Service::Audio { |
| 14 | 14 | ||
| 15 | struct AudioRendererParameters { | ||
| 16 | u32_le sample_rate; | ||
| 17 | u32_le sample_count; | ||
| 18 | u32_le unknown_8; | ||
| 19 | u32_le unknown_c; | ||
| 20 | u32_le voice_count; | ||
| 21 | u32_le sink_count; | ||
| 22 | u32_le effect_count; | ||
| 23 | u32_le unknown_1c; | ||
| 24 | u8 unknown_20; | ||
| 25 | INSERT_PADDING_BYTES(3); | ||
| 26 | u32_le splitter_count; | ||
| 27 | u32_le unknown_2c; | ||
| 28 | INSERT_PADDING_WORDS(1); | ||
| 29 | u32_le revision; | ||
| 30 | }; | ||
| 31 | static_assert(sizeof(AudioRendererParameters) == 52, "AudioRendererParameters is an invalid size"); | ||
| 32 | |||
| 15 | class AudRenU final : public ServiceFramework<AudRenU> { | 33 | class AudRenU final : public ServiceFramework<AudRenU> { |
| 16 | public: | 34 | public: |
| 17 | explicit AudRenU(); | 35 | explicit AudRenU(); |
| @@ -22,25 +40,6 @@ private: | |||
| 22 | void GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx); | 40 | void GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx); |
| 23 | void GetAudioDevice(Kernel::HLERequestContext& ctx); | 41 | void GetAudioDevice(Kernel::HLERequestContext& ctx); |
| 24 | 42 | ||
| 25 | struct AudioRendererParameters { | ||
| 26 | u32_le sample_rate; | ||
| 27 | u32_le sample_count; | ||
| 28 | u32_le unknown8; | ||
| 29 | u32_le unknownC; | ||
| 30 | u32_le voice_count; | ||
| 31 | u32_le sink_count; | ||
| 32 | u32_le effect_count; | ||
| 33 | u32_le unknown1c; | ||
| 34 | u8 unknown20; | ||
| 35 | u8 padding1[3]; | ||
| 36 | u32_le splitter_count; | ||
| 37 | u32_le unknown2c; | ||
| 38 | u8 padding2[4]; | ||
| 39 | u32_le magic; | ||
| 40 | }; | ||
| 41 | static_assert(sizeof(AudioRendererParameters) == 52, | ||
| 42 | "AudioRendererParameters is an invalid size"); | ||
| 43 | |||
| 44 | enum class AudioFeatures : u32 { | 43 | enum class AudioFeatures : u32 { |
| 45 | Splitter, | 44 | Splitter, |
| 46 | }; | 45 | }; |