diff --git a/Source/Engine/Graphics/Async/DefaultGPUTasksExecutor.cpp b/Source/Engine/Graphics/Async/DefaultGPUTasksExecutor.cpp index bb7e082bb..ea090e3c9 100644 --- a/Source/Engine/Graphics/Async/DefaultGPUTasksExecutor.cpp +++ b/Source/Engine/Graphics/Async/DefaultGPUTasksExecutor.cpp @@ -23,19 +23,18 @@ void DefaultGPUTasksExecutor::FrameBegin() _context = createContext(); _context->OnFrameBegin(); -} -void DefaultGPUTasksExecutor::FrameEnd() -{ - ASSERT(_context != nullptr); - - // Default implementation performs async operations on end of the frame which is synchronized with a rendering thread + // Default implementation performs async operations on start of the frame which is synchronized with a rendering thread GPUTask* buffer[32]; const int32 count = GPUDevice::Instance->GetTasksManager()->RequestWork(buffer, 32); for (int32 i = 0; i < count; i++) { _context->Run(buffer[i]); } +} +void DefaultGPUTasksExecutor::FrameEnd() +{ + ASSERT(_context != nullptr); _context->OnFrameEnd(); } diff --git a/Source/Engine/Graphics/Async/GPUTask.h b/Source/Engine/Graphics/Async/GPUTask.h index 2dde19109..45d21479d 100644 --- a/Source/Engine/Graphics/Async/GPUTask.h +++ b/Source/Engine/Graphics/Async/GPUTask.h @@ -19,7 +19,7 @@ public: /// /// Describes GPU work type /// - DECLARE_ENUM_4(Type, Custom, CopyResource, UploadTexture, UploadBuffer); + DECLARE_ENUM_EX_4(Type, byte, 0, Custom, CopyResource, UploadTexture, UploadBuffer); /// /// Describes GPU work result value @@ -32,13 +32,15 @@ private: /// Type _type; + byte _syncLatency; + /// /// Synchronization point when async task has been done /// GPUSyncPoint _syncPoint; /// - /// The context that performed this task, it's should synchronize it. + /// The context that performed this task, it should synchronize it. /// GPUTasksContext* _context; @@ -47,8 +49,10 @@ protected: /// Initializes a new instance of the class. /// /// The type. - GPUTask(const Type type) + /// Amount of frames until async operation is synced with GPU. + GPUTask(const Type type, byte syncLatency = GPU_ASYNC_LATENCY) : _type(type) + , _syncLatency(syncLatency) , _syncPoint(0) , _context(nullptr) { @@ -58,7 +62,6 @@ public: /// /// Gets a task type. /// - /// The type. FORCE_INLINE Type GetType() const { return _type; @@ -67,17 +70,15 @@ public: /// /// Gets work finish synchronization point /// - /// Finish task sync point FORCE_INLINE GPUSyncPoint GetSyncPoint() const { - return _syncPoint; + return _syncPoint + _syncLatency; } public: /// /// Checks if operation is syncing /// - /// True if operation is syncing, otherwise false FORCE_INLINE bool IsSyncing() const { return IsRunning() && _syncPoint != 0; diff --git a/Source/Engine/Graphics/Async/GPUTasksContext.cpp b/Source/Engine/Graphics/Async/GPUTasksContext.cpp index 924276521..e98007a7f 100644 --- a/Source/Engine/Graphics/Async/GPUTasksContext.cpp +++ b/Source/Engine/Graphics/Async/GPUTasksContext.cpp @@ -70,16 +70,16 @@ void GPUTasksContext::OnFrameBegin() ++_currentSyncPoint; // Try to flush done jobs - auto currentSyncPointGPU = _currentSyncPoint - GPU_ASYNC_LATENCY; for (int32 i = 0; i < _tasksDone.Count(); i++) { - if (_tasksDone[i]->GetSyncPoint() <= currentSyncPointGPU) + auto task = _tasksDone[i]; + if (task->GetSyncPoint() <= _currentSyncPoint && task->GetState() != TaskState::Finished) { // TODO: add stats counter and count performed jobs, print to log on exit. - - auto job = _tasksDone[i]; - job->Sync(); - + task->Sync(); + } + if (task->GetState() == TaskState::Finished) + { _tasksDone.RemoveAt(i); i--; _totalTasksDoneCount++; diff --git a/Source/Engine/Graphics/Async/GPUTasksContext.h b/Source/Engine/Graphics/Async/GPUTasksContext.h index 1114144c6..1739e17a3 100644 --- a/Source/Engine/Graphics/Async/GPUTasksContext.h +++ b/Source/Engine/Graphics/Async/GPUTasksContext.h @@ -42,7 +42,6 @@ public: /// /// Gets graphics device handle /// - /// Graphics device FORCE_INLINE GPUDevice* GetDevice() const { return GPU->GetDevice(); @@ -51,7 +50,6 @@ public: /// /// Gets current synchronization point of that context (CPU position, GPU has some latency) /// - /// Context sync point FORCE_INLINE GPUSyncPoint GetCurrentSyncPoint() const { return _currentSyncPoint; @@ -60,7 +58,6 @@ public: /// /// Gets total amount of tasks done by this context /// - /// Done tasks count FORCE_INLINE int32 GetTotalTasksDoneCount() const { return _totalTasksDoneCount; diff --git a/Source/Engine/Graphics/Async/GPUTasksManager.cpp b/Source/Engine/Graphics/Async/GPUTasksManager.cpp index 42df38c0c..54cd45ead 100644 --- a/Source/Engine/Graphics/Async/GPUTasksManager.cpp +++ b/Source/Engine/Graphics/Async/GPUTasksManager.cpp @@ -30,6 +30,11 @@ void GPUTask::Execute(GPUTasksContext* context) // Save task completion point (for synchronization) _syncPoint = context->GetCurrentSyncPoint(); _context = context; + if (_syncLatency == 0) + { + // No delay on sync + Sync(); + } } }