Skip to content

3d texture blitting wrong along depth/third axis? #2562

@mokafolio

Description

@mokafolio

I am generating 3d texture mip maps with the typical blitting loop to do so (originally using linear filtering). After I dismissed odd results on OSX as filtering/driver differences initially, curiosity got a hold of me and I switched everything to NEAREST which is where things got funky.

My input 3D texture is 256 x 256 x 256 with 8 mip levels, i.e. the following chain:

256 -> 128 -> 64 -> 32 -> 16 -> 8 -> 4 -> 2 -> 1

On level 7 the texture is 2x2x2. Along the x and y axis, everything seems as expected and consistent with what I am seeing on linux and windows. Where things differ in a weird way is along the depth/z axis of the texture. Every mip map level >= 5 looks exactly the same along every depth slice. I have no idea why this is happening but this looks like a bug in moltenvk to me (as 3d texture blitting might be a little bit of a niche use case).

Here is a simplified version of the blitting logic involved:

    for (u32 i = 1; i < mipmapLevelCount; ++i)
    {
        const auto sourceMip = i - 1;
        const auto destMip = i;

        // barriers omitted ...

        VkImageBlit blit {};
        blit.srcOffsets[0] = { 0, 0, 0 };
        blit.srcOffsets[1] = { mipWidth, mipHeight, mipDepth };
        blit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;

        blit.srcSubresource.mipLevel = sourceMip;
        blit.srcSubresource.baseArrayLayer = 0;
        blit.srcSubresource.layerCount = arrayLayerCount;
        blit.dstOffsets[0] = { 0, 0, 0 };
        if (mipWidth > 1)
        {
            mipWidth /= 2;
        }
        if (mipHeight > 1)
        {
            mipHeight /= 2;
        }
        if (mipDepth > 1)
        {
            mipDepth /= 2;
        }
        blit.dstOffsets[1] = { mipWidth, mipHeight, mipDepth };
        blit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
        blit.dstSubresource.mipLevel = destMip;
        blit.dstSubresource.baseArrayLayer = 0;
        blit.dstSubresource.layerCount = arrayLayerCount;

        vkCmdBlitImage(commandBuffer,
                       image,
                       VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
                       image,
                       VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
                       1,
                       &blit,
                       VK_FILTER_NEAREST);
    }

My test executable just draws slices of the 3D texture with NEAREST filtering. The texture is just an RGB volume across the corresponding axis:

Image Image

Here is what mip level 7 looks like on linux (which is correct, 2 distinct slices):

Image
Image

And here is what it looks like with SDK shipped moltenvk (anything >= level 5 looks identical for every slice of the texture):

Image Image

Hope this somewhat contrived example illustrates the problem.

Happy to provide a standalone executable/test at some point!

Thanks

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions