Files
FlaxEngine/Source/Engine/GraphicsDevice/Vulkan/CmdBufferVulkan.h
2020-12-20 10:51:29 +01:00

248 lines
5.1 KiB
C++

// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
#pragma once
#include "GPUDeviceVulkan.h"
#include "Engine/Core/Types/BaseTypes.h"
#include "Engine/Core/Collections/Array.h"
#if GRAPHICS_API_VULKAN
class GPUDeviceVulkan;
class CmdBufferPoolVulkan;
class QueueVulkan;
class DescriptorPoolSetContainerVulkan;
/// <summary>
/// Implementation of the command buffer for the Vulkan backend.
/// </summary>
class CmdBufferVulkan
{
friend QueueVulkan;
public:
enum class State
{
ReadyForBegin,
IsInsideBegin,
IsInsideRenderPass,
HasEnded,
Submitted,
};
private:
GPUDeviceVulkan* _device;
VkCommandBuffer _commandBufferHandle;
State _state;
Array<VkPipelineStageFlags> _waitFlags;
Array<SemaphoreVulkan*> _waitSemaphores;
Array<SemaphoreVulkan*> _submittedWaitSemaphores;
void MarkSemaphoresAsSubmitted()
{
_waitFlags.Clear();
// Move to pending delete list
_submittedWaitSemaphores = _waitSemaphores;
_waitSemaphores.Clear();
}
FenceVulkan* _fence;
#if GPU_ALLOW_PROFILE_EVENTS
int32 _eventsBegin = 0;
#endif
// Last value passed after the fence got signaled
volatile uint64 _fenceSignaledCounter;
// Last value when we submitted the cmd buffer; useful to track down if something waiting for the fence has actually been submitted
volatile uint64 _submittedFenceCounter;
CmdBufferPoolVulkan* _commandBufferPool;
DescriptorPoolSetContainerVulkan* _descriptorPoolSetContainer = nullptr;
public:
CmdBufferVulkan(GPUDeviceVulkan* device, CmdBufferPoolVulkan* pool);
~CmdBufferVulkan();
public:
CmdBufferPoolVulkan* GetOwner()
{
return _commandBufferPool;
}
State GetState()
{
return _state;
}
FenceVulkan* GetFence()
{
return _fence;
}
inline bool IsInsideRenderPass() const
{
return _state == State::IsInsideRenderPass;
}
inline bool IsOutsideRenderPass() const
{
return _state == State::IsInsideBegin;
}
inline bool HasBegun() const
{
return _state == State::IsInsideBegin || _state == State::IsInsideRenderPass;
}
inline bool HasEnded() const
{
return _state == State::HasEnded;
}
inline bool IsSubmitted() const
{
return _state == State::Submitted;
}
inline VkCommandBuffer GetHandle() const
{
return _commandBufferHandle;
}
inline volatile uint64 GetFenceSignaledCounter() const
{
return _fenceSignaledCounter;
}
inline volatile uint64 GetSubmittedFenceCounter() const
{
return _submittedFenceCounter;
}
public:
void AddWaitSemaphore(VkPipelineStageFlags waitFlags, SemaphoreVulkan* waitSemaphore);
void Begin();
void End();
void BeginRenderPass(RenderPassVulkan* renderPass, FramebufferVulkan* framebuffer, uint32 clearValueCount, VkClearValue* clearValues);
void EndRenderPass();
DescriptorPoolSetContainerVulkan* GetDescriptorPoolSet() const
{
return _descriptorPoolSetContainer;
}
void AcquirePoolSet();
#if GPU_ALLOW_PROFILE_EVENTS
void BeginEvent(const Char* name);
void EndEvent();
#endif
void RefreshFenceStatus();
};
class CmdBufferPoolVulkan
{
private:
GPUDeviceVulkan* Device;
VkCommandPool Handle;
CmdBufferVulkan* Create();
Array<CmdBufferVulkan*> CmdBuffers;
void Create(uint32 queueFamilyIndex);
friend class CmdBufferManagerVulkan;
public:
CmdBufferPoolVulkan(GPUDeviceVulkan* device);
~CmdBufferPoolVulkan();
public:
inline VkCommandPool GetHandle() const
{
ASSERT(Handle != VK_NULL_HANDLE);
return Handle;
}
void RefreshFenceStatus(CmdBufferVulkan* skipCmdBuffer = nullptr);
};
class CmdBufferManagerVulkan
{
private:
GPUDeviceVulkan* Device;
CmdBufferPoolVulkan Pool;
QueueVulkan* Queue;
CmdBufferVulkan* ActiveCmdBuffer;
Array<GPUTimerQueryVulkan*> QueriesInProgress;
public:
CmdBufferManagerVulkan(GPUDeviceVulkan* device, GPUContextVulkan* context);
public:
inline VkCommandPool GetHandle() const
{
return Pool.GetHandle();
}
inline CmdBufferVulkan* GetActiveCmdBuffer() const
{
return ActiveCmdBuffer;
}
inline bool HasPendingActiveCmdBuffer() const
{
return ActiveCmdBuffer != nullptr;
}
inline bool HasQueriesInProgress() const
{
return QueriesInProgress.Count() != 0;
}
void SubmitActiveCmdBuffer(SemaphoreVulkan* signalSemaphore = nullptr);
void WaitForCmdBuffer(CmdBufferVulkan* cmdBuffer, float timeInSecondsToWait = 1.0f);
// Update the fences of all cmd buffers except SkipCmdBuffer
void RefreshFenceStatus(CmdBufferVulkan* skipCmdBuffer = nullptr)
{
Pool.RefreshFenceStatus(skipCmdBuffer);
}
void PrepareForNewActiveCommandBuffer();
inline CmdBufferVulkan* GetCmdBuffer()
{
if (!ActiveCmdBuffer)
PrepareForNewActiveCommandBuffer();
return ActiveCmdBuffer;
}
void OnQueryBegin(GPUTimerQueryVulkan* query);
void OnQueryEnd(GPUTimerQueryVulkan* query);
};
#endif