Vulkan Cookbook 第四章 14 将数据从图像复制到缓冲区

将数据从图像复制到缓冲区

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

在Vulkan中,我们不仅可以把数据从缓冲区传输到图像,还可以将数据从图像复制到缓冲区。绑定到它们的内存对象的属性是什么并不重要。但是数据复制操作是更新无法映射的设备本地内存的唯一方法。

怎么做...

1.获取命令缓冲区的句柄并将其存储在名为command_buffer的VkCommandBuffer类型变量中。确保命令缓冲区已处于记录状态(请参阅第3章,命令缓冲区和同步中的开始命令缓冲区记录操作)。
2.获取将复制数据的图像。将其句柄存储在名为source_image的VkImage类型变量中。
3.准备源图像的当前内存布局。初始化名为image_layout的VkImageLayout类型变量。
4.获取将要复制数据的缓冲区。存储在名为destination_buffer的VkBuffer类型的变量中准备其句柄。
5.创建名为regions的std::vector<VkBufferImageCopy> 类型的变量。对每个成员指定以下值:
    ·bufferOffset为从缓冲区内存开头的偏移量。
    ·bufferRowLength表示缓冲区单行的数据长度,如果数据紧密打包(根据目标图像大小)则为0值。
    ·bufferImageHeight表示储存在缓冲区中的虚构图像的高度(行数),如果缓冲区的数据紧密打包(根据目标图像大小)则0值。
    ·使用以下值初始化imageSubresource成员:
        ·aspectMask为图像方面(颜色、深度或模板)
        ·mipmap为mipmap级别的编号(索引)
        ·baseArrayLayer为第一个数组层的编号
        ·layerCount为复制的数组层数
    ·imageOffset为图像子区域的初始化偏移(以纹素为单位),从中读取数据并将其复制到缓冲区。
    ·imageExtent为图像的大小(尺寸)。
6.调用vkCmdCopyImageToBuffer(command_buffer,source_image,image_layout,destination_buffer, static_cast<uint32_t>(regions.size()), &regions[0] ),使用command_buffer、source_image、image_layout、destination_buffer变量,regions向量中的元素数量以及指向其第一个元素的指针。

这个怎么运作...

从图像到缓冲区复制数据是一种记录到缓冲区的操作,如下所示:

if( regions.size() > 0 ) { 
  vkCmdCopyImageToBuffer( command_buffer, source_image, image_layout, destination_buffer, static_cast<uint32_t>(regions.size()), &regions[0] ); 
}

命令缓冲区必须已处于记录状态。

要正确复制数据,我们需要提供多个参数来定义数据源和数据复制的目标。这些参数包括x、y和z维度的图像原点(从纹理的左上角)偏移,mipmap级别和从中复制数据的基础数组层以及层数将成为数据的来源。图像尺寸也是必须的。

对于目标缓冲区,我们指定一个内存偏移量(从缓冲区内存的开头),数据行的长度和缓冲区中数据的高度。我们还可以为行长度和高度提供零,这意味着复制到缓冲区的数据将被紧密打包并且将对应于原图像的尺寸。

前面的参数是使用VkBufferImageCopy元素数组指定的,类似于将数据从缓冲区复制到图像,如将数据从缓冲区复制到图像内容中所述。我们可以提供许多区域并复制不连续的内存范围作为一个复制操作的一部分。

提示:必须使用VK_BUFFER_USAGE_TRANSFER_SRC_BIT用法创建用于复制数据的源图像。在传输操作之前,我们还需要将图像的布局转换为VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL。
          必须使用VK_BUFFER_USAGE_TRANSFER_DST_BIT用法创建可以复制数据的目标缓冲区。

在我们从图像中复制数据之前,应该设置一个内存屏障,并将图像的布局从当前使用的布局更改为VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL布局。我们还应该将内存访问的类型从目前发生的内容更改为VK_ACCESS_TRANSFER_READ_BIT。在完成从图像复制数据后,如果从现在开始将其用于其他目的。也应该设置屏障。这次我们应该将内存访问类型从VK_ACCESS_TRANSFER_READ_BIT更改为与使用映像的目的对应的访问类型。同时应该将布局从VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL转换为与图像的下一次使用兼容的布局(请参阅设置图像内存屏障内容)。没有这些屏障,不仅可能以错误的方式执行数据传输操作,而且稍后的命令可能在传输完成之前覆盖图像内容。

应该为缓冲区设置类似的屏障(但它们可以是同一个管线屏障的一部分)。如果之前缓冲区用于其他目的,我们应该在传输操作之前将内存访问权限更改为VK_ACCESS_TRANSFER_WRITE_BIT,如设置缓冲区内存屏障内容。

猜你喜欢

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