在Vulkan中生成Mipmap [英] Generating mipmaps in Vulkan

查看:233
本文介绍了在Vulkan中生成Mipmap的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用vkCmdBlitImage生成mipmaps运行时(实现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 );
    }

每个Mip等级都需要自己的图像吗?应该如何初始化它们?在将暂存缓冲区用于纹理数据时,我应该何时生成mipmap?

我修改了代码,仅按照建议使用一张图像,现在看来可以正常工作(我可以在RenderDoc纹理查看器中看到正确的Mip级图像,并且没有任何验证错误).

解决方案

每个Mip等级都需要自己的图像吗?

否,每个Mip等级都不需要单独的图像.如果为纹理创建图像,则只需设置VkImageCreateInfo的mipLevels.

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

这在很大程度上取决于您想要用什么来喂养您的mi子.您是否只想从纹理文件(静态Mip级别)加载它们,还是需要在运行时生成它们?

如果您只想从文件中加载它们,则不要盲目化.创建一个暂存缓冲区(不是图像),将纹理数据加载到其中,并从该缓冲区对图像执行vkCmdCopyBufferToImage.

但是,请您添加更多详细信息.我看不到任何图像布局转换可能对您至关重要,具体取决于您所使用的实现,图像创建信息上没有任何信息(例如标志),您也没有声明代码是否真正起作用./p>

blit源代码中的mipLevel可能是错误的一件事(如果没有更多代码就很难说出).您是否真的有一个完整的Mip链并按mip复制mip的来源?

I'm trying to generate mipmaps runtime (implement glGenerateMipmap() functionality) using vkCmdBlitImage but don't understand the process. Here's my code so far:

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

Does each mip level need its own image? How should they be initialized? When should I generate mipmaps when using a staging buffer for texture data?

Edit: I modified the code to only use one image as suggested and it seems to work now (I can see correct mip level images in RenderDoc texture viewer and I don't get any validation errors).

解决方案

Does each mip level need its own image?

No, you don't need a separate image for each mip level. If you create the image for your texture you only need to set mipLevels of the VkImageCreateInfo.

How should they be initialized? When should I generate mipmaps when using a staging buffer for texture data?

This heavily depends on what you want to feed your mips with. Do you just want to load them from a texture file (static mip levels) or do you need to generate them at runtime?

If you only want to load them from a file, don't blit at all. Create a staging buffer (not image), load your texture data into it and do a vkCmdCopyBufferToImage to your image from that buffer.

But can you please add some more detail. I don't see any image layout transitions that may be crucial depending on the implementation you're on, there is no info on the image create info (flags e.g.) and you don't state if your code actually works or not.

One thing that could be wrong (hard to tell without a bit more code) is the mipLevel in your blit source. Do you really have a source that has the complete mip chain and copy mip by mip?

这篇关于在Vulkan中生成Mipmap的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