From 7def557f92ef1065c49e79c694aeb3f91914b058 Mon Sep 17 00:00:00 2001 From: Joshua Goins Date: Tue, 4 Oct 2022 09:53:38 -0400 Subject: [PATCH] Initialize Vulkan swapchain and render pass --- src/pc/gfx/gfx_vulkan.cpp | 195 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 189 insertions(+), 6 deletions(-) diff --git a/src/pc/gfx/gfx_vulkan.cpp b/src/pc/gfx/gfx_vulkan.cpp index 38c2804..f3a7e99 100644 --- a/src/pc/gfx/gfx_vulkan.cpp +++ b/src/pc/gfx/gfx_vulkan.cpp @@ -4,15 +4,23 @@ #include #include #include +#include #include "gfx_rendering_api.h" +#include "gfx_pc.h" +#include "gfx_window_manager_api.h" -static VkInstance instance; -static VkPhysicalDevice physical_device; -static VkDevice device; -static VkQueue graphics_queue; -static VkQueue present_queue; -static VkCommandPool command_pool; +static VkInstance instance = VK_NULL_HANDLE; +static VkPhysicalDevice physical_device = VK_NULL_HANDLE; +static VkDevice device = VK_NULL_HANDLE; +static VkQueue graphics_queue = VK_NULL_HANDLE; +static VkQueue present_queue = VK_NULL_HANDLE; +static VkCommandPool command_pool = VK_NULL_HANDLE; +static VkSwapchainKHR swapchain = VK_NULL_HANDLE; +static VkFormat surface_format; +static std::vector swapchain_images; +static std::vector swapchain_views; +static VkRenderPass render_pass = VK_NULL_HANDLE; VKAPI_ATTR VkBool32 VKAPI_CALL gfx_vulkan_debug_callback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, @@ -218,11 +226,15 @@ static void gfx_vulkan_create_device() { } } + std::array device_extensions = {"VK_KHR_swapchain"}; + VkDeviceCreateInfo device_create_info = {}; device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; device_create_info.pQueueCreateInfos = queue_create_infos.data(); device_create_info.queueCreateInfoCount = static_cast(queue_create_infos.size()); + device_create_info.ppEnabledExtensionNames = device_extensions.data(); + device_create_info.enabledExtensionCount = device_extensions.size(); vkCreateDevice(physical_device, &device_create_info, nullptr, &device); @@ -234,9 +246,180 @@ static void gfx_vulkan_create_device() { gfx_vulkan_create_command_pool(graphics_family_index); } +static void gfx_vulkan_create_swapchain() { + vkQueueWaitIdle(present_queue); + + // create surface from wapi + VkSurfaceKHR surface = + static_cast(gfx_get_current_windowing_api()->create_surface(instance)); + + VkBool32 supported; + vkGetPhysicalDeviceSurfaceSupportKHR(physical_device, 0, + surface, &supported); + + // query swapchain support + VkSurfaceCapabilitiesKHR capabilities; + vkGetPhysicalDeviceSurfaceCapabilitiesKHR( + physical_device, surface, &capabilities); + + std::vector formats; + + uint32_t format_count; + vkGetPhysicalDeviceSurfaceFormatsKHR( + physical_device, surface, &format_count, nullptr); + + formats.resize(format_count); + vkGetPhysicalDeviceSurfaceFormatsKHR( + physical_device, surface, &format_count, formats.data()); + + std::vector present_modes; + uint32_t present_mode_count; + vkGetPhysicalDeviceSurfacePresentModesKHR( + physical_device, surface, &present_mode_count, nullptr); + + present_modes.resize(present_mode_count); + vkGetPhysicalDeviceSurfacePresentModesKHR( + physical_device, surface, &present_mode_count, + present_modes.data()); + + // choosing swapchain features + surface_format = formats[0].format; + for (const auto& available_format : formats) { + if (available_format.format == VK_FORMAT_B8G8R8A8_UNORM && available_format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { + surface_format = available_format.format; + } + } + + VkPresentModeKHR present_mode = VK_PRESENT_MODE_FIFO_KHR; + for (const auto& available_mode : present_modes) { + if (available_mode == VK_PRESENT_MODE_MAILBOX_KHR) { + present_mode = available_mode; + } + } + + uint32_t image_count = capabilities.minImageCount + 1; + if (capabilities.maxImageCount > 0 && image_count > capabilities.maxImageCount) { + image_count = capabilities.maxImageCount; + } + + // create swapchain + VkSwapchainCreateInfoKHR swapchain_create_info = {}; + swapchain_create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; + swapchain_create_info.surface = surface; + swapchain_create_info.minImageCount = image_count; + swapchain_create_info.imageFormat = surface_format; + swapchain_create_info.imageColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; // FIXME: hardcoded + swapchain_create_info.imageExtent.width = 640; // FIXME: hardcoded + swapchain_create_info.imageExtent.height = 480; + swapchain_create_info.imageArrayLayers = 1; + swapchain_create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + swapchain_create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; + swapchain_create_info.preTransform = capabilities.currentTransform; + swapchain_create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; + swapchain_create_info.presentMode = present_mode; + swapchain_create_info.clipped = VK_TRUE; + + VkSwapchainKHR old_swapchain = swapchain; + swapchain_create_info.oldSwapchain = old_swapchain; + + vkCreateSwapchainKHR(device, &swapchain_create_info, nullptr, &swapchain); + + if(old_swapchain != VK_NULL_HANDLE) { + vkDestroySwapchainKHR(device, old_swapchain, nullptr); + } + + vkGetSwapchainImagesKHR(device, swapchain, &image_count, + nullptr); + swapchain_images.resize(image_count); + vkGetSwapchainImagesKHR(device, swapchain, &image_count, swapchain_images.data()); + + swapchain_views.resize(swapchain_images.size()); + + for (size_t i = 0; i < swapchain_images.size(); i++) { + VkImageViewCreateInfo view_create_info = {}; + view_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + view_create_info.image = swapchain_images[i]; + view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D; + view_create_info.format = surface_format; + view_create_info.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; + view_create_info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; + view_create_info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; + view_create_info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; + view_create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + view_create_info.subresourceRange.baseMipLevel = 0; + view_create_info.subresourceRange.levelCount = 1; + view_create_info.subresourceRange.baseArrayLayer = 0; + view_create_info.subresourceRange.layerCount = 1; + + vkCreateImageView(device, &view_create_info, nullptr,&swapchain_views[i]); + } + + printf("Initialized swap chain!\n"); +} + +static void gfx_vulkan_create_render_pass() { + VkAttachmentDescription color_attachment = {}; + color_attachment.format = surface_format; + color_attachment.samples = VK_SAMPLE_COUNT_1_BIT; + color_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + color_attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + color_attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + color_attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + color_attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + color_attachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + + VkAttachmentReference color_attachment_ref = {}; + color_attachment_ref.attachment = 0; + color_attachment_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + VkAttachmentDescription depth_attachment = {}; + depth_attachment.format = VK_FORMAT_D32_SFLOAT; + depth_attachment.samples = VK_SAMPLE_COUNT_1_BIT; + depth_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + depth_attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + depth_attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + depth_attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + depth_attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + depth_attachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + + VkAttachmentReference depth_attachment_ref = {}; + depth_attachment_ref.attachment = 1; + depth_attachment_ref.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + + VkSubpassDependency dependency = {}; + dependency.srcSubpass = VK_SUBPASS_EXTERNAL; + dependency.dstSubpass = 0; + dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; + dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; + dependency.srcAccessMask = 0; + dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + dependency.dependencyFlags = 0; + + VkSubpassDescription subpass = {}; + subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + subpass.colorAttachmentCount = 1; + subpass.pColorAttachments = &color_attachment_ref; + subpass.pDepthStencilAttachment = &depth_attachment_ref; + + std::array attachments = { color_attachment, depth_attachment }; + + VkRenderPassCreateInfo render_pass_create_info = {}; + render_pass_create_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + render_pass_create_info.attachmentCount = attachments.size(); + render_pass_create_info.pAttachments = attachments.data(); + render_pass_create_info.subpassCount = 1; + render_pass_create_info.pSubpasses = &subpass; + render_pass_create_info.dependencyCount = 1; + render_pass_create_info.pDependencies = &dependency; + + vkCreateRenderPass(device, &render_pass_create_info, nullptr, &render_pass); +} + static void gfx_vulkan_renderer_init(void) { gfx_vulkan_create_instance(); gfx_vulkan_create_device(); + gfx_vulkan_create_swapchain(); + gfx_vulkan_create_render_pass(); } static void gfx_vulkan_renderer_on_resize(void) {