Graphics 在Vulkan中生成mipmap

Graphics 在Vulkan中生成mipmap,graphics,mipmaps,vulkan,Graphics,Mipmaps,Vulkan,我试图使用vkcmdblimitimage生成mipmap运行时(实现glGenerateMipmap()功能),但不了解该过程。以下是我目前的代码: VkImageCreateInfo imageCreateInfo = {}; imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; imageCreateInfo.pNext = nullptr; imageCreateInfo.imageType = VK_IMAGE_TYP

我试图使用
vkcmdblimitimage
生成mipmap运行时(实现
glGenerateMipmap()
功能),但不了解该过程。以下是我目前的代码:

VkImageCreateInfo imageCreateInfo = {};
imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
imageCreateInfo.pNext = nullptr;
imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
imageCreateInfo.format = format;
imageCreateInfo.mipLevels = mipLevels;
imageCreateInfo.arrayLayers = 1;
imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
imageCreateInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
imageCreateInfo.extent = { static_cast<std::uint32_t>( width ), static_cast<std::uint32_t>( height ), 1 };
imageCreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;

err = vkCreateImage( GfxDeviceGlobal::device, &imageCreateInfo, nullptr, &image );

...

    for (int i = 1; i < mipLevels; ++i)
    {
        const std::int32_t mipWidth = width >> i;
        const std::int32_t mipHeight = height >> i;

        VkImageBlit imageBlit = {};
        imageBlit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
        imageBlit.srcSubresource.baseArrayLayer = 0;
        imageBlit.srcSubresource.layerCount = 1;
        imageBlit.srcSubresource.mipLevel = 0;
        imageBlit.srcOffsets[ 0 ] = { 0, 0, 0 };
        imageBlit.srcOffsets[ 1 ] = { width, height, 1 };

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

        vkCmdBlitImage( texCmdBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
                        image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
                        1, &imageBlit, VK_FILTER_LINEAR );
    }
VkImageCreateInfo-imageCreateInfo={};
imageCreateInfo.sType=VK_结构_类型_图像_创建_信息;
imageCreateInfo.pNext=nullptr;
imageCreateInfo.imageType=VK_IMAGE_TYPE_2D;
imageCreateInfo.format=格式;
imageCreateInfo.mipLevels=mipLevels;
imageCreateInfo.arrayLayers=1;
imageCreateInfo.samples=VK_样本_计数_1_位;
imageCreateInfo.tiling=VK_图像_tiling_最优;
imageCreateInfo.usage=VK_图像_使用率_采样位;
imageCreateInfo.sharingMode=VK_共享_模式_独占;
imageCreateInfo.initialLayout=VK\u IMAGE\u LAYOUT\u预初始化;
imageCreateInfo.extent={static_cast(宽度),static_cast(高度),1};
imageCreateInfo.usage=VK_IMAGE_usage_TRANSFER_SRC_BIT | VK_IMAGE_usage_TRANSFER_DST_BIT | VK_IMAGE_usage_SAMPLED_BIT;
err=vkCreateImage(GfxDeviceGlobal::device,&imageCreateInfo,nullptr,&image);
...
对于(int i=1;i>i;
常数std::int32\u t mipHeight=高度>>i;
VkImageBlit imageBlit={};
imageBlit.srcSubresource.aspectMask=VK\u IMAGE\u ASPECT\u COLOR\u位;
imageBlit.srcSubresource.baseArrayLayer=0;
imageBlit.srcSubresource.layerCount=1;
imageBlit.srcSubresource.mipLevel=0;
srcpoffsets[0]={0,0,0};
srcpoffsets[1]={width,height,1};
imageBlit.dstSubresource.aspectMask=VK_IMAGE_ASPECT_COLOR_位;
imageBlit.dstSubresource.baseArrayLayer=0;
imageBlit.dstSubresource.layerCount=1;
imageBlit.dstSubresource.mipLevel=i;
dstOffsets[0]={0,0,0};
dstOffsets[1]={mipWidth,mipHeight,1};
VKCMDBLTIMAGE(texCmdBuffer,image,VK_image_LAYOUT_TRANSFER_SRC_OPTIMAL,
图像,VK图像布局传输优化,
1、&imageBlit、VK_滤波器(线性);
}
每个mip级别是否需要自己的图像?它们应该如何初始化?当使用纹理数据的暂存缓冲区时,我应该何时生成mipmap

编辑:我修改了代码,按照建议只使用一个图像,现在似乎可以正常工作(我可以在RenderDoc纹理查看器中看到正确的mip级别图像,并且没有任何验证错误)。

每个mip级别是否需要自己的图像

不,每个mip级别不需要单独的图像。如果为纹理创建图像,则只需设置VkImageCreateInfo的mipLevel

它们应该如何初始化?当使用纹理数据的暂存缓冲区时,我应该何时生成mipmap

这在很大程度上取决于您想要为mips提供什么。您只是想从纹理文件(静态mip级别)加载它们,还是需要在运行时生成它们

如果您只想从文件中加载它们,则根本不必进行blit。创建一个暂存缓冲区(不是图像),将纹理数据加载到其中,然后从该缓冲区对图像执行vkCmdCopyBufferToImage

但是你能补充一些细节吗。我看不到任何图像布局转换可能是至关重要的,这取决于您所使用的实现,没有关于图像创建信息(例如标志)的信息,您也没有说明代码是否实际工作


有一件事可能是错误的(如果没有更多的代码就很难说),那就是blit源代码中的MIP级别。您是否真的有一个源具有完整的mip链并通过mip复制mip?

src和dst映像可以相同。为了这个目的,也许我们甚至应该这样做;每个图像至少有1个mip级别(0为基本“纹理”)。将
i
添加到
i
很奇怪。谢谢,我在问题中添加了一些细节。我还没有写转换,因为我不确定我的整个过程。@SurvivalMachine凭借我出色的谷歌搜索技能,找到了一个你正试图做的例子。我要把它背到这个答案上: