Vulkan Cookbook 第四章 5 创建图像

创建图像

译者注:示例代码点击此处

图像表示可以具有一维、二维或三维的数据,并且可以具有额外的mipmap级别和图层。图像数据的每个元素(纹理元素)也可以具有一个或多个样本。

图像可用于许多不同的目的。我们可以将它们用作复制操作的数据源。也可以通过描述符集将图像绑定到管线,并将它们用作纹理(类似于OpenGL)。可以渲染成图像,在这种情况下我们使用图像作为颜色或深度附件(渲染目标)。

我们在图像创建期间指定图像参数,例如大小、格式及其预期用途。

做好准备...

1.获取我们要在其上创建图像的逻辑设备句柄。将其储存在名为logical_device的VkDevice类型变量中。
2.选择图像类型(如果图像应具有一维、二维或三维)并使用适当的值初始化名为type的VkImageType类型变量。
3.选择图像格式,每个图像元素应包含的组件数和位数。将格式储存在名为format的VkFormat类型变量中。
4.选择图像的大小(尺寸)并使用它来初始化名为size的VkExtent3D类型变量。
5.选择应为图像定义的mipmap级别数量储存在名为num_mipmaps的uint32_t类型变量中。
6.选择应为图像定义的图层数量,并将其存储在名为num_layers的uint32_t类型变量中。如果图像将用作立方体贴图,则图层数量必须是6的倍数。
7.创建一个名为samples的VkSampleCountFlagBits类型的变量,并使用表示样本数量的值对其进行初始化。
8.选择预期的图像用法,在名为usage_scenarios的VkImageUsageFlags类型的变量中定义它们。
9.创建名为image_create_info的VkImageCreateInfo类型变量。为其成员赋值:
   ·sType为VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO
    ·pNext为nullptr
    ·flags的话,如果图像应该用作立方体贴图,请使用VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT值,否则使用0值。
    ·type为imageType
    ·format为format
    ·extent为size
    ·mipLevels为num_mipmaps
    ·arrayLayers为num_layers
    ·samples为samples
    ·tiling为VK_IMAGE_TILING_OPTIMAL
    ·usage为usage_scenarios
    ·sharingMode为VK_SHARING_MODE_EXCLUSIVE
    ·queueFamilyIndexCount为0
    ·pQueueFamilyIndices为nullptr
    ·initialLayout为VK_IMAGE_LAYOUT_UNDEFINED
10.创建一个名为image的VkImage类型变量。将创建图像句柄存储其中。
11.调用vkCreateImage( logical_device, &image_create_info, nullptr, &image ),提供逻辑设备句柄、指向image_create_info的指针、null值以及指向image变量的指针。
12.确保vkCreateImage调用返回的值等于VK_SUCCESS。

怎么做...

当我们想要创建图像时,需要准备多个参数:图像的类型、尺寸(大小),组建的数量以及每个组建的位数(格式)。我们还需要知道图像是否包含mipmap或者它是否包含多个图层(普通图像必须包含至少一个,而立方图图像必须至少包含六个)。还必须考虑预期的使用场景,这些场景也是在图像创建过程中定义的。我们不能以一种在创建的过程中未定义的方式使用图像。

提示:图像只能用于创建期间指定的用途(目的)。

以下是可以使用图像的目的列表:
    ·VK_IMAGE_USAGE_TRANSFER_SRC_BIT指定图像可用作复制操作的数据源
    ·VK_IMAGE_USAGE_TRANSFER_DST_BIT指定我们可以将数据赋值到图像
    ·VK_IMAGE_USAGE_SAMPLED_BIT表示我们可以从着色器内的图像中采集数据
    ·VK_IMAGE_USAGE_STORAGE_BIT指定图像可以用作着色器内的存储图像
    ·VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT指定我们可以渲染到图像中(将其用作帧缓冲区中的颜色渲染目标/附件)
    ·VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT表示图像可以用做深度和/或模板缓冲区(作为帧缓冲区中的深度渲染目标/附件)
    ·VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT表示绑定的图像的内存将被懒惰的分配(按需)
    ·VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT指定图像可用作着色器内的输入附件

不同的使用场景需要使用不同的图像布局。这些更改(转换)需使用图像内存屏障。但是在创建过程中,我们只能指定VK_IMAGE_LAYOUT_UNDEFINED (如果我们不关心初始化内容)或VK_IMAGE_LAYOUT_PREINITIALIZED(如果我们想通过映射主机可见内存来上传数据),并且在实际使用之前总是需要转换到另一个布局。

译者注:从上面的提示来理解用途是必须在创建期间指定的,但是这里有一句这些更改(转换)需使用图像内存屏障看样子图像布局是可以在之后使用过程中改变的,而用途不是,这里很容易引起歧义,需要注意!

所有图像参数都通过VkImageCreateInfo类型的变量指定,如下所示:

扫描二维码关注公众号,回复: 4550641 查看本文章
VkImageCreateInfo image_create_info = { 
  VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
  nullptr,
  cubemap ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0u, 
  type,
  format,
  size,
  num_mipmaps,
  cubemap ? 6 * num_layers : num_layers, 
  samples,
  VK_IMAGE_TILING_OPTIMAL, 
  usage_scenarios, 
  VK_SHARING_MODE_EXCLUSIVE,
  0,
  nullptr,
  VK_IMAGE_LAYOUT_UNDEFINED,
};

当我们创建图像时,还需要指定平铺(tiling)。它定义了图像的内存结构。有两种可用的图像拼贴类型:线性和最佳。

当使用线性平铺(linear tiling)时,顾名思义图像的数据以线性方式在内存中,类似于缓冲区或c/c++数组。这准许我们映射图像的内存,并从应用程序中直接读取或初始化它,因此我们知道内存是如何组织的。不幸的是,它限制我们将图像用于许多目的;例如,我们不能将图像用作深度纹理或立方体贴图(某些驱动程序可能支持它,但规范并不要求它,一般来说我们不应该依赖它)。线性平铺会降低我们应用的性能。

提示:为获得最佳性能,简易使用最佳屏幕创建图像。

具有最佳屏幕(optimal tiling)的图像可用于所有目的;他们也有更好的表现。但这需要权衡,我们不知道图像的内存是如何组织的。在下图中,我们可以看到图像数据的示例及其内部结构:

每种类型的图像硬件都可以以对其最佳的不同方式存储图像数据。因此我们无法映射图像的内存并直接从应用程序初始化或读取它。在这种情况下,我们需要使用暂存资源(staging resources)。当准备好后,可以使用以下代码创建一个图像:

VkResult result = vkCreateImage( logical_device, &image_create_info, nullptr, &image ); 
if( VK_SUCCESS != result ) {
  std::cout << "Could not create an image." << std::endl;
  return false; 
}
return true;

猜你喜欢

转载自blog.csdn.net/qq_19473837/article/details/84904941