// 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/core_timing_util.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(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(RenderMessage::AudioRenderer_RenderResponse), static_cast(response)); } ClearCommandBuffers(); } void ADSP::ClearCommandBuffers() { render_mailbox.ClearCommandBuffers(); } } // namespace AudioCore::AudioRenderer::ADSP