160 lines
5.4 KiB
C
160 lines
5.4 KiB
C
/* SPDX-License-Identifier:BSD-3-Clause */
|
|
#include "swapchain.h"
|
|
#include "../../core/log.h"
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#define RGFW_IMPORT
|
|
#include "../../rgfw.h"
|
|
|
|
static VkSurfaceFormatKHR select_surface_format(VkPhysicalDevice device, VkSurfaceKHR surface)
|
|
{
|
|
u32 format_count = 0;
|
|
vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &format_count, NULL);
|
|
|
|
VkSurfaceFormatKHR *formats = malloc(sizeof(VkSurfaceFormatKHR) * format_count);
|
|
vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &format_count, formats);
|
|
|
|
VkSurfaceFormatKHR selected = formats[0];
|
|
for (u32 i = 0; i < format_count; i++) {
|
|
if (formats[i].format == VK_FORMAT_B8G8R8A8_SRGB &&
|
|
formats[i].colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
|
|
selected = formats[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
free(formats);
|
|
return selected;
|
|
}
|
|
|
|
static VkPresentModeKHR select_present_mode(VkPhysicalDevice device, VkSurfaceKHR surface)
|
|
{
|
|
u32 mode_count = 0;
|
|
vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &mode_count, NULL);
|
|
|
|
VkPresentModeKHR *modes = malloc(sizeof(VkPresentModeKHR) * mode_count);
|
|
vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &mode_count, modes);
|
|
|
|
VkPresentModeKHR selected = VK_PRESENT_MODE_FIFO_KHR;
|
|
for (u32 i = 0; i < mode_count; i++) {
|
|
if (modes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
|
|
selected = VK_PRESENT_MODE_MAILBOX_KHR;
|
|
break;
|
|
}
|
|
}
|
|
|
|
free(modes);
|
|
return selected;
|
|
}
|
|
|
|
static VkExtent2D select_extent(VkSurfaceCapabilitiesKHR *caps, RGFW_window *window)
|
|
{
|
|
if (caps->currentExtent.width != 0xFFFFFFFF) {
|
|
return caps->currentExtent;
|
|
}
|
|
|
|
i32 w, h;
|
|
RGFW_window_getSize(window, &w, &h);
|
|
|
|
VkExtent2D extent;
|
|
extent.width = (u32)w;
|
|
extent.height = (u32)h;
|
|
|
|
if (extent.width < caps->minImageExtent.width)
|
|
extent.width = caps->minImageExtent.width;
|
|
if (extent.width > caps->maxImageExtent.width)
|
|
extent.width = caps->maxImageExtent.width;
|
|
if (extent.height < caps->minImageExtent.height)
|
|
extent.height = caps->minImageExtent.height;
|
|
if (extent.height > caps->maxImageExtent.height)
|
|
extent.height = caps->maxImageExtent.height;
|
|
|
|
return extent;
|
|
}
|
|
|
|
void vk_swapchain_init(struct renderer_context *context)
|
|
{
|
|
VkSurfaceCapabilitiesKHR caps;
|
|
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(context->physical_device, context->surface, &caps);
|
|
|
|
VkSurfaceFormatKHR format = select_surface_format(context->physical_device, context->surface);
|
|
VkPresentModeKHR present_mode = select_present_mode(context->physical_device, context->surface);
|
|
VkExtent2D extent = select_extent(&caps, context->window);
|
|
|
|
u32 image_count = caps.minImageCount + 1;
|
|
if (caps.maxImageCount > 0 && image_count > caps.maxImageCount) {
|
|
image_count = caps.maxImageCount;
|
|
}
|
|
|
|
VkSwapchainCreateInfoKHR create_info = {
|
|
.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
|
|
.surface = context->surface,
|
|
.minImageCount = image_count,
|
|
.imageFormat = format.format,
|
|
.imageColorSpace = format.colorSpace,
|
|
.imageExtent = extent,
|
|
.imageArrayLayers = 1,
|
|
.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
|
|
.preTransform = caps.currentTransform,
|
|
.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
|
|
.presentMode = present_mode,
|
|
.clipped = VK_TRUE,
|
|
.oldSwapchain = VK_NULL_HANDLE
|
|
};
|
|
|
|
u32 queue_indices[] = { context->queue_indices.graphics, context->queue_indices.present };
|
|
if (context->queue_indices.graphics != context->queue_indices.present) {
|
|
create_info.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
|
|
create_info.queueFamilyIndexCount = 2;
|
|
create_info.pQueueFamilyIndices = queue_indices;
|
|
} else {
|
|
create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
|
}
|
|
|
|
if (vkCreateSwapchainKHR(context->device, &create_info, NULL, &context->swapchain.handle) != VK_SUCCESS) {
|
|
fatal("Can't create swapchain.\n");
|
|
}
|
|
|
|
context->swapchain.format = format.format;
|
|
context->swapchain.extent = extent;
|
|
|
|
vkGetSwapchainImagesKHR(context->device, context->swapchain.handle, &context->swapchain.image_count, NULL);
|
|
context->swapchain.images = malloc(sizeof(VkImage) * context->swapchain.image_count);
|
|
vkGetSwapchainImagesKHR(context->device, context->swapchain.handle, &context->swapchain.image_count, context->swapchain.images);
|
|
|
|
context->swapchain.image_views = malloc(sizeof(VkImageView) * context->swapchain.image_count);
|
|
for (u32 i = 0; i < context->swapchain.image_count; i++) {
|
|
VkImageViewCreateInfo view_info = {
|
|
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
|
.image = context->swapchain.images[i],
|
|
.viewType = VK_IMAGE_VIEW_TYPE_2D,
|
|
.format = context->swapchain.format,
|
|
.components.r = VK_COMPONENT_SWIZZLE_IDENTITY,
|
|
.components.g = VK_COMPONENT_SWIZZLE_IDENTITY,
|
|
.components.b = VK_COMPONENT_SWIZZLE_IDENTITY,
|
|
.components.a = VK_COMPONENT_SWIZZLE_IDENTITY,
|
|
.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
|
.subresourceRange.baseMipLevel = 0,
|
|
.subresourceRange.levelCount = 1,
|
|
.subresourceRange.baseArrayLayer = 0,
|
|
.subresourceRange.layerCount = 1
|
|
};
|
|
|
|
if (vkCreateImageView(context->device, &view_info, NULL, &context->swapchain.image_views[i]) != VK_SUCCESS) {
|
|
fatal("Can't create image view.\n");
|
|
}
|
|
}
|
|
|
|
log_info("Swapchain created.\n");
|
|
}
|
|
|
|
void vk_swapchain_deinit(struct renderer_context *context)
|
|
{
|
|
for (u32 i = 0; i < context->swapchain.image_count; i++) {
|
|
vkDestroyImageView(context->device, context->swapchain.image_views[i], NULL);
|
|
}
|
|
free(context->swapchain.image_views);
|
|
free(context->swapchain.images);
|
|
vkDestroySwapchainKHR(context->device, context->swapchain.handle, NULL);
|
|
}
|