diff options
author | Kelebek1 <eeeedddccc@hotmail.co.uk> | 2023-08-31 16:09:15 +0200 |
---|---|---|
committer | Kelebek1 <eeeedddccc@hotmail.co.uk> | 2023-09-04 18:12:16 +0200 |
commit | ebd19dec99d9809a669f63294745d7c8facc6d31 (patch) | |
tree | cd1f34cac0c091c2ffd16c429ac33b8fe133e06e /src/audio_core/renderer/adsp | |
parent | Merge pull request #11420 from t895/long-install-fix (diff) | |
download | yuzu-ebd19dec99d9809a669f63294745d7c8facc6d31.tar yuzu-ebd19dec99d9809a669f63294745d7c8facc6d31.tar.gz yuzu-ebd19dec99d9809a669f63294745d7c8facc6d31.tar.bz2 yuzu-ebd19dec99d9809a669f63294745d7c8facc6d31.tar.lz yuzu-ebd19dec99d9809a669f63294745d7c8facc6d31.tar.xz yuzu-ebd19dec99d9809a669f63294745d7c8facc6d31.tar.zst yuzu-ebd19dec99d9809a669f63294745d7c8facc6d31.zip |
Diffstat (limited to '')
-rw-r--r-- | src/audio_core/adsp/apps/audio_renderer/audio_renderer.cpp (renamed from src/audio_core/renderer/adsp/audio_renderer.cpp) | 188 | ||||
-rw-r--r-- | src/audio_core/adsp/apps/audio_renderer/command_list_processor.cpp (renamed from src/audio_core/renderer/adsp/command_list_processor.cpp) | 26 | ||||
-rw-r--r-- | src/audio_core/adsp/apps/audio_renderer/command_list_processor.h (renamed from src/audio_core/renderer/adsp/command_list_processor.h) | 13 | ||||
-rw-r--r-- | src/audio_core/renderer/adsp/adsp.cpp | 117 | ||||
-rw-r--r-- | src/audio_core/renderer/adsp/adsp.h | 171 | ||||
-rw-r--r-- | src/audio_core/renderer/adsp/audio_renderer.h | 204 | ||||
-rw-r--r-- | src/audio_core/renderer/adsp/command_buffer.h | 21 |
7 files changed, 109 insertions, 631 deletions
diff --git a/src/audio_core/renderer/adsp/audio_renderer.cpp b/src/audio_core/adsp/apps/audio_renderer/audio_renderer.cpp index 9ca716b60..3da342ea3 100644 --- a/src/audio_core/renderer/adsp/audio_renderer.cpp +++ b/src/audio_core/adsp/apps/audio_renderer/audio_renderer.cpp @@ -1,12 +1,12 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include <array> #include <chrono> +#include "audio_core/adsp/apps/audio_renderer/audio_renderer.h" #include "audio_core/audio_core.h" #include "audio_core/common/common.h" -#include "audio_core/renderer/adsp/audio_renderer.h" #include "audio_core/sink/sink.h" #include "common/logging/log.h" #include "common/microprofile.h" @@ -16,108 +16,92 @@ MICROPROFILE_DEFINE(Audio_Renderer, "Audio", "DSP", MP_RGB(60, 19, 97)); -namespace AudioCore::AudioRenderer::ADSP { +namespace AudioCore::ADSP::AudioRenderer { -void AudioRenderer_Mailbox::HostSendMessage(RenderMessage message_) { - adsp_messages.enqueue(message_); - adsp_event.Set(); -} +AudioRenderer::AudioRenderer(Core::System& system_, Core::Memory::Memory& memory_, + Sink::Sink& sink_) + : system{system_}, memory{memory_}, sink{sink_} {} -RenderMessage AudioRenderer_Mailbox::HostWaitMessage() { - host_event.Wait(); - RenderMessage msg{RenderMessage::Invalid}; - if (!host_messages.try_dequeue(msg)) { - LOG_ERROR(Service_Audio, "Failed to dequeue host message!"); - } - return msg; +AudioRenderer::~AudioRenderer() { + Stop(); } -void AudioRenderer_Mailbox::ADSPSendMessage(const RenderMessage message_) { - host_messages.enqueue(message_); - host_event.Set(); -} +void AudioRenderer::Start() { + CreateSinkStreams(); -RenderMessage AudioRenderer_Mailbox::ADSPWaitMessage() { - adsp_event.Wait(); - RenderMessage msg{RenderMessage::Invalid}; - if (!adsp_messages.try_dequeue(msg)) { - LOG_ERROR(Service_Audio, "Failed to dequeue ADSP message!"); - } - return msg; -} + mailbox.Initialize(AppMailboxId::AudioRenderer); -CommandBuffer& AudioRenderer_Mailbox::GetCommandBuffer(const u32 session_id) { - return command_buffers[session_id]; -} + main_thread = std::jthread([this](std::stop_token stop_token) { Main(stop_token); }); -void AudioRenderer_Mailbox::SetCommandBuffer(const u32 session_id, const CommandBuffer& buffer) { - command_buffers[session_id] = buffer; + mailbox.Send(Direction::DSP, {Message::InitializeOK, {}}); + if (mailbox.Receive(Direction::Host).msg != Message::InitializeOK) { + LOG_ERROR(Service_Audio, "Host Audio Renderer -- Failed to receive shutdown " + "message response from ADSP!"); + return; + } + running = true; } -u64 AudioRenderer_Mailbox::GetRenderTimeTaken() const { - return command_buffers[0].render_time_taken + command_buffers[1].render_time_taken; -} +void AudioRenderer::Stop() { + if (!running) { + return; + } -u64 AudioRenderer_Mailbox::GetSignalledTick() const { - return signalled_tick; -} + mailbox.Send(Direction::DSP, {Message::Shutdown, {}}); + if (mailbox.Receive(Direction::Host).msg != Message::Shutdown) { + LOG_ERROR(Service_Audio, "Host Audio Renderer -- Failed to receive shutdown " + "message response from ADSP!"); + } + main_thread.request_stop(); + main_thread.join(); -void AudioRenderer_Mailbox::SetSignalledTick(const u64 tick) { - signalled_tick = tick; + for (auto& stream : streams) { + if (stream) { + stream->Stop(); + sink.CloseStream(stream); + stream = nullptr; + } + } + running = false; } -void AudioRenderer_Mailbox::ClearRemainCount(const u32 session_id) { - command_buffers[session_id].remaining_command_count = 0; +void AudioRenderer::Signal() { + signalled_tick = system.CoreTiming().GetGlobalTimeNs().count(); + Send(Direction::DSP, {Message::Render, {}}); } -u32 AudioRenderer_Mailbox::GetRemainCommandCount(const u32 session_id) const { - return command_buffers[session_id].remaining_command_count; +void AudioRenderer::Wait() { + auto received = Receive(Direction::Host); + if (received.msg != Message::RenderResponse) { + LOG_ERROR(Service_Audio, + "Did not receive the expected render response from the AudioRenderer! Expected " + "{}, got {}", + Message::RenderResponse, received.msg); + } } -void AudioRenderer_Mailbox::ClearCommandBuffers() { - command_buffers[0].buffer = 0; - command_buffers[0].size = 0; - command_buffers[0].reset_buffers = false; - command_buffers[1].buffer = 0; - command_buffers[1].size = 0; - command_buffers[1].reset_buffers = false; +void AudioRenderer::Send(Direction dir, MailboxMessage message) { + mailbox.Send(dir, std::move(message)); } -AudioRenderer::AudioRenderer(Core::System& system_) - : system{system_}, sink{system.AudioCore().GetOutputSink()} { - CreateSinkStreams(); +MailboxMessage AudioRenderer::Receive(Direction dir, bool block) { + return mailbox.Receive(dir, block); } -AudioRenderer::~AudioRenderer() { - Stop(); - for (auto& stream : streams) { - if (stream) { - sink.CloseStream(stream); - } - stream = nullptr; - } +void AudioRenderer::SetCommandBuffer(s32 session_id, CommandBuffer& buffer) noexcept { + command_buffers[session_id] = buffer; } -void AudioRenderer::Start(AudioRenderer_Mailbox* mailbox_) { - if (running) { - return; - } - - mailbox = mailbox_; - thread = std::jthread([this](std::stop_token stop_token) { ThreadFunc(stop_token); }); - running = true; +u32 AudioRenderer::GetRemainCommandCount(s32 session_id) const noexcept { + return command_buffers[session_id].remaining_command_count; } -void AudioRenderer::Stop() { - if (!running) { - return; - } +void AudioRenderer::ClearRemainCommandCount(s32 session_id) noexcept { + command_buffers[session_id].remaining_command_count = 0; +} - for (auto& stream : streams) { - stream->Stop(); - } - thread.join(); - running = false; +u64 AudioRenderer::GetRenderingStartTick(s32 session_id) const noexcept { + return (1000 * command_buffers[session_id].render_time_taken_us) + signalled_tick; } void AudioRenderer::CreateSinkStreams() { @@ -130,41 +114,45 @@ void AudioRenderer::CreateSinkStreams() { } } -void AudioRenderer::ThreadFunc(std::stop_token stop_token) { +void AudioRenderer::Main(std::stop_token stop_token) { static constexpr char name[]{"AudioRenderer"}; MicroProfileOnThreadCreate(name); Common::SetCurrentThreadName(name); Common::SetCurrentThreadPriority(Common::ThreadPriority::High); - if (mailbox->ADSPWaitMessage() != RenderMessage::AudioRenderer_InitializeOK) { + + // TODO: Create buffer map/unmap thread + mailbox + // TODO: Create gMix devices, initialize them here + + if (mailbox.Receive(Direction::DSP).msg != Message::InitializeOK) { LOG_ERROR(Service_Audio, "ADSP Audio Renderer -- Failed to receive initialize message from host!"); return; } - mailbox->ADSPSendMessage(RenderMessage::AudioRenderer_InitializeOK); + mailbox.Send(Direction::Host, {Message::InitializeOK, {}}); - // 0.12 seconds (2304000 / 19200000) + // 0.12 seconds (2,304,000 / 19,200,000) constexpr u64 max_process_time{2'304'000ULL}; while (!stop_token.stop_requested()) { - auto message{mailbox->ADSPWaitMessage()}; - switch (message) { - case RenderMessage::AudioRenderer_Shutdown: - mailbox->ADSPSendMessage(RenderMessage::AudioRenderer_Shutdown); + auto received{mailbox.Receive(Direction::DSP)}; + switch (received.msg) { + case Message::Shutdown: + mailbox.Send(Direction::Host, {Message::Shutdown, {}}); return; - case RenderMessage::AudioRenderer_Render: { + case Message::Render: { if (system.IsShuttingDown()) [[unlikely]] { std::this_thread::sleep_for(std::chrono::milliseconds(5)); - mailbox->ADSPSendMessage(RenderMessage::AudioRenderer_RenderResponse); + mailbox.Send(Direction::Host, {Message::RenderResponse, {}}); continue; } std::array<bool, MaxRendererSessions> buffers_reset{}; std::array<u64, MaxRendererSessions> render_times_taken{}; - const auto start_time{system.CoreTiming().GetClockTicks()}; + const auto start_time{system.CoreTiming().GetGlobalTimeUs().count()}; - for (u32 index = 0; index < 2; index++) { - auto& command_buffer{mailbox->GetCommandBuffer(index)}; + for (u32 index = 0; index < MaxRendererSessions; index++) { + auto& command_buffer{command_buffers[index]}; auto& command_list_processor{command_list_processors[index]}; // Check this buffer is valid, as it may not be used. @@ -176,14 +164,14 @@ void AudioRenderer::ThreadFunc(std::stop_token stop_token) { command_buffer.size, streams[index]); } - if (command_buffer.reset_buffers && !buffers_reset[index]) { + if (command_buffer.reset_buffer && !buffers_reset[index]) { streams[index]->ClearQueue(); buffers_reset[index] = true; } u64 max_time{max_process_time}; if (index == 1 && command_buffer.applet_resource_user_id == - mailbox->GetCommandBuffer(0).applet_resource_user_id) { + command_buffers[0].applet_resource_user_id) { max_time = max_process_time - render_times_taken[0]; if (render_times_taken[0] > max_process_time) { max_time = 0; @@ -193,7 +181,9 @@ void AudioRenderer::ThreadFunc(std::stop_token stop_token) { max_time = std::min(command_buffer.time_limit, max_time); command_list_processor.SetProcessTimeMax(max_time); - streams[index]->WaitFreeSpace(stop_token); + if (index == 0) { + streams[index]->WaitFreeSpace(stop_token); + } // Process the command list { @@ -202,24 +192,24 @@ void AudioRenderer::ThreadFunc(std::stop_token stop_token) { command_list_processor.Process(index) - start_time; } - const auto end_time{system.CoreTiming().GetClockTicks()}; + const auto end_time{system.CoreTiming().GetGlobalTimeUs().count()}; command_buffer.remaining_command_count = command_list_processor.GetRemainingCommandCount(); - command_buffer.render_time_taken = end_time - start_time; + command_buffer.render_time_taken_us = end_time - start_time; } } - mailbox->ADSPSendMessage(RenderMessage::AudioRenderer_RenderResponse); + mailbox.Send(Direction::Host, {Message::RenderResponse, {}}); } break; default: LOG_WARNING(Service_Audio, "ADSP AudioRenderer received an invalid message, msg={:02X}!", - static_cast<u32>(message)); + received.msg); break; } } } -} // namespace AudioCore::AudioRenderer::ADSP +} // namespace AudioCore::ADSP::AudioRenderer diff --git a/src/audio_core/renderer/adsp/command_list_processor.cpp b/src/audio_core/adsp/apps/audio_renderer/command_list_processor.cpp index 3a0f1ae38..acbc9100c 100644 --- a/src/audio_core/renderer/adsp/command_list_processor.cpp +++ b/src/audio_core/adsp/apps/audio_renderer/command_list_processor.cpp @@ -1,9 +1,9 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include <string> -#include "audio_core/renderer/adsp/command_list_processor.h" +#include "audio_core/adsp/apps/audio_renderer/command_list_processor.h" #include "audio_core/renderer/command/command_list_header.h" #include "audio_core/renderer/command/commands.h" #include "common/settings.h" @@ -11,15 +11,15 @@ #include "core/core_timing.h" #include "core/memory.h" -namespace AudioCore::AudioRenderer::ADSP { +namespace AudioCore::ADSP::AudioRenderer { void CommandListProcessor::Initialize(Core::System& system_, CpuAddr buffer, u64 size, Sink::SinkStream* stream_) { system = &system_; memory = &system->ApplicationMemory(); stream = stream_; - header = reinterpret_cast<CommandListHeader*>(buffer); - commands = reinterpret_cast<u8*>(buffer + sizeof(CommandListHeader)); + header = reinterpret_cast<Renderer::CommandListHeader*>(buffer); + commands = reinterpret_cast<u8*>(buffer + sizeof(Renderer::CommandListHeader)); commands_buffer_size = size; command_count = header->command_count; sample_count = header->sample_count; @@ -38,7 +38,7 @@ u32 CommandListProcessor::GetRemainingCommandCount() const { } void CommandListProcessor::SetBuffer(const CpuAddr buffer, const u64 size) { - commands = reinterpret_cast<u8*>(buffer + sizeof(CommandListHeader)); + commands = reinterpret_cast<u8*>(buffer + sizeof(Renderer::CommandListHeader)); commands_buffer_size = size; } @@ -47,7 +47,7 @@ Sink::SinkStream* CommandListProcessor::GetOutputSinkStream() const { } u64 CommandListProcessor::Process(u32 session_id) { - const auto start_time_{system->CoreTiming().GetClockTicks()}; + const auto start_time_{system->CoreTiming().GetGlobalTimeUs().count()}; const auto command_base{CpuAddr(commands)}; if (processed_command_count > 0) { @@ -60,12 +60,12 @@ u64 CommandListProcessor::Process(u32 session_id) { std::string dump{fmt::format("\nSession {}\n", session_id)}; for (u32 index = 0; index < command_count; index++) { - auto& command{*reinterpret_cast<ICommand*>(commands)}; + auto& command{*reinterpret_cast<Renderer::ICommand*>(commands)}; if (command.magic != 0xCAFEBABE) { LOG_ERROR(Service_Audio, "Command has invalid magic! Expected 0xCAFEBABE, got {:08X}", command.magic); - return system->CoreTiming().GetClockTicks() - start_time_; + return system->CoreTiming().GetGlobalTimeUs().count() - start_time_; } auto current_offset{CpuAddr(commands) - command_base}; @@ -74,8 +74,8 @@ u64 CommandListProcessor::Process(u32 session_id) { LOG_ERROR(Service_Audio, "Command exceeded command buffer, buffer size {:08X}, command ends at {:08X}", commands_buffer_size, - CpuAddr(commands) + command.size - sizeof(CommandListHeader)); - return system->CoreTiming().GetClockTicks() - start_time_; + CpuAddr(commands) + command.size - sizeof(Renderer::CommandListHeader)); + return system->CoreTiming().GetGlobalTimeUs().count() - start_time_; } if (Settings::values.dump_audio_commands) { @@ -101,8 +101,8 @@ u64 CommandListProcessor::Process(u32 session_id) { last_dump = dump; } - end_time = system->CoreTiming().GetClockTicks(); + end_time = system->CoreTiming().GetGlobalTimeUs().count(); return end_time - start_time_; } -} // namespace AudioCore::AudioRenderer::ADSP +} // namespace AudioCore::ADSP::AudioRenderer diff --git a/src/audio_core/renderer/adsp/command_list_processor.h b/src/audio_core/adsp/apps/audio_renderer/command_list_processor.h index d78269e1d..9d6fe1851 100644 --- a/src/audio_core/renderer/adsp/command_list_processor.h +++ b/src/audio_core/adsp/apps/audio_renderer/command_list_processor.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once @@ -6,6 +6,7 @@ #include <span> #include "audio_core/common/common.h" +#include "audio_core/renderer/command/command_list_header.h" #include "common/common_types.h" namespace Core { @@ -20,10 +21,11 @@ namespace Sink { class SinkStream; } -namespace AudioRenderer { +namespace Renderer { struct CommandListHeader; +} -namespace ADSP { +namespace ADSP::AudioRenderer { /** * A processor for command lists given to the AudioRenderer. @@ -85,7 +87,7 @@ public: /// Stream for the processed samples Sink::SinkStream* stream{}; /// Header info for this command list - CommandListHeader* header{}; + Renderer::CommandListHeader* header{}; /// The command buffer u8* commands{}; /// The command buffer size @@ -114,6 +116,5 @@ public: std::string last_dump{}; }; -} // namespace ADSP -} // namespace AudioRenderer +} // namespace ADSP::AudioRenderer } // namespace AudioCore diff --git a/src/audio_core/renderer/adsp/adsp.cpp b/src/audio_core/renderer/adsp/adsp.cpp deleted file mode 100644 index b1db31e93..000000000 --- a/src/audio_core/renderer/adsp/adsp.cpp +++ /dev/null @@ -1,117 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "audio_core/renderer/adsp/adsp.h" -#include "audio_core/renderer/adsp/command_buffer.h" -#include "audio_core/sink/sink.h" -#include "common/logging/log.h" -#include "core/core.h" -#include "core/core_timing.h" -#include "core/memory.h" - -namespace AudioCore::AudioRenderer::ADSP { - -ADSP::ADSP(Core::System& system_, Sink::Sink& sink_) - : system{system_}, memory{system.ApplicationMemory()}, sink{sink_} {} - -ADSP::~ADSP() { - ClearCommandBuffers(); -} - -State ADSP::GetState() const { - if (running) { - return State::Started; - } - return State::Stopped; -} - -AudioRenderer_Mailbox* ADSP::GetRenderMailbox() { - return &render_mailbox; -} - -void ADSP::ClearRemainCount(const u32 session_id) { - render_mailbox.ClearRemainCount(session_id); -} - -u64 ADSP::GetSignalledTick() const { - return render_mailbox.GetSignalledTick(); -} - -u64 ADSP::GetTimeTaken() const { - return render_mailbox.GetRenderTimeTaken(); -} - -u64 ADSP::GetRenderTimeTaken(const u32 session_id) { - return render_mailbox.GetCommandBuffer(session_id).render_time_taken; -} - -u32 ADSP::GetRemainCommandCount(const u32 session_id) const { - return render_mailbox.GetRemainCommandCount(session_id); -} - -void ADSP::SendCommandBuffer(const u32 session_id, const CommandBuffer& command_buffer) { - render_mailbox.SetCommandBuffer(session_id, command_buffer); -} - -u64 ADSP::GetRenderingStartTick(const u32 session_id) { - return render_mailbox.GetSignalledTick() + - render_mailbox.GetCommandBuffer(session_id).render_time_taken; -} - -bool ADSP::Start() { - if (running) { - return running; - } - - running = true; - systems_active++; - audio_renderer = std::make_unique<AudioRenderer>(system); - audio_renderer->Start(&render_mailbox); - render_mailbox.HostSendMessage(RenderMessage::AudioRenderer_InitializeOK); - if (render_mailbox.HostWaitMessage() != RenderMessage::AudioRenderer_InitializeOK) { - LOG_ERROR( - Service_Audio, - "Host Audio Renderer -- Failed to receive initialize message response from ADSP!"); - } - return running; -} - -void ADSP::Stop() { - systems_active--; - if (running && systems_active == 0) { - { - std::scoped_lock l{mailbox_lock}; - render_mailbox.HostSendMessage(RenderMessage::AudioRenderer_Shutdown); - if (render_mailbox.HostWaitMessage() != RenderMessage::AudioRenderer_Shutdown) { - LOG_ERROR(Service_Audio, "Host Audio Renderer -- Failed to receive shutdown " - "message response from ADSP!"); - } - } - audio_renderer->Stop(); - running = false; - } -} - -void ADSP::Signal() { - const auto signalled_tick{system.CoreTiming().GetClockTicks()}; - render_mailbox.SetSignalledTick(signalled_tick); - render_mailbox.HostSendMessage(RenderMessage::AudioRenderer_Render); -} - -void ADSP::Wait() { - std::scoped_lock l{mailbox_lock}; - auto response{render_mailbox.HostWaitMessage()}; - if (response != RenderMessage::AudioRenderer_RenderResponse) { - LOG_ERROR(Service_Audio, "Invalid ADSP response message, expected 0x{:02X}, got 0x{:02X}", - static_cast<u32>(RenderMessage::AudioRenderer_RenderResponse), - static_cast<u32>(response)); - } - - ClearCommandBuffers(); -} - -void ADSP::ClearCommandBuffers() { - render_mailbox.ClearCommandBuffers(); -} - -} // namespace AudioCore::AudioRenderer::ADSP diff --git a/src/audio_core/renderer/adsp/adsp.h b/src/audio_core/renderer/adsp/adsp.h deleted file mode 100644 index f7a2f25e4..000000000 --- a/src/audio_core/renderer/adsp/adsp.h +++ /dev/null @@ -1,171 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include <memory> -#include <mutex> - -#include "audio_core/renderer/adsp/audio_renderer.h" -#include "common/common_types.h" - -namespace Core { -namespace Memory { -class Memory; -} -class System; -} // namespace Core - -namespace AudioCore { -namespace Sink { -class Sink; -} - -namespace AudioRenderer::ADSP { -struct CommandBuffer; - -enum class State { - Started, - Stopped, -}; - -/** - * Represents the ADSP embedded within the audio sysmodule. - * This is a 32-bit Linux4Tegra kernel from nVidia, which is launched with the sysmodule on boot. - * - * The kernel will run apps you program for it, Nintendo have the following: - * - * Gmix - Responsible for mixing final audio and sending it out to hardware. This is last place all - * audio samples end up, and we skip it entirely, since we have very different backends and - * mixing is implicitly handled by the OS (but also due to lack of research/simplicity). - * - * AudioRenderer - Receives command lists generated by the audio render - * system, processes them, and sends the samples to Gmix. - * - * OpusDecoder - Contains libopus, and controls processing Opus audio and sends it to Gmix. - * Not much research done here, TODO if needed. - * - * We only implement the AudioRenderer for now. - * - * Communication for the apps is done through mailboxes, and some shared memory. - */ -class ADSP { -public: - explicit ADSP(Core::System& system, Sink::Sink& sink); - ~ADSP(); - - /** - * Start the ADSP. - * - * @return True if started or already running, otherwise false. - */ - bool Start(); - - /** - * Stop the ADSP. - */ - void Stop(); - - /** - * Get the ADSP's state. - * - * @return Started or Stopped. - */ - State GetState() const; - - /** - * Get the AudioRenderer mailbox to communicate with it. - * - * @return The AudioRenderer mailbox. - */ - AudioRenderer_Mailbox* GetRenderMailbox(); - - /** - * Get the tick the ADSP was signalled. - * - * @return The tick the ADSP was signalled. - */ - u64 GetSignalledTick() const; - - /** - * Get the total time it took for the ADSP to run the last command lists (both command lists). - * - * @return The tick the ADSP was signalled. - */ - u64 GetTimeTaken() const; - - /** - * Get the last time a given command list took to run. - * - * @param session_id - The session id to check (0 or 1). - * @return The time it took. - */ - u64 GetRenderTimeTaken(u32 session_id); - - /** - * Clear the remaining command count for a given session. - * - * @param session_id - The session id to check (0 or 1). - */ - void ClearRemainCount(u32 session_id); - - /** - * Get the remaining number of commands left to process for a command list. - * - * @param session_id - The session id to check (0 or 1). - * @return The number of commands remaining. - */ - u32 GetRemainCommandCount(u32 session_id) const; - - /** - * Get the last tick a command list started processing. - * - * @param session_id - The session id to check (0 or 1). - * @return The last tick the given command list started. - */ - u64 GetRenderingStartTick(u32 session_id); - - /** - * Set a command buffer to be processed. - * - * @param session_id - The session id to check (0 or 1). - * @param command_buffer - The command buffer to process. - */ - void SendCommandBuffer(u32 session_id, const CommandBuffer& command_buffer); - - /** - * Clear the command buffers (does not clear the time taken or the remaining command count) - */ - void ClearCommandBuffers(); - - /** - * Signal the AudioRenderer to begin processing. - */ - void Signal(); - - /** - * Wait for the AudioRenderer to finish processing. - */ - void Wait(); - -private: - /// Core system - Core::System& system; - /// Core memory - Core::Memory::Memory& memory; - /// Number of systems active, used to prevent accidental shutdowns - u8 systems_active{0}; - /// ADSP running state - std::atomic<bool> running{false}; - /// Output sink used by the ADSP - Sink::Sink& sink; - /// AudioRenderer app - std::unique_ptr<AudioRenderer> audio_renderer{}; - /// Communication for the AudioRenderer - AudioRenderer_Mailbox render_mailbox{}; - /// Mailbox lock ffor the render mailbox - std::mutex mailbox_lock; -}; - -} // namespace AudioRenderer::ADSP -} // namespace AudioCore diff --git a/src/audio_core/renderer/adsp/audio_renderer.h b/src/audio_core/renderer/adsp/audio_renderer.h deleted file mode 100644 index 88e558183..000000000 --- a/src/audio_core/renderer/adsp/audio_renderer.h +++ /dev/null @@ -1,204 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include <array> -#include <memory> -#include <thread> - -#include "audio_core/renderer/adsp/command_buffer.h" -#include "audio_core/renderer/adsp/command_list_processor.h" -#include "common/common_types.h" -#include "common/polyfill_thread.h" -#include "common/reader_writer_queue.h" -#include "common/thread.h" - -namespace Core { -namespace Timing { -struct EventType; -} -class System; -} // namespace Core - -namespace AudioCore { -namespace Sink { -class Sink; -} - -namespace AudioRenderer::ADSP { - -enum class RenderMessage { - /* 0x00 */ Invalid, - /* 0x01 */ AudioRenderer_MapUnmap_Map, - /* 0x02 */ AudioRenderer_MapUnmap_MapResponse, - /* 0x03 */ AudioRenderer_MapUnmap_Unmap, - /* 0x04 */ AudioRenderer_MapUnmap_UnmapResponse, - /* 0x05 */ AudioRenderer_MapUnmap_InvalidateCache, - /* 0x06 */ AudioRenderer_MapUnmap_InvalidateCacheResponse, - /* 0x07 */ AudioRenderer_MapUnmap_Shutdown, - /* 0x08 */ AudioRenderer_MapUnmap_ShutdownResponse, - /* 0x16 */ AudioRenderer_InitializeOK = 0x16, - /* 0x20 */ AudioRenderer_RenderResponse = 0x20, - /* 0x2A */ AudioRenderer_Render = 0x2A, - /* 0x34 */ AudioRenderer_Shutdown = 0x34, -}; - -/** - * A mailbox for the AudioRenderer, allowing communication between the host and the AudioRenderer - * running on the ADSP. - */ -class AudioRenderer_Mailbox { -public: - /** - * Send a message from the host to the AudioRenderer. - * - * @param message - The message to send to the AudioRenderer. - */ - void HostSendMessage(RenderMessage message); - - /** - * Host wait for a message from the AudioRenderer. - * - * @return The message returned from the AudioRenderer. - */ - RenderMessage HostWaitMessage(); - - /** - * Send a message from the AudioRenderer to the host. - * - * @param message - The message to send to the host. - */ - void ADSPSendMessage(RenderMessage message); - - /** - * AudioRenderer wait for a message from the host. - * - * @return The message returned from the AudioRenderer. - */ - RenderMessage ADSPWaitMessage(); - - /** - * Get the command buffer with the given session id (0 or 1). - * - * @param session_id - The session id to get (0 or 1). - * @return The command buffer. - */ - CommandBuffer& GetCommandBuffer(u32 session_id); - - /** - * Set the command buffer with the given session id (0 or 1). - * - * @param session_id - The session id to get (0 or 1). - * @param buffer - The command buffer to set. - */ - void SetCommandBuffer(u32 session_id, const CommandBuffer& buffer); - - /** - * Get the total render time taken for the last command lists sent. - * - * @return Total render time taken for the last command lists. - */ - u64 GetRenderTimeTaken() const; - - /** - * Get the tick the AudioRenderer was signalled. - * - * @return The tick the AudioRenderer was signalled. - */ - u64 GetSignalledTick() const; - - /** - * Set the tick the AudioRenderer was signalled. - * - * @param tick - The tick the AudioRenderer was signalled. - */ - void SetSignalledTick(u64 tick); - - /** - * Clear the remaining command count. - * - * @param session_id - Index for which command list to clear (0 or 1). - */ - void ClearRemainCount(u32 session_id); - - /** - * Get the remaining command count for a given command list. - * - * @param session_id - Index for which command list to clear (0 or 1). - * @return The remaining command count. - */ - u32 GetRemainCommandCount(u32 session_id) const; - - /** - * Clear the command buffers (does not clear the time taken or the remaining command count). - */ - void ClearCommandBuffers(); - -private: - /// Host signalling event - Common::Event host_event{}; - /// AudioRenderer signalling event - Common::Event adsp_event{}; - /// Host message queue - - Common::ReaderWriterQueue<RenderMessage> host_messages{}; - /// AudioRenderer message queue - - Common::ReaderWriterQueue<RenderMessage> adsp_messages{}; - /// Command buffers - - std::array<CommandBuffer, MaxRendererSessions> command_buffers{}; - /// Tick the AudioRnederer was signalled - u64 signalled_tick{}; -}; - -/** - * The AudioRenderer application running on the ADSP. - */ -class AudioRenderer { -public: - explicit AudioRenderer(Core::System& system); - ~AudioRenderer(); - - /** - * Start the AudioRenderer. - * - * @param mailbox The mailbox to use for this session. - */ - void Start(AudioRenderer_Mailbox* mailbox); - - /** - * Stop the AudioRenderer. - */ - void Stop(); - -private: - /** - * Main AudioRenderer thread, responsible for processing the command lists. - */ - void ThreadFunc(std::stop_token stop_token); - - /** - * Creates the streams which will receive the processed samples. - */ - void CreateSinkStreams(); - - /// Core system - Core::System& system; - /// Main thread - std::jthread thread{}; - /// The current state - std::atomic<bool> running{}; - /// The active mailbox - AudioRenderer_Mailbox* mailbox{}; - /// The command lists to process - std::array<CommandListProcessor, MaxRendererSessions> command_list_processors{}; - /// The output sink the AudioRenderer will use - Sink::Sink& sink; - /// The streams which will receive the processed samples - std::array<Sink::SinkStream*, MaxRendererSessions> streams; -}; - -} // namespace AudioRenderer::ADSP -} // namespace AudioCore diff --git a/src/audio_core/renderer/adsp/command_buffer.h b/src/audio_core/renderer/adsp/command_buffer.h deleted file mode 100644 index 880b279d8..000000000 --- a/src/audio_core/renderer/adsp/command_buffer.h +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "audio_core/common/common.h" -#include "common/common_types.h" - -namespace AudioCore::AudioRenderer::ADSP { - -struct CommandBuffer { - CpuAddr buffer; - u64 size; - u64 time_limit; - u32 remaining_command_count; - bool reset_buffers; - u64 applet_resource_user_id; - u64 render_time_taken; -}; - -} // namespace AudioCore::AudioRenderer::ADSP |