system_manager.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include <chrono>
  4. #include "audio_core/audio_core.h"
  5. #include "audio_core/renderer/adsp/adsp.h"
  6. #include "audio_core/renderer/system_manager.h"
  7. #include "common/microprofile.h"
  8. #include "common/thread.h"
  9. #include "core/core.h"
  10. #include "core/core_timing.h"
  11. MICROPROFILE_DEFINE(Audio_RenderSystemManager, "Audio", "Render System Manager",
  12. MP_RGB(60, 19, 97));
  13. namespace AudioCore::AudioRenderer {
  14. constexpr std::chrono::nanoseconds RENDER_TIME{5'000'000UL};
  15. SystemManager::SystemManager(Core::System& core_)
  16. : core{core_}, adsp{core.AudioCore().GetADSP()}, mailbox{adsp.GetRenderMailbox()},
  17. thread_event{Core::Timing::CreateEvent(
  18. "AudioRendererSystemManager", [this](std::uintptr_t, s64 time, std::chrono::nanoseconds) {
  19. return ThreadFunc2(time);
  20. })} {}
  21. SystemManager::~SystemManager() {
  22. Stop();
  23. }
  24. bool SystemManager::InitializeUnsafe() {
  25. if (!active) {
  26. if (adsp.Start()) {
  27. active = true;
  28. thread = std::jthread([this](std::stop_token stop_token) { ThreadFunc(); });
  29. core.CoreTiming().ScheduleLoopingEvent(std::chrono::nanoseconds(0), RENDER_TIME,
  30. thread_event);
  31. }
  32. }
  33. return adsp.GetState() == ADSP::State::Started;
  34. }
  35. void SystemManager::Stop() {
  36. if (!active) {
  37. return;
  38. }
  39. core.CoreTiming().UnscheduleEvent(thread_event, {});
  40. active = false;
  41. update.store(true);
  42. update.notify_all();
  43. thread.join();
  44. adsp.Stop();
  45. }
  46. bool SystemManager::Add(System& system_) {
  47. std::scoped_lock l2{mutex2};
  48. if (systems.size() + 1 > MaxRendererSessions) {
  49. LOG_ERROR(Service_Audio, "Maximum AudioRenderer Systems active, cannot add more!");
  50. return false;
  51. }
  52. {
  53. std::scoped_lock l{mutex1};
  54. if (systems.empty()) {
  55. if (!InitializeUnsafe()) {
  56. LOG_ERROR(Service_Audio, "Failed to start the AudioRenderer SystemManager");
  57. return false;
  58. }
  59. }
  60. }
  61. systems.push_back(&system_);
  62. return true;
  63. }
  64. bool SystemManager::Remove(System& system_) {
  65. std::scoped_lock l2{mutex2};
  66. {
  67. std::scoped_lock l{mutex1};
  68. if (systems.remove(&system_) == 0) {
  69. LOG_ERROR(Service_Audio,
  70. "Failed to remove a render system, it was not found in the list!");
  71. return false;
  72. }
  73. }
  74. if (systems.empty()) {
  75. Stop();
  76. }
  77. return true;
  78. }
  79. void SystemManager::ThreadFunc() {
  80. constexpr char name[]{"AudioRenderSystemManager"};
  81. MicroProfileOnThreadCreate(name);
  82. Common::SetCurrentThreadName(name);
  83. Common::SetCurrentThreadPriority(Common::ThreadPriority::High);
  84. while (active) {
  85. {
  86. std::scoped_lock l{mutex1};
  87. MICROPROFILE_SCOPE(Audio_RenderSystemManager);
  88. for (auto system : systems) {
  89. system->SendCommandToDsp();
  90. }
  91. }
  92. adsp.Signal();
  93. adsp.Wait();
  94. update.wait(false);
  95. update.store(false);
  96. }
  97. }
  98. std::optional<std::chrono::nanoseconds> SystemManager::ThreadFunc2(s64 time) {
  99. update.store(true);
  100. update.notify_all();
  101. return std::nullopt;
  102. }
  103. } // namespace AudioCore::AudioRenderer