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);

}

相关推荐
OEC小胖胖1 分钟前
前端框架状态管理对比:Redux、MobX、Vuex 等的优劣与选择
前端·前端框架·web
通域7 分钟前
Mac (m1) Java 加载本地C共享库函数 .dylib 函数 Unable to load library ‘liblicense‘
java·python·macos
hqxstudying12 分钟前
Java行为型模式---模板方法模式
java·开发语言·设计模式·代码规范·模板方法模式
字节架构前端1 小时前
k8s场景下的指标监控体系构建——Prometheus 简介
前端·架构
iam_leeqing1 小时前
Lambda表达式
java·spring
你我约定有三1 小时前
设计模式--适配器模式
java·设计模式·适配器模式
奕羽晨1 小时前
关于CSS的一些读书笔记
前端·css
Poetry2371 小时前
大屏数据可视化适配方案
前端
JouJz1 小时前
设计模式之代理模式:掌控对象访问的优雅之道
java·spring·设计模式·系统安全·代理模式