1 #include <kiba/renderer/vulkan/swap_chain.h>
3 #include <kiba/renderer/vulkan/image.h>
7 #include <kiba/renderer/vulkan/depth.h>
8 #include <kiba/renderer/vulkan/framebuffers.h>
10 b8 vulkan_verify_swap_chain_format_availability(
vulkan_context *context);
11 b8 vulkan_verify_swap_chain_present_mode_availability(
vulkan_context *context);
16 if (!vulkan_verify_swap_chain_format_availability(context)) {
17 KB_INFO(
"did not find required swap chain format");
20 if (!vulkan_verify_swap_chain_present_mode_availability(context)) {
21 KB_INFO(
"did not find required swap chain present mode");
24 if (!vulkan_query_swap_chain_capabilities(context)) {
25 KB_INFO(
"could not query swap chain capabilities");
30 VkSwapchainCreateInfoKHR swap_chain_info = {
31 .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
32 .surface = context->surface,
33 .imageExtent = context->swap_chain.extent,
34 .minImageCount = context->swap_chain.image_count,
35 .imageFormat = context->swap_chain.requirements.format.format,
36 .imageColorSpace = context->swap_chain.requirements.format.colorSpace,
37 .presentMode = context->swap_chain.requirements.present_mode,
38 .imageArrayLayers = 1,
39 .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
40 .preTransform = context->swap_chain.transform,
42 .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
45 .oldSwapchain = VK_NULL_HANDLE,
47 u32 queue_family_indices[] = {context->device.graphics_queue.index, context->device.present_queue.index};
48 if (context->device.graphics_queue.index != context->device.present_queue.index) {
49 swap_chain_info.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
50 swap_chain_info.queueFamilyIndexCount = 2;
51 swap_chain_info.pQueueFamilyIndices = queue_family_indices;
53 swap_chain_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
56 VK_CALL_B8(vkCreateSwapchainKHR(context->device.logical,
58 &context->alloc.vulkan_callbacks,
59 &context->swap_chain.swap_chain));
63 VK_CALL_B8(vkGetSwapchainImagesKHR(context->device.logical, context->swap_chain.swap_chain, &image_count, 0));
64 context->swap_chain.image_count = image_count;
65 context->swap_chain.images = array_create(VkImage, image_count, &context->alloc.kiba_alloc);
66 if (context->swap_chain.images ==
KB_NULL) {
67 KB_ERROR(
"could not allocate array for swap chain images");
70 context->swap_chain.image_views = array_create(VkImageView, image_count, &context->alloc.kiba_alloc);
71 if (context->swap_chain.image_views ==
KB_NULL) {
72 KB_ERROR(
"could not allocate array for swap chain image views");
75 VK_CALL_B8(vkGetSwapchainImagesKHR(context->device.logical,
76 context->swap_chain.swap_chain,
78 context->swap_chain.images));
79 array_resize(&context->swap_chain.images, image_count);
80 array_resize(&context->swap_chain.image_views, image_count);
83 array_for_each(VkImage, image, context->swap_chain.images) {
84 if (!vulkan_image_view_create(context,
86 context->swap_chain.requirements.format.format,
87 VK_IMAGE_ASPECT_COLOR_BIT,
88 &context->swap_chain.image_views[i++])) {
98 vkDeviceWaitIdle(context->device.logical);
100 vulkan_framebuffers_destroy(context);
101 vulkan_depth_destroy(context);
102 vulkan_swap_chain_destroy(context);
108 return vulkan_swap_chain_create(context) && vulkan_depth_create(context) && vulkan_framebuffers_create(context);
112 array_for_each(VkImageView, view, context->swap_chain.image_views) { vulkan_image_view_destroy(context, view); }
113 array_destroy(&context->swap_chain.image_views);
114 array_destroy(&context->swap_chain.images);
115 vkDestroySwapchainKHR(context->device.logical, context->swap_chain.swap_chain, &context->alloc.vulkan_callbacks);
118 b8 vulkan_verify_swap_chain_format_availability(
vulkan_context *context) {
119 u32 available_format_count = 0;
121 vkGetPhysicalDeviceSurfaceFormatsKHR(context->device.physical, context->surface, &available_format_count, 0));
122 array_of(VkSurfaceFormatKHR) available_formats =
123 array_create(VkSurfaceFormatKHR, available_format_count, &context->alloc.kiba_alloc);
124 if (available_formats ==
KB_NULL) {
125 KB_ERROR(
"could not create array to store available swap chain formats");
128 VK_CALL_B8(vkGetPhysicalDeviceSurfaceFormatsKHR(context->device.physical,
130 &available_format_count,
132 array_resize(&available_formats, available_format_count);
134 b8 found_format =
false;
135 array_for_each(VkSurfaceFormatKHR, surface_format, available_formats) {
136 if (surface_format->format == context->swap_chain.requirements.format.format
137 && surface_format->colorSpace == context->swap_chain.requirements.format.colorSpace) {
143 array_destroy(&available_formats);
147 b8 vulkan_verify_swap_chain_present_mode_availability(
vulkan_context *context) {
148 u32 available_present_mode_count = 0;
149 VK_CALL_B8(vkGetPhysicalDeviceSurfacePresentModesKHR(context->device.physical,
151 &available_present_mode_count,
153 array_of(VkPresentModeKHR) available_present_modes =
154 array_create(VkPresentModeKHR, available_present_mode_count, &context->alloc.kiba_alloc);
155 if (available_present_modes ==
KB_NULL) {
156 KB_ERROR(
"could not create array to store available swap chain present modes");
159 VK_CALL_B8(vkGetPhysicalDeviceSurfacePresentModesKHR(context->device.physical,
161 &available_present_mode_count,
162 available_present_modes));
163 array_resize(&available_present_modes, available_present_mode_count);
165 b8 found_present_mode =
false;
166 array_for_each(VkPresentModeKHR, present_mode, available_present_modes) {
167 if (*present_mode == context->swap_chain.requirements.present_mode) {
168 found_present_mode =
true;
173 array_destroy(&available_present_modes);
174 return found_present_mode;
177 b8 vulkan_query_swap_chain_capabilities(
vulkan_context *context) {
178 VkSurfaceCapabilitiesKHR capabilities;
179 VK_CALL_B8(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(context->device.physical, context->surface, &capabilities));
180 if (capabilities.currentExtent.width == UINT_MAX) {
181 context->swap_chain.extent.height =
182 KB_CLAMP(context->window->
h, capabilities.minImageExtent.height, capabilities.maxImageExtent.height);
183 context->swap_chain.extent.width =
184 KB_CLAMP(context->window->
w, capabilities.minImageExtent.width, capabilities.maxImageExtent.width);
186 context->swap_chain.extent = capabilities.currentExtent;
188 context->swap_chain.image_count = capabilities.minImageCount;
189 if (capabilities.maxImageCount > capabilities.minImageCount) {
190 ++context->swap_chain.image_count;
192 context->swap_chain.transform = capabilities.currentTransform;
#define KB_CLAMP(x, min, max)
Clamp an input value to a certain range.
#define KB_NULL
Value of an invalid ptr (nullptr).
#define KB_ERROR(...)
Log entry with error log level.
#define KB_INFO(...)
Log entry with info log level.