1.图像资源
Vulkan 图像以 1D / 2D / 3D 形式表示连续的纹理数据。 这些图像主要用作附件或纹理:
- 附件 Attachment:图像可以被附加到管线,用于帧缓冲区的颜色附件或深度附件,也可以用作辅助表面,用于多通道处理目的。
- 纹理 Texture:图像用作描述符的接口,并以采样器的形式在着色器阶段(片段着色器)共享。
Vulkan 中纹理的概念主要使用图像,图像布局和图像视图来解释:
- 图像 Image:图像代表 Vulkan 中的纹理对象, 其中包含用于计算内存需求的元数据。 收集的内存需求在内存分配期间很有用。 图像可以表示其他以及众多类型的信息,例如格式,大小和类型(稀疏映射,立方体映射等)。 单个图像可能包含多个子资源,例如基于 mipmap 级别或一系列层的多个图像。 每个图像或图像子资源都使用图像布局进行指定。
- 图像布局 Image layout:图像布局是在图像内存存储空间中,以网格坐标表示形式存储图像纹理信息的一种特定实现方法 。 存储在图像内存中的图像非常依赖具体的实现;每个图像都有特定的用法,例如,颜色附件,着色器中的采样图像,图像加载、存储或大图像的稀疏纹理。 对于这些特殊用途,实现提供了专门用于图像内存使用的图像布局,用来提供最佳的性能。
- 图像视图 Image view:图像不能直接通过 API 调用或管线着色器用于读写目的;相反,可以直接使用图像视图。 它不仅表现的像图像对象的接口那样工作,而且还提供元数据,用于表示连续范围的子图像资源。
2.图像创建
- 首先,创建图像对象:
- 使用 vkCreateImage()API 创建图像对象(VkImage)。 该 API 提供了一个 VkImageCreateInfo 结构的数组,该数组指定了创建一个或多个图像对象的重要图像特征。 在这个时刻,该图像对象在设备上还没有进行物理存储的分配;但是,它携带了下一步中分配存储空间的逻辑内存信息。 此内存信息来自 VkImageCreateInfo 对象,其中包含格式,图像大小,创建标志等。
2.然后,分配图像内存:
- 获取内存要求:在我们分配所需的图像内存块之前,我们需要计算要分配内存的适当尺寸。 这是使用 vkGetImageMemoryRequirements()API 完成的。 它可以根据图像属性自动计算图像的适当尺寸,使用了我们在前面步骤中描述的 VkCreateImageInfo 对象作为参数。
- 确定内存类型:接下来,从可用内存类型中获取适当的内存类型。 类型可用后,就查找与用户需要的属性匹配的类型。
- 分配设备内存:使用 vkAllocateMemory()API 分配设备内存(VkDeviceMemory)。
- 绑定分配的内存:使用 vkBindImageMemory()API 把分配的设备内存(VkDeviceMemory)绑定到图像对象(VkImage)。
3.设置图像布局:
- 根据应用要求设置正确的图像布局;通过 vkCmdPipelineBarrier()并利用管线图像内存屏障执行此操作。
4.创建图像视图
5.销毁图像视图
2.SwapChain流程
- 创建一个空窗口:该过程提供了一个空白的本地平台窗口,该窗口被连接到交换链的彩色图像。 每次写入帧(图像)时,都会将其交换到展示层。 展示层将这些信息传递到附加的本地窗口,用于显示目的。
- 查询交换链扩展:交换链 API 不是标准 API 规范的一部分。 它们是特定于实现的,并且加载器也会以扩展的形式加载这些 API。 加载的扩展以函数指针的形式存储,其函数签名在 Vulkan 规范中是预先定义的。
- 创建表面并将其与创建的窗口关联:这个过程会创建一个逻辑平台特定的表面对象。 这个时候,它还没有彩色图像的物理内存支持,即还没有分配存储空间,仅仅是逻辑层面的一种表示而已。 这个逻辑表面对象会被附加到空窗口,声明该窗口为其所有者。
- 获取支持的图像格式:在这一步中,我们查询物理设备,以检查其支持的所有图像格式。
- 查询交换链图像表面特性:这个过程会获得有关基本表面特性的信息,因为在创建交换链图像时需要用到这些信息。 另外,它还会检查可用的表现模式。
- 管理表现模式信息:这将使用可用的表现模式信息并决定应该在交换链中使用的表现模式技术。 交换链的表现模式决定了传入的展示请求会如何在内部处理以及队列化。
- 创建交换链并检索展示图像:让我们使用上面收集的信息并创建交换链图像。 WSI 扩展返回彩色图像对象;这些图像属于 VkImage 类型,并由应用程序使用
- 创建彩色图像视图 image views:根据系统特性,WSI 实现可能会返回 1-3 个交换链图像(基于一个缓冲区,双个缓冲区以及三个缓冲区)。 要在应用程序中使用每个图像,就需要创建相应的图像视图。
- 创建深度图 depth image:与彩色图像类似,您需要深度图进行深度测试;但与 WSI 预烘烤的交换链图像不同,深度图需要由应用程序创建。首先,您需要创建一个深度图对象(VkImage),按照下面的步骤分配内存,创建图像布局并最终生成图像视图对象(VkImageView)。
- 深度图的内存分配:您需要分配物理设备内存并将其绑定到深度图对象。
- 创建命令池:我们需要命令缓冲区 ------ 用于深度图,由于此图像属于我们;因此我们要使用命令缓冲区来应用图像布局。
- 创建命令缓冲区:您需要创建命令缓冲区并开始使用创建的深度图对象记录负责创建深度图布局的命令。
- 图像布局:这可以让您在深度图对象上应用深度、模板兼容的图像布局。
- 添加管线屏障:为了确保在创建图像视图之前总是执行了图像布局,请添加管线屏障。 当插入管线屏障时,它确保在命令缓冲区中,屏障前面的命令会在屏障后面的命令之前执行。
- 结束命令缓冲区的记录:这允许您停止命令缓冲区的记录。
- 创建深度图视图:将图像对象转换为兼容图像布局后,创建一个图像视图对象(VkImageView)。 该图像不能直接在应用程序中使用;他们必须以图像视图的形式使用。
提示WSI 图像不属于应用程序,而是属于 WSI,因此无法应用图像布局。 图像布局只能应用于应用程序拥有的图像。
3.交换链的框架
3.1窗口管理自定义类
VulkanRender 类在 VulkanRenderer.h / .cpp 中定义。 在应用程序中,该类管理一个特殊的展示窗口及其相关资源,例如设备,交换链,管线等。 一个应用程序可以有多个渲染窗口,如下图所示;每个渲染器都会处理一个单独的展示窗口及其对应的所有资源。
但是,由于我们还处于初学水平,因此我们的示例仅假设只有一个输出展示窗口。 因此,VulkanApplication 包含一个 VulkanRenderer 类对象:
以下是 VulkanRenderer 头文件的声明。 该类创建了展示层的空窗口(createPresentationWindow()),稍后就会使用交换链中的的彩色图像对其进行填充。 空窗口的创建过程是极其特定于具体平台的;此示例演示的仅适用于 Windows 平台:
使用 WSI 创建表面并将其与创建的窗口相关联
Vulkan API 可以在每个平台上无缝实现。 平台是窗口和 OS 服务的抽象, 例如 MS Windows,Android 和 Wayland。 窗口系统集成Window System Integration (WSI)为实现窗口或表面管理提供了一种独立于平台的方式。
Vulkan 使用 VkSurfaceKHR 表示逻辑表面对象。 不同的平台有不同的 API 来创建 VkSurfaceKHR 表面对象,例如 vkCreateWin32SurfaceKHR(),vkCreateAndroidSurfaceKHR()和 vkCreateXcbSurfaceKHR():
Z 字格(swizzling)
在大多数 GPU 上,这种较慢的地址转换是通过使用 Z 字格(swizzling)的形式存储纹理元素来解决的。 这种存储图像纹理元素的方式称为优化平铺 Optimal tiling,其中图像的纹理元素以平铺的方式存储,表示连续内存块中的多个列和行。 例如,在下图中,用不同颜色表示四个图块,其中每个图块具有 2 x 2 行(间距)和列:
总结应用流程
由两部分组成:初始化和渲染。
初始化
初始化过程包括初始化、创建以及处理交换链。 交换链尚未连接到帧缓冲区的渲染过程和图元。 因此,现在渲染的输出会是一个空白的展示窗口。
1,VulkanRenderer 初始化展示窗口并创建本机平台特定的空窗口(500 x 500)。 窗口会渲染交换链的前端缓冲区绘图图像。
2.它会初始化交换链,以符合交换链的先决条件。 交换链图像视图布局是使用命令缓冲区(它们是从预分配的命令缓冲池分配的)创建的。
在交换链初始化期间,查询 WSI 扩展并以函数指针的形式进行存储。逻辑交换链表面对象被创建并且与展示窗口相关联。接下来,从支持展示功能的逻辑设备查询一个合适的图形队列;此队列用于绘制操作并将交换链图像呈现到显示输出窗口。最后,还会检查设备可以用于交换链图像的、所有可能的图像格式。交换链的创建包括查询指定表面配置的交换链表面特性,例如绘图表面的最大尺寸,可用的显示模式等。使用这个表面配置,就可以检索交换链图像对象。一旦交换链检索到图像,就可以用来渲染图元。交换链图像由 WSI 检索;因此,应用程序不拥有这些。这些图像最终转换为图像视图以允许应用程序在实现中使用它们。
我们还需要为深度 / 模板测试创建深度图,与交换链图像不同,深度图完全是应用程序的责任,应用程序拥有它,因此可以使用一个最佳深度布局方案在深度图上应用图像布局转换。 使用内存屏障命令应用图像转换,该命令会打包在命令缓冲区中并提交到队列以进行前期的处理。 内存屏障会插入一些特殊指令,以保证布局在使用之前完成转换。
来源:oschina
链接:https://my.oschina.net/1024and1314/blog/4437346