除了缓冲区之外,图像是 Vulkan 拥有的另一种“存储”类型。与缓冲区不同,由于图像管理的所有逻辑及其设置,图像更加复杂。
VkImage
是保存实际纹理数据的东西。它保存纹理的像素和主内存,但不包含有关如何读取它的大量信息。
VkImageView
是 VkImage
之上的包装器。它包含有关如何解释纹理数据的信息,例如,如果您只想访问区域或图层,以及是否要以特定方式改组像素通道。
最后,我们有 VkSampler
,它保存用于特定着色器访问纹理的数据。 采样器等同于 OpenGL 中的相同事物,它包含有关如何混合像素或如何进行 mipmapping 的信息。采样器与描述符中的 VkImageView
一起使用。
VkImage
我们将通过使用 VulkanMemoryAllocator 创建 VkImages
。 由于 VkImage
由实际像素数据组成,因此有必要在某些内存上分配它们,最好是在 GPU 本地内存上(VK_MEMORY_HEAP_DEVICE_LOCAL_BIT
或 VMA VMA_MEMORY_USAGE_GPU_ONLY
)。 图像通常具有非常高的内存流量使用率,因此您希望它们尽可能快地进行读取和写入。 您可以将图像视为缓冲区之上的图层,但是具有 GPU 中所有固定管线纹理逻辑以及纹理图层或 mipmap 等功能所需的许多额外逻辑和数据。 可以将图像数据复制到缓冲区,反之亦然。 虽然图像以您指定的任何格式保存像素数据,并且具有特定的布局,但它并未指定如何从着色器解释数据。 这由 VkImageView
和采样器计算得出。
图像格式和布局
图像可以由许多不同的内存格式制成。 您可以拥有 1 个像素只是 8 位单个整数字符的图像,也可以拥有每个像素保存 4 个 32 位浮点数的图像。 您可以使用许多不同的格式,其中一些格式只能以特定方式使用。 当您想在代码库中使用格式时,您需要检查该格式是否支持您想要执行的操作。 通常,您可以在着色器中读取许多格式,但是如果您想将图像用作帧缓冲区以渲染到其中,则选择范围更有限。 始终确保检查目标 GPU 中可用的图像格式。 您可以在此处查看以检查 GPU 的可用性。 https://vulkan.gpuinfo.org/listformats.php 。 您要检查目标格式是否可以在最佳布局(而不是线性布局)上读取。
布局是像素在内存中排列的方式。 基本线性布局只是像素的打包 2D 数组,其中每行都是连续的。 此格式与 CPU 内存中使用的典型格式匹配,非常适合加载纹理。 它的问题在于,从具有线性布局的纹理读取通常非常慢,甚至不受支持。 为了获得最快的读取速度,您需要将纹理切换为 OPTIMAL 布局。 最佳布局是完全不透明的,并且在驱动程序供应商之间有所不同。 将纹理更改为最佳布局会告诉驱动程序以其想要的任何方式改组像素,以实现最佳硬件使用率。
图像始终以 VK_IMAGE_LAYOUT_UNDEFINED
布局开始其生命周期,因此您需要将其转换为另一种布局,例如 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
。 要更改纹理的布局,您需要在命令缓冲区上执行管道屏障。 管道屏障通常用于控制着色器的执行,以同步对资源(例如缓冲区或图像)的访问。 如果您将它们用于图像,则图像可以更改其布局。
VkImageView
图像视图是对 VkImage
的引用。 与 VkImage
不同,它不需要在 GPU 内存上分配,因此您可以直接从 Vulkan API 创建它们。 将图像视图视为指向 VkImage
像素数据的花哨指针。 创建图像视图时,您需要指定纹理的格式,以及其他内容,例如基本 mipmap 级别或纹理数组的特定图层。 您可以使用它们执行的操作之一是将给定的像素格式解释为另一种格式。 这可以用于某些特定效果,但您必须小心使用。 也可以使用图像视图来改组图像的颜色通道,例如,使用仅 alpha 图像视图解释 RGBA 纹理,这将是不同的单通道格式。 在 Vulkan API 中使用图像时,几乎总是通过 VkImageView 使用它们。
VkSampler
采样器保存着色器中纹理的精确访问方式。 它们控制固定管线状态,例如 mipmap 混合或最近邻过滤。 它们可以控制各向异性过滤,或控制在采样纹理时超出纹理边界时会发生什么。 创建 VkSampler
与创建 VkImage
对象和 VkImageView
对象是完全不同的路径。 您不会创建连接到纹理的采样器,因为它们是独立的。 在引擎中,将采样器对象缓存在哈希映射中并根据需要分配它们是很常见的。 对于整个引擎,您通常只会得到几个不同的采样器。
当您将纹理绑定到着色器时,有不同的方法,但是我们将为描述符使用 VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER
。 这会将图像 + 采样器对公开给着色器,而不是使采样器和图像在着色器中成为分离的事物。 创建这些描述符时,您将需要所需图像的 imageView,以及用于访问它的采样器。
下一步:加载图像