首页 > 其他分享 >Vulkan 开发(十一):Vulkan 交换链

Vulkan 开发(十一):Vulkan 交换链

时间:2024-11-14 16:50:01浏览次数:3  
标签:十一 COLOR KHR VK 交换 图像 BIT Vulkan

Vulkan 系列文章:

1. 开篇,Vulkan 概述

2. Vulkan 实例

3. Vulkan 物理设备

4. Vulkan 设备队列

5. Vulkan 逻辑设备

6. Vulkan 内存管理

7. Vulkan 缓存

8. Vulkan 图像

9. Vulkan 图像视图

10. Vulkan 窗口表面(Surface)


什么是交换链

图片

FIFO 呈现模式的交换链

Vulkan 交换链(Swapchain)是 Vulkan 应用程序与窗口系统之间的一座桥梁,负责将渲染结果呈现给用户。

换个说法,交换链是一种图元绘制结果呈现的机制,它可以将绘制结果渲染到平台相关的展示窗口/展示层当中。

交换链包含一组图像(一般作为渲染目标),这些图像被用于在屏幕上显示渲染的帧。

交换链中的图像个数与驱动层的实现是密切相关的。如果交换链中有两幅图像,那么称为双缓存,如果有三幅图像,那么称作三缓存。

在这些图像中,如果有一幅图像在后台已经完成了绘制过程,那么它会被交换到前台的展示窗口。

为了充分利用GPU的性能,此时另一幅图像会交换作为后台的缓存来执行下一帧的绘制过程。

这个过程往复执行,图像的交换过程也就持续进行。使用多幅图像可以保持GPU始终处于渲染某一帧图像的忙碌状态,从而降低总体的等待时间,改善输出帧速率。

交换链的作用

  1. 图像管理交换链维护了一组用于显示的图像,称为交换链图像(Swapchain Images)。交换链图像通常至少有两个,这样就可以实现双缓冲或多缓冲,从而避免屏幕闪烁。

  2. 同步: 管理 CPU 和 GPU 之间的同步,确保渲染操作不会在显示更新之前完成,这有助于防止撕裂(tearing)现象,即在同一帧内看到两个不同图像的一部分。

  3. 图像呈现:

  • 应用程序首先在一个缓冲区上进行渲染,完成渲染后,该缓冲区会被提交给交换链,然后交换链会将这个缓冲区的内容显示到屏幕上。

  • 当一个缓冲区正在显示时,另一个缓冲区可以用于下一轮的渲染,这样就形成了一个循环。

创建交换链

创建交换链之前,我们需要利用上一节创建的 VkSurfaceKHR  对象来获取创建交换链所需的尺寸、格式、颜色空间等信息。

 1VkSurfaceKHR surface;
 2
 3//获取表面的特性
 4VkSurfaceCapabilitiesKHR surfaceCapabilities;
 5vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface,
 6                                        &surfaceCapabilities);
 7uint32_t formatCount = 0;
 8vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface,
 9                                   &formatCount, nullptr);
10
11//获取表面所支持的格式
12VkSurfaceFormatKHR* formats = new VkSurfaceFormatKHR[formatCount];
13vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface,
14                                   &formatCount, formats);

获取上述信息之后,我们来填充 VkSwapchainCreateInfoKHR 结构体。

创建交换链的函数 vkCreateSwapchainKHR :

1VkResult vkCreateSwapchainKHR(
2    VkDevice                        device,                  // Vulkan 设备句柄
3    const VkSwapchainCreateInfoKHR* pCreateInfo,             // 指向 VkSwapchainCreateInfoKHR 结构体的指针,描述交换链的创建参数
4    const VkAllocationCallbacks*    pAllocator,              // 自定义的内存分配器回调函数指针,可以为 NULL 表示使用默认分配器
5    VkSwapchainKHR*                 pSwapchain               // 指向 VkSwapchainKHR 句柄的指针,函数成功返回时,包含创建的交换链
6)
7

VkSwapchainCreateInfoKHR 是一个用于描述交换链创建信息的结构体。它包含了创建交换链所需的所有参数,如表面、图像数量、格式、分辨率等。

