123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240 |
- /*******************************************************************************
- The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
- Technology released in source code form as part of the game integration package.
- The content of this file may not be used without valid licenses to the
- AUDIOKINETIC Wwise Technology.
- Note that the use of the game engine is subject to the Unreal(R) Engine End User
- License Agreement at https://www.unrealengine.com/en-US/eula/unreal
-
- License Usage
-
- Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
- this file in accordance with the end user license agreement provided with the
- software or, alternatively, in accordance with the terms contained
- in a written agreement between you and Audiokinetic Inc.
- Copyright (c) 2023 Audiokinetic Inc.
- *******************************************************************************/
- #include "Wwise/WwiseDeferredQueue.h"
- #include "Async/Async.h"
- #include "Wwise/Stats/AsyncStats.h"
- #include "Wwise/Stats/Concurrency.h"
- FWwiseDeferredQueue::FWwiseDeferredQueue()
- {
- }
- FWwiseDeferredQueue::~FWwiseDeferredQueue()
- {
- bClosing = true;
- if (!IsEmpty())
- {
- Wait();
- UE_CLOG(UNLIKELY(!IsEmpty()), LogWwiseConcurrency, Error, TEXT("Still operations in queue while deleting Deferred Queue"));
- }
- }
- void FWwiseDeferredQueue::AsyncDefer(FFunction&& InFunction)
- {
- if (!bClosing)
- {
- AsyncOpQueue.Enqueue(MoveTemp(InFunction));
- }
- }
- void FWwiseDeferredQueue::SyncDefer(FSyncFunction&& InFunction)
- {
- if (!bClosing)
- {
- SyncOpQueue.Enqueue(MoveTemp(InFunction));
- }
- }
- void FWwiseDeferredQueue::GameDefer(FFunction&& InFunction)
- {
- if (!bClosing)
- {
- GameOpQueue.Enqueue(MoveTemp(InFunction));
- }
- }
- void FWwiseDeferredQueue::Run(AK::IAkGlobalPluginContext* InContext)
- {
- SCOPED_WWISECONCURRENCY_EVENT_4(TEXT("FWwiseDeferredQueue::Run"));
- FWwiseAsyncCycleCounter OpCycleCounter(GET_STATID(STAT_WwiseConcurrencySync));
- UE_CLOG(UNLIKELY(Context), LogWwiseConcurrency, Error, TEXT("Executing two Run() at the same time."));
- Context = InContext;
- if (!AsyncOpQueue.IsEmpty())
- {
- AsyncExecutionQueue.Async([this]() mutable
- {
- AsyncExec();
- });
- }
- if (!GameOpQueue.IsEmpty() || OnGameRun.IsBound())
- {
- GameThreadExec();
- }
- if (!SyncOpQueue.IsEmpty() || OnSyncRunTS.IsBound())
- {
- SyncExec();
- }
- OnSyncRunTS.Broadcast(Context);
- Context = nullptr;
- }
- void FWwiseDeferredQueue::Wait()
- {
- const bool bIsInGameThread = IsInGameThread();
- SCOPED_WWISECONCURRENCY_EVENT_4(bIsInGameThread ? TEXT("FWwiseDeferredQueue::Wait GameThread") : TEXT("FWwiseDeferredQueue::Wait"));
- CONDITIONAL_SCOPE_CYCLE_COUNTER(STAT_WwiseConcurrencyGameThreadWait, bIsInGameThread);
- CONDITIONAL_SCOPE_CYCLE_COUNTER(STAT_WwiseConcurrencyWait, !bIsInGameThread);
- if (!AsyncOpQueue.IsEmpty())
- {
- AsyncExecutionQueue.AsyncWait([this]() mutable
- {
- AsyncExec();
- });
- }
- if (!GameOpQueue.IsEmpty())
- {
- FEventRef Done;
- if (bIsInGameThread)
- {
- const bool bNeedToStartLoop = GameThreadExecuting.IncrementExchange() == 0;
- GameOpQueue.Enqueue([this, &Done]() mutable
- {
- Done->Trigger();
- GameThreadExecuting.DecrementExchange();
- return EWwiseDeferredAsyncResult::Done;
- });
- if (bNeedToStartLoop)
- {
- FFunction Func;
- while (GameThreadExecuting.Load() > 0 && GameOpQueue.Dequeue(Func))
- {
- if (Func() == EWwiseDeferredAsyncResult::KeepRunning)
- {
- GameDefer(MoveTemp(Func));
- }
- }
- }
- }
- else
- {
- GameOpQueue.Enqueue([&Done]() mutable
- {
- Done->Trigger();
- return EWwiseDeferredAsyncResult::Done;
- });
- GameThreadExec();
- }
- Done->Wait();
- }
- if (!SyncOpQueue.IsEmpty())
- {
- FWwiseAsyncCycleCounter OpCycleCounter(GET_STATID(STAT_WwiseConcurrencySync));
- SyncExec();
- }
- }
- void FWwiseDeferredQueue::AsyncExec()
- {
- SCOPED_WWISECONCURRENCY_EVENT_4(TEXT("FWwiseDeferredQueue::AsyncExec"));
- SCOPE_CYCLE_COUNTER(STAT_WwiseConcurrencyAsync);
- bool bDone = false;
- AsyncOpQueue.Enqueue([&bDone]() mutable
- {
- bDone = true;
- return EWwiseDeferredAsyncResult::Done;
- });
- while (!bDone)
- {
- FFunction Func;
- const bool bResult = AsyncOpQueue.Dequeue(Func);
- if (UNLIKELY(!bResult))
- {
- UE_LOG(LogWwiseConcurrency, Error, TEXT("FWwiseDeferredQueue: No Result dequeuing Async Deferred Queue"));
- break;
- }
- if (Func() == EWwiseDeferredAsyncResult::KeepRunning)
- {
- AsyncDefer(MoveTemp(Func));
- }
- }
- }
- void FWwiseDeferredQueue::SyncExec()
- {
- SyncOpQueue.Enqueue([this](AK::IAkGlobalPluginContext*) mutable
- {
- bSyncThreadDone = true;
- return EWwiseDeferredAsyncResult::Done;
- });
- SyncExecLoop();
- }
- void FWwiseDeferredQueue::SyncExecLoop()
- {
- FSyncFunction Func;
- while (!bSyncThreadDone && SyncOpQueue.Dequeue(Func))
- {
- if (Func(Context) == EWwiseDeferredAsyncResult::KeepRunning)
- {
- SyncDefer(MoveTemp(Func));
- }
- }
- OnSyncRunTS.Broadcast(Context);
- bSyncThreadDone = false;
- }
- void FWwiseDeferredQueue::GameThreadExec()
- {
- const bool bNeedToStartLoop = GameThreadExecuting.IncrementExchange() == 0;
- GameOpQueue.Enqueue([this]() mutable
- {
- GameThreadExecuting.DecrementExchange();
- return EWwiseDeferredAsyncResult::Done;
- });
- if (bNeedToStartLoop)
- {
- GameThreadExecLoop();
- }
- }
- void FWwiseDeferredQueue::GameThreadExecLoop()
- {
- AsyncTask(ENamedThreads::GameThread, [this]() mutable
- {
- SCOPED_WWISECONCURRENCY_EVENT_4(TEXT("FWwiseDeferredQueue::GameThreadExecLoop"));
- SCOPE_CYCLE_COUNTER(STAT_WwiseConcurrencyGameThread);
- FFunction Func;
- while (GameThreadExecuting.Load() > 0 && GameOpQueue.Dequeue(Func))
- {
- if (Func() == EWwiseDeferredAsyncResult::KeepRunning)
- {
- GameDefer(MoveTemp(Func));
- }
- }
- OnGameRun.Broadcast();
- });
- }
|