复制缓冲到图像

在我们回到createTextureImage函数之前,先编写一个新的辅助函数:copyBufferToImage。

void copyBufferToImage(VkBuffer buffer, VkImage image, uint32_t
width, uint32_t height) {
    VkCommandBuffer commandBuffer = beginSingleTimeCommands();

    endSingleTimeCommands(commandBuffer);
}

和复制缓冲数据一样,我们需要使用VkBufferImageCopy结构体指定将数据复制到图像的哪一部分。

VkBufferImageCopy region = {};
region.bufferOffset = 0;
region.bufferRowLength = 0;
region.bufferImageHeight = 0;

region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
region.imageSubresource.mipLevel = 0;
region.imageSubresource.baseArrayLayer = 0;
region.imageSubresource.layerCount = 1;

region.imageOffset = {0, 0, 0};
region.imageExtent = { width, height, 1};

bufferOffset成员变量用于指定要复制的数据在缓冲中的偏移位置。bufferRowLength和bufferImageHeight成员变量用于指定数据在内存中的存放方式。通过这两个成员变量我们可以对每行图像数据使用额外的空间进行对齐。将这两个成员变量的值都设置为0,数据将会在内存中被紧凑存放。imageSubresource、imageOffset和imageExtent成员变量用于指定数据被复制到图像的哪一部分。

从缓冲复制数据到图像需要调用vkCmdCopyBufferToImage函数来记录指令到指令缓冲:

vkCmdCopyBufferToImage( commandBuffer, buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);

vkCmdCopyBufferToImage函数的第4个参数用于指定目的图像当前使用的图像布局。这里我们假设图像已经被变换为最适合作为复制目的的布局。我们只复制了一张图像,实际上是可以指定一个VkBufferImageCopy数组来一次从一个缓冲复制数据到多个不同的图像对象。