以下是 VkSwapchainCreateInfoKHR 结构体的定义:

 1typedef struct VkSwapchainCreateInfoKHR {
 2VkStructureType                  sType;              // 必须是 VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR
 3const void*                      pNext;              // 指向扩展结构的指针,通常为 nullptr
 4VkSwapchainCreateFlagsKHR        flags;              // 交换链创建标志,当前版本 Vulkan 中未使用,设置为 0
 5VkSurfaceKHR                     surface;            // 渲染表面(窗口或显示设备)
 6uint32_t                         minImageCount;      // 交换链中图像的最小数量
 7VkFormat                         imageFormat;        // 交换链图像的格式(颜色格式)
 8VkColorSpaceKHR                  imageColorSpace;    // 交换链图像的颜色空间
 9VkExtent2D                       imageExtent;        // 交换链图像的宽度和高度
10uint32_t                         imageArrayLayers;   // 交换链图像的数组层数(通常为 1)
11VkImageUsageFlags                imageUsage;         // 交换链图像的用途标志(如颜色附件)
12VkSharingMode                    imageSharingMode;   // 图像共享模式(独占模式或并发模式)
13uint32_t                         queueFamilyIndexCount; // 队列家族索引数量(imageSharingMode 为 VK_SHARING_MODE_CONCURRENT 时使用)
14const uint32_t*                  pQueueFamilyIndices;  // 指向队列家族索引数组的指针(imageSharingMode 为 VK_SHARING_MODE_CONCURRENT 时使用)
15VkSurfaceTransformFlagBitsKHR    preTransform;       // 表面变换(如旋转或翻转)
16VkCompositeAlphaFlagBitsKHR      compositeAlpha;     // 复合 Alpha 混合模式
17VkPresentModeKHR                 presentMode;        // 交换链的呈现模式(如 FIFO、Mailbox 等)
18VkBool32                         clipped;            // 指定剪裁窗口外的像素(VK_TRUE 为剪裁)
19VkSwapchainKHR                   oldSwapchain;       // 旧的交换链(用于重新创建交换链时),否则为 VK_NULL_HANDLE
20} VkSwapchainCreateInfoKHR;

VkSwapchainCreateInfoKHR结构体的属性看起来很多,实际上绝大部分情况下都是固定写死的,所以只需要简单了解下即可。

其中 VkColorSpaceKHR 、VkImageUsageFlags、VkSurfaceTransformFlagBitsKHR、VkPresentModeKHR 这个几个稍微关注下。

VkColorSpaceKHR

VkColorSpaceKHR 定义了交换链图像的颜色空间。

颜色空间表示图像数据如何转换为颜色信息,以在显示设备上正确显示,处理 HDR 图像的时候需要重点关注。

 1typedef enum VkColorSpaceKHR {
 2    VK_COLOR_SPACE_SRGB_NONLINEAR_KHR = 0,                // sRGB 颜色空间,带非线性伽马校正。常用于标准显示器。
 3    VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT = 1000104001, // Display-P3 色域,带非线性伽马校正。用于支持 P3 色域显示器。
 4    VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT = 1000104002, // 扩展 sRGB 颜色空间,线性校正。
 5    VK_COLOR_SPACE_DISPLAY_P3_LINEAR_EXT = 1000104003,    // Display-P3 色域,线性校正。
 6    VK_COLOR_SPACE_DCI_P3_NONLINEAR_EXT = 1000104004,     // DCI-P3 色域,带非线性伽马校正。
 7    VK_COLOR_SPACE_BT709_LINEAR_EXT = 1000104005,         // BT.709 颜色空间,线性校正。
 8    VK_COLOR_SPACE_BT709_NONLINEAR_EXT = 1000104006,      // BT.709 颜色空间,非线性校正。
 9    VK_COLOR_SPACE_BT2020_LINEAR_EXT = 1000104007,        // BT.2020 颜色空间,线性校正。
10    VK_COLOR_SPACE_HDR10_ST2084_EXT = 1000104008,         // HDR10,使用 SMPTE ST 2084 EOTF。
11    VK_COLOR_SPACE_DOLBYVISION_EXT = 1000104009,          // Dolby Vision。
12    VK_COLOR_SPACE_HDR10_HLG_EXT = 1000104010,            // HDR10,使用 Hybrid Log-Gamma。
13    VK_COLOR_SPACE_ADOBERGB_LINEAR_EXT = 1000104011,      // Adobe RGB 颜色空间,线性校正。
14    VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT = 1000104012,   // Adobe RGB 颜色空间,非线性校正。
15    VK_COLOR_SPACE_PASS_THROUGH_EXT = 1000104013,         // 颜色空间通过,不做任何校正。
16    VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT = 1000104014, // 扩展 sRGB 颜色空间,非线性校正。
17    VK_COLOR_SPACE_DISPLAY_NATIVE_AMD = 1000213000,       // 原生显示颜色空间,AMD 扩展。
18    // 更多颜色空间可以通过扩展添加
19} VkColorSpaceKHR;

