diff options
Diffstat (limited to '')
-rw-r--r-- | src/audio_core/adsp/adsp.cpp | 18 | ||||
-rw-r--r-- | src/audio_core/adsp/adsp.h | 50 | ||||
-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/audio_renderer.h | 115 | ||||
-rw-r--r-- | src/audio_core/adsp/apps/audio_renderer/command_buffer.h | 23 | ||||
-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/adsp/mailbox.h | 69 |
8 files changed, 384 insertions, 118 deletions
diff --git a/src/audio_core/adsp/adsp.cpp b/src/audio_core/adsp/adsp.cpp new file mode 100644 index 000000000..0580990f5 --- /dev/null +++ b/src/audio_core/adsp/adsp.cpp @@ -0,0 +1,18 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "audio_core/adsp/adsp.h" +#include "core/core.h" + +namespace AudioCore::ADSP { + +ADSP::ADSP(Core::System& system, Sink::Sink& sink) { + audio_renderer = + std::make_unique<AudioRenderer::AudioRenderer>(system, system.ApplicationMemory(), sink); +} + +AudioRenderer::AudioRenderer& ADSP::AudioRenderer() { + return *audio_renderer.get(); +} + +} // namespace AudioCore::ADSP diff --git a/src/audio_core/adsp/adsp.h b/src/audio_core/adsp/adsp.h new file mode 100644 index 000000000..bd5bcc63b --- /dev/null +++ b/src/audio_core/adsp/adsp.h @@ -0,0 +1,50 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "audio_core/adsp/apps/audio_renderer/audio_renderer.h" +#include "common/common_types.h" + +namespace Core { +class System; +} // namespace Core + +namespace AudioCore { +namespace Sink { +class Sink; +} + +namespace ADSP { + +/** + * 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 the apps you write 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 on the host, processes them, and sends the samples to Gmix. + * + * OpusDecoder - Contains libopus, and decodes Opus audio packets into raw pcm data. + * + * Communication between the host and ADSP is done through mailboxes, and mapping of shared memory. + */ +class ADSP { +public: + explicit ADSP(Core::System& system, Sink::Sink& sink); + ~ADSP() = default; + + AudioRenderer::AudioRenderer& AudioRenderer(); + +private: + /// AudioRenderer app + std::unique_ptr<AudioRenderer::AudioRenderer> audio_renderer{}; +}; + +} // namespace ADSP +} // namespace AudioCore 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/adsp/apps/audio_renderer/audio_renderer.h b/src/audio_core/adsp/apps/audio_renderer/audio_renderer.h new file mode 100644 index 000000000..b225e10fb --- /dev/null +++ b/src/audio_core/adsp/apps/audio_renderer/audio_renderer.h @@ -0,0 +1,115 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include <array> +#include <memory> +#include <thread> + +#include "audio_core/adsp/apps/audio_renderer/command_buffer.h" +#include "audio_core/adsp/apps/audio_renderer/command_list_processor.h" +#include "audio_core/adsp/mailbox.h" +#include "common/common_types.h" +#include "common/polyfill_thread.h" +#include "common/reader_writer_queue.h" +#include "common/thread.h" + +namespace Core { +class System; +namespace Timing { +struct EventType; +} +namespace Memory { +class Memory; +} +class System; +} // namespace Core + +namespace AudioCore { +namespace Sink { +class Sink; +} + +namespace ADSP::AudioRenderer { + +enum Message : u32 { + Invalid = 0x00, + MapUnmap_Map = 0x01, + MapUnmap_MapResponse = 0x02, + MapUnmap_Unmap = 0x03, + MapUnmap_UnmapResponse = 0x04, + MapUnmap_InvalidateCache = 0x05, + MapUnmap_InvalidateCacheResponse = 0x06, + MapUnmap_Shutdown = 0x07, + MapUnmap_ShutdownResponse = 0x08, + InitializeOK = 0x16, + RenderResponse = 0x20, + Render = 0x2A, + Shutdown = 0x34, +}; + +/** + * The AudioRenderer application running on the ADSP. + */ +class AudioRenderer { +public: + explicit AudioRenderer(Core::System& system, Core::Memory::Memory& memory, Sink::Sink& sink); + ~AudioRenderer(); + + /** + * Start the AudioRenderer. + * + * @param mailbox The mailbox to use for this session. + */ + void Start(); + + /** + * Stop the AudioRenderer. + */ + void Stop(); + + void Signal(); + void Wait(); + + void Send(Direction dir, MailboxMessage message); + MailboxMessage Receive(Direction dir, bool block = true); + + void SetCommandBuffer(s32 session_id, CommandBuffer& buffer) noexcept; + u32 GetRemainCommandCount(s32 session_id) const noexcept; + void ClearRemainCommandCount(s32 session_id) noexcept; + u64 GetRenderingStartTick(s32 session_id) const noexcept; + +private: + /** + * Main AudioRenderer thread, responsible for processing the command lists. + */ + void Main(std::stop_token stop_token); + + /** + * Creates the streams which will receive the processed samples. + */ + void CreateSinkStreams(); + + /// Core system + Core::System& system; + /// Memory + Core::Memory::Memory& memory; + /// The output sink the AudioRenderer will use + Sink::Sink& sink; + /// The active mailbox + Mailbox mailbox; + /// Main thread + std::jthread main_thread{}; + /// The current state + std::atomic<bool> running{}; + std::array<CommandBuffer, MaxRendererSessions> command_buffers{}; + /// The command lists to process + std::array<CommandListProcessor, MaxRendererSessions> command_list_processors{}; + /// The streams which will receive the processed samples + std::array<Sink::SinkStream*, MaxRendererSessions> streams{}; + u64 signalled_tick{0}; +}; + +} // namespace ADSP::AudioRenderer +} // namespace AudioCore diff --git a/src/audio_core/adsp/apps/audio_renderer/command_buffer.h b/src/audio_core/adsp/apps/audio_renderer/command_buffer.h new file mode 100644 index 000000000..3fd1b09dc --- /dev/null +++ b/src/audio_core/adsp/apps/audio_renderer/command_buffer.h @@ -0,0 +1,23 @@ +// SPDX-FileCopyrightText: Copyright 2023 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::ADSP::AudioRenderer { + +struct CommandBuffer { + // Set by the host + CpuAddr buffer{}; + u64 size{}; + u64 time_limit{}; + u64 applet_resource_user_id{}; + bool reset_buffer{}; + // Set by the DSP + u32 remaining_command_count{}; + u64 render_time_taken_us{}; +}; + +} // 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/adsp/mailbox.h b/src/audio_core/adsp/mailbox.h new file mode 100644 index 000000000..c31b73717 --- /dev/null +++ b/src/audio_core/adsp/mailbox.h @@ -0,0 +1,69 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "common/bounded_threadsafe_queue.h" +#include "common/common_types.h" + +namespace AudioCore::ADSP { + +enum class AppMailboxId : u32 { + Invalid = 0, + AudioRenderer = 50, + AudioRendererMemoryMapUnmap = 51, +}; + +enum class Direction : u32 { + Host, + DSP, +}; + +struct MailboxMessage { + u32 msg; + std::span<u8> data; +}; + +class Mailbox { +public: + void Initialize(AppMailboxId id_) { + Reset(); + id = id_; + } + + AppMailboxId Id() const noexcept { + return id; + } + + void Send(Direction dir, MailboxMessage&& message) { + auto& queue = dir == Direction::Host ? host_queue : adsp_queue; + queue.EmplaceWait(std::move(message)); + } + + MailboxMessage Receive(Direction dir, bool block = true) { + auto& queue = dir == Direction::Host ? host_queue : adsp_queue; + MailboxMessage t; + if (block) { + queue.PopWait(t); + } else { + queue.TryPop(t); + } + return t; + } + + void Reset() { + id = AppMailboxId::Invalid; + MailboxMessage t; + while (host_queue.TryPop(t)) { + } + while (adsp_queue.TryPop(t)) { + } + } + +private: + AppMailboxId id{0}; + Common::SPSCQueue<MailboxMessage> host_queue; + Common::SPSCQueue<MailboxMessage> adsp_queue; +}; + +} // namespace AudioCore::ADSP |