跳到主要内容

:material-chevron-right-circle: vkCmdBlitImage

函数原型

void vkCmdBlitImage(
VkCommandBuffer commandBuffer,
VkImage srcImage,
VkImageLayout srcImageLayout,
VkImage dstImage,
VkImageLayout dstImageLayout,
uint32_t regionCount,
const VkImageBlit* pRegions,
VkFilter filter);

描述

用于图像缩放、图像格式转换、生成 mipmap等图像复制功能。

补充

VkImageBlit 结构体定义:

typedef struct VkImageBlit {
VkImageSubresourceLayers srcSubresource;
VkOffset3D srcOffsets[2];
VkImageSubresourceLayers dstSubresource;
VkOffset3D dstOffsets[2];
} VkImageBlit;

VkImageSubresourceLayers 结构体定义:

VkImageSubresourceLayers {
VkImageAspectFlags aspectMask; // 通常为 VK_IMAGE_ASPECT_COLOR_BIT
uint32_t mipLevel; // mip 等级
uint32_t baseArrayLayer; // 数组层起始索引(如立方体图为 0-5)
uint32_t layerCount; // 层数(通常为 1)
}

srcOffsets[2] / dstOffsets[2]: 指定 blit 区域的起点和终点:

  • offsets[0]: 左上前(x, y, z)
  • offsets[1]: 右下后(x, y, z)
  • 注意:坐标不包含右下角,行为类似 Python 切片

参数

  • commandBuffer : 录制指令的命令缓冲区。
  • srcImage : 源图像。
  • srcImageLayout : 源图像当前 layout。
  • dstImage : 目标图像。
  • dstImageLayout : 目标图像当前 layout。
  • regionCount : blit 区域的数量。
  • pRegions : 要执行 blit 的区域。
  • filter : VK_FILTER_LINEAR(缩放时线性插值)或 VK_FILTER_NEAREST(最邻近)。

返回值

代码示例

//生成 mipmap
void GenerateMipmaps(VkCommandBuffer cmd, VkImage image, int32_t width, int32_t height, uint32_t mipLevels) {
VkImageMemoryBarrier barrier{};
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
barrier.image = image;
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
barrier.subresourceRange.baseArrayLayer = 0;
barrier.subresourceRange.layerCount = 1;
barrier.subresourceRange.levelCount = 1;

for (uint32_t i = 1; i < mipLevels; i++) {
// Transition mip[i-1] to SRC
barrier.subresourceRange.baseMipLevel = i - 1;
barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;

vkCmdPipelineBarrier(cmd,
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0,
0, nullptr, 0, nullptr, 1, &barrier);

// Blit mip[i-1] to mip[i]
VkImageBlit blit{};
blit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
blit.srcSubresource.mipLevel = i - 1;
blit.srcSubresource.baseArrayLayer = 0;
blit.srcSubresource.layerCount = 1;
blit.srcOffsets[0] = {0, 0, 0};
blit.srcOffsets[1] = {width, height, 1};

int32_t mipWidth = width > 1 ? width / 2 : 1;
int32_t mipHeight = height > 1 ? height / 2 : 1;

blit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
blit.dstSubresource.mipLevel = i;
blit.dstSubresource.baseArrayLayer = 0;
blit.dstSubresource.layerCount = 1;
blit.dstOffsets[0] = {0, 0, 0};
blit.dstOffsets[1] = {mipWidth, mipHeight, 1};

vkCmdBlitImage(cmd, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1, &blit, VK_FILTER_LINEAR);

width = mipWidth;
height = mipHeight;
}
}