VkImageUsageFlags

VkImageUsageFlags 表示图像的用途标志,例如 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT 表示图像将用作颜色附件。

可以组合多个用途标志,以表明图像的多种使用方式。

 1typedef enum VkImageUsageFlagBits {
 2    VK_IMAGE_USAGE_TRANSFER_SRC_BIT = 0x00000001,                     // 图像可以作为传输操作的源。
 3    VK_IMAGE_USAGE_TRANSFER_DST_BIT = 0x00000002,                     // 图像可以作为传输操作的目标。
 4    VK_IMAGE_USAGE_SAMPLED_BIT = 0x00000004,                          // 图像可以被采样器访问。
 5    VK_IMAGE_USAGE_STORAGE_BIT = 0x00000008,                          // 图像可以作为存储图像使用。
 6    VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT = 0x00000010,                 // 图像可以作为颜色附件使用。
 7    VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT = 0x00000020,         // 图像可以作为深度/模板附件使用。
 8    VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT = 0x00000040,             // 图像内容是暂时的,并不会在帧之间保留。
 9    VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT = 0x00000080,                 // 图像可以作为输入附件使用。
10    VK_IMAGE_USAGE_SHADING_RATE_IMAGE_BIT_NV = 0x00000100,            // 图像可以作为着色率图像使用(NVIDIA 扩展)。
11    VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT = 0x00000200,         // 图像可以作为片段密度图使用(EXT 扩展)。
12    VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR =         // 图像可以作为片段着色率附件使用(KHR 扩展)。
13        VK_IMAGE_USAGE_SHADING_RATE_IMAGE_BIT_NV,
14    VK_IMAGE_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF                    // 枚举类型的最大值。
15} VkImageUsageFlagBits;

VkSurfaceTransformFlagBitsKHR

VkSurfaceTransformFlagBitsKHR 枚举类型定义了交换链图像在显示之前可以应用的变换操作。

 1typedef enum VkSurfaceTransformFlagBitsKHR {
 2    VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR = 0x00000001,                    // 不进行任何变换。
 3    VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR = 0x00000002,                   // 顺时针旋转 90 度。
 4    VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR = 0x00000004,                  // 顺时针旋转 180 度。
 5    VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR = 0x00000008,                  // 顺时针旋转 270 度。
 6    VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR = 0x00000010,           // 水平翻转。
 7    VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR = 0x00000020, // 水平翻转后顺时针旋转 90 度。
 8    VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR = 0x00000040,// 水平翻转后顺时针旋转 180 度。
 9    VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR = 0x00000080,// 水平翻转后顺时针旋转 270 度。
10    VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR = 0x00000100                      // 继承当前变换。
11} VkSurfaceTransformFlagBitsKHR;

VkPresentModeKHR

VkPresentModeKHR 枚举类型定义了交换链的呈现模式。呈现模式决定了图像交换和显示的策略。

1typedef enum VkPresentModeKHR {
2    VK_PRESENT_MODE_IMMEDIATE_KHR = 0,           // 图像立即提交到显示设备,可能导致撕裂。
3    VK_PRESENT_MODE_MAILBOX_KHR = 1,             // 使用邮箱模式,提交图像时如果显示队列满了,会覆盖旧的图像。
4    VK_PRESENT_MODE_FIFO_KHR = 2,                // 先进先出模式,提交的图像进入队列,显示设备按顺序显示。
5    VK_PRESENT_MODE_FIFO_RELAXED_KHR = 3,        // 类似于 FIFO 模式,但如果显示设备空闲,立即显示图像,减少延迟。
6    VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR = 1000111000, // 共享刷新模式,在显示设备需要时刷新。
7    VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR = 1000111001 // 持续刷新模式,持续刷新图像。
8} VkPresentModeKHR;

