【问题标题】:generating of mipmaps using vkCmdBlitImage for cubemap textures使用 vkCmdBlitImage 为立方体贴图纹理生成 mipmap
【发布时间】:2026-01-06 08:35:02
【问题描述】:

动态生成mipmap时,VkImageBlit.dstOffsets和VkImageBlit.srcOffsets的参数应该是什么? 我正在逐层执行每个 mipmap 级别,但在某个地方出错了,主要是我认为偏移量。所以我有数据,其中所有六个面都具有第 0 个 mipmap 级别。

for(int j=0; j< bufferCopyRegions.size(); j++) {

    for (int32_t i = 1; i < mipLevels; i++)
    {

        VkImageBlit imageBlit{};

        // Source
        imageBlit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
        imageBlit.srcSubresource.layerCount = 1;
        imageBlit.srcSubresource.mipLevel = 0;

        imageBlit.srcOffsets[1].x = bitmapInfos[j].width;  
        imageBlit.srcOffsets[1].y = bitmapInfos[j].height;  
        imageBlit.srcOffsets[1].z = 1;

        // Destination
        imageBlit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
        imageBlit.dstSubresource.layerCount = 1;
        imageBlit.dstSubresource.mipLevel = i;


        imageBlit.dstOffsets[1].x = int32_t(bitmapInfos[j].width >> (i) == 0 ? 1 : int32_t(bitmapInfos[j].width >> (i )));
        imageBlit.dstOffsets[1].y = int32_t(bitmapInfos[j].height >> (i) == 0 ? 1 : int32_t(bitmapInfos[j].height >> (i)));
        imageBlit.dstOffsets[1].z = 1;

        VkImageMemoryBarrier imageMemoryBarrier = {};
        imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
        imageMemoryBarrier.pNext = NULL;
        imageMemoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
        imageMemoryBarrier.subresourceRange.baseMipLevel = i;
        imageMemoryBarrier.subresourceRange.levelCount = 1;
        imageMemoryBarrier.subresourceRange.baseArrayLayer = j;
        imageMemoryBarrier.subresourceRange.layerCount = 1;

        // change layout of current mip level to transfer dest
        setImageLayout(imageMemoryBarrier,
                       blitCmd,
                       image,
                       VK_IMAGE_ASPECT_COLOR_BIT,
                       VK_IMAGE_LAYOUT_UNDEFINED,
                       VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, imageMemoryBarrier.subresourceRange,
                       VK_PIPELINE_STAGE_TRANSFER_BIT,
                       VK_PIPELINE_STAGE_HOST_BIT);

        // Do blit operation from previous mip level
        vkCmdBlitImage(blitCmd, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, image,
                VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &imageBlit, VK_FILTER_LINEAR);


        setImageLayout(imageMemoryBarrier, blitCmd, image, VK_IMAGE_ASPECT_COLOR_BIT,
                       VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
                       VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, imageMemoryBarrier.subresourceRange,
                       VK_PIPELINE_STAGE_HOST_BIT,
                       VK_PIPELINE_STAGE_TRANSFER_BIT);
    }
}

【问题讨论】:

  • 考虑到有多少这点在被指出后往往会令人惊讶,请自动说您启用了验证层(如果您的 Q 中有警告或错误报告,请包括警告或错误报告)

标签: vulkan


【解决方案1】:

我没有看到 imageBlit.srcSubresourceimageBlit.dstSubresource 中的 baseArrayLayer 设置为 j。这可能是您的直接问题。

你的障碍对我来说也很糟糕。只有 top mip 需要与 host 同步。但即便如此VK_PIPELINE_STAGE_HOST_BIT 应该是必要的,因为vkQueueSubmit 有一个例外,它表示如果主机写入在它被调用之前结束,它会隐式执行这种同步(6.9. Host Write Ordering Guarantees 并在6.1.3. Access Types 中的注释)。

【讨论】:

  • 这里不需要使用host_stage,因为屏障是在子命令缓冲区时隐式完成的
  • @AntoineMorrier 对。忘了那个规矩了。合并。谢谢。