AkJobWorkerScheduler.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. /*******************************************************************************
  2. The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
  3. Technology released in source code form as part of the game integration package.
  4. The content of this file may not be used without valid licenses to the
  5. AUDIOKINETIC Wwise Technology.
  6. Note that the use of the game engine is subject to the Unreal(R) Engine End User
  7. License Agreement at https://www.unrealengine.com/en-US/eula/unreal
  8. License Usage
  9. Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
  10. this file in accordance with the end user license agreement provided with the
  11. software or, alternatively, in accordance with the terms contained
  12. in a written agreement between you and Audiokinetic Inc.
  13. Copyright (c) 2023 Audiokinetic Inc.
  14. *******************************************************************************/
  15. #include "AkJobWorkerScheduler.h"
  16. #include "AkAudioDevice.h"
  17. #include "Wwise/WwiseTask.h"
  18. #include "Wwise/API/WwiseMemoryMgrAPI.h"
  19. #define AK_DECLARE_JOB_TYPE(__job__, __desc__, __thread__) \
  20. DECLARE_CYCLE_STAT(TEXT(__desc__), STAT_AkJob##__job__, STATGROUP_Audio); \
  21. namespace AkJobWorkerSchedulerInternals \
  22. { \
  23. static const TCHAR* const Name##__job__ = TEXT(__desc__); \
  24. static EWwiseTaskPriority Task##__job__ = __thread__; \
  25. }
  26. #define AK_DEFINE_JOB_CASE(__job__) \
  27. case AkJobType_##__job__: \
  28. Name = AkJobWorkerSchedulerInternals::Name##__job__; \
  29. StatId = GET_STATID(STAT_AkJob##__job__); \
  30. TaskPriority = AkJobWorkerSchedulerInternals::Task##__job__
  31. static_assert(AK_NUM_JOB_TYPES == 3, "Update the stat groups and switch cases below for new job types!");
  32. AK_DECLARE_JOB_TYPE(Generic, "Wwise Generic Job", EWwiseTaskPriority::High)
  33. AK_DECLARE_JOB_TYPE(AudioProcessing, "Wwise Audio Processing Job", EWwiseTaskPriority::High)
  34. AK_DECLARE_JOB_TYPE(SpatialAudio, "Wwise Spatial Audio Job", EWwiseTaskPriority::High)
  35. static void OnJobWorkerRequest(AkJobWorkerFunc in_fnJobWorker, AkJobType in_jobType, AkUInt32 in_uNumWorkers, void* in_pUserData)
  36. {
  37. FAkJobWorkerScheduler* Scheduler = static_cast<FAkJobWorkerScheduler*>(in_pUserData);
  38. AkUInt32 MaxExecutionTime = Scheduler->uMaxExecutionTime;
  39. const TCHAR* Name;
  40. TStatId StatId;
  41. EWwiseTaskPriority TaskPriority;
  42. switch (in_jobType)
  43. {
  44. AK_DEFINE_JOB_CASE(AudioProcessing); break;
  45. AK_DEFINE_JOB_CASE(SpatialAudio); break;
  46. default:
  47. check(!"Unknown job type.");
  48. // Fall-through
  49. AK_DEFINE_JOB_CASE(Generic);
  50. }
  51. for (int i=0; i < (int)in_uNumWorkers; i++)
  52. {
  53. LaunchWwiseTask(Name, TaskPriority, [=]() {
  54. #if STATS
  55. #if UE_5_0_OR_LATER
  56. FScopeCycleCounter CycleCount(StatId, FStat_STAT_AkJobGeneric::GetFlags());
  57. #else
  58. FScopeCycleCounter CycleCount(StatId);
  59. #endif
  60. #endif
  61. in_fnJobWorker(in_jobType, MaxExecutionTime);
  62. // After completion of the worker function, release any thread-local memory resources
  63. if (auto* MemoryManager = IWwiseMemoryMgrAPI::Get())
  64. {
  65. MemoryManager->TrimForThread();
  66. }
  67. });
  68. }
  69. }
  70. #undef AK_DECLARE_JOB_TYPE
  71. #undef AK_DEFINE_JOB_TYPE
  72. void FAkJobWorkerScheduler::InstallJobWorkerScheduler(uint32 in_uMaxExecutionTime, uint32 in_uMaxWorkerCount, AkJobMgrSettings & out_settings)
  73. {
  74. if (!FTaskGraphInterface::Get().IsRunning())
  75. {
  76. UE_LOG(LogAkAudio, Warning, TEXT("Multi-core rendering was requested, but Task Graph is not running. Multi-core rendering disabled."));
  77. }
  78. else if (!FPlatformProcess::SupportsMultithreading())
  79. {
  80. UE_LOG(LogAkAudio, Warning, TEXT("Multi-core rendering was requested, platform does not support multi-threading. Multi-core rendering disabled."));
  81. }
  82. else
  83. {
  84. check(ENamedThreads::bHasHighPriorityThreads);
  85. uMaxExecutionTime = in_uMaxExecutionTime;
  86. AkUInt32 uNumWorkerThreads = FTaskGraphInterface::Get().GetNumWorkerThreads();
  87. AkUInt32 uMaxActiveWorkers = FMath::Min(uNumWorkerThreads, in_uMaxWorkerCount);
  88. if (uMaxActiveWorkers > 0)
  89. {
  90. out_settings.fnRequestJobWorker = OnJobWorkerRequest;
  91. out_settings.pClientData = this;
  92. for (int i = 0; i < AK_NUM_JOB_TYPES; i++)
  93. {
  94. out_settings.uMaxActiveWorkers[i] = uMaxActiveWorkers;
  95. }
  96. }
  97. else
  98. {
  99. UE_LOG(LogAkAudio, Warning, TEXT("Multi-core rendering was requested, but Max Num Job Workers is set to 0. Multi-core rendering disabled."));
  100. }
  101. }
  102. }