2 #include <msp/core/algorithm.h>
3 #include <msp/graphics/vulkancontext_platform.h>
6 #include "pixelformat.h"
16 SwapChain::SwapChain(unsigned w, unsigned h, unsigned n_images_min):
17 device(Device::get_current()),
18 surface(handle_cast<VkSurface>(device.get_context().get_private().surface)),
22 const VulkanFunctions &vk = device.get_functions();
24 VkSwapchainCreateInfoKHR swapchain_info = { };
25 swapchain_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
26 swapchain_info.surface = handle_cast<::VkSurfaceKHR>(surface);
27 swapchain_info.minImageCount = n_images_min;
28 swapchain_info.imageExtent.width = width;
29 swapchain_info.imageExtent.height = height;
30 swapchain_info.imageArrayLayers = 1;
31 swapchain_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
32 swapchain_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
33 swapchain_info.clipped = VK_TRUE;
35 VkSurfaceCapabilitiesKHR surface_caps;
36 vk.GetPhysicalDeviceSurfaceCapabilities(surface, surface_caps);
37 swapchain_info.preTransform = surface_caps.currentTransform;
38 swapchain_info.compositeAlpha = static_cast<VkCompositeAlphaFlagBitsKHR>(
39 surface_caps.supportedCompositeAlpha&~(surface_caps.supportedCompositeAlpha-1));
41 uint32_t n_formats = 0;
42 vk.GetPhysicalDeviceSurfaceFormats(surface, n_formats, 0);
43 vector<VkSurfaceFormatKHR> surface_formats(n_formats);
44 vk.GetPhysicalDeviceSurfaceFormats(surface, n_formats, surface_formats.data());
46 PixelFormat image_fmt = NO_PIXELFORMAT;
47 for(const VkSurfaceFormatKHR &f: surface_formats)
49 image_fmt = pixelformat_from_vulkan(f.format);
50 if(!is_srgb(image_fmt))
52 swapchain_info.imageFormat = f.format;
53 swapchain_info.imageColorSpace = f.colorSpace;
58 if(!swapchain_info.imageFormat)
59 throw runtime_error("no suitable swapchain pixelformat");
61 uint32_t n_present_modes = 0;
62 vk.GetPhysicalDeviceSurfacePresentModes(surface, n_present_modes, 0);
63 vector<VkPresentModeKHR> present_modes(n_present_modes);
64 vk.GetPhysicalDeviceSurfacePresentModes(surface, n_present_modes, present_modes.data());
66 if(find(present_modes, VK_PRESENT_MODE_FIFO_KHR)!=present_modes.end())
67 swapchain_info.presentMode = VK_PRESENT_MODE_FIFO_KHR;
69 swapchain_info.presentMode = present_modes.front();
71 vk.CreateSwapchain(swapchain_info, handle);
73 uint32_t n_images = 0;
74 vk.GetSwapchainImages(handle, n_images, 0);
75 vector<VkImage> image_handles(n_images);
76 vk.GetSwapchainImages(handle, n_images, image_handles.data());
78 images.reserve(n_images);
79 for(unsigned i=0; i<n_images; ++i)
80 images.emplace_back(move(SwapChainTexture(image_fmt, width, height, image_handles[i])));
83 SwapChain::~SwapChain()
85 const VulkanFunctions &vk = device.get_functions();
87 vk.DestroySwapchain(handle);
90 unsigned SwapChain::begin_frame(Semaphore &sem)
93 throw invalid_operation("SwapChain::begin_frame");
95 const VulkanFunctions &vk = device.get_functions();
98 vk.AcquireNextImage(handle, numeric_limits<uint64_t>::max(), sem.handle, 0, image_index);
100 current_index = image_index;
105 void SwapChain::present_frame(Semaphore &sem)
108 throw invalid_operation("SwapChain::present_frame");
110 const VulkanFunctions &vk = device.get_functions();
111 ::VkSwapchainKHR vk_handle = handle_cast<::VkSwapchainKHR>(handle);
112 ::VkSemaphore vk_sem = handle_cast<::VkSemaphore>(sem.handle);
113 uint32_t image_index = current_index;
117 VkPresentInfoKHR present_info = { };
118 present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
119 present_info.waitSemaphoreCount = 1;
120 present_info.pWaitSemaphores = &vk_sem;
121 present_info.swapchainCount = 1;
122 present_info.pSwapchains = &vk_handle;
123 present_info.pImageIndices = &image_index;
124 vk.QueuePresent(present_info);