vkGetImageMemoryRequirements() reporting the wrong memory type bits for textures

This occurs on a GeForce GTX 960 running the 364.51 drivers on Windows 7.

I am encountering a strange bug when allocating an image. The code I am using is below:

VkImageCreateInfo    imageCreateInfo = {};
VkMemoryRequirements memReqs         = {};

imageCreateInfo.sType         = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
imageCreateInfo.pNext         = nullptr;
imageCreateInfo.flags         = 0;

imageCreateInfo.imageType     = VK_IMAGE_TYPE_2D;
imageCreateInfo.format        = VK_FORMAT_B8G8R8A8_UNORM;

imageCreateInfo.extent.width  = 256;
imageCreateInfo.extent.height = 256;
imageCreateInfo.extent.depth  = 1;

imageCreateInfo.arrayLayers   = 1;
imageCreateInfo.mipLevels     = 1;

imageCreateInfo.samples       = VK_SAMPLE_COUNT_1_BIT;
imageCreateInfo.tiling        = VK_IMAGE_TILING_OPTIMAL;
imageCreateInfo.usage         = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;

imageCreateInfo.sharingMode   = VK_SHARING_MODE_EXCLUSIVE;

imageCreateInfo.queueFamilyIndexCount = 0;
imageCreateInfo.pQueueFamilyIndices   = nullptr;

imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
    
err = vkCreateImage(m_vkDevice, &imageCreateInfo, nullptr, &image);
if(err)
  goto vk_failed;

vkGetImageMemoryRequirements(m_vkDevice, image, &memReqs);

...

vkCreateImage returns without an error, but vkGetImageMemoryRequirements() returns the following:

size = 262144
alignment = 1024
memoryTypeBits = 2

Size and alignment are OK, but the type bits specify VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT and nothing else. If I allocate memory matching this type and try to bind it with vkBindImageMemory(), the bind function returns an undefined VkResult code of -1000013000. If I ignore the memory type reported by vkGetImageMemoryRequirements() and force it to use the device local memory (memory type 1 on heap index 0), the bind succeeds and I can use the image.

If I change the tiling to VK_IMAGE_TILING_LINEAR, vkGetImageMemoryRequirements() returns the correct compatible memory type bits for the image (15).

It’s a trap!

easy (and often) mixed up, but memoryTypeBits has nothing to do with memory properties.

memoryTypeBits has one bit set for each memortype that you can use with this resource. The memory properties is something you request yourself.

function I use inside gl_vk_threaded_cadscene/resources_vk.cpp at master · nvpro-samples/gl_vk_threaded_cadscene · GitHub

static bool  getMemoryAllocationInfo(
    const VkMemoryRequirements &memReqs, 
    const VkFlags memProps, 
    const VkPhysicalDeviceMemoryProperties  &memoryProperties, 
    VkMemoryAllocateInfo &memInfo)
  {
    memInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
    memInfo.pNext = NULL;

    if (!memReqs.size){
      memInfo.allocationSize  = 0;
      memInfo.memoryTypeIndex = ~0;
      return true;
    }

    // Find an available memory type that satifies the requested properties.
    uint32_t memoryTypeIndex;
    for (memoryTypeIndex = 0; memoryTypeIndex < memoryProperties.memoryTypeCount; ++memoryTypeIndex) {
      if (( memReqs.memoryTypeBits & (1<<memoryTypeIndex)) &&
        ( memoryProperties.memoryTypes[memoryTypeIndex].propertyFlags & memProps) == memProps) 
      {
        break;
      }
    }
    if (memoryTypeIndex >= memoryProperties.memoryTypeCount) {
      assert(0 && "memorytypeindex not found");
      return false;
    }

    memInfo.allocationSize  = memReqs.size;
    memInfo.memoryTypeIndex = memoryTypeIndex;

    return true;
  }

Ah, it makes sense now. Thanks for the help!