vulkan游戏引擎的核心交换链swapchain实现

1.swapchain.h

#pragma once

#include "vulkan_types.inl"

void vulkan_swapchain_create(

vulkan_context* context,

u32 width,

u32 height,

vulkan_swapchain* out_swapchain);

void vulkan_swapchain_recreate(

vulkan_context* context,

u32 width,

u32 height,

vulkan_swapchain* swapchain);

b8 vulkan_swapchain_acquire_next_image_index(

vulkan_context* context,

vulkan_swapchain* swapchain,

u64 timeout_ns,

VkSemaphore image_available_semaphore,

VkFence fence,

u32* out_image_index

);

void vulkan_swapchain_present(

vulkan_context* context,

vulkan_swapchain* swapchain,

VkQueue graphics_queue,

VkQueue present_queue,

VkSemaphore render_complete_semaphore,

u32 present_image_index

);

void vulkan_swapchain_destroy(

vulkan_context* context,

vulkan_swapchain* swapchain

);

2.swapchain.c

#include "vulkan_swapchain.h"

#include "defines.h"

#include "vulkan_image.h"

#include "core/logger.h"

#include "core/kmemory.h"

#include "vulkan_device.h"

b8 create(vulkan_context* context,u32 width,u32 height,vulkan_swapchain* swapchain);

void destroy(vulkan_context* context,vulkan_swapchain* swapchain);

void vulkan_swapchain_create(

vulkan_context* context,

u32 width,

u32 height,

vulkan_swapchain* out_swapchain

)

{

create(context,width,height,out_swapchain);

}

void vulkan_swapchain_recreate(

vulkan_context* context,

u32 width,

u32 height,

vulkan_swapchain* swapchain

)

{

destroy(context,swapchain);

create(context,width,height,swapchain);

}

void vulkan_swapchain_destroy(

vulkan_context* context,

vulkan_swapchain* swapchain

)

{

destroy(context,swapchain);

}

b8 vulkan_swapchain_acquire_next_image_index(

vulkan_context* context,

vulkan_swapchain* swapchain,

u64 timeout_ns,

VkSemaphore image_available_semaphore,

VkFence fence,

u32* out_image_index

)

{

VkResult result = vkAcquireNextImageKHR(

context->device.logical_device,

swapchain->handle,

timeout_ns,

image_available_semaphore,

fence,

out_image_index

);

if(result == VK_ERROR_OUT_OF_DATE_KHR)

{

vulkan_swapchain_recreate(context,context->framebuffer_width,context->framebuffer_height,swapchain);

return false;

}else if(result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR)

{

KFATAL("Fatal to acquire swapchain image!");

return false;

}

return true;

}

void vulkan_swapchain_present(

vulkan_context* context,

vulkan_swapchain* swapchain,

VkQueue graphics_queue,

VkQueue present_queue,

VkSemaphore render_complete_semaphore,

u32 present_image_index)

{

//Reture the image to the swapchain for presentation.

VkPresentInfoKHR present_info = {VK_STRUCTURE_TYPE_PRESENT_INFO_KHR};

present_info.waitSemaphoreCount = 1;

present_info.pWaitSemaphores = &render_complete_semaphore;

present_info.swapchainCount = 1;

present_info.pSwapchains = &swapchain->handle;

present_info.pImageIndices = &present_image_index;

present_info.pResults = 0;

VkResult result = vkQueuePresentKHR(present_queue,&present_info);

if(result == VK_ERROR_OUT_OF_DATE_KHR || result==VK_SUBOPTIMAL_KHR)

{

vulkan_swapchain_recreate(context,context->framebuffer_width,context->framebuffer_height,swapchain);

}else if(result != VK_SUCCESS)

{

KFATAL("Failed to present swap chain image!");

}

//Increment the index

context->current_frame = (context->current_frame+1) % swapchain->max_frames_in_flight;

}

