-
Notifications
You must be signed in to change notification settings - Fork 455
Description
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:


Here is what mip level 7 looks like on linux (which is correct, 2 distinct slices):
And here is what it looks like with SDK shipped moltenvk (anything >= level 5 looks identical for every slice of the texture):


Hope this somewhat contrived example illustrates the problem.
Happy to provide a standalone executable/test at some point!
Thanks