X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fbackends%2Fvulkan%2Fswapchain.cpp;fp=source%2Fbackends%2Fvulkan%2Fswapchain.cpp;h=49add1a70d905d24ee48a9b6198f15d6f6c80130;hb=99ca354f18119f82f1adeca100cd665a8f640317;hp=0000000000000000000000000000000000000000;hpb=4cd245dafe6a7ee5c93edca5aee2d146f1155309;p=libs%2Fgl.git diff --git a/source/backends/vulkan/swapchain.cpp b/source/backends/vulkan/swapchain.cpp new file mode 100644 index 00000000..49add1a7 --- /dev/null +++ b/source/backends/vulkan/swapchain.cpp @@ -0,0 +1,128 @@ +#include +#include +#include +#include "device.h" +#include "error.h" +#include "pixelformat.h" +#include "semaphore.h" +#include "swapchain.h" +#include "vulkan.h" + +using namespace std; + +namespace Msp { +namespace GL { + +SwapChain::SwapChain(unsigned w, unsigned h, unsigned n_images_min): + device(Device::get_current()), + surface(handle_cast(device.get_context().get_private().surface)), + width(w), + height(h) +{ + const VulkanFunctions &vk = device.get_functions(); + + VkSwapchainCreateInfoKHR swapchain_info = { }; + swapchain_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; + swapchain_info.surface = handle_cast<::VkSurfaceKHR>(surface); + swapchain_info.minImageCount = n_images_min; + swapchain_info.imageExtent.width = width; + swapchain_info.imageExtent.height = height; + swapchain_info.imageArrayLayers = 1; + swapchain_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + swapchain_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; + swapchain_info.clipped = VK_TRUE; + + VkSurfaceCapabilitiesKHR surface_caps; + vk.GetPhysicalDeviceSurfaceCapabilities(surface, surface_caps); + swapchain_info.preTransform = surface_caps.currentTransform; + swapchain_info.compositeAlpha = static_cast( + surface_caps.supportedCompositeAlpha&~(surface_caps.supportedCompositeAlpha-1)); + + uint32_t n_formats = 0; + vk.GetPhysicalDeviceSurfaceFormats(surface, n_formats, 0); + vector surface_formats(n_formats); + vk.GetPhysicalDeviceSurfaceFormats(surface, n_formats, surface_formats.data()); + + PixelFormat image_fmt = NO_PIXELFORMAT; + for(const VkSurfaceFormatKHR &f: surface_formats) + { + image_fmt = pixelformat_from_vulkan(f.format); + if(!is_srgb(image_fmt)) + { + swapchain_info.imageFormat = f.format; + swapchain_info.imageColorSpace = f.colorSpace; + break; + } + } + + if(!swapchain_info.imageFormat) + throw runtime_error("no suitable swapchain pixelformat"); + + uint32_t n_present_modes = 0; + vk.GetPhysicalDeviceSurfacePresentModes(surface, n_present_modes, 0); + vector present_modes(n_present_modes); + vk.GetPhysicalDeviceSurfacePresentModes(surface, n_present_modes, present_modes.data()); + + if(find(present_modes, VK_PRESENT_MODE_FIFO_KHR)!=present_modes.end()) + swapchain_info.presentMode = VK_PRESENT_MODE_FIFO_KHR; + else + swapchain_info.presentMode = present_modes.front(); + + vk.CreateSwapchain(swapchain_info, handle); + + uint32_t n_images = 0; + vk.GetSwapchainImages(handle, n_images, 0); + vector image_handles(n_images); + vk.GetSwapchainImages(handle, n_images, image_handles.data()); + + images.reserve(n_images); + for(unsigned i=0; i=0) + throw invalid_operation("SwapChain::begin_frame"); + + const VulkanFunctions &vk = device.get_functions(); + + uint32_t image_index; + vk.AcquireNextImage(handle, numeric_limits::max(), sem.handle, 0, image_index); + + current_index = image_index; + + return image_index; +} + +void SwapChain::present_frame(Semaphore &sem) +{ + if(current_index<0) + throw invalid_operation("SwapChain::present_frame"); + + const VulkanFunctions &vk = device.get_functions(); + ::VkSwapchainKHR vk_handle = handle_cast<::VkSwapchainKHR>(handle); + ::VkSemaphore vk_sem = handle_cast<::VkSemaphore>(sem.handle); + uint32_t image_index = current_index; + + current_index = -1; + + VkPresentInfoKHR present_info = { }; + present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; + present_info.waitSemaphoreCount = 1; + present_info.pWaitSemaphores = &vk_sem; + present_info.swapchainCount = 1; + present_info.pSwapchains = &vk_handle; + present_info.pImageIndices = &image_index; + vk.QueuePresent(present_info); +} + +} // namespace GL +} // namespace Msp