]> git.tdb.fi Git - libs/gl.git/blob - source/backends/vulkan/swapchain.cpp
Add missing includes
[libs/gl.git] / source / backends / vulkan / swapchain.cpp
1 #include <limits>
2 #include <vector>
3 #include <msp/core/algorithm.h>
4 #include <msp/graphics/vulkancontext_platform.h>
5 #include "device.h"
6 #include "error.h"
7 #include "pixelformat.h"
8 #include "semaphore.h"
9 #include "swapchain.h"
10 #include "vulkan.h"
11
12 using namespace std;
13
14 namespace Msp {
15 namespace GL {
16
17 SwapChain::SwapChain(unsigned w, unsigned h, unsigned n_images_min):
18         device(Device::get_current()),
19         surface(handle_cast<VkSurface>(device.get_context().get_private().surface)),
20         width(w),
21         height(h)
22 {
23         const VulkanFunctions &vk = device.get_functions();
24
25         VkSwapchainCreateInfoKHR swapchain_info = { };
26         swapchain_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
27         swapchain_info.surface = handle_cast<::VkSurfaceKHR>(surface);
28         swapchain_info.minImageCount = n_images_min;
29         swapchain_info.imageExtent.width = width;
30         swapchain_info.imageExtent.height = height;
31         swapchain_info.imageArrayLayers = 1;
32         swapchain_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
33         swapchain_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
34         swapchain_info.clipped = VK_TRUE;
35
36         VkSurfaceCapabilitiesKHR surface_caps;
37         vk.GetPhysicalDeviceSurfaceCapabilities(surface, surface_caps);
38         swapchain_info.preTransform = surface_caps.currentTransform;
39         swapchain_info.compositeAlpha = static_cast<VkCompositeAlphaFlagBitsKHR>(
40                 surface_caps.supportedCompositeAlpha&~(surface_caps.supportedCompositeAlpha-1));
41
42         uint32_t n_formats = 0;
43         vk.GetPhysicalDeviceSurfaceFormats(surface, n_formats, 0);
44         vector<VkSurfaceFormatKHR> surface_formats(n_formats);
45         vk.GetPhysicalDeviceSurfaceFormats(surface, n_formats, surface_formats.data());
46
47         PixelFormat image_fmt = NO_PIXELFORMAT;
48         for(const VkSurfaceFormatKHR &f: surface_formats)
49         {
50                 image_fmt = pixelformat_from_vulkan(f.format);
51                 if(!is_srgb(image_fmt))
52                 {
53                         swapchain_info.imageFormat = f.format;
54                         swapchain_info.imageColorSpace = f.colorSpace;
55                         break;
56                 }
57         }
58
59         if(!swapchain_info.imageFormat)
60                 throw runtime_error("no suitable swapchain pixelformat");
61
62         uint32_t n_present_modes = 0;
63         vk.GetPhysicalDeviceSurfacePresentModes(surface, n_present_modes, 0);
64         vector<VkPresentModeKHR> present_modes(n_present_modes);
65         vk.GetPhysicalDeviceSurfacePresentModes(surface, n_present_modes, present_modes.data());
66
67         if(find(present_modes, VK_PRESENT_MODE_FIFO_KHR)!=present_modes.end())
68                 swapchain_info.presentMode = VK_PRESENT_MODE_FIFO_KHR;
69         else
70                 swapchain_info.presentMode = present_modes.front();
71
72         vk.CreateSwapchain(swapchain_info, handle);
73
74         uint32_t n_images = 0;
75         vk.GetSwapchainImages(handle, n_images, 0);
76         vector<VkImage> image_handles(n_images);
77         vk.GetSwapchainImages(handle, n_images, image_handles.data());
78
79         images.reserve(n_images);
80         for(unsigned i=0; i<n_images; ++i)
81                 images.emplace_back(move(SwapChainTexture(image_fmt, width, height, image_handles[i])));
82 }
83
84 SwapChain::~SwapChain()
85 {
86         const VulkanFunctions &vk = device.get_functions();
87
88         vk.DestroySwapchain(handle);
89 }
90
91 unsigned SwapChain::begin_frame(Semaphore &sem)
92 {
93         if(current_index>=0)
94                 throw invalid_operation("SwapChain::begin_frame");
95
96         const VulkanFunctions &vk = device.get_functions();
97
98         uint32_t image_index;
99         vk.AcquireNextImage(handle, numeric_limits<uint64_t>::max(), sem.handle, 0, image_index);
100
101         current_index = image_index;
102
103         return image_index;
104 }
105
106 void SwapChain::present_frame(Semaphore &sem)
107 {
108         if(current_index<0)
109                 throw invalid_operation("SwapChain::present_frame");
110
111         const VulkanFunctions &vk = device.get_functions();
112         ::VkSwapchainKHR vk_handle = handle_cast<::VkSwapchainKHR>(handle);
113         ::VkSemaphore vk_sem = handle_cast<::VkSemaphore>(sem.handle);
114         uint32_t image_index = current_index;
115
116         current_index = -1;
117
118         VkPresentInfoKHR present_info = { };
119         present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
120         present_info.waitSemaphoreCount = 1;
121         present_info.pWaitSemaphores = &vk_sem;
122         present_info.swapchainCount = 1;
123         present_info.pSwapchains = &vk_handle;
124         present_info.pImageIndices = &image_index;
125         vk.QueuePresent(present_info);
126 }
127
128 } // namespace GL
129 } // namespace Msp