Divide Framework 0.1
A free and open-source 3D Framework under heavy development
Loading...
Searching...
No Matches
vkSwapChain.cpp
Go to the documentation of this file.
1
2
4#include "Headers/vkDevice.h"
5
7
10
11namespace Divide {
12
13 VKSwapChain::VKSwapChain(VK_API& context, const VKDevice& device, const DisplayWindow& window)
14 : _context(context)
15 , _device(device)
16 , _window(window)
17 {
18 const auto& windowDimensions = _window.getDrawableSize();
19 surfaceExtent({ windowDimensions.width, windowDimensions.height } );
20 }
21
23 {
24 destroy();
25 }
26
28 {
29 vkb::destroy_swapchain(_swapChain);
30
31 _swapChain.destroy_image_views(_swapchainImageViews);
32 _swapchainImages.clear();
34
35 if ( _swapChain.swapchain != VK_NULL_HANDLE )
36 {
37 const VkDevice device = _device.getVKDevice();
38 for (U8 i = 0u; i < Config::MAX_FRAMES_IN_FLIGHT; ++i)
39 {
40
41 vkDestroySemaphore(device, _frames[i]._presentSemaphore, nullptr);
42 vkDestroySemaphore(device, _frames[i]._renderSemaphore, nullptr);
43 vkDestroyFence(device, _frames[i]._renderFence._handle, nullptr);
44 _frames[i]._renderFence._tag = U8_MAX;
45 }
46 _swapChain.swapchain = VK_NULL_HANDLE;
47 }
48 }
49
50 ErrorCode VKSwapChain::create(const bool vSync, const bool adaptiveSync, VkSurfaceKHR targetSurface)
51 {
53
54 vkb::SwapchainBuilder swapchainBuilder{ _device.getPhysicalDevice(),
56 targetSurface,
59
60 if ( _swapChain.swapchain != VK_NULL_HANDLE )
61 {
62 swapchainBuilder.set_old_swapchain( _swapChain );
63 }
64
65 // adaptiveSync not supported yet
66 DIVIDE_UNUSED(adaptiveSync);
67
68 auto vkbSwapchain = swapchainBuilder.set_desired_format( { VK_FORMAT_A2R10G10B10_UNORM_PACK32, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR } )
69 .set_desired_format( { VK_FORMAT_A2B10G10R10_UNORM_PACK32, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR } )
70 .set_desired_format( { VK_FORMAT_B8G8R8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR } )
71 .add_fallback_format( { VK_FORMAT_R8G8B8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR } )
72 .set_desired_present_mode( vSync ? VK_PRESENT_MODE_FIFO_KHR : VK_PRESENT_MODE_IMMEDIATE_KHR )
73 .add_fallback_present_mode( VK_PRESENT_MODE_FIFO_KHR )
74 .set_desired_extent( surfaceExtent().width, surfaceExtent().height )
75 .build();
76
77
78 if ( !vkbSwapchain )
79 {
80 Console::errorfn( LOCALE_STR( "ERROR_VK_INIT" ), vkbSwapchain.error().message().c_str() );
82 }
83
84 destroy();
85
86 _swapChain = vkbSwapchain.value();
87 _swapchainImages = _swapChain.get_images().value();
88 _swapchainImageViews = _swapChain.get_image_views().value();
89
90 if ( _swapChain.image_format == VK_FORMAT_UNDEFINED )
91 {
93 }
94
95
96 const VkSemaphoreCreateInfo semaphoreCreateInfo = vk::semaphoreCreateInfo();
97 const VkFenceCreateInfo fenceCreateInfo = vk::fenceCreateInfo( VK_FENCE_CREATE_SIGNALED_BIT );
98 const VkCommandBufferAllocateInfo cmdAllocInfo = vk::commandBufferAllocateInfo( _device.getQueue( QueueType::GRAPHICS)._pool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1u );
99
100 const VkDevice device = _device.getVKDevice();
101 for ( U8 i = 0u; i < Config::MAX_FRAMES_IN_FLIGHT; ++i )
102 {
103 VK_CHECK( vkCreateSemaphore( device, &semaphoreCreateInfo, nullptr, &_frames[i]._presentSemaphore ) );
104 VK_CHECK( vkCreateSemaphore( device, &semaphoreCreateInfo, nullptr, &_frames[i]._renderSemaphore ) );
105 VK_CHECK( vkCreateFence( device, &fenceCreateInfo, nullptr, &_frames[i]._renderFence._handle ) );
106 VK_CHECK( vkAllocateCommandBuffers( device, &cmdAllocInfo, &_frames[i]._commandBuffer ) );
107 _frames[i]._renderFence._tag = i;
108 }
109
110 const auto& windowDimensions = _window.getDrawableSize();
111 surfaceExtent( VkExtent2D{ windowDimensions.width, windowDimensions.height } );
112
113 return ErrorCode::NO_ERR;
114 }
115
117 {
119
120 FrameData& crtFrame = getFrameData();
121
122 //wait until the GPU has finished rendering the last frame.
123 {
124 PROFILE_SCOPE( "Wait for fences", Profiler::Category::Graphics);
125 VK_CHECK( vkWaitForFences( _device.getVKDevice(), 1, &crtFrame._renderFence._handle, VK_TRUE, U64_MAX ) );
126 }
127 {
129 VK_CHECK( vkResetFences( _device.getVKDevice(), 1, &crtFrame._renderFence._handle ) );
130 }
131
132 //request image from the swapchain, one second timeout
133 VkResult ret = VK_ERROR_UNKNOWN;
134 {
135 PROFILE_SCOPE( "Aquire Next Image", Profiler::Category::Graphics );
136 ret = vkAcquireNextImageKHR(_device.getVKDevice(), _swapChain.swapchain, U64_MAX, crtFrame._presentSemaphore, nullptr, &_swapchainImageIndex);
137 }
138
139 if ( ret == VK_SUCCESS )
140 {
141 PROFILE_SCOPE( "Begin Command Buffer", Profiler::Category::Graphics );
142 //begin the command buffer recording. We will use this command buffer exactly once, so we want to let Vulkan know that
143 VkCommandBufferBeginInfo cmdBeginInfo = vk::commandBufferBeginInfo( VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT );
144 VK_CHECK( vkBeginCommandBuffer( crtFrame._commandBuffer, &cmdBeginInfo ) );
145 }
146
147 return ret;
148 }
149
151 {
153
154 FrameData& crtFrame = getFrameData();
155 VK_CHECK( vkEndCommandBuffer( crtFrame._commandBuffer ) );
156
157 // prepare the submission to the queue.
158 // we want to wait on the _presentSemaphore, as that semaphore is signaled when the swapchain is ready
159 // we will signal the _renderSemaphore, to signal that rendering has finished
160 constexpr VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
161
162 VkSubmitInfo submit = vk::submitInfo();
163 submit.pWaitDstStageMask = waitStages;
164 submit.waitSemaphoreCount = 1;
165 submit.pWaitSemaphores = &crtFrame._presentSemaphore;
166 submit.signalSemaphoreCount = 1;
167 submit.pSignalSemaphores = &crtFrame._renderSemaphore;
168 submit.commandBufferCount = 1;
169 submit.pCommandBuffers = &crtFrame._commandBuffer;
170
171 // submit command buffer to the queue and execute it. _renderFence will now block until the graphic commands finish execution
173 PROFILE_VK_PRESENT( &_swapChain.swapchain );
174
175 // this will put the image we just rendered into the visible window.
176 // we want to wait on the _renderSemaphore for that, as it's necessary that drawing commands have finished before the image is displayed to the user
177 VkPresentInfoKHR presentInfo = {};
178 presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
179 presentInfo.pSwapchains = &_swapChain.swapchain;
180 presentInfo.swapchainCount = 1;
181 presentInfo.pWaitSemaphores = &crtFrame._renderSemaphore;
182 presentInfo.waitSemaphoreCount = 1;
183 presentInfo.pImageIndices = &_swapchainImageIndex;
184
185 const VkResult ret = _device.queuePresent( QueueType::GRAPHICS, presentInfo);
186
187 return ret;
188 }
189
190 vkb::Swapchain& VKSwapChain::getSwapChain() noexcept
191 {
192 return _swapChain;
193 }
194
195 VkImage VKSwapChain::getCurrentImage() const noexcept
196 {
198 }
199
200 VkImageView VKSwapChain::getCurrentImageView() const noexcept
201 {
203 }
204
206 {
208 }
209}; //namespace Divide
#define LOCALE_STR(X)
Definition: Localization.h:91
#define DIVIDE_UNUSED(X)
#define PROFILE_SCOPE_AUTO(CATEGORY)
Definition: Profiler.h:87
#define PROFILE_VK_PRESENT(SWAP_CHAIN)
Definition: Profiler.h:95
#define PROFILE_SCOPE(NAME, CATEGORY)
Definition: Profiler.h:86
vec2< U16 > getDrawableSize() const noexcept
static U64 FrameCount() noexcept
Definition: GFXDevice.h:340
const vkb::PhysicalDevice & getPhysicalDevice() const noexcept
Definition: vkDevice.cpp:218
U32 getPresentQueueIndex() const noexcept
Definition: vkDevice.cpp:147
void submitToQueue(QueueType queue, const VkSubmitInfo &submitInfo, VkFence &fence) const
Definition: vkDevice.cpp:235
VKQueue getQueue(QueueType type) const noexcept
Definition: vkDevice.cpp:152
const vkb::Device & getDevice() const noexcept
Definition: vkDevice.cpp:213
VkResult queuePresent(QueueType queue, const VkPresentInfoKHR &presentInfo) const
Definition: vkDevice.cpp:245
VkDevice getVKDevice() const noexcept
Definition: vkDevice.cpp:203
vkb::Swapchain _swapChain
Definition: vkSwapChain.h:83
VkImageView getCurrentImageView() const noexcept
VkImage getCurrentImage() const noexcept
ErrorCode create(bool vSync, bool adaptiveSync, VkSurfaceKHR targetSurface)
Definition: vkSwapChain.cpp:50
VKSwapChain(VK_API &context, const VKDevice &device, const DisplayWindow &window)
Definition: vkSwapChain.cpp:13
std::vector< VkImage > _swapchainImages
Definition: vkSwapChain.h:86
std::array< FrameData, Config::MAX_FRAMES_IN_FLIGHT > _frames
Definition: vkSwapChain.h:82
const DisplayWindow & _window
Definition: vkSwapChain.h:80
FrameData & getFrameData() noexcept
vkb::Swapchain & getSwapChain() noexcept
std::vector< VkImageView > _swapchainImageViews
Definition: vkSwapChain.h:87
const VKDevice & _device
Definition: vkSwapChain.h:79
constexpr U8 MAX_FRAMES_IN_FLIGHT
Maximum number of active frames until we start waiting on a fence/sync.
Definition: config.h:100
constexpr Optick::Category::Type Graphics
Definition: Profiler.h:60
VkCommandBufferAllocateInfo commandBufferAllocateInfo(VkCommandPool commandPool, VkCommandBufferLevel level, uint32_t bufferCount)
VkSubmitInfo submitInfo()
VkFenceCreateInfo fenceCreateInfo(VkFenceCreateFlags flags=0)
VkSemaphoreCreateInfo semaphoreCreateInfo()
VkCommandBufferBeginInfo commandBufferBeginInfo(VkCommandBufferUsageFlags flags=0)
Handle console commands that start with a forward slash.
Definition: AIProcessor.cpp:7
constexpr U64 U64_MAX
uint8_t U8
constexpr U8 U8_MAX
static NO_INLINE void errorfn(const char *format, T &&... args)
VkFence _handle
Definition: vkSwapChain.h:46
VkCommandBuffer _commandBuffer
Definition: vkSwapChain.h:54
VkSemaphore _presentSemaphore
Definition: vkSwapChain.h:52
VkSemaphore _renderSemaphore
Definition: vkSwapChain.h:53
VkCommandPool _pool
Definition: vkResources.h:94
#define VK_CHECK(x)
Definition: vkResources.h:327