From 8279acc1a4754bedaad0ba8bf00541c7b2a043e9 Mon Sep 17 00:00:00 2001 From: Steven Le Rouzic Date: Wed, 12 Jun 2024 23:57:24 +0200 Subject: Swapchain creation --- deimos/vulkan/vulkan_backend.cpp | 109 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) (limited to 'deimos/vulkan/vulkan_backend.cpp') diff --git a/deimos/vulkan/vulkan_backend.cpp b/deimos/vulkan/vulkan_backend.cpp index 87e4451..cc54d4d 100644 --- a/deimos/vulkan/vulkan_backend.cpp +++ b/deimos/vulkan/vulkan_backend.cpp @@ -22,8 +22,14 @@ VulkanLoaderApi* vulkan_loader_api; const VkAllocationCallbacks* kVkAlloc = nullptr; +struct VulkanSwapchain: public RenderSwapchain +{ + VkSwapchainKHR swapchain{}; +}; + class VulkanBackendImpl : public IVulkanBackend, public IRenderBackend { + Allocator* m_allocator; VulkanApi* m_vk; VkInstance m_instance; VkPhysicalDevice m_physical_device; @@ -41,12 +47,14 @@ class VulkanBackendImpl : public IVulkanBackend, public IRenderBackend public: VulkanBackendImpl( + Allocator* allocator, VulkanApi* vk, VkInstance instance, VkPhysicalDevice physical_device, uint32_t queue_family, VkSurfaceKHR surface, VkDevice device) : + m_allocator{allocator}, m_vk{vk}, m_instance{instance}, m_physical_device{physical_device}, m_queue_family{queue_family}, m_surface{surface}, m_device{device} { @@ -80,6 +88,106 @@ public: m_vk->DeviceWaitIdle(m_device); m_vk->DestroyCommandPool(m_device, m_frame_resources.cmd_pool, kVkAlloc); } + + StatusOr> CreateSwapchain() override + { + auto temp_alloc = temp_api->Acquire(); + + VkSurfaceCapabilitiesKHR caps; + VkResult res = m_vk->GetPhysicalDeviceSurfaceCapabilitiesKHR(m_physical_device, m_surface, &caps); + if (res != VK_SUCCESS) + { + return RuntimeError("Couldn't retrieve Vulkan surface capabitilies"); + } + + uint32_t format_count = 0; + uint32_t present_mode_count = 0; + + m_vk->GetPhysicalDeviceSurfaceFormatsKHR(m_physical_device, m_surface, &format_count, nullptr); + m_vk->GetPhysicalDeviceSurfacePresentModesKHR(m_physical_device, m_surface, &present_mode_count, nullptr); + + auto formats = temp_alloc.allocator().NewArray(format_count); + auto present_modes = temp_alloc.allocator().NewArray(present_mode_count); + + m_vk->GetPhysicalDeviceSurfaceFormatsKHR(m_physical_device, m_surface, &format_count, formats.data()); + m_vk->GetPhysicalDeviceSurfacePresentModesKHR(m_physical_device, m_surface, &present_mode_count, present_modes.data()); + + VkPresentModeKHR present_mode = VK_PRESENT_MODE_FIFO_KHR; + if (present_modes.Contains(VK_PRESENT_MODE_MAILBOX_KHR)) + { + present_mode = VK_PRESENT_MODE_MAILBOX_KHR; + } + + static constexpr VkFormat kAcceptableFormats[] = { + VK_FORMAT_R8G8B8_SRGB, + VK_FORMAT_B8G8R8_SRGB, + VK_FORMAT_R8G8B8A8_SRGB, + VK_FORMAT_B8G8R8A8_SRGB, + }; + + bool has_format = false; + VkSurfaceFormatKHR format; + for (const auto& candidate: kAcceptableFormats) + { + for (const auto& f: formats) + { + if (f.format == candidate && f.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) + { + has_format = true; + format = f; + break; + } + } + + if (has_format) { break; } + } + + + if (!has_format) + { + return RuntimeError("No acceptable Vulkan swapchain format found"); + } + + VkSwapchainCreateInfoKHR create_info = { + .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, + .pNext = nullptr, + .flags = 0, + .surface = m_surface, + .minImageCount = Clamp(2, caps.minImageCount, caps.maxImageCount), + .imageFormat = format.format, + .imageColorSpace = format.colorSpace, + .imageExtent = caps.currentExtent, + .imageArrayLayers = 1, + .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, + .imageSharingMode = VK_SHARING_MODE_EXCLUSIVE, + .queueFamilyIndexCount = 0, + .pQueueFamilyIndices = nullptr, + .preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR, + .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, + .presentMode = present_mode, + .clipped = VK_TRUE, + .oldSwapchain = VK_NULL_HANDLE, + }; + + VkSwapchainKHR vk_swapchain{}; + res = m_vk->CreateSwapchainKHR(m_device, &create_info, kVkAlloc, &vk_swapchain); + if (res != VK_SUCCESS) + { + return RuntimeError("Error when creating Vulkan swapchain"); + } + + auto* swapchain = m_allocator->New(); + swapchain->swapchain = vk_swapchain; + + return swapchain; + } + + void DestroySwapchain(gsl::owner swapchain) override + { + auto* vk_swapchain = (VulkanSwapchain*)swapchain; + m_vk->DestroySwapchainKHR(m_device, vk_swapchain->swapchain, kVkAlloc); + m_allocator->Delete(swapchain); + } }; StatusOr CreateInstance(VulkanApi* vk) @@ -315,6 +423,7 @@ StatusOr> InitializeVulkan(Allocator* allocator, OsW vulkan_loader_api->LoadDevice(vk, device); return allocator->New( + allocator, vk, instance, physical_device, queue_family, surface, device); } -- cgit