Files
FlaxEngine/Source/Engine/GraphicsDevice/Vulkan/CmdBufferVulkan.h
2021-01-02 14:28:49 +01:00

244 lines
5.0 KiB
C++

// Copyright (c) 2012-2021 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 _commandBuffer;
State _state;
Array<VkPipelineStageFlags> _waitFlags;
Array<SemaphoreVulkan*> _waitSemaphores;
Array<SemaphoreVulkan*> _submittedWaitSemaphores;
void MarkSemaphoresAsSubmitted()
{
_waitFlags.Clear();
_submittedWaitSemaphores = _waitSemaphores;
_waitSemaphores.Clear();
}
FenceVulkan* _fence;
#if GPU_ALLOW_PROFILE_EVENTS
int32 _eventsBegin = 0;
#endif
// The latest value when command buffer was submitted.
volatile uint64 _submittedFenceCounter;
// The latest value passed after the fence was signaled.
volatile uint64 _fenceSignaledCounter;
CmdBufferPoolVulkan* _commandBufferPool;
DescriptorPoolSetContainerVulkan* _descriptorPoolSetContainer = nullptr;
public:
CmdBufferVulkan(GPUDeviceVulkan* device, CmdBufferPoolVulkan* pool);
~CmdBufferVulkan();
public:
CmdBufferPoolVulkan* GetOwner() const
{
return _commandBufferPool;
}
State GetState() const
{
return _state;
}
FenceVulkan* GetFence() const
{
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 _commandBuffer;
}
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
{
friend class CmdBufferManagerVulkan;
private:
GPUDeviceVulkan* _device;
VkCommandPool _handle;
Array<CmdBufferVulkan*> _cmdBuffers;
CmdBufferVulkan* Create();
void Create(uint32 queueFamilyIndex);
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:
FORCE_INLINE VkCommandPool GetHandle() const
{
return _pool.GetHandle();
}
FORCE_INLINE CmdBufferVulkan* GetActiveCmdBuffer() const
{
return _activeCmdBuffer;
}
FORCE_INLINE bool HasPendingActiveCmdBuffer() const
{
return _activeCmdBuffer != nullptr;
}
FORCE_INLINE bool HasQueriesInProgress() const
{
return _queriesInProgress.Count() != 0;
}
CmdBufferVulkan* GetCmdBuffer()
{
if (!_activeCmdBuffer)
PrepareForNewActiveCommandBuffer();
return _activeCmdBuffer;
}
public:
void SubmitActiveCmdBuffer(SemaphoreVulkan* signalSemaphore = nullptr);
void WaitForCmdBuffer(CmdBufferVulkan* cmdBuffer, float timeInSecondsToWait = 1.0f);
void RefreshFenceStatus(CmdBufferVulkan* skipCmdBuffer = nullptr)
{
_pool.RefreshFenceStatus(skipCmdBuffer);
}
void PrepareForNewActiveCommandBuffer();
void OnQueryBegin(GPUTimerQueryVulkan* query);
void OnQueryEnd(GPUTimerQueryVulkan* query);
};
#endif