mirror of https://git.suyu.dev/suyu/suyu
Merge pull request #11428 from Kelebek1/adsp_rework
Rework ADSP into a wrapper for appsmerge-requests/60/head
commit
69949e7964
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue