Files
RedScarfEngine/graphics/src/vulkan_swapchain.c
T
Piotr Krygier 984a56a8e8 Fix image size and semaphore issues
There was an issue with image size for depth
and color attachment, which has been fixed.
Also, finally found and issue with semaphore indexing

Signed-off-by: Piotr Krygier <piotrkrygier@everyonecancode@xyz>
2026-03-14 10:01:24 +01:00

211 lines
8.0 KiB
C

#include "vulkan_swapchain.h"
#include <SDL3/SDL_events.h>
#include <stdlib.h>
#include <string.h>
#include "src/graphics_context.h"
#include "utilities/commons.h"
#include "utilities/errors_common.h"
#include "vulkan/vulkan_core.h"
#include "vulkan_commons.h"
#include "vulkan_image.h"
/**
* @brief Create a Swapchain
*
* @return rse_err_t RSE_ERROR_NO_ERROR on success. Possible errors:
* VULKAN_ERROR_SWAPCHAIN_CREATION_FAILED
*/
static rse_err_t create_swapchain(struct graphics_context_t* context)
{
VkSwapchainCreateInfoKHR create_info;
VkSurfaceCapabilitiesKHR physical_device_surface_capabilities;
rse_err_t status = RSE_ERROR_NO_ERROR;
VkBool32 surfaceSupported;
VkExtent2D extent = {0};
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(context->vulkan_handles.physical_device,
context->vulkan_handles.surface,
&physical_device_surface_capabilities);
STATUS_CHECK(image_get_extent(context, &extent));
/* Store extent in global variable, for later use */
context->swapchain_data.swapchain_extent = extent;
/* Check if device supports surface for presentation */
vkGetPhysicalDeviceSurfaceSupportKHR(context->vulkan_handles.physical_device,
context->queue_family_indices[0],
context->vulkan_handles.surface,
&surfaceSupported);
create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
create_info.pNext = NULL;
create_info.flags = 0U;
create_info.surface = context->vulkan_handles.surface;
create_info.minImageCount = SWAP_BUFFER_COUNT;
create_info.imageFormat = IMAGE_FORMAT;
create_info.imageColorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
create_info.imageExtent = context->swapchain_data.swapchain_extent;
create_info.imageArrayLayers = 1U; /* For non-stereoscopic-3D applications, this value is 1. */
create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; /* Using only one queue family, so this is ok
*/
create_info.queueFamilyIndexCount = 1U;
create_info.pQueueFamilyIndices = context->queue_family_indices;
create_info.preTransform = physical_device_surface_capabilities.currentTransform;
create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
create_info.presentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
create_info.clipped = VK_TRUE;
create_info.oldSwapchain = VK_NULL_HANDLE;
if (VK_SUCCESS !=
vkCreateSwapchainKHR(context->vulkan_handles.device, &create_info, NULL, &context->swapchain_data.swapchain)) {
SDL_LogCritical(SDL_LOG_CATEGORY_GPU, "Failed to create swapchain");
return RSE_ERROR_INTERNAL_ERROR;
}
/* Obtain swapchain images */
vkGetSwapchainImagesKHR(context->vulkan_handles.device,
context->swapchain_data.swapchain,
&context->swapchain_images_count,
NULL);
vkGetSwapchainImagesKHR(context->vulkan_handles.device,
context->swapchain_data.swapchain,
&context->swapchain_images_count,
context->swapchain_data.swapchain_images);
return RSE_ERROR_NO_ERROR;
}
/**
* @brief Create a Swapchain Image Views
*
* @return rse_err_t RSE_ERROR_NO_ERROR on success. Possible errors:
*/
static rse_err_t create_swapchain_image_views(struct graphics_context_t* context)
{
for (size_t i = 0; i < SWAPCHAIN_IMAGE_COUNT; i++) {
VkImageViewCreateInfo create_info;
create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
create_info.pNext = NULL;
create_info.flags = 0U;
create_info.image = context->swapchain_data.swapchain_images[i];
create_info.viewType = VK_IMAGE_VIEW_TYPE_2D; /* 2D Texture */
create_info.format = VK_FORMAT_B8G8R8A8_SRGB;
create_info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
create_info.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
create_info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
create_info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
create_info.subresourceRange.baseMipLevel = 0U;
create_info.subresourceRange.levelCount = 1U;
create_info.subresourceRange.baseArrayLayer = 0U;
create_info.subresourceRange.layerCount = 1U;
if (VK_SUCCESS != vkCreateImageView(context->vulkan_handles.device,
&create_info,
NULL,
&context->swapchain_data.swapchain_image_views[i])) {
SDL_LogCritical(SDL_LOG_CATEGORY_GPU, "Failed to create swapchain image view");
return RSE_ERROR_INTERNAL_ERROR;
}
}
return RSE_ERROR_NO_ERROR;
}
/**
* @brief Create Frambuffers
*
* @return rse_err_t RSE_ERROR_NO_ERROR on success. Possible errors:
*/
static rse_err_t create_framebuffers(struct graphics_context_t* context)
{
for (size_t i = 0; i < context->swapchain_images_count; i++) {
VkImageView attachments[] = {context->color_image.image_view,
context->depth_image.image_view,
context->swapchain_data.swapchain_image_views[i]};
VkFramebufferCreateInfo framebufferInfo = {0};
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
framebufferInfo.renderPass = context->vulkan_handles.render_pass;
framebufferInfo.attachmentCount = 3;
framebufferInfo.pAttachments = attachments;
framebufferInfo.width = context->swapchain_data.swapchain_extent.width;
framebufferInfo.height = context->swapchain_data.swapchain_extent.height;
framebufferInfo.layers = 1;
if (vkCreateFramebuffer(context->vulkan_handles.device,
&framebufferInfo,
NULL,
&context->swapchain_data.swapchain_framebuffers[i]) != VK_SUCCESS) {
SDL_LogCritical(SDL_LOG_CATEGORY_GPU, "Failed to create framebuffer");
return RSE_ERROR_INTERNAL_ERROR;
}
}
return RSE_ERROR_NO_ERROR;
}
/**
* @brief Recreate swapchain
*
*/
void recreate_swapchain(struct graphics_context_t* context)
{
SDL_Event event;
int width = 0;
int height = 0;
SDL_GetWindowSizeInPixels(context->window_handle, &width, &height);
while (width == 0 || height == 0) {
SDL_GetWindowSizeInPixels(context->window_handle, &width, &height);
SDL_WaitEvent(&event);
}
vkDeviceWaitIdle(context->vulkan_handles.device);
cleanup_swapchain(context);
create_swapchain(context);
create_swapchain_image_views(context);
create_color_resource(context);
create_depth_resources(context);
create_framebuffers(context);
}
/**
* @brief Cleanup swapchain
*
*/
void cleanup_swapchain(struct graphics_context_t* context)
{
size_t i;
destroy_color_resource(context);
destroy_depth_resource(context);
for (i = 0; i < context->swapchain_images_count; i++) {
vkDestroyFramebuffer(context->vulkan_handles.device, context->swapchain_data.swapchain_framebuffers[i], NULL);
}
for (i = 0; i < context->swapchain_images_count; i++) {
vkDestroyImageView(context->vulkan_handles.device, context->swapchain_data.swapchain_image_views[i], NULL);
}
vkDestroySwapchainKHR(context->vulkan_handles.device, context->swapchain_data.swapchain, NULL);
}
rse_err_t create_swapchain_and_framebuffers(struct graphics_context_t* context)
{
rse_err_t status = RSE_ERROR_NO_ERROR;
STATUS_CHECK(create_swapchain(context));
STATUS_CHECK(create_swapchain_image_views(context));
STATUS_CHECK(create_framebuffers(context));
return status;
}