交换链(SwapChain)概述
Vulkan
交换链(Swapchain
)是 Vulkan
应用程序和窗口系统的一座桥梁,负责将渲染结果呈现给用户
换个说法,交换链机制是一种图元绘制结果呈现的机制,它可以将绘制的结果渲染到平台相关的展示窗口/展示层当中
(这里我理解和 android
中的 bufferqueue
机制类似,可以 dequeu buffer
绘制,同时 queue buffer
到显示系统显示)
交换链包含一组图像(一般作为渲染目标),这些图像被用于在屏幕上显示渲染的帧
注意这里在屏幕上渲染才需要 swapchain
,如果是离屏渲染,可以直接创建 vkImage
和 vkImageView
,不需要 swapchain
交换链中的图像个数和驱动层的实现是密切相关的。如果交换链中有两幅图像,那么称为双缓存,如果有三幅图像,称为三缓存
这些图像中,如果有一幅图像在后台完成了绘制过程,那么它会被交换到前台的展示窗口,为了充分利用 GPU
的性能,此时的另一幅图像会交换作为后台缓存来执行下一帧的绘制过程
这个过程往复执行,图像的交换就可以持续进行,使用多幅图像就可以保持GPU
始终处于渲染一帧图像的忙碌状态,从而降低总体的等待时间,改善输出帧速率
交换链(SwapChain)的作用
-
图像管理:交换链维护了一组用于显示的图像,称为交换链图像(Swapchain Images),交换链图像通常至少有两个,这样就可以实现双缓冲或者或缓冲,从而避免屏幕闪烁
-
同步:管理
CPU
和GPU
之间的同步,确保渲染操作不会在显示更新之前完成,这有助于防止(tearing
) 现象, 避免同一帧内看到图像的不同部分 -
图像呈现:
-
应用程序首先在一个缓冲区上进行渲染,完成渲染后,该缓冲区会被提交给交换链,然后交换链将这个缓冲区的内容显示到屏幕上
-
当一个缓冲区正在显示的时候,另一个缓冲区可以进行下一轮的渲染,这样就形成了一个循环
Vulkan tutorial:
- The swap chain is a collection of render targets(一系列 render target 的集合). Its basic purpose is to ensure that the image that we’re currently rendering to is different from the one that is currently on the screen
- The number of render targets and conditions for presenting finished images to the screen depends on the present mode. (render target 的数量和使用 present mode 比较相关)
交换链(SwapChain)的创建
交换链创建需要比较多的参数,需要通过其他的API
获取,下面是vkCreateSwapchainKHR
的函数原型:
VKAPI_ATTR VkResult VKAPI_CALL vkCreateSwapchainKHR(
VkDevice device,
const VkSwapchainCreateInfoKHR* pCreateInfo,
const VkAllocationCallbacks* pAllocator, // 自定义内存分配器回调函数指针
VkSwapchainKHR* pSwapchain); // 指向 VkSwapchainKHR 句柄的指针,函数成功返回时,包含创建的交换链
VkSwapchainCreateInfoKHR
主要包含的结构如下:
typedef struct VkSwapchainCreateInfoKHR {
VkStructureType sType; // 必须是 VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR
const void* pNext; // 指向扩展结构的指针,通常为 nullptr
VkSwapchainCreateFlagsKHR flags; // 交换链创建标志,当前版本 Vulkan 中未使用,设置为 0
VkSurfaceKHR surface; // 渲染表面(窗口或显示设备)
uint32_t minImageCount; // 交换链中图像的最小数量
VkFormat imageFormat; // 交换链中的图像格式(颜色格式)
VkColorSpaceKHR imageColorSpace; // 交换链中图像的颜色空间
VkExtent2D imageExtent; // 交换链中图像的高度和宽度
uint32_t imageArrayLayers;// 交换链中的数组层数,通常为1
VkImageUsageFlags imageUsage; // 交换链中图像的用用途标志(如颜色附件)
VkSharingMode imageSharingMode;// 图像共享模式(独占模式或者并发模式)
uint32_t queueFamilyIndexCount;// 队列家族索引数量(imageSharingMode 为 VK_SHARING_MODE_CONCURRENT 时使用)
const uint32_t* pQueueFamilyIndices; // 指向队列家族索引数组的指针(imageSharingMode 为 VK_SHARING_MODE_CONCURRENT 时使用)
VkSurfaceTransformFlagBitsKHR preTransform; // 表面变换(比如旋转或者翻转)
VkCompositeAlphaFlagBitsKHR compositeAlpha; // 复合 Alpha 混合模式
VkPresentModeKHR presentMode; // 交换链的呈现模式(比如 FIFO 或者 MailBox)
VkBool32 clipped; // 指定裁剪窗口外的像素(VK_TRUE 为裁剪)
VkSwapchainKHR oldSwapchain; // 旧的交换链(用于重新创建交换链时),否则为 VK_NULL_HANDLE
} VkSwapchainCreateInfoKHR;
VkSwapchainCreateInfoKHR
结构体的属性比较多,绝大多数都是固定写死的,只需要简单了解下就行
其中 VkColorSpaceKHR
、VkImageUsageFlags
、VkSurfaceTransformFlagBitsKHR
、VkPresentModeKHR
的含义如下:
VkColorSpaceKHR
用于定义Image
的 色域和校正信息:
typedef enum VkColorSpaceKHR {
VK_COLOR_SPACE_SRGB_NONLINEAR_KHR = 0, // SRGB 色域,带有非线性的色彩校准,常用于标准显示器
VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT = 1000104001, // Display-P3 色域,带非线性伽马校正。用于支持 P3 色域显示器
VK_C