summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngineVulkan
diff options
context:
space:
mode:
authorEgor Yusov <egor.yusov@gmail.com>2018-04-08 18:00:47 +0000
committerEgor Yusov <egor.yusov@gmail.com>2018-04-08 18:00:47 +0000
commitf41cab9a3aed92f6b9febbe58760a0573c0b2d6d (patch)
tree197f6a31e622fa17a3f7aaba479af10c3d4be3a3 /Graphics/GraphicsEngineVulkan
parentAdded buffer view initialization (diff)
downloadDiligentCore-f41cab9a3aed92f6b9febbe58760a0573c0b2d6d.tar.gz
DiligentCore-f41cab9a3aed92f6b9febbe58760a0573c0b2d6d.zip
Vulkan progress:
* added vulkan logical device & vulkan object wrappers * added texture intialization * added cmd buffer pool* * added fence pool * added object release queues
Diffstat (limited to 'Graphics/GraphicsEngineVulkan')
-rw-r--r--Graphics/GraphicsEngineVulkan/CMakeLists.txt9
-rw-r--r--Graphics/GraphicsEngineVulkan/include/BufferViewVkImpl.h8
-rw-r--r--Graphics/GraphicsEngineVulkan/include/BufferVkImpl.h8
-rw-r--r--Graphics/GraphicsEngineVulkan/include/CommandListManager.h67
-rw-r--r--Graphics/GraphicsEngineVulkan/include/CommandQueueVkImpl.h41
-rw-r--r--Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.h75
-rw-r--r--Graphics/GraphicsEngineVulkan/include/SwapChainVkImpl.h2
-rw-r--r--Graphics/GraphicsEngineVulkan/include/TextureViewVkImpl.h8
-rw-r--r--Graphics/GraphicsEngineVulkan/include/TextureVkImpl.h21
-rw-r--r--Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBufferPool.h59
-rw-r--r--Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanDebug.h3
-rw-r--r--Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanFencePool.h52
-rw-r--r--Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanInstance.h25
-rw-r--r--Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.h104
-rw-r--r--Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanObjectWrappers.h96
-rw-r--r--Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.h6
-rw-r--r--Graphics/GraphicsEngineVulkan/interface/CommandQueueVk.h12
-rw-r--r--Graphics/GraphicsEngineVulkan/interface/RenderDeviceVk.h13
-rw-r--r--Graphics/GraphicsEngineVulkan/src/BufferViewVkImpl.cpp11
-rw-r--r--Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp94
-rw-r--r--Graphics/GraphicsEngineVulkan/src/CommandContext.cpp1
-rw-r--r--Graphics/GraphicsEngineVulkan/src/CommandListManager.cpp109
-rw-r--r--Graphics/GraphicsEngineVulkan/src/CommandQueueVkImpl.cpp98
-rw-r--r--Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp2
-rw-r--r--Graphics/GraphicsEngineVulkan/src/RenderDeviceFactoryVk.cpp41
-rw-r--r--Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp282
-rw-r--r--Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp18
-rw-r--r--Graphics/GraphicsEngineVulkan/src/TextureViewVkImpl.cpp11
-rw-r--r--Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp193
-rw-r--r--Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanCommandBufferPool.cpp115
-rw-r--r--Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanDebug.cpp15
-rw-r--r--Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanFencePool.cpp69
-rw-r--r--Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp9
-rw-r--r--Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp292
-rw-r--r--Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp6
35 files changed, 1395 insertions, 580 deletions
diff --git a/Graphics/GraphicsEngineVulkan/CMakeLists.txt b/Graphics/GraphicsEngineVulkan/CMakeLists.txt
index 6b71a279..2ceabf85 100644
--- a/Graphics/GraphicsEngineVulkan/CMakeLists.txt
+++ b/Graphics/GraphicsEngineVulkan/CMakeLists.txt
@@ -7,7 +7,6 @@ set(INCLUDE
include/BufferViewVkImpl.h
include/CommandContext.h
include/CommandListVkImpl.h
- include/CommandListManager.h
include/CommandQueueVkImpl.h
include/VulkanResourceBase.h
include/VulkanTypeConversions.h
@@ -34,8 +33,12 @@ set(INCLUDE
)
set(VULKAN_UTILS_INCLUDE
+ include/VulkanUtilities/VulkanCommandBufferPool.h
include/VulkanUtilities/VulkanDebug.h
+ include/VulkanUtilities/VulkanFencePool.h
include/VulkanUtilities/VulkanInstance.h
+ include/VulkanUtilities/VulkanLogicalDevice.h
+ include/VulkanUtilities/VulkanObjectWrappers.h
include/VulkanUtilities/VulkanPhysicalDevice.h
)
@@ -61,7 +64,6 @@ set(SRC
src/BufferVkImpl.cpp
src/BufferViewVkImpl.cpp
src/CommandContext.cpp
- src/CommandListManager.cpp
src/CommandQueueVkImpl.cpp
src/VulkanResourceBase.cpp
src/VulkanTypeConversions.cpp
@@ -86,8 +88,11 @@ set(SRC
)
set(VULKAN_UTILS_SRC
+ src/VulkanUtilities/VulkanCommandBufferPool.cpp
src/VulkanUtilities/VulkanDebug.cpp
+ src/VulkanUtilities/VulkanFencePool.cpp
src/VulkanUtilities/VulkanInstance.cpp
+ src/VulkanUtilities/VulkanLogicalDevice.cpp
src/VulkanUtilities/VulkanPhysicalDevice.cpp
)
diff --git a/Graphics/GraphicsEngineVulkan/include/BufferViewVkImpl.h b/Graphics/GraphicsEngineVulkan/include/BufferViewVkImpl.h
index ff203851..71506640 100644
--- a/Graphics/GraphicsEngineVulkan/include/BufferViewVkImpl.h
+++ b/Graphics/GraphicsEngineVulkan/include/BufferViewVkImpl.h
@@ -30,6 +30,7 @@
#include "RenderDeviceVk.h"
#include "BufferViewBase.h"
#include "DescriptorHeap.h"
+#include "VulkanUtilities/VulkanObjectWrappers.h"
namespace Diligent
{
@@ -45,16 +46,17 @@ public:
IRenderDevice *pDevice,
const BufferViewDesc& ViewDesc,
class IBuffer *pBuffer,
- VkBufferView vkBuffView,
+ VulkanUtilities::BufferViewWrapper &&BuffView,
bool bIsDefaultView);
+ ~BufferViewVkImpl();
virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface );
- virtual VkBufferView GetVkBufferView()override final{return m_VkBuffView;}
+ virtual VkBufferView GetVkBufferView()override final{return m_BuffView;}
protected:
- VkBufferView m_VkBuffView;
+ VulkanUtilities::BufferViewWrapper m_BuffView;
};
}
diff --git a/Graphics/GraphicsEngineVulkan/include/BufferVkImpl.h b/Graphics/GraphicsEngineVulkan/include/BufferVkImpl.h
index 2b70c416..31b58787 100644
--- a/Graphics/GraphicsEngineVulkan/include/BufferVkImpl.h
+++ b/Graphics/GraphicsEngineVulkan/include/BufferVkImpl.h
@@ -32,6 +32,7 @@
#include "BufferViewVkImpl.h"
#include "VulkanResourceBase.h"
#include "DynamicUploadHeap.h"
+#include "VulkanUtilities/VulkanObjectWrappers.h"
namespace Diligent
{
@@ -122,7 +123,7 @@ public:
private:
virtual void CreateViewInternal( const struct BufferViewDesc &ViewDesc, IBufferView **ppView, bool bIsDefaultView )override;
- VkBufferView CreateView(struct BufferViewDesc &ViewDesc);
+ VulkanUtilities::BufferViewWrapper CreateView(struct BufferViewDesc &ViewDesc);
/* DescriptorHeapAllocation m_CBVDescriptorAllocation;
#ifdef _DEBUG
@@ -132,8 +133,9 @@ private:
friend class DeviceContextVkImpl;
// Array of dynamic allocations for every device context
std::vector<DynamicAllocation, STDAllocatorRawMem<DynamicAllocation> > m_DynamicData;*/
- VkBuffer m_VkBuffer = VK_NULL_HANDLE;
- VkDeviceMemory m_BufferMemory = VK_NULL_HANDLE;
+
+ VulkanUtilities::BufferWrapper m_VulkanBuffer;
+ VulkanUtilities::DeviceMemoryWrapper m_BufferMemory;
};
}
diff --git a/Graphics/GraphicsEngineVulkan/include/CommandListManager.h b/Graphics/GraphicsEngineVulkan/include/CommandListManager.h
deleted file mode 100644
index 461e7116..00000000
--- a/Graphics/GraphicsEngineVulkan/include/CommandListManager.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/* Copyright 2015-2018 Egor Yusov
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
- *
- * In no event and under no legal theory, whether in tort (including negligence),
- * contract, or otherwise, unless required by applicable law (such as deliberate
- * and grossly negligent acts) or agreed to in writing, shall any Contributor be
- * liable for any damages, including any direct, indirect, special, incidental,
- * or consequential damages of any character arising as a result of this License or
- * out of the use or inability to use the software (including but not limited to damages
- * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
- * all other commercial damages or losses), even if such Contributor has been advised
- * of the possibility of such damages.
- */
-
-#pragma once
-
-#include <vector>
-#include <deque>
-#include <mutex>
-#include <stdint.h>
-
-namespace Diligent
-{
-
-class CommandListManager
-{
-public:
- CommandListManager(class RenderDeviceVkImpl *pDeviceVk);
- ~CommandListManager();
-
- CommandListManager(const CommandListManager&) = delete;
- CommandListManager(CommandListManager&&) = delete;
- CommandListManager& operator = (const CommandListManager&) = delete;
- CommandListManager& operator = (CommandListManager&&) = delete;
-
- /*void CreateNewCommandList( IVkGraphicsCommandList** ppList, IVkCommandAllocator** ppAllocator );
-
- // Discards the allocator.
- // FenceValue is the value that was signaled by the command queue after it
- // executed the the command list created by the allocator
- void DiscardAllocator( Uint64 FenceValue, IVkCommandAllocator* pAllocator );
-
- void RequestAllocator(IVkCommandAllocator** ppAllocator);
-
-private:
- // fist - the fence value associated with the command list that was created by the allocator
- // second - the allocator to be discarded
- typedef std::pair<Uint64, CComPtr<IVkCommandAllocator> > DiscardedAllocatorQueueElemType;
- std::deque< DiscardedAllocatorQueueElemType, STDAllocatorRawMem<DiscardedAllocatorQueueElemType> > m_DiscardedAllocators;
-
- std::mutex m_AllocatorMutex;
- RenderDeviceVkImpl *m_pDeviceVk;
-
- Atomics::AtomicLong m_NumAllocators = 0; // For debug purposes only
- */
-};
-
-} \ No newline at end of file
diff --git a/Graphics/GraphicsEngineVulkan/include/CommandQueueVkImpl.h b/Graphics/GraphicsEngineVulkan/include/CommandQueueVkImpl.h
index c655b67d..bf8a2866 100644
--- a/Graphics/GraphicsEngineVulkan/include/CommandQueueVkImpl.h
+++ b/Graphics/GraphicsEngineVulkan/include/CommandQueueVkImpl.h
@@ -26,9 +26,13 @@
/// \file
/// Declaration of Diligent::CommandQueueVkImpl class
+#include <mutex>
+#include <deque>
#include "vulkan.h"
#include "CommandQueueVk.h"
#include "ObjectBase.h"
+#include "VulkanUtilities/VulkanLogicalDevice.h"
+#include "VulkanUtilities/VulkanFencePool.h"
namespace Diligent
{
@@ -39,43 +43,44 @@ class CommandQueueVkImpl : public ObjectBase<ICommandQueueVk>
public:
typedef ObjectBase<ICommandQueueVk> TBase;
- CommandQueueVkImpl(IReferenceCounters *pRefCounters, VkQueue VkNativeCmdQueue, uint32_t QueueFamilyIndex);
+ CommandQueueVkImpl(IReferenceCounters *pRefCounters,
+ std::shared_ptr<VulkanUtilities::VulkanLogicalDevice> LogicalDevice,
+ uint32_t QueueFamilyIndex);
~CommandQueueVkImpl();
virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface )override;
// Returns the fence value that will be signaled next time
- //virtual UINT64 GetNextFenceValue()override final { return m_NextFenceValue; }
+ virtual UINT64 GetNextFenceValue()override final { return m_NextFenceValue; }
- // Executes a given command list
- //virtual UINT64 ExecuteCommandList(IVkGraphicsCommandList* commandList)override final;
+ // Executes a given command buffer
+ virtual Uint64 ExecuteCommandBuffer(VkCommandBuffer cmdBuffer)override final;
virtual VkQueue GetVkQueue()override final{return m_VkQueue;}
virtual uint32_t GetQueueFamilyIndex()override final { return m_QueueFamilyIndex; }
+
+ virtual void IdleGPU()override final;
-
- //virtual void IdleGPU()override final;
-
- //virtual Uint64 GetCompletedFenceValue()override final;
+ virtual Uint64 GetCompletedFenceValue()override final;
private:
// A value that will be signaled by the command queue next
- //Atomics::AtomicInt64 m_NextFenceValue;
+ Atomics::AtomicInt64 m_NextFenceValue;
- // Last fence value completed by the GPU
- //volatile Uint64 m_LastCompletedFenceValue = 0;
+ // Last fence value that is known to be completed by the GPU
+ volatile Uint64 m_LastCompletedFenceValue = 0;
+ std::shared_ptr<VulkanUtilities::VulkanLogicalDevice> m_LogicalDevice;
+
const VkQueue m_VkQueue;
const uint32_t m_QueueFamilyIndex;
-/*
- // The fence is signaled right after the command list has been
+ VulkanUtilities::VulkanFencePool m_FencePool;
+ // Queue of fences signaled right after a command buffer has been
// submitted to the command queue for execution.
- // All command lists with fence value less or equal to the signaled value
+ // All command buffers with fence value less or equal to the signaled value
// are guaranteed to be finished by the GPU
- CComPtr<IVkFence> m_VkFence;
-
- HANDLE m_WaitForGPUEventHandle = {};
- */
+ std::deque<std::pair<Uint64, VulkanUtilities::FenceWrapper>> m_PendingFences;
+ std::mutex m_QueueMutex;
};
}
diff --git a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.h b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.h
index d46806ae..98275f24 100644
--- a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.h
+++ b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.h
@@ -25,17 +25,20 @@
/// \file
/// Declaration of Diligent::RenderDeviceVkImpl class
+#include <memory>
#include "RenderDeviceVk.h"
#include "RenderDeviceBase.h"
#include "DescriptorHeap.h"
-#include "CommandListManager.h"
#include "CommandContext.h"
#include "DynamicUploadHeap.h"
#include "Atomics.h"
#include "CommandQueueVk.h"
#include "VulkanUtilities/VulkanInstance.h"
#include "VulkanUtilities/VulkanPhysicalDevice.h"
+#include "VulkanUtilities/VulkanCommandBufferPool.h"
+#include "VulkanUtilities/VulkanLogicalDevice.h"
+#include "VulkanUtilities/VulkanObjectWrappers.h"
/// Namespace for the Direct3D11 implementation of the graphics engine
namespace Diligent
@@ -53,7 +56,7 @@ public:
ICommandQueueVk *pCmdQueue,
std::shared_ptr<VulkanUtilities::VulkanInstance> Instance,
std::unique_ptr<VulkanUtilities::VulkanPhysicalDevice> PhysicalDevice,
- VkDevice vkLogicalDevice,
+ std::shared_ptr<VulkanUtilities::VulkanLogicalDevice> LogicalDevice,
Uint32 NumDeferredContexts );
~RenderDeviceVkImpl();
@@ -71,7 +74,7 @@ public:
virtual void CreateSampler(const SamplerDesc& SamplerDesc, ISampler **ppSampler)override final;
- //virtual IVkDevice* GetVkDevice()override final{return m_pVkDevice;}
+ virtual VkDevice GetVkDevice()override final{ return m_LogicalVkDevice->GetVkDevice();}
//virtual void CreateTextureFromD3DResource(IVkResource *pVkTexture, ITexture **ppTexture)override final;
@@ -80,7 +83,7 @@ public:
/*
DescriptorHeapAllocation AllocateDescriptor( Vk_DESCRIPTOR_HEAP_TYPE Type, UINT Count = 1 );
DescriptorHeapAllocation AllocateGPUDescriptors( Vk_DESCRIPTOR_HEAP_TYPE Type, UINT Count = 1 );
-
+*/
Uint64 GetCompletedFenceValue();
virtual Uint64 GetNextFenceValue() override final
{
@@ -89,40 +92,39 @@ public:
Uint64 GetCurrentFrameNumber()const {return static_cast<Uint64>(m_FrameNumber);}
virtual Bool IsFenceSignaled(Uint64 FenceValue) override final;
- */
+
ICommandQueueVk *GetCmdQueue(){return m_pCommandQueue;}
- /*
- void IdleGPU(bool ReleaseStaleObjects);
- CommandContext* AllocateCommandContext(const Char *ID = "");
- void CloseAndExecuteCommandContext(CommandContext *pCtx, bool DiscardStaleObjects);
- void DisposeCommandContext(CommandContext*);
-*/
- void SafeReleaseVkBuffer(VkBuffer vkBuffer);
-/*
+ void IdleGPU(bool ReleaseStaleObjects);
+ VkCommandBuffer AllocateCommandBuffer(const Char *DebugName = nullptr);
+ void ExecuteCommandBuffer(VkCommandBuffer CmdBuff, bool DiscardStaleObjects);
+ void DisposeCommandBuffer(VkCommandBuffer CmdBuff);
+
+
+ template<typename VulkanObjectType>
+ void SafeReleaseVkObject(VulkanUtilities::VulkanObjectWrapper<VulkanObjectType>&& vkObject);
+
+
void FinishFrame(bool ReleaseAllResources);
virtual void FinishFrame()override final { FinishFrame(false); }
-
+ /*
DynamicUploadHeap* RequestUploadHeap();
void ReleaseUploadHeap(DynamicUploadHeap* pUploadHeap);
*/
-
- std::shared_ptr<VulkanUtilities::VulkanInstance> GetVulkanInstance(){return m_VulkanInstance;}
+ std::shared_ptr<const VulkanUtilities::VulkanInstance> GetVulkanInstance()const{return m_VulkanInstance;}
const VulkanUtilities::VulkanPhysicalDevice &GetPhysicalDevice(){return *m_PhysicalDevice;}
- VkDevice GetVkDevice()const{return m_VkDevice;}
+ const auto &GetLogicalDevice(){return *m_LogicalVkDevice;}
private:
- virtual void TestTextureFormat( TEXTURE_FORMAT TexFormat );
-#if 0
+ virtual void TestTextureFormat( TEXTURE_FORMAT TexFormat )override final;
void ProcessReleaseQueue(Uint64 CompletedFenceValue);
void DiscardStaleVkObjects(Uint64 CmdListNumber, Uint64 FenceValue);
-#endif
+
std::shared_ptr<VulkanUtilities::VulkanInstance> m_VulkanInstance;
std::unique_ptr<VulkanUtilities::VulkanPhysicalDevice> m_PhysicalDevice;
-
- /// Vk device
- VkDevice m_VkDevice = VK_NULL_HANDLE;
+ std::shared_ptr<VulkanUtilities::VulkanLogicalDevice> m_LogicalVkDevice;
+
RefCntAutoPtr<ICommandQueueVk> m_pCommandQueue;
EngineVkAttribs m_EngineAttribs;
@@ -132,12 +134,12 @@ private:
// Vk_DESCRIPTOR_HEAP_TYPE_SAMPLER == 1
const Uint32 m_DynamicDescriptorAllocationChunkSize[2];
-
+#endif
std::mutex m_CmdQueueMutex;
Atomics::AtomicInt64 m_FrameNumber;
Atomics::AtomicInt64 m_NextCmdListNumber;
-
+#if 0
// The following basic requirement guarantees correctness of resource deallocation:
//
// A resource is never released before the last draw command referencing it is invoked on the immediate context
@@ -170,18 +172,29 @@ private:
typedef std::unique_ptr<CommandContext, STDDeleterRawMem<CommandContext> > ContextPoolElemType;
std::vector< ContextPoolElemType, STDAllocatorRawMem<ContextPoolElemType> > m_ContextPool;
-
- std::deque<CommandContext*, STDAllocatorRawMem<CommandContext*> > m_AvailableContexts;
- std::mutex m_ContextAllocationMutex;
+ std::deque<CommandContext*, STDAllocatorRawMem<CommandContext*> > m_AvailableContexts;
+#endif
+
+ VulkanUtilities::VulkanCommandBufferPool m_CmdBufferPool;
+ std::mutex m_CmdPoolMutex;
std::mutex m_ReleaseQueueMutex;
- typedef std::pair<Uint64, CComPtr<IVkObject> > ReleaseQueueElemType;
+
+ class StaleVulkanObjectBase
+ {
+ public:
+ virtual ~StaleVulkanObjectBase() = 0 {}
+ };
+ template<typename VulkanObjectType>
+ class StaleVulkanObject;
+
+ using ReleaseQueueElemType = std::pair<Uint64, std::unique_ptr<StaleVulkanObjectBase> >;
std::deque< ReleaseQueueElemType, STDAllocatorRawMem<ReleaseQueueElemType> > m_VkObjReleaseQueue;
-#endif
+
std::mutex m_StaleObjectsMutex;
-#if 0
std::deque< ReleaseQueueElemType, STDAllocatorRawMem<ReleaseQueueElemType> > m_StaleVkObjects;
+#if 0
std::mutex m_UploadHeapMutex;
typedef std::unique_ptr<DynamicUploadHeap, STDDeleterRawMem<DynamicUploadHeap> > UploadHeapPoolElemType;
std::vector< UploadHeapPoolElemType, STDAllocatorRawMem<UploadHeapPoolElemType> > m_UploadHeaps;
diff --git a/Graphics/GraphicsEngineVulkan/include/SwapChainVkImpl.h b/Graphics/GraphicsEngineVulkan/include/SwapChainVkImpl.h
index 7b543619..bad8c1ed 100644
--- a/Graphics/GraphicsEngineVulkan/include/SwapChainVkImpl.h
+++ b/Graphics/GraphicsEngineVulkan/include/SwapChainVkImpl.h
@@ -64,7 +64,7 @@ public:
private:
void InitBuffersAndViews();
- std::shared_ptr<VulkanUtilities::VulkanInstance> m_VulkanInstance;
+ std::shared_ptr<const VulkanUtilities::VulkanInstance> m_VulkanInstance;
VkSurfaceKHR m_VkSurface = VK_NULL_HANDLE;
VkSwapchainKHR m_VkSwapChain = VK_NULL_HANDLE;
VkFormat m_VkColorFormat = VK_FORMAT_UNDEFINED;
diff --git a/Graphics/GraphicsEngineVulkan/include/TextureViewVkImpl.h b/Graphics/GraphicsEngineVulkan/include/TextureViewVkImpl.h
index 911d1699..78dee56e 100644
--- a/Graphics/GraphicsEngineVulkan/include/TextureViewVkImpl.h
+++ b/Graphics/GraphicsEngineVulkan/include/TextureViewVkImpl.h
@@ -29,6 +29,7 @@
#include "TextureViewVk.h"
#include "RenderDeviceVk.h"
#include "TextureViewBase.h"
+#include "VulkanUtilities/VulkanObjectWrappers.h"
namespace Diligent
{
@@ -44,18 +45,19 @@ public:
IRenderDevice *pDevice,
const TextureViewDesc& ViewDesc,
class ITexture *pTexture,
- VkImageView vkImgView,
+ VulkanUtilities::ImageViewWrapper &&ImgView,
bool bIsDefaultView);
+ ~TextureViewVkImpl();
virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface )override;
void GenerateMips( IDeviceContext *pContext )override;
- VkImageView GetVulkanImageView()const{return m_VkImageView;}
+ VkImageView GetVulkanImageView()const{return m_ImageView;}
protected:
/// Vulkan image view descriptor handle
- VkImageView m_VkImageView;
+ VulkanUtilities::ImageViewWrapper m_ImageView;
};
}
diff --git a/Graphics/GraphicsEngineVulkan/include/TextureVkImpl.h b/Graphics/GraphicsEngineVulkan/include/TextureVkImpl.h
index 3ca2e580..754a063d 100644
--- a/Graphics/GraphicsEngineVulkan/include/TextureVkImpl.h
+++ b/Graphics/GraphicsEngineVulkan/include/TextureVkImpl.h
@@ -77,15 +77,15 @@ public:
*/
void CopyData(IDeviceContext *pContext,
- ITexture *pSrcTexture,
- Uint32 SrcMipLevel,
- Uint32 SrcSlice,
- const Box *pSrcBox,
- Uint32 DstMipLevel,
- Uint32 DstSlice,
- Uint32 DstX,
- Uint32 DstY,
- Uint32 DstZ);
+ ITexture *pSrcTexture,
+ Uint32 SrcMipLevel,
+ Uint32 SrcSlice,
+ const Box *pSrcBox,
+ Uint32 DstMipLevel,
+ Uint32 DstSlice,
+ Uint32 DstX,
+ Uint32 DstY,
+ Uint32 DstZ);
/*
Vk_CPU_DESCRIPTOR_HANDLE GetMipLevelUAV(Uint32 Mip)
{
@@ -114,7 +114,8 @@ protected:
friend class RenderDeviceVkImpl;
*/
- VkImage m_VkImage;
+ VulkanUtilities::ImageWrapper m_VulkanImage;
+ VulkanUtilities::DeviceMemoryWrapper m_ImageMemory;
const bool m_IsExternalHandle;
};
diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBufferPool.h b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBufferPool.h
new file mode 100644
index 00000000..74e6bb35
--- /dev/null
+++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBufferPool.h
@@ -0,0 +1,59 @@
+/* Copyright 2015-2018 Egor Yusov
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+*
+* In no event and under no legal theory, whether in tort (including negligence),
+* contract, or otherwise, unless required by applicable law (such as deliberate
+* and grossly negligent acts) or agreed to in writing, shall any Contributor be
+* liable for any damages, including any direct, indirect, special, incidental,
+* or consequential damages of any character arising as a result of this License or
+* out of the use or inability to use the software (including but not limited to damages
+* for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+* all other commercial damages or losses), even if such Contributor has been advised
+* of the possibility of such damages.
+*/
+
+#pragma once
+
+#include <deque>
+#include <memory>
+#include "vulkan.h"
+#include "VulkanLogicalDevice.h"
+#include "VulkanObjectWrappers.h"
+
+namespace VulkanUtilities
+{
+ class VulkanCommandBufferPool
+ {
+ public:
+ VulkanCommandBufferPool(std::shared_ptr<VulkanUtilities::VulkanLogicalDevice> LogicalDevice,
+ uint32_t queueFamilyIndex,
+ VkCommandPoolCreateFlags flags);
+ VulkanCommandBufferPool(const VulkanCommandBufferPool&) = delete;
+ VulkanCommandBufferPool(VulkanCommandBufferPool&&) = delete;
+ VulkanCommandBufferPool& operator = (const VulkanCommandBufferPool&) = delete;
+ VulkanCommandBufferPool& operator = (VulkanCommandBufferPool&&) = delete;
+ ~VulkanCommandBufferPool();
+
+ VkCommandBuffer GetCommandBuffer(uint64_t LastCompletedFence, const char* DebugName = "");
+ void DisposeCommandBuffer(VkCommandBuffer CmdBuffer, uint64_t FenceValue);
+
+ private:
+ // Shared point to logical device must be defined before the command pool
+ std::shared_ptr<VulkanUtilities::VulkanLogicalDevice> m_LogicalDevice;
+ CommandPoolWrapper m_CmdPool;
+
+ // fist - the fence value associated with the command buffer when it was executed
+ // second - the command buffer
+ typedef std::pair<uint64_t, VkCommandBuffer > QueueElemType;
+ std::deque< QueueElemType > m_DiscardedCmdBuffers;
+ };
+}
diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanDebug.h b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanDebug.h
index bd213544..a68a56f2 100644
--- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanDebug.h
+++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanDebug.h
@@ -60,11 +60,14 @@ namespace VulkanUtilities
//void EndRegion(VkCommandBuffer cmdBuffer);
// Object specific naming functions
+ void SetCommandPoolName(VkDevice device, VkCommandPool cmdPool, const char * name);
void SetCommandBufferName(VkDevice device, VkCommandBuffer cmdBuffer, const char * name);
void SetQueueName(VkDevice device, VkQueue queue, const char * name);
void SetImageName(VkDevice device, VkImage image, const char * name);
+ void SetImageViewName(VkDevice device, VkImageView imageView, const char * name);
void SetSamplerName(VkDevice device, VkSampler sampler, const char * name);
void SetBufferName(VkDevice device, VkBuffer buffer, const char * name);
+ void SetBufferViewName(VkDevice device, VkBufferView bufferView, const char * name);
void SetDeviceMemoryName(VkDevice device, VkDeviceMemory memory, const char * name);
void SetShaderModuleName(VkDevice device, VkShaderModule shaderModule, const char * name);
void SetPipelineName(VkDevice device, VkPipeline pipeline, const char * name);
diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanFencePool.h b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanFencePool.h
new file mode 100644
index 00000000..3e4f5168
--- /dev/null
+++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanFencePool.h
@@ -0,0 +1,52 @@
+/* Copyright 2015-2018 Egor Yusov
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+*
+* In no event and under no legal theory, whether in tort (including negligence),
+* contract, or otherwise, unless required by applicable law (such as deliberate
+* and grossly negligent acts) or agreed to in writing, shall any Contributor be
+* liable for any damages, including any direct, indirect, special, incidental,
+* or consequential damages of any character arising as a result of this License or
+* out of the use or inability to use the software (including but not limited to damages
+* for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+* all other commercial damages or losses), even if such Contributor has been advised
+* of the possibility of such damages.
+*/
+
+#pragma once
+
+#include <vector>
+#include <memory>
+#include "vulkan.h"
+#include "VulkanLogicalDevice.h"
+#include "VulkanUtilities/VulkanObjectWrappers.h"
+
+namespace VulkanUtilities
+{
+ class VulkanFencePool
+ {
+ public:
+ VulkanFencePool(std::shared_ptr<const VulkanLogicalDevice> LogicalDevice);
+ VulkanFencePool(const VulkanFencePool&) = delete;
+ VulkanFencePool(VulkanFencePool&&) = delete;
+ VulkanFencePool& operator = (const VulkanFencePool&) = delete;
+ VulkanFencePool& operator = (VulkanFencePool&&) = delete;
+ ~VulkanFencePool();
+
+ VulkanUtilities::FenceWrapper GetFence();
+ void DisposeFence(VulkanUtilities::FenceWrapper&& Fence);
+
+ private:
+ // Shared pointer to logical device must be declared before fences
+ std::shared_ptr<const VulkanLogicalDevice> m_LogicalDevice;
+ std::vector<VulkanUtilities::FenceWrapper> m_Fences;
+ };
+}
diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanInstance.h b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanInstance.h
index 0320afb9..0a8d67a6 100644
--- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanInstance.h
+++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanInstance.h
@@ -24,19 +24,30 @@
#pragma once
#include <vector>
+#include <memory>
#include "vulkan.h"
namespace VulkanUtilities
{
- class VulkanInstance
+ class VulkanInstance : private std::enable_shared_from_this<VulkanInstance>
{
public:
- VulkanInstance(bool EnableValidation,
- uint32_t GlobalExtensionCount,
- const char* const* ppGlobalExtensionNames,
- VkAllocationCallbacks* pVkAllocator);
+ static std::shared_ptr<VulkanInstance> Create(bool EnableValidation,
+ uint32_t GlobalExtensionCount,
+ const char* const* ppGlobalExtensionNames,
+ VkAllocationCallbacks* pVkAllocator);
~VulkanInstance();
+ std::shared_ptr<VulkanInstance> GetSharedPtr()
+ {
+ return shared_from_this();
+ }
+
+ std::shared_ptr<const VulkanInstance> GetSharedPtr()const
+ {
+ return shared_from_this();
+ }
+
bool IsLayerAvailable(const char *LayerName)const;
bool IsExtensionAvailable(const char *ExtensionName)const;
VkPhysicalDevice SelectPhysicalDevice();
@@ -44,6 +55,10 @@ namespace VulkanUtilities
VkInstance GetVkInstance()const{return m_VkInstance;}
private:
+ VulkanInstance(bool EnableValidation,
+ uint32_t GlobalExtensionCount,
+ const char* const* ppGlobalExtensionNames,
+ VkAllocationCallbacks* pVkAllocator);
bool m_ValidationEnabled = false;
VkAllocationCallbacks* const m_pVkAllocator;
diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.h b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.h
new file mode 100644
index 00000000..c4b6e480
--- /dev/null
+++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.h
@@ -0,0 +1,104 @@
+/* Copyright 2015-2018 Egor Yusov
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+*
+* In no event and under no legal theory, whether in tort (including negligence),
+* contract, or otherwise, unless required by applicable law (such as deliberate
+* and grossly negligent acts) or agreed to in writing, shall any Contributor be
+* liable for any damages, including any direct, indirect, special, incidental,
+* or consequential damages of any character arising as a result of this License or
+* out of the use or inability to use the software (including but not limited to damages
+* for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+* all other commercial damages or losses), even if such Contributor has been advised
+* of the possibility of such damages.
+*/
+
+#pragma once
+
+#include <memory>
+#include "vulkan.h"
+#include "VulkanObjectWrappers.h"
+
+namespace VulkanUtilities
+{
+ class VulkanLogicalDevice : private std::enable_shared_from_this<VulkanLogicalDevice>
+ {
+ public:
+ static std::shared_ptr<VulkanLogicalDevice> Create(VkPhysicalDevice vkPhysicalDevice,
+ const VkDeviceCreateInfo &DeviceCI,
+ const VkAllocationCallbacks* vkAllocator,
+ bool EnableDebugMarkers);
+ VulkanLogicalDevice(const VulkanLogicalDevice&) = delete;
+ VulkanLogicalDevice(VulkanLogicalDevice&&) = delete;
+ VulkanLogicalDevice& operator = (const VulkanLogicalDevice&) = delete;
+ VulkanLogicalDevice& operator = (VulkanLogicalDevice&&) = delete;
+
+ ~VulkanLogicalDevice();
+
+ std::shared_ptr<VulkanLogicalDevice> GetSharedPtr()
+ {
+ return shared_from_this();
+ }
+
+ std::shared_ptr<const VulkanLogicalDevice> GetSharedPtr()const
+ {
+ return shared_from_this();
+ }
+
+ VkQueue GetQueue(uint32_t queueFamilyIndex, uint32_t queueIndex);
+
+ VkDevice GetVkDevice()const
+ {
+ return m_VkDevice;
+ }
+
+ void WaitIdle()const;
+
+ CommandPoolWrapper CreateCommandPool (const VkCommandPoolCreateInfo &CmdPoolCI, const char *DebugName = "")const;
+ BufferWrapper CreateBuffer (const VkBufferCreateInfo &BufferCI, const char *DebugName = "")const;
+ BufferViewWrapper CreateBufferView (const VkBufferViewCreateInfo &BuffViewCI, const char *DebugName = "")const;
+ ImageWrapper CreateImage (const VkImageCreateInfo &ImageCI, const char *DebugName = "")const;
+ ImageViewWrapper CreateImageView (const VkImageViewCreateInfo &ImageViewCI, const char *DebugName = "")const;
+ FenceWrapper CreateFence (const VkFenceCreateInfo &FenceCI, const char *DebugName = "")const;
+ DeviceMemoryWrapper AllocateDeviceMemory(const VkMemoryAllocateInfo &AllocInfo, const char *DebugName = "")const;
+
+ VkCommandBuffer AllocateVkCommandBuffer(const VkCommandBufferAllocateInfo &AllocInfo, const char *DebugName = "")const;
+
+ void ReleaseVulkanObject(CommandPoolWrapper&& CmdPool)const;
+ void ReleaseVulkanObject(BufferWrapper&& Buffer)const;
+ void ReleaseVulkanObject(BufferViewWrapper&& BufferView)const;
+ void ReleaseVulkanObject(ImageWrapper&& Image)const;
+ void ReleaseVulkanObject(ImageViewWrapper&& ImageView)const;
+ void ReleaseVulkanObject(FenceWrapper&& Fence)const;
+ void ReleaseVulkanObject(DeviceMemoryWrapper&& Memory)const;
+
+ VkMemoryRequirements GetBufferMemoryRequirements(VkBuffer vkBuffer)const;
+ VkMemoryRequirements GetImageMemoryRequirements (VkImage vkImage )const;
+
+ VkResult BindBufferMemory(VkBuffer buffer, VkDeviceMemory memory, VkDeviceSize memoryOffset)const;
+ VkResult BindImageMemory (VkImage image, VkDeviceMemory memory, VkDeviceSize memoryOffset)const;
+
+ VkResult MapMemory(VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void** ppData)const;
+ void UnmapMemory(VkDeviceMemory memory)const;
+
+ VkResult GetFenceStatus(VkFence fence)const;
+ VkResult ResetFence(VkFence fence)const;
+
+ private:
+ VulkanLogicalDevice(VkPhysicalDevice vkPhysicalDevice,
+ const VkDeviceCreateInfo &DeviceCI,
+ const VkAllocationCallbacks* vkAllocator,
+ bool EnableDebugMarkers);
+
+ VkDevice m_VkDevice = VK_NULL_HANDLE;
+ const VkAllocationCallbacks* const m_VkAllocator;
+ };
+}
diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanObjectWrappers.h b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanObjectWrappers.h
new file mode 100644
index 00000000..00dd44d9
--- /dev/null
+++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanObjectWrappers.h
@@ -0,0 +1,96 @@
+/* Copyright 2015-2018 Egor Yusov
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+*
+* In no event and under no legal theory, whether in tort (including negligence),
+* contract, or otherwise, unless required by applicable law (such as deliberate
+* and grossly negligent acts) or agreed to in writing, shall any Contributor be
+* liable for any damages, including any direct, indirect, special, incidental,
+* or consequential damages of any character arising as a result of this License or
+* out of the use or inability to use the software (including but not limited to damages
+* for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+* all other commercial damages or losses), even if such Contributor has been advised
+* of the possibility of such damages.
+*/
+
+#pragma once
+
+#include <memory>
+#include "vulkan.h"
+
+namespace VulkanUtilities
+{
+ class VulkanLogicalDevice;
+
+ template<typename VulkanObjectType>
+ class VulkanObjectWrapper
+ {
+ public:
+ VulkanObjectWrapper() :
+ m_pLogicalDevice(nullptr),
+ m_VkObject(VK_NULL_HANDLE)
+ {}
+ VulkanObjectWrapper(std::shared_ptr<const VulkanLogicalDevice> pLogicalDevice, VulkanObjectType vkObject) :
+ m_pLogicalDevice(pLogicalDevice),
+ m_VkObject(vkObject)
+ {}
+ VulkanObjectWrapper(const VulkanObjectWrapper&) = delete;
+ VulkanObjectWrapper& operator = (const VulkanObjectWrapper&) = delete;
+ VulkanObjectWrapper(VulkanObjectWrapper&& rhs) :
+ m_pLogicalDevice(std::move(rhs.m_pLogicalDevice)),
+ m_VkObject(rhs.m_VkObject)
+ {
+ rhs.m_VkObject = VK_NULL_HANDLE;
+ }
+ VulkanObjectWrapper& operator = (VulkanObjectWrapper&& rhs)
+ {
+ m_pLogicalDevice = std::move(rhs.m_pLogicalDevice);
+ m_VkObject = rhs.m_VkObject;
+ rhs.m_VkObject = VK_NULL_HANDLE;
+ return *this;
+ }
+
+ operator VulkanObjectType()const
+ {
+ return m_VkObject;
+ }
+
+ void Release()
+ {
+ // For externally managed objects, m_pLogicalDevice is null
+ if(m_pLogicalDevice && m_VkObject != VK_NULL_HANDLE)
+ {
+ m_pLogicalDevice->ReleaseVulkanObject(std::move(*this));
+ }
+ m_VkObject = VK_NULL_HANDLE;
+ m_pLogicalDevice.reset();
+ }
+
+ ~VulkanObjectWrapper()
+ {
+ Release();
+ }
+
+ private:
+ friend class VulkanLogicalDevice;
+
+ std::shared_ptr<const VulkanLogicalDevice> m_pLogicalDevice;
+ VulkanObjectType m_VkObject;
+ };
+
+ using CommandPoolWrapper = VulkanObjectWrapper<VkCommandPool>;
+ using BufferWrapper = VulkanObjectWrapper<VkBuffer>;
+ using BufferViewWrapper = VulkanObjectWrapper<VkBufferView>;
+ using ImageWrapper = VulkanObjectWrapper<VkImage>;
+ using ImageViewWrapper = VulkanObjectWrapper<VkImageView>;
+ using DeviceMemoryWrapper = VulkanObjectWrapper<VkDeviceMemory>;
+ using FenceWrapper = VulkanObjectWrapper<VkFence>;
+}
diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.h b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.h
index b64ce488..15f9c8da 100644
--- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.h
+++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.h
@@ -23,6 +23,7 @@
#pragma once
+#include <memory>
#include <vector>
#include "vulkan.h"
@@ -31,7 +32,8 @@ namespace VulkanUtilities
class VulkanPhysicalDevice
{
public:
- VulkanPhysicalDevice(VkPhysicalDevice vkDevice);
+ static std::unique_ptr<VulkanPhysicalDevice> Create(VkPhysicalDevice vkDevice);
+
uint32_t FindQueueFamily(VkQueueFlags QueueFlags)const;
VkPhysicalDevice GetVkDeviceHandle()const{return m_VkDevice;}
bool IsExtensionSupported(const char *ExtensionName)const;
@@ -41,6 +43,8 @@ namespace VulkanUtilities
uint32_t GetMemoryTypeIndex(uint32_t typeBits, VkMemoryPropertyFlags properties)const;
private:
+ VulkanPhysicalDevice(VkPhysicalDevice vkDevice);
+
const VkPhysicalDevice m_VkDevice;
VkPhysicalDeviceProperties m_Properties = {};
VkPhysicalDeviceFeatures m_Features = {};
diff --git a/Graphics/GraphicsEngineVulkan/interface/CommandQueueVk.h b/Graphics/GraphicsEngineVulkan/interface/CommandQueueVk.h
index c712ca84..9ed10106 100644
--- a/Graphics/GraphicsEngineVulkan/interface/CommandQueueVk.h
+++ b/Graphics/GraphicsEngineVulkan/interface/CommandQueueVk.h
@@ -41,12 +41,12 @@ class ICommandQueueVk : public Diligent::IObject
{
public:
/// Returns the fence value that will be signaled next time
- //virtual UINT64 GetNextFenceValue() = 0;
+ virtual UINT64 GetNextFenceValue() = 0;
- /// Executes a given command list
+ /// Executes a given command buffer
- /// \return Fence value associated with the executed command list
- //virtual UINT64 ExecuteCommandList(ID3D12GraphicsCommandList* commandList) = 0;
+ /// \return Fence value associated with the executed command buffer
+ virtual Uint64 ExecuteCommandBuffer(VkCommandBuffer cmdBuffer) = 0;
/// Returns Vulkan command queue. May return VK_NULL_HANDLE if queue is anavailable
virtual VkQueue GetVkQueue() = 0;
@@ -55,10 +55,10 @@ public:
virtual uint32_t GetQueueFamilyIndex() = 0;
/// Returns value of the last completed fence
- //virtual Uint64 GetCompletedFenceValue() = 0;
+ virtual Uint64 GetCompletedFenceValue() = 0;
/// Blocks execution until all pending GPU commands are complete
- //virtual void IdleGPU() = 0;
+ virtual void IdleGPU() = 0;
};
}
diff --git a/Graphics/GraphicsEngineVulkan/interface/RenderDeviceVk.h b/Graphics/GraphicsEngineVulkan/interface/RenderDeviceVk.h
index a5a03328..1b93ebfe 100644
--- a/Graphics/GraphicsEngineVulkan/interface/RenderDeviceVk.h
+++ b/Graphics/GraphicsEngineVulkan/interface/RenderDeviceVk.h
@@ -40,22 +40,19 @@ class IRenderDeviceVk : public IRenderDevice
{
public:
- /// Returns ID3D12Device interface of the internal Direct3D12 device object.
-
- /// The method does *NOT* call AddRef() on the returned interface,
- /// so Release() must not be called.
- //virtual ID3D12Device* GetD3D12Device() = 0;
+ /// Returns logical Vulkan device handle
+ virtual VkDevice GetVkDevice() = 0;
/// Returns the fence value that will be signaled by the GPU command queue next
- //virtual Uint64 GetNextFenceValue() = 0;
+ virtual Uint64 GetNextFenceValue() = 0;
/// Checks if the fence value has been signaled by the GPU. True means
/// that all associated work has been finished
- //virtual Bool IsFenceSignaled(Uint64 FenceValue) = 0;
+ virtual Bool IsFenceSignaled(Uint64 FenceValue) = 0;
/// Should be called at the end of the frame when attached to existing D3D12 device
/// Otherwise the method is automatically called before present
- //virtual void FinishFrame() = 0;
+ virtual void FinishFrame() = 0;
/// Creates a texture object from native d3d12 resource
diff --git a/Graphics/GraphicsEngineVulkan/src/BufferViewVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/BufferViewVkImpl.cpp
index ceb6f830..98b87a14 100644
--- a/Graphics/GraphicsEngineVulkan/src/BufferViewVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/BufferViewVkImpl.cpp
@@ -23,6 +23,7 @@
#include "pch.h"
#include "BufferViewVkImpl.h"
+#include "RenderDeviceVkImpl.h"
namespace Diligent
{
@@ -31,13 +32,19 @@ BufferViewVkImpl::BufferViewVkImpl( IReferenceCounters *pRefCounters,
IRenderDevice *pDevice,
const BufferViewDesc& ViewDesc,
IBuffer *pBuffer,
- VkBufferView vkBuffView,
+ VulkanUtilities::BufferViewWrapper &&BuffView,
bool bIsDefaultView ) :
TBufferViewBase( pRefCounters, pDevice, ViewDesc, pBuffer, bIsDefaultView ),
- m_VkBuffView(vkBuffView)
+ m_BuffView(std::move(BuffView))
{
}
+BufferViewVkImpl::~BufferViewVkImpl()
+{
+ auto *pDeviceVkImpl = ValidatedCast<RenderDeviceVkImpl>(GetDevice());
+ pDeviceVkImpl->SafeReleaseVkObject(std::move(m_BuffView));
+}
+
IMPLEMENT_QUERY_INTERFACE( BufferViewVkImpl, IID_BufferViewVk, TBufferViewBase )
}
diff --git a/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp
index a99afd71..3878c5cf 100644
--- a/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp
@@ -67,7 +67,7 @@ BufferVkImpl :: BufferVkImpl(IReferenceCounters *pRefCounters,
}
}
- auto vkAllocator = pRenderDeviceVk->GetVulkanInstance()->GetVkAllocator();
+ const auto& LogicalDevice = pRenderDeviceVk->GetLogicalDevice();
if(m_Desc.Usage == USAGE_DYNAMIC && (m_Desc.BindFlags & (BIND_SHADER_RESOURCE|BIND_UNORDERED_ACCESS)) == 0)
{
UNSUPPORTED("Dynamic buffers are not yet implemented");
@@ -107,12 +107,9 @@ BufferVkImpl :: BufferVkImpl(IReferenceCounters *pRefCounters,
VkBuffCI.pQueueFamilyIndices = nullptr; // list of queue families that will access this buffer
// (ignored if sharingMode is not VK_SHARING_MODE_CONCURRENT).
- auto vkDevice = pRenderDeviceVk->GetVkDevice();
- auto err = vkCreateBuffer(vkDevice, &VkBuffCI, vkAllocator, &m_VkBuffer);
- CHECK_VK_ERROR_AND_THROW(err, "Failed to create Vulkan buffer object");
+ m_VulkanBuffer = LogicalDevice.CreateBuffer(VkBuffCI, m_Desc.Name);
- VkMemoryRequirements MemReqs = {};
- vkGetBufferMemoryRequirements(vkDevice, m_VkBuffer, &MemReqs);
+ VkMemoryRequirements MemReqs = LogicalDevice.GetBufferMemoryRequirements(m_VulkanBuffer);
VkMemoryAllocateInfo MemAlloc = {};
MemAlloc.pNext = nullptr;
@@ -144,32 +141,31 @@ BufferVkImpl :: BufferVkImpl(IReferenceCounters *pRefCounters,
LOG_ERROR_AND_THROW("Failed to find suitable device memory type for a buffer");
}
- err = vkAllocateMemory(vkDevice, &MemAlloc, vkAllocator, &m_BufferMemory);
- CHECK_VK_ERROR_AND_THROW(err, "Failed to allocate device local memory for a Vulkan buffer object");
+ {
+ std::string MemoryName("Device local memory for buffer '");
+ MemoryName += m_Desc.Name;
+ MemoryName += '\'';
+ m_BufferMemory = LogicalDevice.AllocateDeviceMemory(MemAlloc, MemoryName.c_str());
+ }
- err = vkBindBufferMemory(vkDevice, m_VkBuffer, m_BufferMemory, 0 /*offset*/);
+ auto err = LogicalDevice.BindBufferMemory(m_VulkanBuffer, m_BufferMemory, 0 /*offset*/);
CHECK_VK_ERROR_AND_THROW(err, "Failed to bind buffer memory");
bool bInitializeBuffer = (BuffData.pData != nullptr && BuffData.DataSize > 0);
//if(bInitializeBuffer)
// m_UsageState = Vk_RESOURCE_STATE_COPY_DEST;
- if( *m_Desc.Name != 0)
- VulkanUtilities::SetBufferName(vkDevice, m_VkBuffer, m_Desc.Name);
-
if( bInitializeBuffer )
{
VkBufferCreateInfo VkStaginBuffCI = VkBuffCI;
VkStaginBuffCI.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
- VkBuffer vkStagingBuffer = VK_NULL_HANDLE;
- err = vkCreateBuffer(vkDevice, &VkStaginBuffCI, vkAllocator, &vkStagingBuffer);
- CHECK_VK_ERROR_AND_THROW(err, "Failed to create staging buffer");
+ std::string StagingBufferName = "Staging buffer for '";
+ StagingBufferName += m_Desc.Name;
+ StagingBufferName += '\'';
+ VulkanUtilities::BufferWrapper StagingBuffer = LogicalDevice.CreateBuffer(VkStaginBuffCI, StagingBufferName.c_str());
- VulkanUtilities::SetBufferName(vkDevice, vkStagingBuffer, "Staging buffer");
-
- VkMemoryRequirements StagingBufferMemReqs = {};
- vkGetBufferMemoryRequirements(vkDevice, vkStagingBuffer, &StagingBufferMemReqs);
+ VkMemoryRequirements StagingBufferMemReqs = LogicalDevice.GetBufferMemoryRequirements(StagingBuffer);
VkMemoryAllocateInfo StagingMemAlloc = {};
StagingMemAlloc.pNext = nullptr;
@@ -187,32 +183,43 @@ BufferVkImpl :: BufferVkImpl(IReferenceCounters *pRefCounters,
"corresponding to a VkMemoryType with a propertyFlags that has both the VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT bit "
"and the VK_MEMORY_PROPERTY_HOST_COHERENT_BIT bit set(11.6)");
- VkDeviceMemory vkStagingBufferMemory = VK_NULL_HANDLE;
- err = vkAllocateMemory(vkDevice, &StagingMemAlloc, vkAllocator, &vkStagingBufferMemory);
- CHECK_VK_ERROR_AND_THROW(err, "Failed to allocate memory for a staging buffer object");
+ std::string StagingMemoryName("Staging memory for buffer '");
+ StagingMemoryName += m_Desc.Name;
+ StagingMemoryName += '\'';
+ VulkanUtilities::DeviceMemoryWrapper StagingBufferMemory = LogicalDevice.AllocateDeviceMemory(StagingMemAlloc, StagingMemoryName.c_str());
{
void *StagingData = nullptr;
- err = vkMapMemory(vkDevice, vkStagingBufferMemory,
+ err = LogicalDevice.MapMemory(StagingBufferMemory,
0, // offset
StagingMemAlloc.allocationSize,
0, // flags, reserved for future use
&StagingData);
CHECK_VK_ERROR_AND_THROW(err, "Failed to map staging memory");
memcpy(StagingData, BuffData.pData, BuffData.DataSize);
- vkUnmapMemory(vkDevice, vkStagingBufferMemory);
+ LogicalDevice.UnmapMemory(StagingBufferMemory);
}
- err = vkBindBufferMemory(vkDevice, vkStagingBuffer, vkStagingBufferMemory, 0 /*offset*/);
+ err = LogicalDevice.BindBufferMemory(StagingBuffer, StagingBufferMemory, 0 /*offset*/);
CHECK_VK_ERROR_AND_THROW(err, "Failed to bind staging bufer memory");
+
+ auto vkCmdBuff = pRenderDeviceVk->AllocateCommandBuffer("Transient cmd buff to copy staging data to a device buffer");
+
#if 0
- auto *pInitContext = pRenderDeviceVk->AllocateCommandContext();
// copy data to the intermediate upload heap and then schedule a copy from the upload heap to the default buffer
VERIFY_EXPR(m_UsageState == Vk_RESOURCE_STATE_COPY_DEST);
+#endif
// We MUST NOT call TransitionResource() from here, because
// it will call AddRef() and potentially Release(), while
// the object is not constructed yet
- pInitContext->CopyResource(m_pVkResource, UploadBuffer);
+
+ // Copy commands MUST be recorded outside of a render pass instance. This is OK here
+ // as copy will be the only command in the cmd buffer
+ VkBufferCopy BuffCopy = {};
+ BuffCopy.srcOffset = 0;
+ BuffCopy.dstOffset = 0;
+ BuffCopy.size = VkBuffCI.size;
+ vkCmdCopyBuffer(vkCmdBuff, StagingBuffer, m_VulkanBuffer, 1, &BuffCopy);
// Command list fence should only be signaled when submitting cmd list
// from the immediate context, otherwise the basic requirement will be violated
@@ -232,13 +239,14 @@ BufferVkImpl :: BufferVkImpl(IReferenceCounters *pRefCounters,
// | N+1, but resource it references | |
// | was added to the delete queue | |
// | with value N | |
- pRenderDeviceVk->CloseAndExecuteCommandContext(pInitContext, false);
+ pRenderDeviceVk->ExecuteCommandBuffer(vkCmdBuff, false);
+ pRenderDeviceVk->DisposeCommandBuffer(vkCmdBuff);
// Add reference to the object to the release queue to keep it alive
// until copy operation is complete. This must be done after
// submitting command list for execution!
- pRenderDeviceVk->SafeReleaseVkObject(UploadBuffer);
-#endif
+ pRenderDeviceVk->SafeReleaseVkObject(std::move(StagingBuffer));
+ pRenderDeviceVk->SafeReleaseVkObject(std::move(StagingBufferMemory));
}
//if (m_Desc.BindFlags & BIND_UNIFORM_BUFFER)
@@ -316,12 +324,10 @@ BufferVkImpl :: BufferVkImpl(IReferenceCounters *pRefCounters,
}
BufferVkImpl :: ~BufferVkImpl()
{
+ auto *pDeviceVkImpl = ValidatedCast<RenderDeviceVkImpl>(GetDevice());
// Vk object can only be destroyed when it is no longer used by the GPU
- if(m_VkBuffer!=VK_NULL_HANDLE)
- {
- auto *pDeviceVkImpl = ValidatedCast<RenderDeviceVkImpl>(GetDevice());
- pDeviceVkImpl->SafeReleaseVkBuffer(m_VkBuffer);
- }
+ pDeviceVkImpl->SafeReleaseVkObject(std::move(m_VulkanBuffer));
+ pDeviceVkImpl->SafeReleaseVkObject(std::move(m_BufferMemory));
}
IMPLEMENT_QUERY_INTERFACE( BufferVkImpl, IID_BufferVk, TBufferBase )
@@ -469,9 +475,9 @@ void BufferVkImpl::CreateViewInternal( const BufferViewDesc &OrigViewDesc, IBuff
BufferViewDesc ViewDesc = OrigViewDesc;
if( ViewDesc.ViewType == BUFFER_VIEW_UNORDERED_ACCESS || ViewDesc.ViewType == BUFFER_VIEW_SHADER_RESOURCE )
{
- auto vkView = CreateView(ViewDesc);
+ auto View = CreateView(ViewDesc);
*ppView = NEW_RC_OBJ(BuffViewAllocator, "BufferViewVkImpl instance", BufferViewVkImpl, bIsDefaultView ? this : nullptr)
- (GetDevice(), ViewDesc, this, vkView, bIsDefaultView );
+ (GetDevice(), ViewDesc, this, std::move(View), bIsDefaultView );
}
if( !bIsDefaultView && *ppView )
@@ -485,9 +491,9 @@ void BufferVkImpl::CreateViewInternal( const BufferViewDesc &OrigViewDesc, IBuff
}
-VkBufferView BufferVkImpl::CreateView(struct BufferViewDesc &ViewDesc)
+VulkanUtilities::BufferViewWrapper BufferVkImpl::CreateView(struct BufferViewDesc &ViewDesc)
{
- VkBufferView vkBuffView = VK_NULL_HANDLE;
+ VulkanUtilities::BufferViewWrapper BuffView;
CorrectBufferViewDesc(ViewDesc);
if( (ViewDesc.ViewType == BUFFER_VIEW_SHADER_RESOURCE || ViewDesc.ViewType == BUFFER_VIEW_UNORDERED_ACCESS) &&
m_Desc.Mode == BUFFER_MODE_FORMATTED)
@@ -496,18 +502,16 @@ VkBufferView BufferVkImpl::CreateView(struct BufferViewDesc &ViewDesc)
ViewCI.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO;
ViewCI.pNext = nullptr;
ViewCI.flags = 0; // reserved for future use
- ViewCI.buffer = m_VkBuffer;
+ ViewCI.buffer = m_VulkanBuffer;
ViewCI.format = TypeToVkFormat(m_Desc.Format.ValueType, m_Desc.Format.NumComponents, m_Desc.Format.IsNormalized);
ViewCI.offset = ViewDesc.ByteOffset;
ViewCI.range = ViewDesc.ByteWidth; // size in bytes of the buffer view
auto *pDeviceVkImpl = static_cast<RenderDeviceVkImpl*>(GetDevice());
- auto vkAllocator = pDeviceVkImpl->GetVulkanInstance()->GetVkAllocator();
- auto vkDevice = pDeviceVkImpl->GetVkDevice();
- auto err = vkCreateBufferView(vkDevice, &ViewCI, vkAllocator, &vkBuffView);
- CHECK_VK_ERROR_AND_THROW(err, "Failed to create Vulkan buffer view");
+ const auto& LogicalDevice = pDeviceVkImpl->GetLogicalDevice();
+ BuffView = LogicalDevice.CreateBufferView(ViewCI, ViewDesc.Name);
}
- return vkBuffView;
+ return BuffView;
}
#if 0
diff --git a/Graphics/GraphicsEngineVulkan/src/CommandContext.cpp b/Graphics/GraphicsEngineVulkan/src/CommandContext.cpp
index fa1157a1..0b254cfc 100644
--- a/Graphics/GraphicsEngineVulkan/src/CommandContext.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/CommandContext.cpp
@@ -25,7 +25,6 @@
#include "CommandContext.h"
#include "TextureVkImpl.h"
#include "BufferVkImpl.h"
-#include "CommandListManager.h"
namespace Diligent
{
diff --git a/Graphics/GraphicsEngineVulkan/src/CommandListManager.cpp b/Graphics/GraphicsEngineVulkan/src/CommandListManager.cpp
deleted file mode 100644
index b4d67c9a..00000000
--- a/Graphics/GraphicsEngineVulkan/src/CommandListManager.cpp
+++ /dev/null
@@ -1,109 +0,0 @@
-/* Copyright 2015-2018 Egor Yusov
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
- *
- * In no event and under no legal theory, whether in tort (including negligence),
- * contract, or otherwise, unless required by applicable law (such as deliberate
- * and grossly negligent acts) or agreed to in writing, shall any Contributor be
- * liable for any damages, including any direct, indirect, special, incidental,
- * or consequential damages of any character arising as a result of this License or
- * out of the use or inability to use the software (including but not limited to damages
- * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
- * all other commercial damages or losses), even if such Contributor has been advised
- * of the possibility of such damages.
- */
-
-#include "pch.h"
-#include "CommandListManager.h"
-#include "RenderDeviceVkImpl.h"
-
-namespace Diligent
-{
-
-CommandListManager::CommandListManager(RenderDeviceVkImpl *pDeviceVk)/* :
- m_pDeviceVk(pDeviceVk),
- m_DiscardedAllocators(STD_ALLOCATOR_RAW_MEM(DiscardedAllocatorQueueElemType, GetRawAllocator(), "Allocator for deque<DiscardedAllocatorQueueElemType>"))
- */
-{
-}
-
-CommandListManager::~CommandListManager()
-{
-}
-
-#if 0
-void CommandListManager::CreateNewCommandList( IVkGraphicsCommandList** List, IVkCommandAllocator** Allocator )
-{
- RequestAllocator(Allocator);
- auto *pVkDevice = m_pDeviceVk->GetVkDevice();
- auto hr = pVkDevice->CreateCommandList(1, Vk_COMMAND_LIST_TYPE_DIRECT, *Allocator, nullptr, __uuidof(*List), reinterpret_cast<void**>(List) );
- VERIFY(SUCCEEDED(hr), "Failed to create command list");
- (*List)->SetName(L"CommandList");
-}
-
-
-void CommandListManager::RequestAllocator(IVkCommandAllocator** ppAllocator)
-{
- std::lock_guard<std::mutex> LockGuard(m_AllocatorMutex);
-
- VERIFY( (*ppAllocator) == nullptr, "Allocator pointer is not null" );
- (*ppAllocator) = nullptr;
-
- if (!m_DiscardedAllocators.empty())
- {
- // Pick the oldest allocator at the front of the deque
- // If this allocator is not yet available, there is no point in
- // looking at other allocators since they were released even
- // later
- auto& AllocatorPair = m_DiscardedAllocators.front();
-
- // Get the last completed fence value
- auto CompletedFenceValue = m_pDeviceVk->GetCompletedFenceValue();
- // Note that CompletedFenceValue only grows. So if after we queried
- // the value, the actual value is increased in other thread, this will not
- // be an issue as the only consequence is that potentially available
- // allocator may not be used.
-
- // AllocatorPair.first is the fence value that was signaled AFTER the
- // command list has been submitted. If CompletedFenceValue is at least
- // this value, the allocator can be safely reused
- if ( CompletedFenceValue >= AllocatorPair.first )
- {
- *ppAllocator = AllocatorPair.second.Detach();
- auto hr = (*ppAllocator)->Reset();
- VERIFY_EXPR(SUCCEEDED(hr));
- m_DiscardedAllocators.pop_front();
- }
- }
-
- // If no allocators were ready to be reused, create a new one
- if ((*ppAllocator) == nullptr)
- {
- auto *pVkDevice = m_pDeviceVk->GetVkDevice();
- auto hr = pVkDevice->CreateCommandAllocator(Vk_COMMAND_LIST_TYPE_DIRECT, __uuidof(*ppAllocator), reinterpret_cast<void**>(ppAllocator));
- VERIFY(SUCCEEDED(hr), "Failed to create command allocator");
- wchar_t AllocatorName[32];
- swprintf(AllocatorName, _countof(AllocatorName), L"Cmd list allocator %ld", Atomics::AtomicIncrement(m_NumAllocators)-1);
- (*ppAllocator)->SetName(AllocatorName);
- }
-}
-
-void CommandListManager::DiscardAllocator( Uint64 FenceValue, IVkCommandAllocator* pAllocator )
-{
- std::lock_guard<std::mutex> LockGuard(m_AllocatorMutex);
-
- // FenceValue is the value that was signaled by the command queue after it
- // executed the command list created by the allocator
- m_DiscardedAllocators.emplace_back( FenceValue, CComPtr<IVkCommandAllocator>(pAllocator) );
-}
-#endif
-
-}
diff --git a/Graphics/GraphicsEngineVulkan/src/CommandQueueVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/CommandQueueVkImpl.cpp
index dc6eb140..b25c412c 100644
--- a/Graphics/GraphicsEngineVulkan/src/CommandQueueVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/CommandQueueVkImpl.cpp
@@ -27,17 +27,16 @@
namespace Diligent
{
-CommandQueueVkImpl::CommandQueueVkImpl(IReferenceCounters *pRefCounters, VkQueue VkNativeCmdQueue, uint32_t QueueFamilyIndex) :
- TBase(pRefCounters),
- m_VkQueue(VkNativeCmdQueue),
- m_QueueFamilyIndex(QueueFamilyIndex)
- /*m_VkFence(pVkFence),
- m_NextFenceValue(1),
- m_WaitForGPUEventHandle( CreateEvent(nullptr, false, false, nullptr) )
- */
+CommandQueueVkImpl::CommandQueueVkImpl(IReferenceCounters *pRefCounters,
+ std::shared_ptr<VulkanUtilities::VulkanLogicalDevice> LogicalDevice,
+ uint32_t QueueFamilyIndex) :
+ TBase(pRefCounters),
+ m_LogicalDevice(LogicalDevice),
+ m_VkQueue(LogicalDevice->GetQueue(QueueFamilyIndex, 0)),
+ m_QueueFamilyIndex(QueueFamilyIndex),
+ m_NextFenceValue(1),
+ m_FencePool(LogicalDevice)
{
- //VERIFY_EXPR(m_WaitForGPUEventHandle != INVALID_HANDLE_VALUE);
- //m_VkFence->Signal(0);
}
CommandQueueVkImpl::~CommandQueueVkImpl()
@@ -45,18 +44,43 @@ CommandQueueVkImpl::~CommandQueueVkImpl()
// Queues are created along with a logical device during vkCreateDevice.
// All queues associated with a logical device are destroyed when vkDestroyDevice
// is called on that device.
+
+ while(!m_PendingFences.empty())
+ {
+ m_FencePool.DisposeFence(std::move(m_PendingFences.front().second));
+ m_PendingFences.pop_front();
+ }
}
IMPLEMENT_QUERY_INTERFACE( CommandQueueVkImpl, IID_CommandQueueVk, TBase )
-#if 0
-UINT64 CommandQueueVkImpl::ExecuteCommandList(IVkGraphicsCommandList* commandList)
+
+Uint64 CommandQueueVkImpl::ExecuteCommandBuffer(VkCommandBuffer cmdBuffer)
{
- IVkCommandList *const ppCmdLists[] = {commandList};
- m_pVkCmdQueue->ExecuteCommandLists(1, ppCmdLists);
+ std::lock_guard<std::mutex> Lock(m_QueueMutex);
+
+ VkSubmitInfo SubmitInfo = {};
+ SubmitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+ SubmitInfo.commandBufferCount = 1;
+ SubmitInfo.pCommandBuffers = &cmdBuffer;
+ SubmitInfo.waitSemaphoreCount = 0; // the number of semaphores upon which to wait before executing the command buffers
+ SubmitInfo.pWaitSemaphores = nullptr; // a pointer to an array of semaphores upon which to wait before the command
+ // buffers begin execution
+ SubmitInfo.pWaitDstStageMask = nullptr; // a pointer to an array of pipeline stages at which each corresponding
+ // semaphore wait will occur
+ SubmitInfo.signalSemaphoreCount = 0; // the number of semaphores to be signaled once the commands specified in
+ // pCommandBuffers have completed execution
+ SubmitInfo.pSignalSemaphores = nullptr; // a pointer to an array of semaphores which will be signaled when the
+ // command buffers for this batch have completed execution
+
+ auto Fence = m_FencePool.GetFence();
+ auto err = vkQueueSubmit(m_VkQueue, 1, &SubmitInfo, Fence);
+ VERIFY(err == VK_SUCCESS, "Failed to submit command buffer to the command queue");
+
+ // We must atomically place the (value, fence) pair into the deque
auto FenceValue = m_NextFenceValue;
- // Signal the fence
- m_pVkCmdQueue->Signal(m_VkFence, FenceValue);
+ m_PendingFences.emplace_back(FenceValue, std::move(Fence));
+
// Increment the value
Atomics::AtomicIncrement(m_NextFenceValue);
return FenceValue;
@@ -64,24 +88,46 @@ UINT64 CommandQueueVkImpl::ExecuteCommandList(IVkGraphicsCommandList* commandLis
void CommandQueueVkImpl::IdleGPU()
{
- Uint64 LastSignaledFenceValue = m_NextFenceValue;
- m_pVkCmdQueue->Signal(m_VkFence, LastSignaledFenceValue);
+ std::lock_guard<std::mutex> Lock(m_QueueMutex);
+
+ // Update last completed fence value to unlock all waiting events
+ Uint64 LastCompletedFenceValue = m_NextFenceValue;
+ // Increment fence before idling the queue
Atomics::AtomicIncrement(m_NextFenceValue);
- if (GetCompletedFenceValue() < LastSignaledFenceValue)
+ vkQueueWaitIdle(m_VkQueue);
+ if(LastCompletedFenceValue > m_LastCompletedFenceValue)
+ m_LastCompletedFenceValue = LastCompletedFenceValue;
+ for(auto& val_fence : m_PendingFences)
{
- m_VkFence->SetEventOnCompletion(LastSignaledFenceValue, m_WaitForGPUEventHandle);
- WaitForSingleObject(m_WaitForGPUEventHandle, INFINITE);
- VERIFY(GetCompletedFenceValue() == LastSignaledFenceValue, "Unexpected signaled fence value");
+ auto status = m_LogicalDevice->GetFenceStatus(val_fence.second);
+ VERIFY(status == VK_SUCCESS, "All pending fences must now be complete!");
+ m_FencePool.DisposeFence(std::move(val_fence.second));
}
+ m_PendingFences.clear();
}
Uint64 CommandQueueVkImpl::GetCompletedFenceValue()
{
- auto CompletedFenceValue = m_VkFence->GetCompletedValue();
- if(CompletedFenceValue > m_LastCompletedFenceValue)
- m_LastCompletedFenceValue = CompletedFenceValue;
+ std::lock_guard<std::mutex> Lock(m_QueueMutex);
+
+ while(!m_PendingFences.empty())
+ {
+ auto &Value_Fence = m_PendingFences.front();
+ auto status = m_LogicalDevice->GetFenceStatus(Value_Fence.second);
+ if(status == VK_SUCCESS)
+ {
+ if(Value_Fence.first > m_LastCompletedFenceValue)
+ m_LastCompletedFenceValue = Value_Fence.first;
+ m_FencePool.DisposeFence(std::move(Value_Fence.second));
+ m_PendingFences.pop_front();
+ }
+ else
+ {
+ break;
+ }
+ }
+
return m_LastCompletedFenceValue;
}
-#endif
}
diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
index 95d681b7..8c1580bd 100644
--- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
@@ -550,9 +550,9 @@ namespace Diligent
m_CommittedIBFormat = VT_UNDEFINED;
m_bCommittedVkVBsUpToDate = false;
m_bCommittedVkIBUpToDate = false;
+#endif
m_pPipelineState.Release();
-#endif
}
void DeviceContextVkImpl::Flush()
diff --git a/Graphics/GraphicsEngineVulkan/src/RenderDeviceFactoryVk.cpp b/Graphics/GraphicsEngineVulkan/src/RenderDeviceFactoryVk.cpp
index 36118793..d61c05b8 100644
--- a/Graphics/GraphicsEngineVulkan/src/RenderDeviceFactoryVk.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/RenderDeviceFactoryVk.cpp
@@ -54,7 +54,7 @@ public:
void AttachToVulkanDevice(std::shared_ptr<VulkanUtilities::VulkanInstance>,
std::unique_ptr<VulkanUtilities::VulkanPhysicalDevice> PhysicalDevice,
- VkDevice vkLogicalDevice,
+ std::shared_ptr<VulkanUtilities::VulkanLogicalDevice> LogicalDevice,
ICommandQueueVk *pCommandQueue,
const EngineVkAttribs& EngineAttribs,
IRenderDevice **ppDevice,
@@ -114,17 +114,16 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk( const EngineVkAttribs& Crea
*ppDevice = nullptr;
memset(ppContexts, 0, sizeof(*ppContexts) * (1 + NumDeferredContexts));
- std::shared_ptr<VulkanUtilities::VulkanInstance> Instance;
try
{
- Instance = std::make_shared<VulkanUtilities::VulkanInstance>(
+ auto Instance = VulkanUtilities::VulkanInstance::Create(
CreationAttribs.EnableValidation,
CreationAttribs.GlobalExtensionCount,
CreationAttribs.ppGlobalExtensionNames,
reinterpret_cast<VkAllocationCallbacks*>(CreationAttribs.pVkAllocator));
auto vkDevice = Instance->SelectPhysicalDevice();
- std::unique_ptr<VulkanUtilities::VulkanPhysicalDevice> PhysicalDevice(new VulkanUtilities::VulkanPhysicalDevice(vkDevice));
+ auto PhysicalDevice = VulkanUtilities::VulkanPhysicalDevice::Create(vkDevice);
// If an implementation exposes any queue family that supports graphics operations,
// at least one queue family of at least one physical device exposed by the implementation
@@ -163,30 +162,20 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk( const EngineVkAttribs& Crea
DeviceCreateInfo.ppEnabledExtensionNames = DeviceExtensions.empty() ? nullptr : DeviceExtensions.data();
DeviceCreateInfo.enabledExtensionCount = static_cast<uint32_t>(DeviceExtensions.size());
- VkDevice VulkanDevice = VK_NULL_HANDLE;
- auto res = vkCreateDevice(PhysicalDevice->GetVkDeviceHandle(), &DeviceCreateInfo, Instance->GetVkAllocator(), &VulkanDevice);
- CHECK_VK_ERROR_AND_THROW(res, "Failed to create logical device");
-
- if (CreationAttribs.EnableValidation)
+ if (!DebugMarkersSupported && CreationAttribs.EnableValidation)
{
- if(DebugMarkersSupported)
- VulkanUtilities::SetupDebugMarkers(VulkanDevice);
- else
- LOG_INFO_MESSAGE("Debug marker extensions is not found on the system");
+ LOG_INFO_MESSAGE("Debug marker extensions is not found on the system");
}
- VkQueue Queue = VK_NULL_HANDLE;
- vkGetDeviceQueue(VulkanDevice,
- QueueInfo.queueFamilyIndex, // Index of the queue family to which the queue belongs
- 0, // Index within this queue family of the queue to retrieve
- &Queue);
- VERIFY_EXPR(Queue != VK_NULL_HANDLE);
- RefCntAutoPtr<CommandQueueVkImpl> pCmdQueueVk;
+ auto vkAllocator = Instance->GetVkAllocator();
+ auto vkPhysicalDevice = PhysicalDevice->GetVkDeviceHandle();
+ auto LogicalDevice = VulkanUtilities::VulkanLogicalDevice::Create(vkPhysicalDevice, DeviceCreateInfo, vkAllocator, DebugMarkersSupported && CreationAttribs.EnableValidation);
+ RefCntAutoPtr<CommandQueueVkImpl> pCmdQueueVk;
auto &RawMemAllocator = GetRawAllocator();
- pCmdQueueVk = NEW_RC_OBJ(RawMemAllocator, "CommandQueueVk instance", CommandQueueVkImpl)(Queue, QueueInfo.queueFamilyIndex);
+ pCmdQueueVk = NEW_RC_OBJ(RawMemAllocator, "CommandQueueVk instance", CommandQueueVkImpl)(LogicalDevice, QueueInfo.queueFamilyIndex);
- AttachToVulkanDevice(Instance, std::move(PhysicalDevice), VulkanDevice, pCmdQueueVk, CreationAttribs, ppDevice, ppContexts, NumDeferredContexts);
+ AttachToVulkanDevice(Instance, std::move(PhysicalDevice), LogicalDevice, pCmdQueueVk, CreationAttribs, ppDevice, ppContexts, NumDeferredContexts);
}
catch(std::runtime_error& )
{
@@ -198,7 +187,7 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk( const EngineVkAttribs& Crea
/// \param [in] Instance - shared pointer to a VulkanUtilities::VulkanInstance object
/// \param [in] PhysicalDevice - pointer to the object representing physical device
-/// \param [in] vkLogicalDevice - logical Vulkan device handle
+/// \param [in] LogicalDevice - shared pointer to a VulkanUtilities::VulkanLogicalDevice object
/// \param [in] pCommandQueue - pointer to the implementation of command queue
/// \param [in] EngineAttribs - Engine creation attributes.
/// \param [out] ppDevice - Address of the memory location where pointer to
@@ -213,7 +202,7 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk( const EngineVkAttribs& Crea
/// at position 1
void EngineFactoryVkImpl::AttachToVulkanDevice(std::shared_ptr<VulkanUtilities::VulkanInstance> Instance,
std::unique_ptr<VulkanUtilities::VulkanPhysicalDevice> PhysicalDevice,
- VkDevice vkLogicalDevice,
+ std::shared_ptr<VulkanUtilities::VulkanLogicalDevice> LogicalDevice,
ICommandQueueVk *pCommandQueue,
const EngineVkAttribs& EngineAttribs,
IRenderDevice **ppDevice,
@@ -221,7 +210,7 @@ void EngineFactoryVkImpl::AttachToVulkanDevice(std::shared_ptr<VulkanUtilities::
Uint32 NumDeferredContexts)
{
VERIFY( pCommandQueue && ppDevice && ppContexts, "Null pointer provided" );
- if(vkLogicalDevice == VK_NULL_HANDLE || !pCommandQueue || !ppDevice || !ppContexts )
+ if(!LogicalDevice || !pCommandQueue || !ppDevice || !ppContexts )
return;
*ppDevice = nullptr;
@@ -230,7 +219,7 @@ void EngineFactoryVkImpl::AttachToVulkanDevice(std::shared_ptr<VulkanUtilities::
try
{
auto &RawMemAllocator = GetRawAllocator();
- RenderDeviceVkImpl *pRenderDeviceVk( NEW_RC_OBJ(RawMemAllocator, "RenderDeviceVkImpl instance", RenderDeviceVkImpl)(RawMemAllocator, EngineAttribs, pCommandQueue, Instance, std::move(PhysicalDevice), vkLogicalDevice, NumDeferredContexts ) );
+ RenderDeviceVkImpl *pRenderDeviceVk( NEW_RC_OBJ(RawMemAllocator, "RenderDeviceVkImpl instance", RenderDeviceVkImpl)(RawMemAllocator, EngineAttribs, pCommandQueue, Instance, std::move(PhysicalDevice), LogicalDevice, NumDeferredContexts ) );
pRenderDeviceVk->QueryInterface(IID_RenderDevice, reinterpret_cast<IObject**>(ppDevice) );
RefCntAutoPtr<DeviceContextVkImpl> pImmediateCtxVk( NEW_RC_OBJ(RawMemAllocator, "DeviceContextVkImpl instance", DeviceContextVkImpl)(pRenderDeviceVk, false, EngineAttribs, 0) );
diff --git a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp
index 53e28f9a..db6fc6e6 100644
--- a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp
@@ -26,7 +26,7 @@
#include "PipelineStateVkImpl.h"
#include "ShaderVkImpl.h"
#include "TextureVkImpl.h"
-//#include "DXGITypeConversions.h"
+#include "VulkanTypeConversions.h"
#include "SamplerVkImpl.h"
#include "BufferVkImpl.h"
#include "ShaderResourceBindingVkImpl.h"
@@ -42,17 +42,17 @@ RenderDeviceVkImpl :: RenderDeviceVkImpl(IReferenceCounters *pRefCounters,
ICommandQueueVk *pCmdQueue,
std::shared_ptr<VulkanUtilities::VulkanInstance> Instance,
std::unique_ptr<VulkanUtilities::VulkanPhysicalDevice> PhysicalDevice,
- VkDevice vkLogicalDevice,
+ std::shared_ptr<VulkanUtilities::VulkanLogicalDevice> LogicalDevice,
Uint32 NumDeferredContexts) :
TRenderDeviceBase(pRefCounters, RawMemAllocator, NumDeferredContexts, sizeof(TextureVkImpl), sizeof(TextureViewVkImpl), sizeof(BufferVkImpl), sizeof(BufferViewVkImpl), sizeof(ShaderVkImpl), sizeof(SamplerVkImpl), sizeof(PipelineStateVkImpl), sizeof(ShaderResourceBindingVkImpl)),
m_VulkanInstance(Instance),
m_PhysicalDevice(std::move(PhysicalDevice)),
- m_VkDevice(vkLogicalDevice),
+ m_LogicalVkDevice(LogicalDevice),
m_pCommandQueue(pCmdQueue),
- m_EngineAttribs(CreationAttribs)
- /*m_FrameNumber(0),
+ m_EngineAttribs(CreationAttribs),
+ m_FrameNumber(0),
m_NextCmdListNumber(0),
- m_CmdListManager(this),
+ /*m_CmdListManager(this),
m_CPUDescriptorHeaps
{
{RawMemAllocator, this, CreationAttribs.CPUDescriptorHeapAllocationSize[0], Vk_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, Vk_DESCRIPTOR_HEAP_FLAG_NONE},
@@ -71,54 +71,62 @@ RenderDeviceVkImpl :: RenderDeviceVkImpl(IReferenceCounters *pRefCounters,
CreationAttribs.DynamicDescriptorAllocationChunkSize[1] // Vk_DESCRIPTOR_HEAP_TYPE_SAMPLER
},
m_ContextPool(STD_ALLOCATOR_RAW_MEM(ContextPoolElemType, GetRawAllocator(), "Allocator for vector<unique_ptr<CommandContext>>")),
- m_AvailableContexts(STD_ALLOCATOR_RAW_MEM(CommandContext*, GetRawAllocator(), "Allocator for vector<CommandContext*>")),
+ m_AvailableContexts(STD_ALLOCATOR_RAW_MEM(CommandContext*, GetRawAllocator(), "Allocator for vector<CommandContext*>")),*/
m_VkObjReleaseQueue(STD_ALLOCATOR_RAW_MEM(ReleaseQueueElemType, GetRawAllocator(), "Allocator for queue<ReleaseQueueElemType>")),
- m_StaleVkObjects(STD_ALLOCATOR_RAW_MEM(ReleaseQueueElemType, GetRawAllocator(), "Allocator for queue<ReleaseQueueElemType>")),
+ m_StaleVkObjects(STD_ALLOCATOR_RAW_MEM(ReleaseQueueElemType, GetRawAllocator(), "Allocator for queue<ReleaseQueueElemType>")),/*,
m_UploadHeaps(STD_ALLOCATOR_RAW_MEM(UploadHeapPoolElemType, GetRawAllocator(), "Allocator for vector<unique_ptr<DynamicUploadHeap>>"))
*/
+ m_CmdBufferPool(m_LogicalVkDevice, pCmdQueue->GetQueueFamilyIndex(), VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)
{
m_DeviceCaps.DevType = DeviceType::Vulkan;
m_DeviceCaps.MajorVersion = 1;
m_DeviceCaps.MinorVersion = 0;
m_DeviceCaps.bSeparableProgramSupported = True;
m_DeviceCaps.bMultithreadedResourceCreationSupported = True;
+ for(int fmt = 1; fmt < m_TextureFormatsInfo.size(); ++fmt)
+ m_TextureFormatsInfo[fmt].Supported = true; // We will test every format on a specific hardware device
}
RenderDeviceVkImpl::~RenderDeviceVkImpl()
{
-#if 0
// Finish current frame. This will release resources taken by previous frames, and
// will move all stale resources to the release queues. The resources will not be
// release until next call to FinishFrame()
- FinishFrame();
+ FinishFrame(false);
// Wait for the GPU to complete all its operations
IdleGPU(true);
// Call FinishFrame() again to destroy resources in
// release queues
FinishFrame(true);
-
+
+#if 0
m_ContextPool.clear();
#endif
- if(m_PhysicalDevice)
- {
- // If m_PhysicalDevice is empty, the device does not own vulkan logical device and must not
- // destroy it
- vkDestroyDevice(m_VkDevice, m_VulkanInstance->GetVkAllocator());
- }
+ VERIFY(m_StaleVkObjects.empty(), "Not all stale objects were destroyed");
+ VERIFY(m_VkObjReleaseQueue.empty(), "Release queue is not empty");
+
+ //if(m_PhysicalDevice)
+ //{
+ // // If m_PhysicalDevice is empty, the device does not own vulkan logical device and must not
+ // // destroy it
+ // vkDestroyDevice(m_VkDevice, m_VulkanInstance->GetVkAllocator());
+ //}
}
-#if 0
-void RenderDeviceVkImpl::DisposeCommandContext(CommandContext* pCtx)
+
+void RenderDeviceVkImpl::DisposeCommandBuffer(VkCommandBuffer CmdBuff)
{
- std::lock_guard<std::mutex> LockGuard(m_ContextAllocationMutex);
- m_AvailableContexts.push_back(pCtx);
+ std::lock_guard<std::mutex> LockGuard(m_CmdPoolMutex);
+ m_CmdBufferPool.DisposeCommandBuffer(CmdBuff, GetNextFenceValue());
}
-void RenderDeviceVkImpl::CloseAndExecuteCommandContext(CommandContext *pCtx, bool DiscardStaleObjects)
+
+void RenderDeviceVkImpl::ExecuteCommandBuffer(VkCommandBuffer CmdBuff, bool DiscardStaleObjects)
{
- CComPtr<IVkCommandAllocator> pAllocator;
- auto *pCmdList = pCtx->Close(&pAllocator);
+ VERIFY_EXPR(CmdBuff != VK_NULL_HANDLE);
+ auto err = vkEndCommandBuffer(CmdBuff);
+ VERIFY(err == VK_SUCCESS, "Failed to end command buffer");
Uint64 FenceValue = 0;
Uint64 CmdListNumber = 0;
@@ -126,7 +134,7 @@ void RenderDeviceVkImpl::CloseAndExecuteCommandContext(CommandContext *pCtx, boo
std::lock_guard<std::mutex> LockGuard(m_CmdQueueMutex);
auto NextFenceValue = m_pCommandQueue->GetNextFenceValue();
// Submit the command list to the queue
- FenceValue = m_pCommandQueue->ExecuteCommandList(pCmdList);
+ FenceValue = m_pCommandQueue->ExecuteCommandBuffer(CmdBuff);
VERIFY(FenceValue >= NextFenceValue, "Fence value of the executed command list is less than the next fence value previously queried through GetNextFenceValue()");
FenceValue = std::max(FenceValue, NextFenceValue);
CmdListNumber = m_NextCmdListNumber;
@@ -167,7 +175,7 @@ void RenderDeviceVkImpl::CloseAndExecuteCommandContext(CommandContext *pCtx, boo
// the command list (as is the case with Unity command queue).
DiscardStaleVkObjects(CmdListNumber, FenceValue);
}
-
+#if 0
// DiscardAllocator() is thread-safe
m_CmdListManager.DiscardAllocator(FenceValue, pAllocator);
@@ -177,26 +185,30 @@ void RenderDeviceVkImpl::CloseAndExecuteCommandContext(CommandContext *pCtx, boo
std::lock_guard<std::mutex> LockGuard(m_ContextAllocationMutex);
m_AvailableContexts.push_back(pCtx);
}
-}
#endif
+}
+
-#if 0
void RenderDeviceVkImpl::IdleGPU(bool ReleaseStaleObjects)
{
Uint64 FenceValue = 0;
Uint64 CmdListNumber = 0;
+
{
// Lock the command queue to avoid other threads interfering with the GPU
std::lock_guard<std::mutex> LockGuard(m_CmdQueueMutex);
FenceValue = m_pCommandQueue->GetNextFenceValue();
m_pCommandQueue->IdleGPU();
+
+ m_LogicalVkDevice->WaitIdle();
+
// Increment cmd list number while keeping queue locked.
// This guarantees that any Vk object released after the lock
// is released, will be associated with the incremented cmd list number
CmdListNumber = m_NextCmdListNumber;
Atomics::AtomicIncrement(m_NextCmdListNumber);
}
-
+
if (ReleaseStaleObjects)
{
// Do not wait until the end of the frame and force deletion.
@@ -208,6 +220,7 @@ void RenderDeviceVkImpl::IdleGPU(bool ReleaseStaleObjects)
}
}
+
Bool RenderDeviceVkImpl::IsFenceSignaled(Uint64 FenceValue)
{
return FenceValue <= GetCompletedFenceValue();
@@ -218,8 +231,10 @@ Uint64 RenderDeviceVkImpl::GetCompletedFenceValue()
return m_pCommandQueue->GetCompletedFenceValue();
}
+
void RenderDeviceVkImpl::FinishFrame(bool ReleaseAllResources)
{
+#if 0
{
if (auto pImmediateCtx = m_wpImmediateContext.Lock())
{
@@ -238,7 +253,7 @@ void RenderDeviceVkImpl::FinishFrame(bool ReleaseAllResources)
}
}
}
-
+#endif
auto CompletedFenceValue = ReleaseAllResources ? std::numeric_limits<Uint64>::max() : GetCompletedFenceValue();
// We must use NextFenceValue here, NOT current value, because the
@@ -258,6 +273,7 @@ void RenderDeviceVkImpl::FinishFrame(bool ReleaseAllResources)
Atomics::AtomicIncrement(m_NextCmdListNumber);
}
+#if 0
{
// There is no need to lock as new heaps are only created during initialization
// time for every context
@@ -298,7 +314,7 @@ void RenderDeviceVkImpl::FinishFrame(bool ReleaseAllResources)
{
m_GPUDescriptorHeaps[GPUHeap].ReleaseStaleAllocations(CompletedFenceValue);
}
-
+#endif
// Discard all remaining objects. This is important to do if there were
// no command lists submitted during the frame
DiscardStaleVkObjects(CmdListNumber, NextFenceValue);
@@ -307,6 +323,7 @@ void RenderDeviceVkImpl::FinishFrame(bool ReleaseAllResources)
Atomics::AtomicIncrement(m_FrameNumber);
}
+#if 0
DynamicUploadHeap* RenderDeviceVkImpl::RequestUploadHeap()
{
std::lock_guard<std::mutex> LockGuard(m_UploadHeapMutex);
@@ -328,11 +345,15 @@ void RenderDeviceVkImpl::ReleaseUploadHeap(DynamicUploadHeap* pUploadHeap)
{
}
+#endif
-CommandContext* RenderDeviceVkImpl::AllocateCommandContext(const Char *ID)
+VkCommandBuffer RenderDeviceVkImpl::AllocateCommandBuffer(const Char *DebugName)
{
- std::lock_guard<std::mutex> LockGuard(m_ContextAllocationMutex);
+ std::lock_guard<std::mutex> LockGuard(m_CmdPoolMutex);
+ auto CmdBuffer = m_CmdBufferPool.GetCommandBuffer(GetCompletedFenceValue(), DebugName);
+ return CmdBuffer;
+#if 0
CommandContext* ret = nullptr;
if (m_AvailableContexts.empty())
{
@@ -353,21 +374,44 @@ CommandContext* RenderDeviceVkImpl::AllocateCommandContext(const Char *ID)
// EngineProfiling::BeginBlock(ID, NewContext);
return ret;
-}
#endif
+}
-void RenderDeviceVkImpl::SafeReleaseVkBuffer(VkBuffer vkBuffer)
+
+template<typename VulkanObjectType>
+class RenderDeviceVkImpl::StaleVulkanObject : public StaleVulkanObjectBase
+{
+public:
+ StaleVulkanObject(VulkanUtilities::VulkanObjectWrapper<VulkanObjectType> &&Object) :
+ m_VkObject(std::move(Object))
+ {}
+
+ ~StaleVulkanObject()
+ {
+ m_VkObject.Release();
+ }
+
+private:
+ VulkanUtilities::VulkanObjectWrapper<VulkanObjectType> m_VkObject;
+};
+
+template<typename VulkanObjectType>
+void RenderDeviceVkImpl::SafeReleaseVkObject(VulkanUtilities::VulkanObjectWrapper<VulkanObjectType>&& vkObject)
{
// When Vk object is released, it is first moved into the
// stale objects list. The list is moved into a release queue
// when the next command list is executed.
std::lock_guard<std::mutex> LockGuard(m_StaleObjectsMutex);
-#if 0
- m_StaleVkObjects.emplace_back( m_NextCmdListNumber, CComPtr<IVkObject>(pObj) );
-#endif
+ m_StaleVkObjects.emplace_back(m_NextCmdListNumber, new StaleVulkanObject<VulkanObjectType>(std::move(vkObject)) );
}
-#if 0
+template void RenderDeviceVkImpl::SafeReleaseVkObject<VkBuffer>(VulkanUtilities::BufferWrapper &&Object);
+template void RenderDeviceVkImpl::SafeReleaseVkObject<VkBufferView>(VulkanUtilities::BufferViewWrapper &&Object);
+template void RenderDeviceVkImpl::SafeReleaseVkObject<VkImage>(VulkanUtilities::ImageWrapper &&Object);
+template void RenderDeviceVkImpl::SafeReleaseVkObject<VkImageView>(VulkanUtilities::ImageViewWrapper &&Object);
+template void RenderDeviceVkImpl::SafeReleaseVkObject<VkDeviceMemory>(VulkanUtilities::DeviceMemoryWrapper &&Object);
+
+
void RenderDeviceVkImpl::DiscardStaleVkObjects(Uint64 CmdListNumber, Uint64 FenceValue)
{
// Only discard these stale objects that were released before CmdListNumber
@@ -403,122 +447,94 @@ void RenderDeviceVkImpl::ProcessReleaseQueue(Uint64 CompletedFenceValue)
}
}
-bool CreateTestResource(IVkDevice *pDevice, const Vk_RESOURCE_DESC &ResDesc)
-{
- // Set the texture pointer address to nullptr to validate input parameters
- // without creating the texture
- // https://msdn.microsoft.com/en-us/library/windows/desktop/dn899178(v=vs.85).aspx
-
- Vk_HEAP_PROPERTIES HeapProps;
- HeapProps.Type = Vk_HEAP_TYPE_DEFAULT;
- HeapProps.CPUPageProperty = Vk_CPU_PAGE_PROPERTY_UNKNOWN;
- HeapProps.MemoryPoolPreference = Vk_MEMORY_POOL_UNKNOWN;
- HeapProps.CreationNodeMask = 1;
- HeapProps.VisibleNodeMask = 1;
-
- auto hr = pDevice->CreateCommittedResource( &HeapProps, Vk_HEAP_FLAG_NONE, &ResDesc, Vk_RESOURCE_STATE_COMMON, nullptr, __uuidof(IVkResource), nullptr );
- return hr == S_FALSE; // S_FALSE means that input parameters passed validation
-}
-#endif
void RenderDeviceVkImpl::TestTextureFormat( TEXTURE_FORMAT TexFormat )
{
-#if 0
auto &TexFormatInfo = m_TextureFormatsInfo[TexFormat];
VERIFY( TexFormatInfo.Supported, "Texture format is not supported" );
- auto DXGIFormat = TexFormatToDXGI_Format(TexFormat);
- Vk_RESOURCE_FLAGS DefaultResourceFlags = Vk_RESOURCE_FLAG_NONE;
- if( TexFormatInfo.ComponentType == COMPONENT_TYPE_DEPTH ||
- TexFormatInfo.ComponentType == COMPONENT_TYPE_DEPTH_STENCIL )
- DefaultResourceFlags = Vk_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
-
- const int TestTextureDim = 32;
- const int TestTextureDepth = 8;
-
- Vk_RESOURCE_DESC ResDesc =
- {
- Vk_RESOURCE_DIMENSION_TEXTURE1D,
- 0, // Alignment
- TestTextureDim,
- 1, // Height
- 1, // DepthOrArraySize
- 1, // MipLevels
- DXGIFormat,
- {1, 0},
- Vk_TEXTURE_LAYOUT_UNKNOWN,
- DefaultResourceFlags
- };
-
- // Create test texture 1D
- TexFormatInfo.Tex1DFmt = false;
- if( TexFormatInfo.ComponentType != COMPONENT_TYPE_COMPRESSED )
- {
- TexFormatInfo.Tex1DFmt = CreateTestResource(m_pVkDevice, ResDesc );
- }
+ auto vkPhysicalDevice = m_PhysicalDevice->GetVkDeviceHandle();
- // Create test texture 2D
- TexFormatInfo.Tex2DFmt = false;
- TexFormatInfo.TexCubeFmt = false;
- TexFormatInfo.ColorRenderable = false;
- TexFormatInfo.DepthRenderable = false;
- TexFormatInfo.SupportsMS = false;
+ auto SRVFormat = GetDefaultTextureViewFormat(TexFormat, TEXTURE_VIEW_SHADER_RESOURCE, BIND_SHADER_RESOURCE);
+ auto RTVFormat = GetDefaultTextureViewFormat(TexFormat, TEXTURE_VIEW_RENDER_TARGET, BIND_RENDER_TARGET);
+ auto DSVFormat = GetDefaultTextureViewFormat(TexFormat, TEXTURE_VIEW_DEPTH_STENCIL, BIND_DEPTH_STENCIL);
+
+ if(SRVFormat != TEX_FORMAT_UNKNOWN)
{
- ResDesc.Dimension = Vk_RESOURCE_DIMENSION_TEXTURE2D;
- ResDesc.Height = TestTextureDim;
- TexFormatInfo.Tex2DFmt = CreateTestResource( m_pVkDevice, ResDesc );
+ VkFormat vkSrvFormat = TexFormatToVkFormat(SRVFormat);
+ VkFormatProperties vkSrvFmtProps = {};
+ vkGetPhysicalDeviceFormatProperties(vkPhysicalDevice, vkSrvFormat, &vkSrvFmtProps);
- if( TexFormatInfo.Tex2DFmt )
+ if(vkSrvFmtProps.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)
{
+ TexFormatInfo.Filterable = true;
+
{
- // Vk_TEXTURE2D_DESC CubeTexDesc = Tex2DDesc;
- ResDesc.DepthOrArraySize = 6;
- // CubeTexDesc.MiscFlags = Vk_RESOURCE_MISC_TEXTURECUBE;
- TexFormatInfo.TexCubeFmt = CreateTestResource( m_pVkDevice, ResDesc );
- ResDesc.DepthOrArraySize = 1;
+ VkImageFormatProperties ImgFmtProps = {};
+ auto err = vkGetPhysicalDeviceImageFormatProperties(vkPhysicalDevice, vkSrvFormat, VK_IMAGE_TYPE_1D, VK_IMAGE_TILING_OPTIMAL,
+ VK_IMAGE_USAGE_SAMPLED_BIT, 0, &ImgFmtProps);
+ TexFormatInfo.Tex1DFmt = err == VK_SUCCESS;
}
- if( TexFormatInfo.ComponentType == COMPONENT_TYPE_DEPTH ||
- TexFormatInfo.ComponentType == COMPONENT_TYPE_DEPTH_STENCIL )
{
- ResDesc.Flags = Vk_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
- ResDesc.SampleDesc.Count = 1;
- TexFormatInfo.DepthRenderable = CreateTestResource( m_pVkDevice, ResDesc );
-
- if( TexFormatInfo.DepthRenderable )
- {
- ResDesc.SampleDesc.Count = 4;
- TexFormatInfo.SupportsMS = CreateTestResource( m_pVkDevice, ResDesc );
- }
+ VkImageFormatProperties ImgFmtProps = {};
+ auto err = vkGetPhysicalDeviceImageFormatProperties(vkPhysicalDevice, vkSrvFormat, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
+ VK_IMAGE_USAGE_SAMPLED_BIT, 0, &ImgFmtProps);
+ TexFormatInfo.Tex2DFmt = err == VK_SUCCESS;
}
- else if( TexFormatInfo.ComponentType != COMPONENT_TYPE_COMPRESSED &&
- TexFormatInfo.Format != DXGI_FORMAT_R9G9B9E5_SHAREDEXP )
+
+ {
+ VkImageFormatProperties ImgFmtProps = {};
+ auto err = vkGetPhysicalDeviceImageFormatProperties(vkPhysicalDevice, vkSrvFormat, VK_IMAGE_TYPE_3D, VK_IMAGE_TILING_OPTIMAL,
+ VK_IMAGE_USAGE_SAMPLED_BIT, 0, &ImgFmtProps);
+ TexFormatInfo.Tex3DFmt = err == VK_SUCCESS;
+ }
+
+ {
+ VkImageFormatProperties ImgFmtProps = {};
+ auto err = vkGetPhysicalDeviceImageFormatProperties(vkPhysicalDevice, vkSrvFormat, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
+ VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT, &ImgFmtProps);
+ TexFormatInfo.TexCubeFmt = err == VK_SUCCESS;
+ }
+
+ }
+ }
+
+ if (RTVFormat != TEX_FORMAT_UNKNOWN)
+ {
+ VkFormat vkRtvFormat = TexFormatToVkFormat(RTVFormat);
+ VkFormatProperties vkRtvFmtProps = {};
+ vkGetPhysicalDeviceFormatProperties(vkPhysicalDevice, vkRtvFormat, &vkRtvFmtProps);
+ if (vkRtvFmtProps.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)
+ {
+ VkImageFormatProperties ImgFmtProps = {};
+ auto err = vkGetPhysicalDeviceImageFormatProperties(vkPhysicalDevice, vkRtvFormat, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
+ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, 0, &ImgFmtProps);
+ TexFormatInfo.ColorRenderable = err == VK_SUCCESS;
+ if (TexFormatInfo.ColorRenderable)
{
- ResDesc.Flags = Vk_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
- ResDesc.SampleDesc.Count = 1;
- TexFormatInfo.ColorRenderable = CreateTestResource( m_pVkDevice, ResDesc );
- if( TexFormatInfo.ColorRenderable )
- {
- ResDesc.SampleDesc.Count = 4;
- TexFormatInfo.SupportsMS = CreateTestResource( m_pVkDevice, ResDesc );
- }
+ TexFormatInfo.SupportsMS = ImgFmtProps.sampleCounts > VK_SAMPLE_COUNT_1_BIT;
}
}
}
- // Create test texture 3D
- TexFormatInfo.Tex3DFmt = false;
- // 3D textures do not support depth formats
- if( !(TexFormatInfo.ComponentType == COMPONENT_TYPE_DEPTH ||
- TexFormatInfo.ComponentType == COMPONENT_TYPE_DEPTH_STENCIL) )
+ if (DSVFormat != TEX_FORMAT_UNKNOWN)
{
- ResDesc.SampleDesc.Count = 1;
- ResDesc.Dimension = Vk_RESOURCE_DIMENSION_TEXTURE3D;
- ResDesc.Flags = DefaultResourceFlags;
- ResDesc.DepthOrArraySize = TestTextureDepth;
- TexFormatInfo.Tex3DFmt = CreateTestResource( m_pVkDevice, ResDesc );
+ VkFormat vkDsvFormat = TexFormatToVkFormat(DSVFormat);
+ VkFormatProperties vkDsvFmtProps = {};
+ vkGetPhysicalDeviceFormatProperties(vkPhysicalDevice, vkDsvFormat, &vkDsvFmtProps);
+ if (vkDsvFmtProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)
+ {
+ VkImageFormatProperties ImgFmtProps = {};
+ auto err = vkGetPhysicalDeviceImageFormatProperties(vkPhysicalDevice, vkDsvFormat, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
+ VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, 0, &ImgFmtProps);
+ TexFormatInfo.DepthRenderable = err == VK_SUCCESS;
+ if (TexFormatInfo.DepthRenderable)
+ {
+ TexFormatInfo.SupportsMS = ImgFmtProps.sampleCounts > VK_SAMPLE_COUNT_1_BIT;
+ }
+ }
}
-#endif
}
diff --git a/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp
index 30543134..606abc1f 100644
--- a/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp
@@ -314,12 +314,14 @@ void SwapChainVkImpl::InitBuffersAndViews()
BackBufferDesc.Width = m_SwapChainDesc.Width;
BackBufferDesc.Height = m_SwapChainDesc.Height;
BackBufferDesc.Format = m_SwapChainDesc.ColorBufferFormat;
+ BackBufferDesc.BindFlags = BIND_RENDER_TARGET;
BackBufferDesc.MipLevels = 1;
RefCntAutoPtr<TextureVkImpl> pBackBufferTex;
ValidatedCast<RenderDeviceVkImpl>(m_pRenderDevice.RawPtr())->CreateTexture(BackBufferDesc, swapchainImages[i], &pBackBufferTex);
- UNSUPPORTED("TODO: move all this code to Texture creation");
+ //UNSUPPORTED("TODO: move all this code to Texture creation");
+
VkImageViewCreateInfo color_image_view = {};
color_image_view.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
color_image_view.pNext = NULL;
@@ -396,12 +398,6 @@ IMPLEMENT_QUERY_INTERFACE( SwapChainVkImpl, IID_SwapChainVk, TSwapChainBase )
void SwapChainVkImpl::Present(Uint32 SyncInterval)
{
-#if 0
- UINT SyncInterval = 0;
-#if PLATFORM_UNIVERSAL_WINDOWS
- SyncInterval = 1; // Interval 0 is not supported on Windows Phone
-#endif
-
auto pDeviceContext = m_wpDeviceContext.Lock();
if( !pDeviceContext )
{
@@ -412,16 +408,18 @@ void SwapChainVkImpl::Present(Uint32 SyncInterval)
auto *pImmediateCtx = pDeviceContext.RawPtr();
auto *pImmediateCtxVk = ValidatedCast<DeviceContextVkImpl>( pImmediateCtx );
+#if 0
auto *pCmdCtx = pImmediateCtxVk->RequestCmdContext();
auto *pBackBuffer = ValidatedCast<TextureVkImpl>( GetCurrentBackBufferRTV()->GetTexture() );
pCmdCtx->TransitionResource( pBackBuffer, Vk_RESOURCE_STATE_PRESENT);
-
+#endif
pImmediateCtxVk->Flush();
auto *pDeviceVk = ValidatedCast<RenderDeviceVkImpl>( pImmediateCtxVk->GetDevice() );
-
+#if 0
auto hr = m_pSwapChain->Present( SyncInterval, 0 );
VERIFY(SUCCEEDED(hr), "Present failed");
+#endif
pDeviceVk->FinishFrame();
@@ -434,7 +432,6 @@ void SwapChainVkImpl::Present(Uint32 SyncInterval)
pImmediateCtxVk->CommitRenderTargets();
#endif
#endif
-#endif
}
void SwapChainVkImpl::Resize( Uint32 NewWidth, Uint32 NewHeight )
@@ -506,5 +503,4 @@ void SwapChainVkImpl::SetWindowedMode()
{
}
-
}
diff --git a/Graphics/GraphicsEngineVulkan/src/TextureViewVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/TextureViewVkImpl.cpp
index be36e9dd..48536542 100644
--- a/Graphics/GraphicsEngineVulkan/src/TextureViewVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/TextureViewVkImpl.cpp
@@ -24,6 +24,7 @@
#include "pch.h"
#include "TextureViewVkImpl.h"
#include "DeviceContextVkImpl.h"
+#include "RenderDeviceVkImpl.h"
namespace Diligent
{
@@ -32,13 +33,19 @@ TextureViewVkImpl::TextureViewVkImpl( IReferenceCounters *pRefCounters,
IRenderDevice *pDevice,
const TextureViewDesc& ViewDesc,
ITexture *pTexture,
- VkImageView vkImgView,
+ VulkanUtilities::ImageViewWrapper &&ImgView,
bool bIsDefaultView ) :
TTextureViewBase( pRefCounters, pDevice, ViewDesc, pTexture, bIsDefaultView ),
- m_VkImageView(vkImgView)
+ m_ImageView(std::move(ImgView))
{
}
+TextureViewVkImpl::~TextureViewVkImpl()
+{
+ auto *pDeviceVkImpl = ValidatedCast<RenderDeviceVkImpl>(GetDevice());
+ pDeviceVkImpl->SafeReleaseVkObject(std::move(m_ImageView));
+}
+
IMPLEMENT_QUERY_INTERFACE( TextureViewVkImpl, IID_TextureViewVk, TTextureViewBase )
void TextureViewVkImpl::GenerateMips( IDeviceContext *pContext )
diff --git a/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp
index fabf8323..bb069dd9 100644
--- a/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp
@@ -58,59 +58,92 @@ DXGI_FORMAT GetClearFormat(DXGI_FORMAT Fmt, Vk_RESOURCE_FLAGS Flags)
#endif
TextureVkImpl :: TextureVkImpl(IReferenceCounters *pRefCounters,
- FixedBlockMemoryAllocator &TexViewObjAllocator,
- RenderDeviceVkImpl *pRenderDeviceVk,
- const TextureDesc& TexDesc,
- const TextureData &InitData /*= TextureData()*/) :
+ FixedBlockMemoryAllocator &TexViewObjAllocator,
+ RenderDeviceVkImpl *pRenderDeviceVk,
+ const TextureDesc& TexDesc,
+ const TextureData &InitData /*= TextureData()*/) :
TTextureBase(pRefCounters, TexViewObjAllocator, pRenderDeviceVk, TexDesc),
m_IsExternalHandle(false)
{
if( m_Desc.Usage == USAGE_STATIC && InitData.pSubResources == nullptr )
LOG_ERROR_AND_THROW("Static Texture must be initialized with data at creation time");
-#if 0
- Vk_RESOURCE_DESC Desc = {};
- Desc.Alignment = 0;
- if(m_Desc.Type == RESOURCE_DIM_TEX_1D_ARRAY || m_Desc.Type == RESOURCE_DIM_TEX_2D_ARRAY || m_Desc.Type == RESOURCE_DIM_TEX_CUBE || m_Desc.Type == RESOURCE_DIM_TEX_CUBE_ARRAY)
- Desc.DepthOrArraySize = (UINT16)m_Desc.ArraySize;
- else if(m_Desc.Type == RESOURCE_DIM_TEX_3D )
- Desc.DepthOrArraySize = (UINT16)m_Desc.Depth;
- else
- Desc.DepthOrArraySize = 1;
-
- if( m_Desc.Type == RESOURCE_DIM_TEX_1D || m_Desc.Type == RESOURCE_DIM_TEX_1D_ARRAY )
- Desc.Dimension = Vk_RESOURCE_DIMENSION_TEXTURE1D;
- else if( m_Desc.Type == RESOURCE_DIM_TEX_2D || m_Desc.Type == RESOURCE_DIM_TEX_2D_ARRAY || m_Desc.Type == RESOURCE_DIM_TEX_CUBE || m_Desc.Type == RESOURCE_DIM_TEX_CUBE_ARRAY)
- Desc.Dimension = Vk_RESOURCE_DIMENSION_TEXTURE2D;
- else if( m_Desc.Type == RESOURCE_DIM_TEX_3D )
- Desc.Dimension = Vk_RESOURCE_DIMENSION_TEXTURE3D;
+
+ const auto& LogicalDevice = pRenderDeviceVk->GetLogicalDevice();
+ const auto& PhysicalDevice = pRenderDeviceVk->GetPhysicalDevice();
+
+ VkImageCreateInfo ImageCI = {};
+ ImageCI.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
+ ImageCI.pNext = nullptr;
+ ImageCI.flags = 0;
+ if(m_Desc.Type == RESOURCE_DIM_TEX_CUBE || m_Desc.Type == RESOURCE_DIM_TEX_CUBE_ARRAY)
+ ImageCI.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
+ const auto &FmtAttribs = GetTextureFormatAttribs(TexDesc.Format);
+ if(FmtAttribs.IsTypeless)
+ ImageCI.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT; // Specifies that the image can be used to create a
+ // VkImageView with a different format from the image.
+
+ if (m_Desc.Type == RESOURCE_DIM_TEX_1D || m_Desc.Type == RESOURCE_DIM_TEX_1D_ARRAY)
+ ImageCI.imageType = VK_IMAGE_TYPE_1D;
+ else if (m_Desc.Type == RESOURCE_DIM_TEX_2D || m_Desc.Type == RESOURCE_DIM_TEX_2D_ARRAY || m_Desc.Type == RESOURCE_DIM_TEX_CUBE || m_Desc.Type == RESOURCE_DIM_TEX_CUBE_ARRAY)
+ ImageCI.imageType = VK_IMAGE_TYPE_2D;
+ else if (m_Desc.Type == RESOURCE_DIM_TEX_3D)
+ ImageCI.imageType = VK_IMAGE_TYPE_3D;
else
{
LOG_ERROR_AND_THROW("Unknown texture type");
}
+ if (FmtAttribs.IsTypeless)
+ {
+ // Use SRV format to create the texture
+ auto SRVFormat = GetDefaultTextureViewFormat(m_Desc, TEXTURE_VIEW_SHADER_RESOURCE);
+ ImageCI.format = TexFormatToVkFormat(SRVFormat);
+ }
+ else
+ {
+ ImageCI.format = TexFormatToVkFormat(m_Desc.Format);
+ }
+
+ ImageCI.extent.width = m_Desc.Width;
+ ImageCI.extent.height = (m_Desc.Type == RESOURCE_DIM_TEX_1D || m_Desc.Type == RESOURCE_DIM_TEX_1D_ARRAY) ? 1 : m_Desc.Height;
+ ImageCI.extent.depth = (m_Desc.Type == RESOURCE_DIM_TEX_3D) ? m_Desc.Depth : 1;
+
+ ImageCI.mipLevels = m_Desc.MipLevels;
+ if (m_Desc.Type == RESOURCE_DIM_TEX_1D_ARRAY ||
+ m_Desc.Type == RESOURCE_DIM_TEX_2D_ARRAY ||
+ m_Desc.Type == RESOURCE_DIM_TEX_CUBE ||
+ m_Desc.Type == RESOURCE_DIM_TEX_CUBE_ARRAY)
+ ImageCI.arrayLayers = m_Desc.ArraySize;
+ else
+ ImageCI.arrayLayers = 1;
+
+ ImageCI.samples = static_cast<VkSampleCountFlagBits>(1 << (m_Desc.SampleCount-1));
+ ImageCI.tiling = VK_IMAGE_TILING_OPTIMAL;
+
+ ImageCI.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
+ if (m_Desc.BindFlags & BIND_RENDER_TARGET)
+ ImageCI.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+ if (m_Desc.BindFlags & BIND_DEPTH_STENCIL)
+ ImageCI.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
+ if ((m_Desc.BindFlags & BIND_UNORDERED_ACCESS) || (m_Desc.MiscFlags & MISC_TEXTURE_FLAG_GENERATE_MIPS))
+ ImageCI.usage |= VK_IMAGE_USAGE_STORAGE_BIT;
+ if ((m_Desc.BindFlags & BIND_SHADER_RESOURCE) == 0)
+ ImageCI.usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
+
+ ImageCI.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ ImageCI.queueFamilyIndexCount = 0;
+ ImageCI.pQueueFamilyIndices = nullptr;
+ ImageCI.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+
+#if 0
Desc.Flags = Vk_RESOURCE_FLAG_NONE;
- if( m_Desc.BindFlags & BIND_RENDER_TARGET )
- Desc.Flags |= Vk_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
- if( m_Desc.BindFlags & BIND_DEPTH_STENCIL )
- Desc.Flags |= Vk_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
- if( (m_Desc.BindFlags & BIND_UNORDERED_ACCESS) || (m_Desc.MiscFlags & MISC_TEXTURE_FLAG_GENERATE_MIPS) )
- Desc.Flags |= Vk_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
- if( (m_Desc.BindFlags & BIND_SHADER_RESOURCE) == 0 )
- Desc.Flags |= Vk_RESOURCE_FLAG_DENY_SHADER_RESOURCE;
auto Format = TexFormatToDXGI_Format(m_Desc.Format, m_Desc.BindFlags);
if (Format == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB && (Desc.Flags & Vk_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS))
Desc.Format = DXGI_FORMAT_R8G8B8A8_TYPELESS;
else
Desc.Format = Format;
- Desc.Height = (UINT)m_Desc.Height;
- Desc.Layout = Vk_TEXTURE_LAYOUT_UNKNOWN;
- Desc.MipLevels = static_cast<Uint16>(m_Desc.MipLevels);
- Desc.SampleDesc.Count = m_Desc.SampleCount;
- Desc.SampleDesc.Quality = 0;
- Desc.Width = (UINT64)m_Desc.Width;
-
Vk_HEAP_PROPERTIES HeapProps;
HeapProps.Type = Vk_HEAP_TYPE_DEFAULT;
@@ -141,19 +174,50 @@ TextureVkImpl :: TextureVkImpl(IReferenceCounters *pRefCounters,
}
pClearValue = &ClearValue;
}
+#endif
bool bInitializeTexture = (InitData.pSubResources != nullptr && InitData.NumSubresources > 0);
- if(bInitializeTexture)
- m_UsageState = Vk_RESOURCE_STATE_COPY_DEST;
+ //if(bInitializeTexture)
+ // m_UsageState = Vk_RESOURCE_STATE_COPY_DEST;
+
+ m_VulkanImage = LogicalDevice.CreateImage(ImageCI, m_Desc.Name);
+
+ VkMemoryRequirements MemReqs = LogicalDevice.GetImageMemoryRequirements(m_VulkanImage);
+
+ VkMemoryAllocateInfo MemAlloc = {};
+ MemAlloc.pNext = nullptr;
+ MemAlloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
+ MemAlloc.allocationSize = MemReqs.size;
+
+ VkMemoryPropertyFlags ImageMemoryFlags = 0;
+ if (m_Desc.Usage == USAGE_CPU_ACCESSIBLE)
+ ImageMemoryFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
+ else
+ ImageMemoryFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
+
+ // memoryTypeBits is a bitmask and contains one bit set for every supported memory type for the resource.
+ // Bit i is set if and only if the memory type i in the VkPhysicalDeviceMemoryProperties structure for the
+ // physical device is supported for the resource.
+ MemAlloc.memoryTypeIndex = PhysicalDevice.GetMemoryTypeIndex(MemReqs.memoryTypeBits, ImageMemoryFlags);
+ if (ImageMemoryFlags == VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
+ {
+ // There must be at least one memory type with the DEVICE_LOCAL_BIT bit set
+ VERIFY(MemAlloc.memoryTypeIndex != VulkanUtilities::VulkanPhysicalDevice::InvalidMemoryTypeIndex,
+ "Vulkan spec requires that memoryTypeBits member always contains "
+ "at least one bit set corresponding to a VkMemoryType with a propertyFlags that has the "
+ "VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT bit set (11.6)");
+ }
+ else if (MemAlloc.memoryTypeIndex != VulkanUtilities::VulkanPhysicalDevice::InvalidMemoryTypeIndex)
+ {
+ LOG_ERROR_AND_THROW("Failed to find suitable device memory type for an image");
+ }
- auto hr = pVkDevice->CreateCommittedResource( &HeapProps, Vk_HEAP_FLAG_NONE,
- &Desc, m_UsageState, pClearValue, __uuidof(m_pVkResource), reinterpret_cast<void**>(static_cast<IVkResource**>(&m_pVkResource)) );
- if(FAILED(hr))
- LOG_ERROR_AND_THROW("Failed to create Vk texture");
+ m_ImageMemory = LogicalDevice.AllocateDeviceMemory(MemAlloc);
- if( *m_Desc.Name != 0)
- m_pVkResource->SetName(WidenString(m_Desc.Name).c_str());
+ auto err = LogicalDevice.BindImageMemory(m_VulkanImage, m_ImageMemory, 0 /*offset*/);
+ CHECK_VK_ERROR_AND_THROW(err, "Failed to bind image memory");
+#if 0
if(bInitializeTexture)
{
Uint32 ExpectedNumSubresources = static_cast<Uint32>(Desc.MipLevels * (Desc.Dimension == Vk_RESOURCE_DIMENSION_TEXTURE3D ? 1 : Desc.DepthOrArraySize) );
@@ -277,12 +341,12 @@ static TextureDesc InitTexDescFromVkImage(VkImage vkImg, const TextureDesc& SrcT
TextureVkImpl::TextureVkImpl(IReferenceCounters *pRefCounters,
- FixedBlockMemoryAllocator &TexViewObjAllocator,
- RenderDeviceVkImpl *pDeviceVk,
- const TextureDesc& TexDesc,
- VkImage VkImageHandle) :
+ FixedBlockMemoryAllocator &TexViewObjAllocator,
+ RenderDeviceVkImpl *pDeviceVk,
+ const TextureDesc& TexDesc,
+ VkImage VkImageHandle) :
TTextureBase(pRefCounters, TexViewObjAllocator, pDeviceVk, InitTexDescFromVkImage(VkImageHandle, TexDesc)),
- m_VkImage(VkImageHandle),
+ m_VulkanImage(nullptr, VkImageHandle),
m_IsExternalHandle(true)
{
}
@@ -295,7 +359,7 @@ void TextureVkImpl::CreateViewInternal( const struct TextureViewDesc &ViewDesc,
VERIFY( *ppView == nullptr, "Overwriting reference to existing object may cause memory leaks" );
*ppView = nullptr;
-#if 0
+
try
{
auto *pDeviceVkImpl = ValidatedCast<RenderDeviceVkImpl>(GetDevice());
@@ -305,38 +369,38 @@ void TextureVkImpl::CreateViewInternal( const struct TextureViewDesc &ViewDesc,
auto UpdatedViewDesc = ViewDesc;
CorrectTextureViewDesc( UpdatedViewDesc );
- DescriptorHeapAllocation ViewHandleAlloc;
+ VulkanUtilities::ImageViewWrapper ImgView;
switch( ViewDesc.ViewType )
{
case TEXTURE_VIEW_SHADER_RESOURCE:
{
VERIFY( m_Desc.BindFlags & BIND_SHADER_RESOURCE, "BIND_SHADER_RESOURCE flag is not set" );
- ViewHandleAlloc = pDeviceVkImpl->AllocateDescriptor(Vk_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
- CreateSRV( UpdatedViewDesc, ViewHandleAlloc.GetCpuHandle() );
+ //ViewHandleAlloc = pDeviceVkImpl->AllocateDescriptor(Vk_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
+ //CreateSRV( UpdatedViewDesc, ViewHandleAlloc.GetCpuHandle() );
}
break;
case TEXTURE_VIEW_RENDER_TARGET:
{
VERIFY( m_Desc.BindFlags & BIND_RENDER_TARGET, "BIND_RENDER_TARGET flag is not set" );
- ViewHandleAlloc = pDeviceVkImpl->AllocateDescriptor(Vk_DESCRIPTOR_HEAP_TYPE_RTV);
- CreateRTV( UpdatedViewDesc, ViewHandleAlloc.GetCpuHandle() );
+ //ViewHandleAlloc = pDeviceVkImpl->AllocateDescriptor(Vk_DESCRIPTOR_HEAP_TYPE_RTV);
+ //CreateRTV( UpdatedViewDesc, ViewHandleAlloc.GetCpuHandle() );
}
break;
case TEXTURE_VIEW_DEPTH_STENCIL:
{
VERIFY( m_Desc.BindFlags & BIND_DEPTH_STENCIL, "BIND_DEPTH_STENCIL is not set" );
- ViewHandleAlloc = pDeviceVkImpl->AllocateDescriptor(Vk_DESCRIPTOR_HEAP_TYPE_DSV);
- CreateDSV( UpdatedViewDesc, ViewHandleAlloc.GetCpuHandle() );
+ //ViewHandleAlloc = pDeviceVkImpl->AllocateDescriptor(Vk_DESCRIPTOR_HEAP_TYPE_DSV);
+ //CreateDSV( UpdatedViewDesc, ViewHandleAlloc.GetCpuHandle() );
}
break;
case TEXTURE_VIEW_UNORDERED_ACCESS:
{
VERIFY( m_Desc.BindFlags & BIND_UNORDERED_ACCESS, "BIND_UNORDERED_ACCESS flag is not set" );
- ViewHandleAlloc = pDeviceVkImpl->AllocateDescriptor(Vk_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
- CreateUAV( UpdatedViewDesc, ViewHandleAlloc.GetCpuHandle() );
+ //ViewHandleAlloc = pDeviceVkImpl->AllocateDescriptor(Vk_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
+ //CreateUAV( UpdatedViewDesc, ViewHandleAlloc.GetCpuHandle() );
}
break;
@@ -344,7 +408,7 @@ void TextureVkImpl::CreateViewInternal( const struct TextureViewDesc &ViewDesc,
}
auto pViewVk = NEW_RC_OBJ(TexViewAllocator, "TextureViewVkImpl instance", TextureViewVkImpl, bIsDefaultView ? this : nullptr)
- (GetDevice(), UpdatedViewDesc, this, std::move(ViewHandleAlloc), bIsDefaultView );
+ (GetDevice(), UpdatedViewDesc, this, std::move(ImgView), bIsDefaultView );
VERIFY( pViewVk->GetDesc().ViewType == ViewDesc.ViewType, "Incorrect view type" );
if( bIsDefaultView )
@@ -357,20 +421,17 @@ void TextureVkImpl::CreateViewInternal( const struct TextureViewDesc &ViewDesc,
const auto *ViewTypeName = GetTexViewTypeLiteralName(ViewDesc.ViewType);
LOG_ERROR("Failed to create view \"", ViewDesc.Name ? ViewDesc.Name : "", "\" (", ViewTypeName, ") for texture \"", m_Desc.Name ? m_Desc.Name : "", "\"" );
}
-#endif
}
TextureVkImpl :: ~TextureVkImpl()
{
if(!m_IsExternalHandle)
{
-
+ auto *pDeviceVkImpl = ValidatedCast<RenderDeviceVkImpl>(GetDevice());
+ // Vk object can only be destroyed when it is no longer used by the GPU
+ pDeviceVkImpl->SafeReleaseVkObject(std::move(m_VulkanImage));
+ pDeviceVkImpl->SafeReleaseVkObject(std::move(m_ImageMemory));
}
-#if 0
- // Vk object can only be destroyed when it is no longer used by the GPU
- auto *pDeviceVkImpl = ValidatedCast<RenderDeviceVkImpl>(GetDevice());
- pDeviceVkImpl->SafeReleaseVkObject(m_pVkResource);
-#endif
}
void TextureVkImpl::UpdateData( IDeviceContext *pContext, Uint32 MipLevel, Uint32 Slice, const Box &DstBox, const TextureSubResData &SubresData )
diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanCommandBufferPool.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanCommandBufferPool.cpp
new file mode 100644
index 00000000..89214191
--- /dev/null
+++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanCommandBufferPool.cpp
@@ -0,0 +1,115 @@
+/* Copyright 2015-2018 Egor Yusov
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+*
+* In no event and under no legal theory, whether in tort (including negligence),
+* contract, or otherwise, unless required by applicable law (such as deliberate
+* and grossly negligent acts) or agreed to in writing, shall any Contributor be
+* liable for any damages, including any direct, indirect, special, incidental,
+* or consequential damages of any character arising as a result of this License or
+* out of the use or inability to use the software (including but not limited to damages
+* for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+* all other commercial damages or losses), even if such Contributor has been advised
+* of the possibility of such damages.
+*/
+#include <sstream>
+
+#include "VulkanUtilities/VulkanCommandBufferPool.h"
+#include "VulkanUtilities/VulkanDebug.h"
+#include "Errors.h"
+#include "DebugUtilities.h"
+#include "VulkanErrors.h"
+
+namespace VulkanUtilities
+{
+ VulkanCommandBufferPool::VulkanCommandBufferPool(std::shared_ptr<VulkanUtilities::VulkanLogicalDevice> LogicalDevice,
+ uint32_t queueFamilyIndex,
+ VkCommandPoolCreateFlags flags) :
+ m_LogicalDevice(LogicalDevice)
+ {
+ VkCommandPoolCreateInfo CmdPoolCI = {};
+ CmdPoolCI.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
+ CmdPoolCI.pNext = nullptr;
+ CmdPoolCI.queueFamilyIndex = queueFamilyIndex;
+ CmdPoolCI.flags = flags;
+ m_CmdPool = m_LogicalDevice->CreateCommandPool(CmdPoolCI);
+ VERIFY_EXPR(m_CmdPool != VK_NULL_HANDLE);
+ }
+
+ VulkanCommandBufferPool::~VulkanCommandBufferPool()
+ {
+ m_CmdPool.Release();
+ }
+
+ VkCommandBuffer VulkanCommandBufferPool::GetCommandBuffer(uint64_t LastCompletedFence, const char* DebugName)
+ {
+ VkCommandBuffer CmdBuffer = VK_NULL_HANDLE;
+
+ if (!m_DiscardedCmdBuffers.empty())
+ {
+ // Pick the oldest cmd buffer at the front of the deque
+ // If this buffer is not yet available, there is no point in
+ // looking at other buffers since they were released even
+ // later
+ auto& OldestBuff = m_DiscardedCmdBuffers.front();
+
+ // Note that LastCompletedFence only grows. So if after we queried
+ // the value, the actual value is increased in other thread, this will not
+ // be an issue as the only consequence is that potentially available
+ // cmd buffer may not be used.
+
+ // OldestBuff.first is the fence value that was signaled AFTER the
+ // command buffer has been submitted. If LastCompletedFence is at least
+ // this value, the buffer can be safely reused
+ if (LastCompletedFence >= OldestBuff.first)
+ {
+ CmdBuffer = OldestBuff.second;
+ auto err = vkResetCommandBuffer(CmdBuffer,
+ 0 // VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT - specifies that most or all memory resources currently owned by the command buffer should be returned to the parent command pool.
+ );
+ VERIFY(err == VK_SUCCESS, "Failed to reset command buffer");
+ m_DiscardedCmdBuffers.pop_front();
+ }
+ }
+
+ // If no allocators were ready to be reused, create a new one
+ if (CmdBuffer == VK_NULL_HANDLE)
+ {
+ VkCommandBufferAllocateInfo BuffAllocInfo = {};
+ BuffAllocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
+ BuffAllocInfo.pNext = nullptr;
+ BuffAllocInfo.commandPool = m_CmdPool;
+ BuffAllocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
+ BuffAllocInfo.commandBufferCount = 1;
+
+ CmdBuffer = m_LogicalDevice->AllocateVkCommandBuffer(BuffAllocInfo);
+ }
+
+ VkCommandBufferBeginInfo CmdBuffBeginInfo = {};
+ CmdBuffBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+ CmdBuffBeginInfo.pNext = nullptr;
+ CmdBuffBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; // Each recording of the command buffer will only be
+ // submitted once, and the command buffer will be reset
+ // and recorded again between each submission.
+ CmdBuffBeginInfo.pInheritanceInfo = nullptr; // Ignored for a primary command buffer
+ auto err = vkBeginCommandBuffer(CmdBuffer, &CmdBuffBeginInfo);
+ VERIFY(err == VK_SUCCESS, "Failed to begin command buffer");
+
+ return CmdBuffer;
+ }
+
+ void VulkanCommandBufferPool::DisposeCommandBuffer(VkCommandBuffer CmdBuffer, uint64_t FenceValue)
+ {
+ // FenceValue is the value that was signaled by the command queue after it
+ // executed the command buffer
+ m_DiscardedCmdBuffers.emplace_back(FenceValue, CmdBuffer);
+ }
+}
diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanDebug.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanDebug.cpp
index dabeef91..a66f267a 100644
--- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanDebug.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanDebug.cpp
@@ -187,6 +187,11 @@ namespace VulkanUtilities
// }
//}
+ void SetCommandPoolName(VkDevice device, VkCommandPool cmdPool, const char * name)
+ {
+ SetObjectName(device, (uint64_t)cmdPool, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT, name);
+ }
+
void SetCommandBufferName(VkDevice device, VkCommandBuffer cmdBuffer, const char * name)
{
SetObjectName(device, (uint64_t)cmdBuffer, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, name);
@@ -202,6 +207,11 @@ namespace VulkanUtilities
SetObjectName(device, (uint64_t)image, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, name);
}
+ void SetImageViewName(VkDevice device, VkImageView imageView, const char * name)
+ {
+ SetObjectName(device, (uint64_t)imageView, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT, name);
+ }
+
void SetSamplerName(VkDevice device, VkSampler sampler, const char * name)
{
SetObjectName(device, (uint64_t)sampler, VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT, name);
@@ -212,6 +222,11 @@ namespace VulkanUtilities
SetObjectName(device, (uint64_t)buffer, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, name);
}
+ void SetBufferViewName(VkDevice device, VkBufferView bufferView, const char * name)
+ {
+ SetObjectName(device, (uint64_t)bufferView, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT, name);
+ }
+
void SetDeviceMemoryName(VkDevice device, VkDeviceMemory memory, const char * name)
{
SetObjectName(device, (uint64_t)memory, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, name);
diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanFencePool.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanFencePool.cpp
new file mode 100644
index 00000000..eaf6bd7c
--- /dev/null
+++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanFencePool.cpp
@@ -0,0 +1,69 @@
+/* Copyright 2015-2018 Egor Yusov
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+*
+* In no event and under no legal theory, whether in tort (including negligence),
+* contract, or otherwise, unless required by applicable law (such as deliberate
+* and grossly negligent acts) or agreed to in writing, shall any Contributor be
+* liable for any damages, including any direct, indirect, special, incidental,
+* or consequential damages of any character arising as a result of this License or
+* out of the use or inability to use the software (including but not limited to damages
+* for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+* all other commercial damages or losses), even if such Contributor has been advised
+* of the possibility of such damages.
+*/
+#include <sstream>
+
+#include "VulkanUtilities/VulkanFencePool.h"
+#include "Errors.h"
+#include "DebugUtilities.h"
+
+namespace VulkanUtilities
+{
+ VulkanFencePool::VulkanFencePool(std::shared_ptr<const VulkanLogicalDevice> LogicalDevice) :
+ m_LogicalDevice(LogicalDevice)
+ {}
+
+ VulkanFencePool::~VulkanFencePool()
+ {
+ for(const auto &fence : m_Fences)
+ {
+ VERIFY(m_LogicalDevice->GetFenceStatus(fence) == VK_SUCCESS, "Destroying a fence that has not been signaled");
+ }
+ m_Fences.clear();
+ }
+
+ VulkanUtilities::FenceWrapper VulkanFencePool::GetFence()
+ {
+ VulkanUtilities::FenceWrapper Fence;
+ if(!m_Fences.empty())
+ {
+ Fence = std::move(m_Fences.back());
+ m_LogicalDevice->ResetFence(Fence);
+ m_Fences.pop_back();
+ }
+ else
+ {
+ VkFenceCreateInfo FenceCI = {};
+ FenceCI.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
+ FenceCI.pNext = nullptr;
+ FenceCI.flags = 0; // Available flag: VK_FENCE_CREATE_SIGNALED_BIT
+ Fence = m_LogicalDevice->CreateFence(FenceCI);
+ }
+ return Fence;
+ }
+
+ void VulkanFencePool::DisposeFence(VulkanUtilities::FenceWrapper&& Fence)
+ {
+ VERIFY(m_LogicalDevice->GetFenceStatus(Fence) == VK_SUCCESS, "Disposing a fence that has not been signaled");
+ m_Fences.emplace_back(std::move(Fence));
+ }
+}
diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp
index 4679b874..43c6d6cc 100644
--- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp
@@ -46,6 +46,15 @@ namespace VulkanUtilities
return false;
}
+ std::shared_ptr<VulkanInstance> VulkanInstance::Create(bool EnableValidation,
+ uint32_t GlobalExtensionCount,
+ const char* const* ppGlobalExtensionNames,
+ VkAllocationCallbacks* pVkAllocator)
+ {
+ auto Instance = new VulkanInstance(EnableValidation, GlobalExtensionCount, ppGlobalExtensionNames, pVkAllocator);
+ return std::shared_ptr<VulkanInstance>(Instance);
+ }
+
VulkanInstance::VulkanInstance(bool EnableValidation,
uint32_t GlobalExtensionCount,
const char* const* ppGlobalExtensionNames,
diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp
new file mode 100644
index 00000000..cc1370d0
--- /dev/null
+++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp
@@ -0,0 +1,292 @@
+/* Copyright 2015-2018 Egor Yusov
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+*
+* In no event and under no legal theory, whether in tort (including negligence),
+* contract, or otherwise, unless required by applicable law (such as deliberate
+* and grossly negligent acts) or agreed to in writing, shall any Contributor be
+* liable for any damages, including any direct, indirect, special, incidental,
+* or consequential damages of any character arising as a result of this License or
+* out of the use or inability to use the software (including but not limited to damages
+* for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+* all other commercial damages or losses), even if such Contributor has been advised
+* of the possibility of such damages.
+*/
+
+#include <limits>
+#include "VulkanErrors.h"
+#include "VulkanUtilities/VulkanLogicalDevice.h"
+#include "VulkanUtilities/VulkanDebug.h"
+
+namespace VulkanUtilities
+{
+ std::shared_ptr<VulkanLogicalDevice> VulkanLogicalDevice::Create(VkPhysicalDevice vkPhysicalDevice,
+ const VkDeviceCreateInfo &DeviceCI,
+ const VkAllocationCallbacks* vkAllocator,
+ bool EnableDebugMarkers)
+ {
+ auto *LogicalDevice = new VulkanLogicalDevice(vkPhysicalDevice, DeviceCI, vkAllocator, EnableDebugMarkers);
+ return std::shared_ptr<VulkanLogicalDevice>(LogicalDevice);
+ }
+
+ VulkanLogicalDevice::~VulkanLogicalDevice()
+ {
+ vkDestroyDevice(m_VkDevice, m_VkAllocator);
+ }
+
+ VulkanLogicalDevice::VulkanLogicalDevice(VkPhysicalDevice vkPhysicalDevice,
+ const VkDeviceCreateInfo &DeviceCI,
+ const VkAllocationCallbacks* vkAllocator,
+ bool EnableDebugMarkers) :
+ m_VkAllocator(vkAllocator)
+ {
+ auto res = vkCreateDevice(vkPhysicalDevice, &DeviceCI, vkAllocator, &m_VkDevice);
+ CHECK_VK_ERROR_AND_THROW(res, "Failed to create logical device");
+
+ if (EnableDebugMarkers)
+ {
+ VulkanUtilities::SetupDebugMarkers(m_VkDevice);
+ }
+ }
+
+ VkQueue VulkanLogicalDevice::GetQueue(uint32_t queueFamilyIndex, uint32_t queueIndex)
+ {
+ VkQueue vkQueue = VK_NULL_HANDLE;
+ vkGetDeviceQueue(m_VkDevice,
+ queueFamilyIndex, // Index of the queue family to which the queue belongs
+ 0, // Index within this queue family of the queue to retrieve
+ &vkQueue);
+ VERIFY_EXPR(vkQueue != VK_NULL_HANDLE);
+ return vkQueue;
+ }
+
+ void VulkanLogicalDevice::WaitIdle()const
+ {
+ auto err = vkDeviceWaitIdle(m_VkDevice);
+ VERIFY_EXPR(err == VK_SUCCESS);
+ }
+
+ CommandPoolWrapper VulkanLogicalDevice::CreateCommandPool(const VkCommandPoolCreateInfo &CmdPoolCI,
+ const char *DebugName) const
+ {
+ if(DebugName == nullptr)
+ DebugName = "";
+
+ VkCommandPool CmdPool = VK_NULL_HANDLE;
+ auto err = vkCreateCommandPool(m_VkDevice, &CmdPoolCI, m_VkAllocator, &CmdPool);
+ CHECK_VK_ERROR_AND_THROW(err, "Failed to create Vulkan command pool '", DebugName, '\'');
+
+ if(DebugName != nullptr && *DebugName != 0)
+ VulkanUtilities::SetCommandPoolName(m_VkDevice, CmdPool, DebugName);
+
+ return CommandPoolWrapper{ GetSharedPtr(), CmdPool};
+ }
+
+ BufferWrapper VulkanLogicalDevice::CreateBuffer(const VkBufferCreateInfo &BufferCI,
+ const char *DebugName)const
+ {
+ if (DebugName == nullptr)
+ DebugName = "";
+
+ VkBuffer vkBuffer = VK_NULL_HANDLE;
+ auto err = vkCreateBuffer(m_VkDevice, &BufferCI, m_VkAllocator, &vkBuffer);
+ CHECK_VK_ERROR_AND_THROW(err, "Failed to create Vulkan buffer '", DebugName, '\'');
+
+ if (DebugName != nullptr && *DebugName != 0)
+ VulkanUtilities::SetBufferName(m_VkDevice, vkBuffer, DebugName);
+
+ return BufferWrapper{ GetSharedPtr(), vkBuffer };
+ }
+
+ BufferViewWrapper VulkanLogicalDevice::CreateBufferView(const VkBufferViewCreateInfo &BuffViewCI,
+ const char *DebugName)const
+ {
+ if (DebugName == nullptr)
+ DebugName = "";
+
+ VkBufferView vkBufferView = VK_NULL_HANDLE;
+ auto err = vkCreateBufferView(m_VkDevice, &BuffViewCI, m_VkAllocator, &vkBufferView);
+ CHECK_VK_ERROR_AND_THROW(err, "Failed to create Vulkan buffer view '", DebugName, '\'');
+
+ if (DebugName != nullptr && *DebugName != 0)
+ VulkanUtilities::SetBufferViewName(m_VkDevice, vkBufferView, DebugName);
+
+ return BufferViewWrapper{ GetSharedPtr(), vkBufferView };
+ }
+
+ ImageWrapper VulkanLogicalDevice::CreateImage(const VkImageCreateInfo &ImageCI,
+ const char *DebugName)const
+ {
+ if (DebugName == nullptr)
+ DebugName = "";
+
+ VkImage vkImage = VK_NULL_HANDLE;
+ auto err = vkCreateImage(m_VkDevice, &ImageCI, m_VkAllocator, &vkImage);
+ CHECK_VK_ERROR_AND_THROW(err, "Failed to create Vulkan image '", DebugName, '\'');
+
+ if (DebugName != nullptr && *DebugName != 0)
+ VulkanUtilities::SetImageName(m_VkDevice, vkImage, DebugName);
+
+ return ImageWrapper{ GetSharedPtr(), vkImage };
+ }
+
+ ImageViewWrapper VulkanLogicalDevice::CreateImageView(const VkImageViewCreateInfo &ImageViewCI,
+ const char *DebugName)const
+ {
+ if (DebugName == nullptr)
+ DebugName = "";
+
+ VkImageView vkImageView = VK_NULL_HANDLE;
+ auto err = vkCreateImageView(m_VkDevice, &ImageViewCI, m_VkAllocator, &vkImageView);
+ CHECK_VK_ERROR_AND_THROW(err, "Failed to create Vulkan image view '", DebugName, '\'');
+
+ if (DebugName != nullptr && *DebugName != 0)
+ VulkanUtilities::SetImageViewName(m_VkDevice, vkImageView, DebugName);
+
+ return ImageViewWrapper{ GetSharedPtr(), vkImageView };
+ }
+
+ FenceWrapper VulkanLogicalDevice::CreateFence(const VkFenceCreateInfo &FenceCI, const char *DebugName)const
+ {
+ if (DebugName == nullptr)
+ DebugName = "";
+
+ VkFence vkFence = VK_NULL_HANDLE;
+ auto err = vkCreateFence(m_VkDevice, &FenceCI, m_VkAllocator, &vkFence);
+ CHECK_VK_ERROR_AND_THROW(err, "Failed to create fence '", DebugName, '\'');
+
+ if (DebugName != nullptr && *DebugName != 0)
+ VulkanUtilities::SetFenceName(m_VkDevice, vkFence, DebugName);
+
+ return FenceWrapper{ GetSharedPtr(), vkFence };
+ }
+
+ DeviceMemoryWrapper VulkanLogicalDevice::AllocateDeviceMemory(const VkMemoryAllocateInfo &AllocInfo,
+ const char *DebugName)const
+ {
+ if (DebugName == nullptr)
+ DebugName = "";
+
+ VkDeviceMemory vkDeviceMem = VK_NULL_HANDLE;
+
+ auto err = vkAllocateMemory(m_VkDevice, &AllocInfo, m_VkAllocator, &vkDeviceMem);
+ CHECK_VK_ERROR_AND_THROW(err, "Failed to allocate device memory '", DebugName, '\'');
+
+ if (DebugName != nullptr && *DebugName != 0)
+ VulkanUtilities::SetDeviceMemoryName(m_VkDevice, vkDeviceMem, DebugName);
+
+ return DeviceMemoryWrapper{ GetSharedPtr(), vkDeviceMem };
+ }
+
+
+ VkCommandBuffer VulkanLogicalDevice::AllocateVkCommandBuffer(const VkCommandBufferAllocateInfo &AllocInfo, const char *DebugName)const
+ {
+ if (DebugName == nullptr)
+ DebugName = "";
+
+ VkCommandBuffer CmdBuff = VK_NULL_HANDLE;
+ auto err = vkAllocateCommandBuffers(m_VkDevice, &AllocInfo, &CmdBuff);
+ VERIFY(err == VK_SUCCESS, "Failed to allocate command buffer '", DebugName, '\'');
+
+ if (DebugName != nullptr && *DebugName != 0)
+ SetCommandBufferName(m_VkDevice, CmdBuff, DebugName);
+
+ return CmdBuff;
+ }
+
+ void VulkanLogicalDevice::ReleaseVulkanObject(CommandPoolWrapper &&CmdPool)const
+ {
+ vkDestroyCommandPool(m_VkDevice, CmdPool.m_VkObject, m_VkAllocator);
+ CmdPool.m_VkObject = VK_NULL_HANDLE;
+ }
+
+ void VulkanLogicalDevice::ReleaseVulkanObject(BufferWrapper&& Buffer)const
+ {
+ vkDestroyBuffer(m_VkDevice, Buffer.m_VkObject, m_VkAllocator);
+ Buffer.m_VkObject = VK_NULL_HANDLE;
+ }
+
+ void VulkanLogicalDevice::ReleaseVulkanObject(BufferViewWrapper&& BufferView)const
+ {
+ vkDestroyBufferView(m_VkDevice, BufferView.m_VkObject, m_VkAllocator);
+ BufferView.m_VkObject = VK_NULL_HANDLE;
+ }
+
+ void VulkanLogicalDevice::ReleaseVulkanObject(ImageWrapper&& Image)const
+ {
+ vkDestroyImage(m_VkDevice, Image.m_VkObject, m_VkAllocator);
+ Image.m_VkObject = VK_NULL_HANDLE;
+ }
+
+ void VulkanLogicalDevice::ReleaseVulkanObject(ImageViewWrapper&& ImageView)const
+ {
+ vkDestroyImageView(m_VkDevice, ImageView.m_VkObject, m_VkAllocator);
+ ImageView.m_VkObject = VK_NULL_HANDLE;
+ }
+
+ void VulkanLogicalDevice::ReleaseVulkanObject(FenceWrapper&& Fence)const
+ {
+ vkDestroyFence(m_VkDevice, Fence.m_VkObject, m_VkAllocator);
+ Fence.m_VkObject = VK_NULL_HANDLE;
+ }
+
+ void VulkanLogicalDevice::ReleaseVulkanObject(DeviceMemoryWrapper&& Memory)const
+ {
+ vkFreeMemory(m_VkDevice, Memory.m_VkObject, m_VkAllocator);
+ Memory.m_VkObject = VK_NULL_HANDLE;
+ }
+
+ VkMemoryRequirements VulkanLogicalDevice::GetBufferMemoryRequirements(VkBuffer vkBuffer)const
+ {
+ VkMemoryRequirements MemReqs = {};
+ vkGetBufferMemoryRequirements(m_VkDevice, vkBuffer, &MemReqs);
+ return MemReqs;
+ }
+
+ VkMemoryRequirements VulkanLogicalDevice::GetImageMemoryRequirements(VkImage vkImage)const
+ {
+ VkMemoryRequirements MemReqs = {};
+ vkGetImageMemoryRequirements(m_VkDevice, vkImage, &MemReqs);
+ return MemReqs;
+ }
+
+ VkResult VulkanLogicalDevice::BindBufferMemory(VkBuffer buffer, VkDeviceMemory memory, VkDeviceSize memoryOffset)const
+ {
+ return vkBindBufferMemory(m_VkDevice, buffer, memory, memoryOffset);
+ }
+
+ VkResult VulkanLogicalDevice::BindImageMemory(VkImage image, VkDeviceMemory memory, VkDeviceSize memoryOffset)const
+ {
+ return vkBindImageMemory(m_VkDevice, image, memory, memoryOffset);
+ }
+
+ VkResult VulkanLogicalDevice::MapMemory(VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void** ppData)const
+ {
+ return vkMapMemory(m_VkDevice, memory, offset, size, flags, ppData);
+ }
+
+ void VulkanLogicalDevice::UnmapMemory(VkDeviceMemory memory)const
+ {
+ vkUnmapMemory(m_VkDevice, memory);
+ }
+
+ VkResult VulkanLogicalDevice::GetFenceStatus(VkFence fence)const
+ {
+ return vkGetFenceStatus(m_VkDevice, fence);
+ }
+
+ VkResult VulkanLogicalDevice::ResetFence(VkFence fence)const
+ {
+ auto err = vkResetFences(m_VkDevice, 1, &fence);
+ VERIFY(err == VK_SUCCESS, "Failed to reset fence");
+ return err;
+ }
+}
diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp
index f09dd271..26f5e18a 100644
--- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp
@@ -27,6 +27,12 @@
namespace VulkanUtilities
{
+ std::unique_ptr<VulkanPhysicalDevice> VulkanPhysicalDevice::Create(VkPhysicalDevice vkDevice)
+ {
+ auto *PhysicalDevice = new VulkanPhysicalDevice(vkDevice);
+ return std::unique_ptr<VulkanPhysicalDevice>(PhysicalDevice);
+ }
+
VulkanPhysicalDevice::VulkanPhysicalDevice(VkPhysicalDevice vkDevice) :
m_VkDevice(vkDevice)
{