创建交换链、获取交换链图像示例

 1VkSurfaceKHR surface;//上一节获取的表面
 2
 3// 获取表面的特性
 4VkSurfaceCapabilitiesKHR surfaceCapabilities;
 5vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, &surfaceCapabilities);
 6
 7uint32_t formatCount = 0;
 8vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &formatCount, nullptr);
 9
10// 获取表面所支持的格式
11VkSurfaceFormatKHR* formats = new VkSurfaceFormatKHR[formatCount];
12vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &formatCount, formats);
13
14// 查找 VK_FORMAT_R8G8B8A8_UNORM 格式
15uint32_t targetFormatIdx;
16for (targetFormatIdx = 0; targetFormatIdx < formatCount; targetFormatIdx++) {
17    if (formats[targetFormatIdx].format == VK_FORMAT_R8G8B8A8_UNORM) break;
18}
19assert(targetFormatIdx < formatCount); // 确保找到目标格式
20
21VkSwapchainCreateInfoKHR swapchainCreateInfo = {};
22swapchainCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; // 设置结构体类型
23swapchainCreateInfo.surface = surface; // 设置表面句柄
24swapchainCreateInfo.minImageCount = surfaceCapabilities.minImageCount; // 最小图像数量(修正:minImageCoun 改为 minImageCount)
25swapchainCreateInfo.imageFormat = formats[targetFormatIdx].format; // 图像格式
26swapchainCreateInfo.imageColorSpace = formats[targetFormatIdx].colorSpace; // 颜色空间
27swapchainCreateInfo.imageExtent = surfaceCapabilities.currentExtent; // 图像范围
28swapchainCreateInfo.imageArrayLayers = 1; // 图像数组层数
29swapchainCreateInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; // 图像用途
30swapchainCreateInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; // 图像共享模式
31swapchainCreateInfo.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; // 表面变换
32swapchainCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; // 复合 alpha 模式
33swapchainCreateInfo.presentMode = VK_PRESENT_MODE_FIFO_KHR; // 显示模式
34swapchainCreateInfo.clipped = VK_FALSE; // 是否剪辑
35swapchainCreateInfo.oldSwapchain = VK_NULL_HANDLE; // 旧交换链句柄
36
37VkSwapchainKHR swapchain;
38VkResult result = vkCreateSwapchainKHR(device, &swapchainCreateInfo, nullptr, &swapchain); // 创建交换链
39if (result != VK_SUCCESS) {
40    // 错误处理
41}
42
43// 获取交换链中的图像
44uint32_t imageCount;
45vkGetSwapchainImagesKHR(device, swapchain, &imageCount, nullptr);
46std::vector<VkImage> swapChainImages(imageCount);
47vkGetSwapchainImagesKHR(device, swapchain, &imageCount, swapChainImages.data());
48
49// 为每个交换链图像创建图像视图,这些图像视图将会作为帧缓冲区的 attachments
50std::vector<VkImageView> swapChainImageViews(swapChainImages.size());
51for (size_t i = 0; i < swapChainImages.size(); i++) {
52    VkImageViewCreateInfo createInfo = {};
53    createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; // 设置结构体类型
54    createInfo.image = swapChainImages[i]; // 图像句柄
55    createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; // 视图类型
56    createInfo.format = formats[targetFormatIdx].format; // 图像格式
57    createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; // 组件重映射
58    createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
59    createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
60    createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
61    createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; // 子资源范围
62    createInfo.subresourceRange.baseMipLevel = 0;
63    createInfo.subresourceRange.levelCount = 1;
64    createInfo.subresourceRange.baseArrayLayer = 0;
65    createInfo.subresourceRange.layerCount = 1;
66
67    if (vkCreateImageView(device, &createInfo, nullptr, &swapChainImageViews[i]) != VK_SUCCESS) {
68        throw std::runtime_error("failed to create image views!"); // 错误处理
69    }
70}
71
72// 销毁交换链、释放资源
73for (size_t i = 0; i < swapChainImages.size(); i++) {
74    vkDestroyImageView(device, swapChainImageViews[i], nullptr); // 销毁图像视图
75}
76vkDestroySwapchainKHR(device, swapchain, nullptr); // 销毁交换链
77delete[] formats; // 释放格式数组内存

参考

《Vulkan学习指南》 — [新加坡] 帕敏德·辛格(Parminder Singh)
https://www.intel.com/content/www/us/en/developer/articles/training/api-without-secrets-introduction-to-vulkan-part-2.html

