summaryrefslogtreecommitdiff
path: root/deimos/vulkan/vulkan_backend.cpp
diff options
context:
space:
mode:
authorSteven Le Rouzic <steven.lerouzic@gmail.com>2024-06-12 23:57:24 +0200
committerSteven Le Rouzic <steven.lerouzic@gmail.com>2024-06-12 23:57:24 +0200
commit8279acc1a4754bedaad0ba8bf00541c7b2a043e9 (patch)
tree586a05c6b4e2338d621d78d9107090d5b587c683 /deimos/vulkan/vulkan_backend.cpp
parent55bc67bf7989acfeadf0233a4bdd5660e8f0bb69 (diff)
Swapchain creation
Diffstat (limited to 'deimos/vulkan/vulkan_backend.cpp')
-rw-r--r--deimos/vulkan/vulkan_backend.cpp109
1 files changed, 109 insertions, 0 deletions
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<gsl::owner<RenderSwapchain*>> 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<VkSurfaceFormatKHR>(format_count);
+ auto present_modes = temp_alloc.allocator().NewArray<VkPresentModeKHR>(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<uint32_t>(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<VulkanSwapchain>();
+ swapchain->swapchain = vk_swapchain;
+
+ return swapchain;
+ }
+
+ void DestroySwapchain(gsl::owner<RenderSwapchain*> swapchain) override
+ {
+ auto* vk_swapchain = (VulkanSwapchain*)swapchain;
+ m_vk->DestroySwapchainKHR(m_device, vk_swapchain->swapchain, kVkAlloc);
+ m_allocator->Delete(swapchain);
+ }
};
StatusOr<VkInstance> CreateInstance(VulkanApi* vk)
@@ -315,6 +423,7 @@ StatusOr<gsl::owner<IVulkanBackend*>> InitializeVulkan(Allocator* allocator, OsW
vulkan_loader_api->LoadDevice(vk, device);
return allocator->New<VulkanBackendImpl>(
+ allocator,
vk, instance, physical_device,
queue_family, surface, device);
}