1
Fork 0

Initialize Vulkan swapchain and render pass

This commit is contained in:
Joshua Goins 2022-10-04 09:53:38 -04:00
parent a6895f1d5f
commit 7def557f92

View file

@ -4,15 +4,23 @@
#include <vector>
#include <cstring>
#include <cstdio>
#include <array>
#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<VkImage> swapchain_images;
static std::vector<VkImageView> 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<const char*, 1> 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<uint32_t>(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<VkSurfaceKHR>(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<VkSurfaceFormatKHR> 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<VkPresentModeKHR> 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<VkAttachmentDescription, 2> 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) {