技术交流

进技术交流群/获取源码,添加我的微信:Byte-Flow

 

标签:十一,COLOR,KHR,VK,交换,图像,BIT,Vulkan
From: https://blog.csdn.net/Kennethdroid/article/details/143775381

相关文章

  • 云服务器双十一活动火爆开启中
    云服务器双11活动火爆开启中[腾讯云] 2核2G云服务器低至68元/年https://curl.qcloud.com/xgsbEbOF云产品特惠福利热卖中https://curl.qcloud.com/74iJUr08跨境电商业务扬帆出海https://curl.qcloud.com/b9muz7PB游戏服务器专属优惠https://curl.qcloud.com/qBtwesxm[京东云]2核2G......
  • 第十一:BurpSuite安装浏览器安装Burp Suite证书(一)-重点
    一.浏览器安装BurpSuite证书(BurpSuite抓取浏览器https协议需要安装BurpSuite的证书)1.浏览器设置-搜索:证书-点击:安全2.点击:管理设备的证书3.为受信任的根证书颁布机构(安装证书)3.1.为中间证书颁发机构(安装证书)注意:为什么要给两个都安装证......
  • 关于Vulkan应用程序运行时编译GLSL Shader文件的方法
    最近在学习Vulkan,在相关参考书中给出的示例代码因为使用的VulkanSDK较老,出现无法构建成功的问题。而且示例代码给出的Vulkan应用程序运行时编译GLSLShader文件的方法放在现在已经是非常的麻烦。现在新版的VulkanSDK(1.3.X以上)将GLSL编译为SPIR-V非常方便了,可以使用Google提供的S......
  • 双十一课代表|最强省钱攻略
    双十一课代表|最强省钱攻略经济背景买什么&怎么买购买方式一购买方式二购买方式三省钱宝典经济背景在文章开始之前,为了烘托咱们确实是为了让用户省钱,那么先来大概聊一下当前的经济形势。2024年,可以说是经济形势不容乐观的一年。各个行业都面临着行业严冬带来的考验,......
  • HDMI规范-第十一章 HEAC
    1.简介HEAC技术是HDMI接口的一部分,旨在提供以太网连接和音频回传功能。HEAC通过HEAC-和HEAC+线对或仅通过HEAC+线实现数据传输。此技术分为两部分:HEC(HDMI以太网通道)和ARC(音频回传通道)。HEC 使用差分模式下的MLT-3信令,允许源设备和接收设备之间进行100BASE-TX数据的全双工......
  • 交换机
    ......
  • (系列十一)Vue3框架中路由守卫及请求拦截(实现前后端交互)
    说明  该文章是属于OverallAuth2.0系列文章,每周更新一篇该系列文章(从0到1完成系统开发)。   该系统文章,我会尽量说的非常详细,做到不管新手、老手都能看懂。   说明:OverallAuth2.0是一个简单、易懂、功能强大的权限+可视化流程管理系统。友情提醒:本篇文章是属于系......
  • H3C交换机ACL配置
    不知道大家有没有这样的需求,就是我们的dmz区域,可以使用防火墙和其他区域隔离,但实际使用过程中,防火墙策略配置起来还是比较繁琐,具体就是策略数目太多,一眼看上去不清晰。那么在交换机上面是不是可以实现可视感观比较好的功能呢?交换机通过acl也就是包过滤去实现创建aclnumber300......
  • 华为路由器/交换机配置Console口AAA认证以及Telnet登录
    一、Console口登录 Console口是路由器/交换机的本地管理接口,通常用于设备初始配置和管理。本文将介绍console登录的两种配置方式1、密码模式配置成这种模式后Console登录只需要输入密码。配置方法一[Huawei]user-interfaceconsole0 [Huawei-ui-console0]authentica......
  • HarmonyOS蓝牙串口协议(SPP)详解:实现设备间可靠数据交换
    本文旨在深入探讨华为鸿蒙HarmonyOSNext系统(截止目前API12)的技术细节,基于实际开发实践进行总结。主要作为技术分享与交流载体,难免错漏,欢迎各位同仁提出宝贵意见和问题,以便共同进步。本文为原创内容,任何形式的转载必须注明出处及原作者。在智能设备互联互通的世界里,蓝牙技术扮......