: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;
}
}