1 // Copyright 2001-2018 Crytek GmbH / Crytek Group. All rights reserved.
6 #include "VKCommandList.hpp"
7 #include "VKAsyncCommandQueue.hpp"
8 #include "VKDevice.hpp"
9 #include "VKImageResource.hpp"
14 class CSwapChain
: public CRefCounted
16 static bool GetSupportedSurfaceFormats(VkPhysicalDevice
& physicalDevice
, VkSurfaceKHR
& surface
, std::vector
<VkSurfaceFormatKHR
>& outFormatsSupported
);
17 static bool GetSupportedPresentModes(VkPhysicalDevice
& physicalDevice
, VkSurfaceKHR
& surface
, std::vector
<VkPresentModeKHR
>& outPresentModes
);
20 static _smart_ptr
<CSwapChain
> Create(CCommandListPool
& commandQueue
, VkSwapchainKHR KHRSwapChain
, uint32_t numberOfBuffers
, uint32_t width
, uint32_t height
, VkSurfaceKHR surface
, VkFormat format
, VkPresentModeKHR presentMode
, VkImageUsageFlags imageUsage
);
21 static _smart_ptr
<CSwapChain
> Create(CCommandListPool
& commandQueue
, VkSwapchainKHR KHRSwapChain
, uint32_t numberOfBuffers
, uint32_t width
, uint32_t height
, VkSurfaceKHR surface
, VkFormat format
, VkPresentModeKHR presentMode
, VkImageUsageFlags imageUsage
, VkSurfaceTransformFlagBitsKHR transform
);
22 static _smart_ptr
<CSwapChain
> Create(CCommandListPool
& commandQueue
, VkSwapchainCreateInfoKHR
* pInfo
);
25 CSwapChain(CCommandListPool
& commandQueue
, VkSurfaceKHR KHRSurface
, VkSwapchainKHR KHRSwapChain
, VkSwapchainCreateInfoKHR
* pInfo
);
27 virtual ~CSwapChain();
30 ILINE VkSwapchainKHR
GetKHRSwapChain() const
32 return m_KHRSwapChain
;
35 ILINE VkSurfaceKHR
GetKHRSurface() const
40 ILINE
const VkSwapchainCreateInfoKHR
& GetKHRSwapChainInfo() const
45 ILINE UINT
GetBackBufferCount() const
47 return m_NumBackbuffers
;
50 // Get the index of the back-buffer which is to be used for the next Present().
51 // Cache the value for multiple calls between Present()s, as vkAcquireNextImageKHR() will always increment the counter regardless if flips occured.
52 ILINE UINT
GetCurrentBackbufferIndex() const
54 if (!m_bChangedBackBufferIndex
)
55 return m_nCurrentBackBufferIndex
;
57 // Pick a semaphore from the ring-buffer ...
58 auto* const pFence
= m_presentFence
.GetFence();
59 VkSemaphore Semaphore
= pFence
->second
[m_semaphoreIndex
++ % pFence
->second
.size()];
61 m_asyncQueue
.FlushNextPresent(); VK_ASSERT(!IsPresentScheduled(), "Flush didn't dry out all outstanding Present() calls!");
62 VkResult result
= vkAcquireNextImageKHR(m_pDevice
->GetVkDevice(), m_KHRSwapChain
, ~0ULL, Semaphore
, VK_NULL_HANDLE
, &m_nCurrentBackBufferIndex
);
63 VK_ASSERT(result
== VK_SUCCESS
);
64 m_bChangedBackBufferIndex
= false;
66 // ... and inject it as sync-primitive into the core-command-list - which is the one active at the moment of this call (which can be mid-frame)
67 // Adding the semaphore will make the command-list submit even if there are no commands in it, because semaphores can not set/reset from CPU side.
68 m_pDevice
->GetScheduler().GetCommandList(CMDQUEUE_GRAPHICS
)->WaitForFinishOnGPU(Semaphore
);
70 return m_nCurrentBackBufferIndex
;
72 ILINE CImageResource
& GetBackBuffer(UINT index
)
74 return m_BackBuffers
[index
];
76 ILINE CImageResource
& GetCurrentBackBuffer()
78 return m_BackBuffers
[GetCurrentBackbufferIndex()];
81 ILINE
bool IsPresentScheduled() const
83 return m_asyncQueue
.GetQueuedFramesCount() > 0;
86 // Run Present() asynchronuously, which means the next back-buffer index is not queryable within this function.
87 // Instead defer acquiring the next index to the next call of GetCurrentBackbufferIndex().
88 void Present(UINT SyncInterval
, UINT Flags
, VkSemaphore sem
)
90 m_asyncQueue
.Present(m_KHRSwapChain
, GetCurrentBackbufferIndex(), 1, &sem
, &m_presentResult
);
91 m_bChangedBackBufferIndex
= true;
94 VkResult
GetLastPresentReturnValue() { return m_presentResult
; }
96 // VkResult ResizeTarget(const DXGI_MODE_DESC* pNewTargetParameters);
97 // VkResult ResizeBuffers(UINT BufferCount, UINT Width, UINT Height, DXGI_FORMAT NewFormat, UINT SwapChainFlags);
99 void AcquireBuffers();
100 void UnblockBuffers(CCommandList
* pCommandList
);
101 void VerifyBufferCounters();
102 void ForfeitBuffers();
106 CAsyncCommandQueue
& m_asyncQueue
;
107 CCommandListPool
& m_pCommandQueue
;
108 CCommandListFence m_presentFence
;
110 VkSwapchainCreateInfoKHR m_Info
;
111 uint32_t m_NumBackbuffers
;
112 mutable bool m_bChangedBackBufferIndex
;
113 mutable uint32_t m_nCurrentBackBufferIndex
;
114 mutable uint32_t m_semaphoreIndex
= 0;
116 VkResult m_presentResult
;
117 VkSurfaceKHR m_KHRSurface
;
118 VkSwapchainKHR m_KHRSwapChain
;
120 std::vector
<CImageResource
> m_BackBuffers
;