diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/audio_core/sink/cubeb_sink.cpp | 7 | ||||
| -rw-r--r-- | src/audio_core/sink/sink_details.cpp | 4 | ||||
| -rw-r--r-- | src/core/hle/service/audio/hwopus.cpp | 49 | ||||
| -rw-r--r-- | src/core/hle/service/audio/hwopus.h | 5 | ||||
| -rw-r--r-- | src/video_core/buffer_cache/buffer_cache.h | 10 |
5 files changed, 63 insertions, 12 deletions
diff --git a/src/audio_core/sink/cubeb_sink.cpp b/src/audio_core/sink/cubeb_sink.cpp index 04d98a865..bbb598bc5 100644 --- a/src/audio_core/sink/cubeb_sink.cpp +++ b/src/audio_core/sink/cubeb_sink.cpp | |||
| @@ -364,7 +364,7 @@ bool IsCubebSuitable() { | |||
| 364 | } | 364 | } |
| 365 | #endif | 365 | #endif |
| 366 | 366 | ||
| 367 | // Test min latency | 367 | // Get min latency |
| 368 | cubeb_stream_params params{}; | 368 | cubeb_stream_params params{}; |
| 369 | params.rate = TargetSampleRate; | 369 | params.rate = TargetSampleRate; |
| 370 | params.channels = 2; | 370 | params.channels = 2; |
| @@ -380,11 +380,6 @@ bool IsCubebSuitable() { | |||
| 380 | } | 380 | } |
| 381 | latency = std::max(latency, TargetSampleCount * 2); | 381 | latency = std::max(latency, TargetSampleCount * 2); |
| 382 | 382 | ||
| 383 | if (latency > TargetSampleCount * 3) { | ||
| 384 | LOG_ERROR(Audio_Sink, "Cubeb latency is too high, it is not suitable."); | ||
| 385 | return false; | ||
| 386 | } | ||
| 387 | |||
| 388 | // Test opening a device with standard parameters | 383 | // Test opening a device with standard parameters |
| 389 | cubeb_devid output_device{0}; | 384 | cubeb_devid output_device{0}; |
| 390 | cubeb_devid input_device{0}; | 385 | cubeb_devid input_device{0}; |
diff --git a/src/audio_core/sink/sink_details.cpp b/src/audio_core/sink/sink_details.cpp index 6bec8ee7c..7c9a4e3ac 100644 --- a/src/audio_core/sink/sink_details.cpp +++ b/src/audio_core/sink/sink_details.cpp | |||
| @@ -83,8 +83,8 @@ const SinkDetails& GetOutputSinkDetails(Settings::AudioEngine sink_id) { | |||
| 83 | break; | 83 | break; |
| 84 | } | 84 | } |
| 85 | } | 85 | } |
| 86 | LOG_ERROR(Service_Audio, "Auto-selecting the {} backend", | 86 | LOG_INFO(Service_Audio, "Auto-selecting the {} backend", |
| 87 | Settings::CanonicalizeEnum(iter->id)); | 87 | Settings::CanonicalizeEnum(iter->id)); |
| 88 | } else { | 88 | } else { |
| 89 | if (iter != std::end(sink_details) && !iter->is_suitable()) { | 89 | if (iter != std::end(sink_details) && !iter->is_suitable()) { |
| 90 | LOG_ERROR(Service_Audio, "Selected backend {} is not suitable, falling back to null", | 90 | LOG_ERROR(Service_Audio, "Selected backend {} is not suitable, falling back to null", |
diff --git a/src/core/hle/service/audio/hwopus.cpp b/src/core/hle/service/audio/hwopus.cpp index fa77007f3..4a8276ed1 100644 --- a/src/core/hle/service/audio/hwopus.cpp +++ b/src/core/hle/service/audio/hwopus.cpp | |||
| @@ -174,7 +174,7 @@ public: | |||
| 174 | {6, &IHardwareOpusDecoderManager::DecodeInterleaved, "DecodeInterleavedWithPerfAndResetOld"}, | 174 | {6, &IHardwareOpusDecoderManager::DecodeInterleaved, "DecodeInterleavedWithPerfAndResetOld"}, |
| 175 | {7, nullptr, "DecodeInterleavedForMultiStreamWithPerfAndResetOld"}, | 175 | {7, nullptr, "DecodeInterleavedForMultiStreamWithPerfAndResetOld"}, |
| 176 | {8, &IHardwareOpusDecoderManager::DecodeInterleaved, "DecodeInterleaved"}, | 176 | {8, &IHardwareOpusDecoderManager::DecodeInterleaved, "DecodeInterleaved"}, |
| 177 | {9, nullptr, "DecodeInterleavedForMultiStream"}, | 177 | {9, &IHardwareOpusDecoderManager::DecodeInterleavedForMultiStream, "DecodeInterleavedForMultiStream"}, |
| 178 | }; | 178 | }; |
| 179 | // clang-format on | 179 | // clang-format on |
| 180 | 180 | ||
| @@ -206,6 +206,16 @@ private: | |||
| 206 | decoder_state.DecodeInterleaved(ctx, OpusDecoderState::PerfTime::Enabled, extra_behavior); | 206 | decoder_state.DecodeInterleaved(ctx, OpusDecoderState::PerfTime::Enabled, extra_behavior); |
| 207 | } | 207 | } |
| 208 | 208 | ||
| 209 | void DecodeInterleavedForMultiStream(HLERequestContext& ctx) { | ||
| 210 | LOG_DEBUG(Audio, "called"); | ||
| 211 | |||
| 212 | IPC::RequestParser rp{ctx}; | ||
| 213 | const auto extra_behavior = rp.Pop<bool>() ? OpusDecoderState::ExtraBehavior::ResetContext | ||
| 214 | : OpusDecoderState::ExtraBehavior::None; | ||
| 215 | |||
| 216 | decoder_state.DecodeInterleaved(ctx, OpusDecoderState::PerfTime::Enabled, extra_behavior); | ||
| 217 | } | ||
| 218 | |||
| 209 | OpusDecoderState decoder_state; | 219 | OpusDecoderState decoder_state; |
| 210 | }; | 220 | }; |
| 211 | 221 | ||
| @@ -354,6 +364,40 @@ void HwOpus::OpenHardwareOpusDecoderEx(HLERequestContext& ctx) { | |||
| 354 | system, OpusDecoderState{std::move(decoder), sample_rate, channel_count}); | 364 | system, OpusDecoderState{std::move(decoder), sample_rate, channel_count}); |
| 355 | } | 365 | } |
| 356 | 366 | ||
| 367 | void HwOpus::OpenHardwareOpusDecoderForMultiStreamEx(HLERequestContext& ctx) { | ||
| 368 | OpusMultiStreamParametersEx params; | ||
| 369 | std::memcpy(¶ms, ctx.ReadBuffer().data(), ctx.GetReadBufferSize()); | ||
| 370 | |||
| 371 | const auto& sample_rate = params.sample_rate; | ||
| 372 | const auto& channel_count = params.channel_count; | ||
| 373 | |||
| 374 | LOG_INFO( | ||
| 375 | Audio, | ||
| 376 | "called with sample_rate={}, channel_count={}, number_streams={}, number_stereo_streams={}", | ||
| 377 | sample_rate, channel_count, params.number_streams, params.number_stereo_streams); | ||
| 378 | |||
| 379 | ASSERT_MSG(sample_rate == 48000 || sample_rate == 24000 || sample_rate == 16000 || | ||
| 380 | sample_rate == 12000 || sample_rate == 8000, | ||
| 381 | "Invalid sample rate"); | ||
| 382 | |||
| 383 | int error = 0; | ||
| 384 | OpusDecoderPtr decoder{opus_multistream_decoder_create( | ||
| 385 | sample_rate, static_cast<int>(channel_count), params.number_streams, | ||
| 386 | params.number_stereo_streams, params.channel_mappings.data(), &error)}; | ||
| 387 | if (error != OPUS_OK || decoder == nullptr) { | ||
| 388 | LOG_ERROR(Audio, "Failed to create Opus decoder (error={}).", error); | ||
| 389 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 390 | // TODO(ogniK): Use correct error code | ||
| 391 | rb.Push(ResultUnknown); | ||
| 392 | return; | ||
| 393 | } | ||
| 394 | |||
| 395 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 396 | rb.Push(ResultSuccess); | ||
| 397 | rb.PushIpcInterface<IHardwareOpusDecoderManager>( | ||
| 398 | system, OpusDecoderState{std::move(decoder), sample_rate, channel_count}); | ||
| 399 | } | ||
| 400 | |||
| 357 | HwOpus::HwOpus(Core::System& system_) : ServiceFramework{system_, "hwopus"} { | 401 | HwOpus::HwOpus(Core::System& system_) : ServiceFramework{system_, "hwopus"} { |
| 358 | static const FunctionInfo functions[] = { | 402 | static const FunctionInfo functions[] = { |
| 359 | {0, &HwOpus::OpenHardwareOpusDecoder, "OpenHardwareOpusDecoder"}, | 403 | {0, &HwOpus::OpenHardwareOpusDecoder, "OpenHardwareOpusDecoder"}, |
| @@ -362,7 +406,8 @@ HwOpus::HwOpus(Core::System& system_) : ServiceFramework{system_, "hwopus"} { | |||
| 362 | {3, nullptr, "GetWorkBufferSizeForMultiStream"}, | 406 | {3, nullptr, "GetWorkBufferSizeForMultiStream"}, |
| 363 | {4, &HwOpus::OpenHardwareOpusDecoderEx, "OpenHardwareOpusDecoderEx"}, | 407 | {4, &HwOpus::OpenHardwareOpusDecoderEx, "OpenHardwareOpusDecoderEx"}, |
| 364 | {5, &HwOpus::GetWorkBufferSizeEx, "GetWorkBufferSizeEx"}, | 408 | {5, &HwOpus::GetWorkBufferSizeEx, "GetWorkBufferSizeEx"}, |
| 365 | {6, nullptr, "OpenHardwareOpusDecoderForMultiStreamEx"}, | 409 | {6, &HwOpus::OpenHardwareOpusDecoderForMultiStreamEx, |
| 410 | "OpenHardwareOpusDecoderForMultiStreamEx"}, | ||
| 366 | {7, &HwOpus::GetWorkBufferSizeForMultiStreamEx, "GetWorkBufferSizeForMultiStreamEx"}, | 411 | {7, &HwOpus::GetWorkBufferSizeForMultiStreamEx, "GetWorkBufferSizeForMultiStreamEx"}, |
| 367 | {8, nullptr, "GetWorkBufferSizeExEx"}, | 412 | {8, nullptr, "GetWorkBufferSizeExEx"}, |
| 368 | {9, nullptr, "GetWorkBufferSizeForMultiStreamExEx"}, | 413 | {9, nullptr, "GetWorkBufferSizeForMultiStreamExEx"}, |
diff --git a/src/core/hle/service/audio/hwopus.h b/src/core/hle/service/audio/hwopus.h index ece65c02c..91d9998ac 100644 --- a/src/core/hle/service/audio/hwopus.h +++ b/src/core/hle/service/audio/hwopus.h | |||
| @@ -18,8 +18,10 @@ struct OpusMultiStreamParametersEx { | |||
| 18 | u32 number_stereo_streams; | 18 | u32 number_stereo_streams; |
| 19 | u32 use_large_frame_size; | 19 | u32 use_large_frame_size; |
| 20 | u32 padding; | 20 | u32 padding; |
| 21 | std::array<u32, 64> channel_mappings; | 21 | std::array<u8, 0x100> channel_mappings; |
| 22 | }; | 22 | }; |
| 23 | static_assert(sizeof(OpusMultiStreamParametersEx) == 0x118, | ||
| 24 | "OpusMultiStreamParametersEx has incorrect size"); | ||
| 23 | 25 | ||
| 24 | class HwOpus final : public ServiceFramework<HwOpus> { | 26 | class HwOpus final : public ServiceFramework<HwOpus> { |
| 25 | public: | 27 | public: |
| @@ -29,6 +31,7 @@ public: | |||
| 29 | private: | 31 | private: |
| 30 | void OpenHardwareOpusDecoder(HLERequestContext& ctx); | 32 | void OpenHardwareOpusDecoder(HLERequestContext& ctx); |
| 31 | void OpenHardwareOpusDecoderEx(HLERequestContext& ctx); | 33 | void OpenHardwareOpusDecoderEx(HLERequestContext& ctx); |
| 34 | void OpenHardwareOpusDecoderForMultiStreamEx(HLERequestContext& ctx); | ||
| 32 | void GetWorkBufferSize(HLERequestContext& ctx); | 35 | void GetWorkBufferSize(HLERequestContext& ctx); |
| 33 | void GetWorkBufferSizeEx(HLERequestContext& ctx); | 36 | void GetWorkBufferSizeEx(HLERequestContext& ctx); |
| 34 | void GetWorkBufferSizeForMultiStreamEx(HLERequestContext& ctx); | 37 | void GetWorkBufferSizeForMultiStreamEx(HLERequestContext& ctx); |
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index f0f450edb..8be7bd594 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h | |||
| @@ -289,8 +289,11 @@ std::pair<typename P::Buffer*, u32> BufferCache<P>::ObtainBuffer(GPUVAddr gpu_ad | |||
| 289 | MarkWrittenBuffer(buffer_id, *cpu_addr, size); | 289 | MarkWrittenBuffer(buffer_id, *cpu_addr, size); |
| 290 | break; | 290 | break; |
| 291 | case ObtainBufferOperation::DiscardWrite: { | 291 | case ObtainBufferOperation::DiscardWrite: { |
| 292 | IntervalType interval{*cpu_addr, size}; | 292 | VAddr cpu_addr_start = Common::AlignDown(*cpu_addr, 64); |
| 293 | VAddr cpu_addr_end = Common::AlignUp(*cpu_addr + size, 64); | ||
| 294 | IntervalType interval{cpu_addr_start, cpu_addr_end}; | ||
| 293 | ClearDownload(interval); | 295 | ClearDownload(interval); |
| 296 | common_ranges.subtract(interval); | ||
| 294 | break; | 297 | break; |
| 295 | } | 298 | } |
| 296 | default: | 299 | default: |
| @@ -1159,6 +1162,11 @@ void BufferCache<P>::UpdateDrawIndirect() { | |||
| 1159 | .size = static_cast<u32>(size), | 1162 | .size = static_cast<u32>(size), |
| 1160 | .buffer_id = FindBuffer(*cpu_addr, static_cast<u32>(size)), | 1163 | .buffer_id = FindBuffer(*cpu_addr, static_cast<u32>(size)), |
| 1161 | }; | 1164 | }; |
| 1165 | VAddr cpu_addr_start = Common::AlignDown(*cpu_addr, 64); | ||
| 1166 | VAddr cpu_addr_end = Common::AlignUp(*cpu_addr + size, 64); | ||
| 1167 | IntervalType interval{cpu_addr_start, cpu_addr_end}; | ||
| 1168 | ClearDownload(interval); | ||
| 1169 | common_ranges.subtract(interval); | ||
| 1162 | }; | 1170 | }; |
| 1163 | if (current_draw_indirect->include_count) { | 1171 | if (current_draw_indirect->include_count) { |
| 1164 | update(current_draw_indirect->count_start_address, sizeof(u32), | 1172 | update(current_draw_indirect->count_start_address, sizeof(u32), |