3 #include <msp/core/algorithm.h>
4 #include <msp/graphics/vulkancontext_platform.h>
7 #include "pixelformat.h"
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)),
23 const VulkanFunctions &vk = device.get_functions();
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;
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));
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());
47 PixelFormat image_fmt = NO_PIXELFORMAT;
48 for(const VkSurfaceFormatKHR &f: surface_formats)
50 image_fmt = pixelformat_from_vulkan(f.format);
51 if(!is_srgb(image_fmt))
53 swapchain_info.imageFormat = f.format;
54 swapchain_info.imageColorSpace = f.colorSpace;
59 if(!swapchain_info.imageFormat)
60 throw runtime_error("no suitable swapchain pixelformat");
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());
67 if(find(present_modes, VK_PRESENT_MODE_FIFO_KHR)!=present_modes.end())
68 swapchain_info.presentMode = VK_PRESENT_MODE_FIFO_KHR;
70 swapchain_info.presentMode = present_modes.front();
72 vk.CreateSwapchain(swapchain_info, handle);
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());
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])));
84 SwapChain::~SwapChain()
86 const VulkanFunctions &vk = device.get_functions();
88 vk.DestroySwapchain(handle);
91 unsigned SwapChain::begin_frame(Semaphore &sem)
94 throw invalid_operation("SwapChain::begin_frame");
96 const VulkanFunctions &vk = device.get_functions();
99 vk.AcquireNextImage(handle, numeric_limits<uint64_t>::max(), sem.handle, 0, image_index);
101 current_index = image_index;
106 void SwapChain::present_frame(Semaphore &sem)
109 throw invalid_operation("SwapChain::present_frame");
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;
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);