// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once #include #include #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. * * @return True if started or already running, otherwise false. */ 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, 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 running{false}; /// Output sink used by the ADSP Sink::Sink& sink; /// AudioRenderer app std::unique_ptr 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