b8 create(vulkan_context* context,u32 width,u32 height,vulkan_swapchain* swapchain)

{

VkExtent2D swapchain_extent = {width,height};

vulkan_device_query_swapchain_support(

context->device.physical_device,

context->surface,

&context->device.swapchain_support

);

//Choose a swap surface format.

b8 found = false;

for(u32 i = 0;i <context->device.swapchain_support.format_count;++i)

{

VkSurfaceFormatKHR format = context->device.swapchain_support.formats[i];

//Preferred formats

if(format.format == VK_FORMAT_B8G8R8A8_UNORM &&

format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)

{

swapchain->image_format = format;

found = true;

break;

}

}

if(!found)

{

swapchain->image_format = context->device.swapchain_support.formats[0];

}

VkPresentModeKHR present_mode = VK_PRESENT_MODE_FIFO_KHR;

for(u32 i = 0;i<context->device.swapchain_support.present_mode_count;++i)

{

VkPresentModeKHR mode = context->device.swapchain_support.present_modes[i];

if(mode == VK_PRESENT_MODE_MAILBOX_KHR)

{

present_mode = mode;

break;

}

}

vulkan_swapchain_support_info* swapchain_support = &context->device.swapchain_support;

if (swapchain_support->format_count < 1 || swapchain_support->present_mode_count < 1) {

if (swapchain_support->formats) {

kfree(swapchain_support->formats, sizeof(VkSurfaceFormatKHR) * swapchain_support->format_count, MEMORY_TAG_RENDERER);

}

if (swapchain_support->present_modes) {

kfree(swapchain_support->present_modes, sizeof(VkPresentModeKHR) * swapchain_support->present_mode_count, MEMORY_TAG_RENDERER);

}

KINFO("Required swapchain support not present, skipping device.");

return false;

}

//Swapchain extent

if(context->device.swapchain_support.capabilities.currentExtent.width != UINT32_MAX)

{

swapchain_extent = context->device.swapchain_support.capabilities.currentExtent;

}

//to value allowed to gpu

VkExtent2D min = context->device.swapchain_support.capabilities.minImageExtent;

VkExtent2D max = context->device.swapchain_support.capabilities.maxImageExtent;

swapchain_extent.width = KCLAMP(swapchain_extent.width,min.width,max.width);

swapchain_extent.height = KCLAMP(swapchain_extent.height,min.height,max.height);

u32 image_count = context->device.swapchain_support.capabilities.minImageCount + 1;

if(context->device.swapchain_support.capabilities.maxImageCount >0&& image_count > context->device.swapchain_support.capabilities.maxImageCount)

{

image_count = context->device.swapchain_support.capabilities.maxImageCount;

}

swapchain->max_frames_in_flight = image_count - 1;

VkSwapchainCreateInfoKHR swapchain_create_info = {VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR};

swapchain_create_info.surface =context->surface;

swapchain_create_info.minImageCount = image_count;

swapchain_create_info.imageFormat = swapchain->image_format.format;

swapchain_create_info.imageColorSpace = swapchain->image_format.colorSpace;

swapchain_create_info.imageExtent = swapchain_extent;

swapchain_create_info.imageArrayLayers = 1;

swapchain_create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;

//Setup the queue family indices

if(context->device.graphics_queue_index != context->device.present_queue_index)

{

u32 queueFamilyIndices[] = {

(u32)context->device.graphics_queue_index,

(u32)context->device.present_queue_index

};

swapchain_create_info.imageSharingMode = VK_SHARING_MODE_CONCURRENT;

swapchain_create_info.queueFamilyIndexCount = 2;

swapchain_create_info.pQueueFamilyIndices = queueFamilyIndices;

}else

{

swapchain_create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;

swapchain_create_info.queueFamilyIndexCount = 0;

swapchain_create_info.pQueueFamilyIndices = 0;

}

swapchain_create_info.preTransform = context->device.swapchain_support.capabilities.currentTransform;

swapchain_create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;

swapchain_create_info.presentMode = present_mode;

swapchain_create_info.clipped = VK_TRUE;

swapchain_create_info.oldSwapchain = 0;

//VkResult result = vkCreateSwapchainKHR(context->device.logical_device, &swapchain_create_info, context->allocator, &swapchain->handle);

VK_CHECK(vkCreateSwapchainKHR(context->device.logical_device,&swapchain_create_info,context->allocator,&swapchain->handle));

// Verify the swapchain creation.

context->current_frame = 0;

swapchain->image_count = 0;

//VkImage swapchain_images[32];

// result = vkGetSwapchainImagesKHR(context->device.logical_device, swapchain->handle, &swapchain->image_count, 0);

VK_CHECK(vkGetSwapchainImagesKHR(context->device.logical_device,swapchain->handle,&swapchain->image_count,0));

if(!swapchain->images)

{

swapchain->images = (VkImage*)kallocate(sizeof(VkImage)* swapchain->image_count,MEMORY_TAG_RENDERER);

}

if(!swapchain->views)

{

swapchain->views = (VkImageView*)kallocate(sizeof(VkImageView) * swapchain->image_count,MEMORY_TAG_RENDERER);

}

VK_CHECK(vkGetSwapchainImagesKHR(context->device.logical_device,swapchain->handle,&swapchain->image_count,swapchain->images));

//Views

for(u32 i=0;i<swapchain->image_count;++i)

{

VkImageViewCreateInfo view_info = {VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO};

view_info.image = swapchain->images[i];

view_info.viewType = VK_IMAGE_VIEW_TYPE_2D;

view_info.format = swapchain->image_format.format;

view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;

view_info.subresourceRange.baseMipLevel = 0;

view_info.subresourceRange.levelCount = 1;

view_info.subresourceRange.baseArrayLayer = 0;

view_info.subresourceRange.layerCount = 1;

VK_CHECK(vkCreateImageView(context->device.logical_device,&view_info,context->allocator,&swapchain->views[i]));

}

//Depth resource

if(!vulkan_device_detect_depth_format(&context->device))

{

context->device.depth_format = VK_FORMAT_UNDEFINED;

KFATAL("Failed to find a supported format!");

}

vulkan_image_create(

context,

VK_IMAGE_TYPE_2D,

swapchain_extent.width,

swapchain_extent.height,

context->device.depth_format,

VK_IMAGE_TILING_OPTIMAL,

VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,

VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,

true,

VK_IMAGE_ASPECT_DEPTH_BIT,

&swapchain->depth_attachment

);

KINFO("Swapchain created successfully!");

return true;

}

void destroy(vulkan_context* context,vulkan_swapchain* swapchain)

{

vkDeviceWaitIdle(context->device.logical_device);

vulkan_image_destroy(context,&swapchain->depth_attachment);

for(u32 i = 0;i <swapchain->image_count;++i)

{

vkDestroyImageView(context->device.logical_device,swapchain->views[i],context->allocator);

}

vkDestroySwapchainKHR(context->device.logical_device,swapchain->handle,context->allocator);

}

相关推荐
崔庆才丨静觅9 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
曹牧10 小时前
Spring Boot:如何测试Java Controller中的POST请求?
java·开发语言
passerby606110 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了10 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅10 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅11 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
爬山算法11 小时前
Hibernate(90)如何在故障注入测试中使用Hibernate?
java·后端·hibernate
kfyty72511 小时前
集成 spring-ai 2.x 实践中遇到的一些问题及解决方案
java·人工智能·spring-ai
猫头虎11 小时前
如何排查并解决项目启动时报错Error encountered while processing: java.io.IOException: closed 的问题
java·开发语言·jvm·spring boot·python·开源·maven
李少兄11 小时前
在 IntelliJ IDEA 中修改 Git 远程仓库地址
java·git·intellij-idea