summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngineVulkan
diff options
context:
space:
mode:
authorEgor Yusov <egor.yusov@gmail.com>2018-04-21 02:27:11 +0000
committerEgor Yusov <egor.yusov@gmail.com>2018-04-21 02:27:11 +0000
commitfadc28867982ec4088fa323d7702ba124a07df35 (patch)
tree7e376510434bc71df07924cd51ccd2a54a47dd45 /Graphics/GraphicsEngineVulkan
parentAdded CreateSemaphore to VulkanLogicalDevice (diff)
downloadDiligentCore-fadc28867982ec4088fa323d7702ba124a07df35.tar.gz
DiligentCore-fadc28867982ec4088fa323d7702ba124a07df35.zip
Implemented present in Vulkan swap chain; implemented clear color & depth outside of render pass
Diffstat (limited to 'Graphics/GraphicsEngineVulkan')
-rw-r--r--Graphics/GraphicsEngineVulkan/include/CommandQueueVkImpl.h2
-rw-r--r--Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.h14
-rw-r--r--Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.h1
-rw-r--r--Graphics/GraphicsEngineVulkan/include/SwapChainVkImpl.h12
-rw-r--r--Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.h6
-rw-r--r--Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanObjectWrappers.h1
-rw-r--r--Graphics/GraphicsEngineVulkan/interface/CommandQueueVk.h5
-rw-r--r--Graphics/GraphicsEngineVulkan/interface/SwapChainVk.h14
-rw-r--r--Graphics/GraphicsEngineVulkan/src/CommandQueueVkImpl.cpp28
-rw-r--r--Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp121
-rw-r--r--Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp12
-rw-r--r--Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp92
-rw-r--r--Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanCommandBuffer.cpp12
13 files changed, 248 insertions, 72 deletions
diff --git a/Graphics/GraphicsEngineVulkan/include/CommandQueueVkImpl.h b/Graphics/GraphicsEngineVulkan/include/CommandQueueVkImpl.h
index bf8a2866..99db417c 100644
--- a/Graphics/GraphicsEngineVulkan/include/CommandQueueVkImpl.h
+++ b/Graphics/GraphicsEngineVulkan/include/CommandQueueVkImpl.h
@@ -56,6 +56,8 @@ public:
// Executes a given command buffer
virtual Uint64 ExecuteCommandBuffer(VkCommandBuffer cmdBuffer)override final;
+ virtual Uint64 ExecuteCommandBuffer(const VkSubmitInfo& SubmitInfo)override final;
+
virtual VkQueue GetVkQueue()override final{return m_VkQueue;}
virtual uint32_t GetQueueFamilyIndex()override final { return m_QueueFamilyIndex; }
diff --git a/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.h b/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.h
index 56ee55f5..82b94413 100644
--- a/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.h
+++ b/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.h
@@ -88,6 +88,16 @@ public:
virtual void TransitionImageLayout(ITexture *pTexture, VkImageLayout NewLayout)override final;
+ void AddWaitSemaphore(VkSemaphore Semaphore, VkPipelineStageFlags WaitDstStageMask)
+ {
+ m_WaitSemaphores.push_back(Semaphore);
+ m_WaitDstStageMasks.push_back(WaitDstStageMask);
+ }
+ void AddSignalSemaphore(VkSemaphore Semaphore)
+ {
+ m_SignalSemaphores.push_back(Semaphore);
+ }
+
#if 0
virtual void TransitionBufferState(IBuffer *pBuffer, Vk_RESOURCE_STATES State)override final;
@@ -162,6 +172,10 @@ private:
const Uint32 m_ContextId;
#endif
VulkanUtilities::VulkanCommandBufferPool m_CmdPool;
+
+ std::vector<VkSemaphore> m_WaitSemaphores;
+ std::vector<VkPipelineStageFlags> m_WaitDstStageMasks;
+ std::vector<VkSemaphore> m_SignalSemaphores;
};
}
diff --git a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.h b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.h
index 471ed78c..5751b35b 100644
--- a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.h
+++ b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.h
@@ -98,6 +98,7 @@ public:
void IdleGPU(bool ReleaseStaleObjects);
VkCommandBuffer AllocateCommandBuffer(const Char *DebugName = nullptr);
+ void ExecuteCommandBuffer(const VkSubmitInfo &SubmitInfo, bool DiscardStaleObjects);
void ExecuteCommandBuffer(VkCommandBuffer CmdBuff, bool DiscardStaleObjects);
void DisposeCommandBuffer(VkCommandBuffer CmdBuff);
diff --git a/Graphics/GraphicsEngineVulkan/include/SwapChainVkImpl.h b/Graphics/GraphicsEngineVulkan/include/SwapChainVkImpl.h
index e8304c94..d5832b79 100644
--- a/Graphics/GraphicsEngineVulkan/include/SwapChainVkImpl.h
+++ b/Graphics/GraphicsEngineVulkan/include/SwapChainVkImpl.h
@@ -29,6 +29,7 @@
#include "SwapChainVk.h"
#include "SwapChainBase.h"
#include "VulkanUtilities/VulkanInstance.h"
+#include "VulkanUtilities/VulkanObjectWrappers.h"
namespace Diligent
{
@@ -56,23 +57,26 @@ public:
virtual void SetWindowedMode()override final;
-/*
- virtual IDXGISwapChain* GetDXGISwapChain()override final{ return m_pSwapChain; }
+ virtual VkSwapchainKHR GetVkSwapChain()override final{ return m_VkSwapChain; }
virtual ITextureViewVk* GetCurrentBackBufferRTV()override final;
virtual ITextureViewVk* GetDepthBufferDSV()override final{return m_pDepthBufferDSV;}
- */
+
private:
void CreateVulkanSwapChain();
void InitBuffersAndViews();
+ void AcquireNextImage(DeviceContextVkImpl *pDeviceCtxVk);
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;
+ std::vector<VulkanUtilities::SemaphoreWrapper> m_ImageAcquiredSemaphores;
+ std::vector<VulkanUtilities::SemaphoreWrapper> m_DrawCompleteSemaphores;
std::vector< RefCntAutoPtr<ITextureViewVk>, STDAllocatorRawMem<RefCntAutoPtr<ITextureViewVk>> > m_pBackBufferRTV;
RefCntAutoPtr<ITextureViewVk> m_pDepthBufferDSV;
-
+ Uint32 m_SemaphoreIndex = 0;
+ uint32_t m_BackBufferIndex = 0;
};
}
diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.h b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.h
index 9d800f48..90341766 100644
--- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.h
+++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.h
@@ -179,6 +179,12 @@ namespace VulkanUtilities
m_State.Framebuffer = VK_NULL_HANDLE;
}
+ void EndCommandBuffer()
+ {
+ VERIFY_EXPR(m_VkCmdBuffer != VK_NULL_HANDLE);
+ vkEndCommandBuffer(m_VkCmdBuffer);
+ }
+
void Reset()
{
m_VkCmdBuffer = VK_NULL_HANDLE;
diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanObjectWrappers.h b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanObjectWrappers.h
index 783a1e66..5507d94e 100644
--- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanObjectWrappers.h
+++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanObjectWrappers.h
@@ -56,6 +56,7 @@ namespace VulkanUtilities
}
VulkanObjectWrapper& operator = (VulkanObjectWrapper&& rhs)
{
+ Release();
m_pLogicalDevice = std::move(rhs.m_pLogicalDevice);
m_VkObject = rhs.m_VkObject;
rhs.m_VkObject = VK_NULL_HANDLE;
diff --git a/Graphics/GraphicsEngineVulkan/interface/CommandQueueVk.h b/Graphics/GraphicsEngineVulkan/interface/CommandQueueVk.h
index 9ed10106..ca1a4acc 100644
--- a/Graphics/GraphicsEngineVulkan/interface/CommandQueueVk.h
+++ b/Graphics/GraphicsEngineVulkan/interface/CommandQueueVk.h
@@ -48,6 +48,11 @@ public:
/// \return Fence value associated with the executed command buffer
virtual Uint64 ExecuteCommandBuffer(VkCommandBuffer cmdBuffer) = 0;
+ /// Submits a given chunk of work to the command queue
+
+ /// \return Fence value associated with the executed command buffer
+ virtual Uint64 ExecuteCommandBuffer(const VkSubmitInfo& SubmitInfo) = 0;
+
/// Returns Vulkan command queue. May return VK_NULL_HANDLE if queue is anavailable
virtual VkQueue GetVkQueue() = 0;
diff --git a/Graphics/GraphicsEngineVulkan/interface/SwapChainVk.h b/Graphics/GraphicsEngineVulkan/interface/SwapChainVk.h
index 77b1a7b2..89294efb 100644
--- a/Graphics/GraphicsEngineVulkan/interface/SwapChainVk.h
+++ b/Graphics/GraphicsEngineVulkan/interface/SwapChainVk.h
@@ -43,23 +43,17 @@ class ISwapChainVk : public ISwapChain
{
public:
- /// Returns a pointer to the IDXGISwapChain interface of the internal DXGI object.
-
- /// The method does *NOT* call AddRef() on the returned interface,
- /// so Release() must not be called.
- //virtual IDXGISwapChain *GetDXGISwapChain() = 0;
+ /// Returns a handle to the Vulkan swap chain object.
+ virtual VkSwapchainKHR GetVkSwapChain() = 0;
/// Returns a pointer to the render target view of the current back buffer in the swap chain
-
- /// The method does *NOT* call AddRef() on the returned interface,
- /// so Release() must not be called.
- //virtual ITextureViewD3D12* GetCurrentBackBufferRTV() = 0;
+ virtual ITextureViewVk* GetCurrentBackBufferRTV() = 0;
/// Returns a pointer to the depth-stencil view of the depth buffer
/// The method does *NOT* call AddRef() on the returned interface,
/// so Release() must not be called.
- //virtual ITextureViewD3D12* GetDepthBufferDSV() = 0;
+ virtual ITextureViewVk* GetDepthBufferDSV() = 0;
};
}
diff --git a/Graphics/GraphicsEngineVulkan/src/CommandQueueVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/CommandQueueVkImpl.cpp
index b25c412c..99ff89e8 100644
--- a/Graphics/GraphicsEngineVulkan/src/CommandQueueVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/CommandQueueVkImpl.cpp
@@ -55,10 +55,24 @@ CommandQueueVkImpl::~CommandQueueVkImpl()
IMPLEMENT_QUERY_INTERFACE( CommandQueueVkImpl, IID_CommandQueueVk, TBase )
-Uint64 CommandQueueVkImpl::ExecuteCommandBuffer(VkCommandBuffer cmdBuffer)
+Uint64 CommandQueueVkImpl::ExecuteCommandBuffer(const VkSubmitInfo& SubmitInfo)
{
std::lock_guard<std::mutex> Lock(m_QueueMutex);
+ 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;
+ m_PendingFences.emplace_back(FenceValue, std::move(Fence));
+
+ // Increment the value
+ Atomics::AtomicIncrement(m_NextFenceValue);
+ return FenceValue;
+}
+Uint64 CommandQueueVkImpl::ExecuteCommandBuffer(VkCommandBuffer cmdBuffer)
+{
VkSubmitInfo SubmitInfo = {};
SubmitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
SubmitInfo.commandBufferCount = 1;
@@ -73,17 +87,7 @@ Uint64 CommandQueueVkImpl::ExecuteCommandBuffer(VkCommandBuffer cmdBuffer)
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;
- m_PendingFences.emplace_back(FenceValue, std::move(Fence));
-
- // Increment the value
- Atomics::AtomicIncrement(m_NextFenceValue);
- return FenceValue;
+ return ExecuteCommandBuffer(SubmitInfo);
}
void CommandQueueVkImpl::IdleGPU()
diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
index 42ded191..91b058e9 100644
--- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
@@ -492,13 +492,12 @@ namespace Diligent
void DeviceContextVkImpl::ClearDepthStencil( ITextureView *pView, Uint32 ClearFlags, float fDepth, Uint8 Stencil )
{
-#if 0
- ITextureViewVk *pDSVVk = nullptr;
+ ITextureViewVk *pVkDSV = nullptr;
if( pView != nullptr )
{
- pDSVVk = ValidatedCast<ITextureViewVk>(pView);
+ pVkDSV = ValidatedCast<ITextureViewVk>(pView);
#ifdef _DEBUG
- const auto& ViewDesc = pDSVVk->GetDesc();
+ const auto& ViewDesc = pVkDSV->GetDesc();
VERIFY( ViewDesc.ViewType == TEXTURE_VIEW_DEPTH_STENCIL, "Incorrect view type: depth stencil is expected" );
#endif
}
@@ -506,7 +505,7 @@ namespace Diligent
{
if (m_pSwapChain)
{
- pDSVVk = m_pSwapChain.RawPtr<ISwapChainVk>()->GetDepthBufferDSV();
+ pVkDSV = m_pSwapChain.RawPtr<ISwapChainVk>()->GetDepthBufferDSV();
}
else
{
@@ -514,19 +513,62 @@ namespace Diligent
return;
}
}
- Vk_CLEAR_FLAGS VkClearFlags = (Vk_CLEAR_FLAGS)0;
- if( ClearFlags & CLEAR_DEPTH_FLAG ) VkClearFlags |= Vk_CLEAR_FLAG_DEPTH;
- if( ClearFlags & CLEAR_STENCIL_FLAG ) VkClearFlags |= Vk_CLEAR_FLAG_STENCIL;
- // The full extent of the resource view is always cleared.
- // Viewport and scissor settings are not applied??
- RequestCmdContext()->AsGraphicsContext().ClearDepthStencil( pDSVVk, VkClearFlags, fDepth, Stencil );
-#endif
+
+ auto *pTexture = pVkDSV->GetTexture();
+ auto *pTextureVk = ValidatedCast<TextureVkImpl>(pTexture);
+ const auto &ViewDesc = pVkDSV->GetDesc();
+ EnsureVkCmdBuffer();
+ if(m_CommandBuffer.GetState().RenderPass != VK_NULL_HANDLE)
+ {
+ UNSUPPORTED("Not yet implemented");
+ }
+ else
+ {
+ // Image layout must be VK_IMAGE_LAYOUT_GENERAL or VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL (17.1)
+ TransitionImageLayout(pTexture, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
+ VkClearDepthStencilValue ClearValue;
+ ClearValue.depth = fDepth;
+ ClearValue.stencil = Stencil;
+ VkImageSubresourceRange Subresource;
+ Subresource.aspectMask = 0;
+ if (ClearFlags & CLEAR_DEPTH_FLAG) Subresource.aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
+ if (ClearFlags & CLEAR_STENCIL_FLAG) Subresource.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
+ Subresource.baseArrayLayer = ViewDesc.FirstArraySlice;
+ Subresource.layerCount = ViewDesc.NumArraySlices;
+ Subresource.baseMipLevel = ViewDesc.MostDetailedMip;
+ Subresource.levelCount = ViewDesc.NumMipLevels;
+
+ m_CommandBuffer.ClearDepthStencilImage(pTextureVk->GetVkImage(), ClearValue, Subresource);
+ }
+
++m_State.NumCommands;
}
+ VkClearColorValue ClearValueToVkClearValue(const float *RGBA, TEXTURE_FORMAT TexFmt)
+ {
+ VkClearColorValue ClearValue;
+ const auto& FmtAttribs = GetTextureFormatAttribs(TexFmt);
+ if(FmtAttribs.ComponentType == COMPONENT_TYPE_SINT)
+ {
+ for(int i=0; i < 4; ++i)
+ ClearValue.int32[i] = static_cast<int32_t>(RGBA[i]);
+ }
+ else if (FmtAttribs.ComponentType == COMPONENT_TYPE_UINT)
+ {
+ for (int i = 0; i < 4; ++i)
+ ClearValue.uint32[i] = static_cast<uint32_t>(RGBA[i]);
+ }
+ else
+ {
+ for (int i = 0; i < 4; ++i)
+ ClearValue.float32[i] = RGBA[i];
+ }
+
+ return ClearValue;
+ }
+
void DeviceContextVkImpl::ClearRenderTarget( ITextureView *pView, const float *RGBA )
{
-#if 0
ITextureViewVk *pVkRTV = nullptr;
if( pView != nullptr )
{
@@ -552,11 +594,30 @@ namespace Diligent
static constexpr float Zero[4] = { 0.f, 0.f, 0.f, 0.f };
if( RGBA == nullptr )
RGBA = Zero;
+
+ auto *pTexture = pVkRTV->GetTexture();
+ auto *pTextureVk = ValidatedCast<TextureVkImpl>(pTexture);
+ const auto &ViewDesc = pVkRTV->GetDesc();
+ EnsureVkCmdBuffer();
+ if(m_CommandBuffer.GetState().RenderPass != VK_NULL_HANDLE)
+ {
+ UNSUPPORTED("Not yet implemented");
+ }
+ else
+ {
+ // Image layout must be VK_IMAGE_LAYOUT_GENERAL or VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL (17.1)
+ TransitionImageLayout(pTexture, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
+ auto ClearValue = ClearValueToVkClearValue(RGBA, ViewDesc.Format);
+ VkImageSubresourceRange Subresource;
+ Subresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ Subresource.baseArrayLayer = ViewDesc.FirstArraySlice;
+ Subresource.layerCount = ViewDesc.NumArraySlices;
+ Subresource.baseMipLevel = ViewDesc.MostDetailedMip;
+ Subresource.levelCount = ViewDesc.NumMipLevels;
+
+ m_CommandBuffer.ClearColorImage(pTextureVk->GetVkImage(), ClearValue, Subresource);
+ }
- // The full extent of the resource view is always cleared.
- // Viewport and scissor settings are not applied??
- RequestCmdContext()->AsGraphicsContext().ClearRenderTarget( pVkRTV, RGBA );
-#endif
++m_State.NumCommands;
}
@@ -571,8 +632,30 @@ namespace Diligent
VERIFY(!m_bIsDeferred, "Deferred contexts cannot execute command lists directly");
if (m_State.NumCommands != 0)
{
- //m_pCurrCmdCtx->FlushResourceBarriers();
- pDeviceVkImpl->ExecuteCommandBuffer(vkCmdBuff, true);
+ if (m_CommandBuffer.GetState().RenderPass != VK_NULL_HANDLE)
+ {
+ m_CommandBuffer.EndRenderPass();
+ }
+
+ m_CommandBuffer.FlushBarriers();
+ m_CommandBuffer.EndCommandBuffer();
+
+ VkSubmitInfo SubmitInfo = {};
+ SubmitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+ SubmitInfo.pNext = nullptr;
+ SubmitInfo.waitSemaphoreCount = static_cast<uint32_t>(m_WaitSemaphores.size());
+ VERIFY_EXPR(m_WaitSemaphores.size() == m_WaitDstStageMasks.size());
+ SubmitInfo.pWaitSemaphores = SubmitInfo.waitSemaphoreCount != 0 ? m_WaitSemaphores.data() : nullptr;
+ SubmitInfo.pWaitDstStageMask = SubmitInfo.waitSemaphoreCount != 0 ? m_WaitDstStageMasks.data() : nullptr;
+ SubmitInfo.commandBufferCount = 1;
+ SubmitInfo.pCommandBuffers = &vkCmdBuff;
+ SubmitInfo.signalSemaphoreCount = static_cast<uint32_t>(m_SignalSemaphores.size());
+ SubmitInfo.pSignalSemaphores = SubmitInfo.signalSemaphoreCount != 0 ? m_SignalSemaphores.data() : nullptr;
+ pDeviceVkImpl->ExecuteCommandBuffer(SubmitInfo, true);
+
+ m_WaitSemaphores.clear();
+ m_WaitDstStageMasks.clear();
+ m_SignalSemaphores.clear();
}
DisposeVkCmdBuffer();
}
diff --git a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp
index 0992c17f..6d370ca0 100644
--- a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp
@@ -129,13 +129,23 @@ void RenderDeviceVkImpl::ExecuteCommandBuffer(VkCommandBuffer CmdBuff, bool Disc
auto err = vkEndCommandBuffer(CmdBuff);
VERIFY(err == VK_SUCCESS, "Failed to end command buffer");
+ VkSubmitInfo SubmitInfo = {};
+ SubmitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+ SubmitInfo.commandBufferCount = 1;
+ SubmitInfo.pCommandBuffers = &CmdBuff;
+ ExecuteCommandBuffer(SubmitInfo, DiscardStaleObjects);
+}
+
+
+void RenderDeviceVkImpl::ExecuteCommandBuffer(const VkSubmitInfo &SubmitInfo, bool DiscardStaleObjects)
+{
Uint64 FenceValue = 0;
Uint64 CmdListNumber = 0;
{
std::lock_guard<std::mutex> LockGuard(m_CmdQueueMutex);
auto NextFenceValue = m_pCommandQueue->GetNextFenceValue();
// Submit the command list to the queue
- FenceValue = m_pCommandQueue->ExecuteCommandBuffer(CmdBuff);
+ FenceValue = m_pCommandQueue->ExecuteCommandBuffer(SubmitInfo);
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;
diff --git a/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp
index 0dfe082b..2b02a874 100644
--- a/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp
@@ -94,6 +94,7 @@ SwapChainVkImpl::SwapChainVkImpl(IReferenceCounters *pRefCounters,
CreateVulkanSwapChain();
InitBuffersAndViews();
+ AcquireNextImage(pDeviceContextVk);
}
void SwapChainVkImpl::CreateVulkanSwapChain()
@@ -263,7 +264,9 @@ void SwapChainVkImpl::CreateVulkanSwapChain()
swapchain_ci.oldSwapchain = oldSwapchain;
swapchain_ci.clipped = VK_TRUE;
swapchain_ci.imageColorSpace = ColorSpace;
- swapchain_ci.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+ swapchain_ci.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
+ // vkCmdClearColorImage() command requires the image to use VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL layout
+ // that requires VK_IMAGE_USAGE_TRANSFER_DST_BIT to be set
swapchain_ci.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
swapchain_ci.queueFamilyIndexCount = 0;
swapchain_ci.pQueueFamilyIndices = NULL;
@@ -278,17 +281,18 @@ void SwapChainVkImpl::CreateVulkanSwapChain()
// swapchain_ci.pQueueFamilyIndices = queueFamilyIndices;
//}
- auto LogicalVkDevice = pRenderDeviceVk->GetVkDevice();
- err = vkCreateSwapchainKHR(LogicalVkDevice, &swapchain_ci, NULL, &m_VkSwapChain);
+ const auto& LogicalDevice = pRenderDeviceVk->GetLogicalDevice();
+ auto vkDevice = pRenderDeviceVk->GetVkDevice();
+ err = vkCreateSwapchainKHR(vkDevice, &swapchain_ci, NULL, &m_VkSwapChain);
CHECK_VK_ERROR_AND_THROW(err, "Failed to create Vulkan swapchain");
if(oldSwapchain != VK_NULL_HANDLE)
{
- vkDestroySwapchainKHR(LogicalVkDevice, oldSwapchain, NULL);
+ vkDestroySwapchainKHR(vkDevice, oldSwapchain, NULL);
}
uint32_t swapchainImageCount = 0;
- err = vkGetSwapchainImagesKHR(LogicalVkDevice, m_VkSwapChain, &swapchainImageCount, NULL);
+ err = vkGetSwapchainImagesKHR(vkDevice, m_VkSwapChain, &swapchainImageCount, NULL);
CHECK_VK_ERROR_AND_THROW(err, "Failed to request swap chain image count");
VERIFY_EXPR(swapchainImageCount > 0);
if (swapchainImageCount != m_SwapChainDesc.BufferCount)
@@ -296,6 +300,18 @@ void SwapChainVkImpl::CreateVulkanSwapChain()
LOG_INFO_MESSAGE("Actual number of images in the created swap chain: ", m_SwapChainDesc.BufferCount);
m_SwapChainDesc.BufferCount = swapchainImageCount;
}
+
+ m_ImageAcquiredSemaphores.resize(swapchainImageCount);
+ m_DrawCompleteSemaphores.resize(swapchainImageCount);
+ for(uint32_t i = 0; i < swapchainImageCount; ++i)
+ {
+ VkSemaphoreCreateInfo SemaphoreCI = {};
+ SemaphoreCI.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
+ SemaphoreCI.pNext = nullptr;
+ SemaphoreCI.flags = 0; // reserved for future use
+ m_ImageAcquiredSemaphores[i] = LogicalDevice.CreateSemaphore(SemaphoreCI);
+ m_DrawCompleteSemaphores[i] = LogicalDevice.CreateSemaphore(SemaphoreCI);
+ }
}
SwapChainVkImpl::~SwapChainVkImpl()
@@ -329,8 +345,8 @@ void SwapChainVkImpl::InitBuffersAndViews()
CHECK_VK_ERROR_AND_THROW(err, "Failed to get swap chain images");
VERIFY_EXPR(swapchainImageCount == swapchainImages.size());
- for (uint32_t i = 0; i < swapchainImageCount; i++) {
-
+ for (uint32_t i = 0; i < swapchainImageCount; i++)
+ {
TextureDesc BackBufferDesc;
BackBufferDesc.Format = m_SwapChainDesc.ColorBufferFormat;
std::stringstream name_ss;
@@ -373,6 +389,18 @@ void SwapChainVkImpl::InitBuffersAndViews()
m_pDepthBufferDSV = RefCntAutoPtr<ITextureViewVk>(pDSV, IID_TextureViewVk);
}
+void SwapChainVkImpl::AcquireNextImage(DeviceContextVkImpl *pDeviceCtxVk)
+{
+ auto *pDeviceVk = m_pRenderDevice.RawPtr<RenderDeviceVkImpl>();
+ const auto& LogicalDevice = pDeviceVk->GetLogicalDevice();
+
+ auto res = vkAcquireNextImageKHR(LogicalDevice.GetVkDevice(), m_VkSwapChain, UINT64_MAX, m_ImageAcquiredSemaphores[m_SemaphoreIndex], (VkFence)nullptr, &m_BackBufferIndex);
+ VERIFY(res == VK_SUCCESS, "Failed to acquire next swap chain image");
+
+ // Next command in the device context must wait for the next image to be acquired
+ pDeviceCtxVk->AddWaitSemaphore(m_ImageAcquiredSemaphores[m_SemaphoreIndex], VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
+}
+
IMPLEMENT_QUERY_INTERFACE( SwapChainVkImpl, IID_SwapChainVk, TSwapChainBase )
@@ -385,21 +413,30 @@ void SwapChainVkImpl::Present(Uint32 SyncInterval)
return;
}
- auto *pImmediateCtx = pDeviceContext.RawPtr();
- auto *pImmediateCtxVk = ValidatedCast<DeviceContextVkImpl>( pImmediateCtx );
+ auto *pImmediateCtxVk = pDeviceContext.RawPtr<DeviceContextVkImpl>();
-#if 0
- auto *pCmdCtx = pImmediateCtxVk->RequestCmdContext();
- auto *pBackBuffer = ValidatedCast<TextureVkImpl>( GetCurrentBackBufferRTV()->GetTexture() );
- pCmdCtx->TransitionResource( pBackBuffer, Vk_RESOURCE_STATE_PRESENT);
-#endif
+ // TransitionImageLayout() never triggers flush
+ pImmediateCtxVk->TransitionImageLayout(GetCurrentBackBufferRTV()->GetTexture(), VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
+ VERIFY(pImmediateCtxVk->GetNumCommandsInCtx() != 0, "The context must not be flushed");
+ pImmediateCtxVk->AddSignalSemaphore(m_DrawCompleteSemaphores[m_SemaphoreIndex]);
pImmediateCtxVk->Flush();
- auto *pDeviceVk = ValidatedCast<RenderDeviceVkImpl>( pImmediateCtxVk->GetDevice() );
-#if 0
- auto hr = m_pSwapChain->Present( SyncInterval, 0 );
- VERIFY(SUCCEEDED(hr), "Present failed");
-#endif
+ VkPresentInfoKHR PresentInfo = {};
+ PresentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
+ PresentInfo.pNext = nullptr;
+ PresentInfo.waitSemaphoreCount = 1;
+ VkSemaphore WaitSemaphore[] = { m_DrawCompleteSemaphores[m_SemaphoreIndex] };
+ PresentInfo.pWaitSemaphores = WaitSemaphore;
+ PresentInfo.swapchainCount = 1;
+ PresentInfo.pSwapchains = &m_VkSwapChain;
+ PresentInfo.pImageIndices = &m_BackBufferIndex;
+ VkResult Result = VK_SUCCESS;
+ PresentInfo.pResults = &Result;
+ VERIFY(Result == VK_SUCCESS, "Present failed");
+
+ auto *pDeviceVk = m_pRenderDevice.RawPtr<RenderDeviceVkImpl>();
+ auto vkCmdQueue = pDeviceVk->GetCmdQueue()->GetVkQueue();
+ vkQueuePresentKHR(vkCmdQueue, &PresentInfo);
pDeviceVk->FinishFrame();
@@ -412,6 +449,11 @@ void SwapChainVkImpl::Present(Uint32 SyncInterval)
pImmediateCtxVk->CommitRenderTargets();
#endif
#endif
+ ++m_SemaphoreIndex;
+ if (m_SemaphoreIndex >= m_SwapChainDesc.BufferCount)
+ m_SemaphoreIndex = 0;
+
+ AcquireNextImage(pImmediateCtxVk);
}
void SwapChainVkImpl::Resize( Uint32 NewWidth, Uint32 NewHeight )
@@ -433,6 +475,9 @@ void SwapChainVkImpl::Resize( Uint32 NewWidth, Uint32 NewHeight )
// All references to the swap chain must be released before it can be resized
m_pBackBufferRTV.clear();
m_pDepthBufferDSV.Release();
+ m_ImageAcquiredSemaphores.clear();
+ m_DrawCompleteSemaphores.clear();
+ m_SemaphoreIndex = 0;
// This will release references to Vk swap chain buffers hold by
// m_pBackBufferRTV[]
@@ -440,6 +485,7 @@ void SwapChainVkImpl::Resize( Uint32 NewWidth, Uint32 NewHeight )
CreateVulkanSwapChain();
InitBuffersAndViews();
+ AcquireNextImage(pImmediateCtxVk);
if( bIsDefaultFBBound )
{
@@ -456,14 +502,12 @@ void SwapChainVkImpl::Resize( Uint32 NewWidth, Uint32 NewHeight )
}
}
-#if 0
ITextureViewVk *SwapChainVkImpl::GetCurrentBackBufferRTV()
{
- auto CurrentBackBufferIndex = m_pSwapChain->GetCurrentBackBufferIndex();
- VERIFY_EXPR(CurrentBackBufferIndex >= 0 && CurrentBackBufferIndex < m_SwapChainDesc.BufferCount);
- return m_pBackBufferRTV[CurrentBackBufferIndex];
+ VERIFY_EXPR(m_BackBufferIndex >= 0 && m_BackBufferIndex < m_SwapChainDesc.BufferCount);
+ return m_pBackBufferRTV[m_BackBufferIndex];
}
-#endif
+
void SwapChainVkImpl::SetFullscreenMode(const DisplayModeAttribs &DisplayMode)
{
diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanCommandBuffer.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanCommandBuffer.cpp
index 2f06cdb5..a4c996a6 100644
--- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanCommandBuffer.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanCommandBuffer.cpp
@@ -295,7 +295,11 @@ void VulkanCommandBuffer::TransitionImageLayout(VkCommandBuffer CmdBuffer,
if(SrcStages == 0)
{
- if(ImgBarrier.srcAccessMask != 0)
+ if(OldLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)
+ {
+ SrcStages = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
+ }
+ else if(ImgBarrier.srcAccessMask != 0)
{
SrcStages = PipelineStageFromAccessFlags(ImgBarrier.srcAccessMask);
}
@@ -309,7 +313,11 @@ void VulkanCommandBuffer::TransitionImageLayout(VkCommandBuffer CmdBuffer,
if (DestStages == 0)
{
- if(ImgBarrier.dstAccessMask != 0)
+ if(NewLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)
+ {
+ DestStages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
+ }
+ else if(ImgBarrier.dstAccessMask != 0)
{
DestStages = PipelineStageFromAccessFlags(ImgBarrier.dstAccessMask);
}