使用 vkCmdBlitImage 为立方体贴图纹理生成 mipmap

generating of mipmaps using vkCmdBlitImage for cubemap textures

动态生成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);
    }
}

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

我觉得你的障碍也很糟糕。只有 top mip 需要与主机同步。但即便如此 VK_PIPELINE_STAGE_HOST_BIT 应该 不是 是必要的,因为 vkQueueSubmit 有一个例外,它说如果主机写入在它被调用之前结束,它会隐式地进行这种同步(6.9. Host Write Ordering Guarantees and reminded in the Note in 6.1.3. Access Types).