2
votes

I'm trying to export the handle of a memory allocation made by Vulkan to import it into OpenGL. But when I add a vk::ExportMemoryAllocateInfo in the pNext chain of the vk::MemoryAllocateInfo, vk::Device::allocateMemory throws an OutOfDeviceMemory exception.

When I don't export the handle, the allocation does not fail but the returned handle is not valid.

Here is the guilty code (based jherico's example: vulkan-opengl-interop-example):

// The physical device and the device are correct
// requirements are for a RGBA image of 1024x1024 pixels
// memory properties is just vk::MemoryPropertyFlagBits::eDeviceLocal
void IMemoryObject::Allocate(vk::PhysicalDevice physicalDevice, vk::Device device, const vk::MemoryRequirements& requirements, vk::MemoryPropertyFlags properties)
{
        unsigned int memoryTypeIndex = 0;
        bool memoryIndexTypeFound = false;
        vk::PhysicalDeviceMemoryProperties memoryProperties = physicalDevice.getMemoryProperties();

        for (unsigned int i = 0; i < memoryProperties.memoryTypeCount && !memoryIndexTypeFound; i++)
        {
            vk::MemoryType memoryType = memoryProperties.memoryTypes[i];
            if (requirements.memoryTypeBits & 1 << i && (memoryType.propertyFlags & properties) == properties)
            {
                memoryTypeIndex = i;
                memoryIndexTypeFound = true;
            }
        }

        if (!memoryIndexTypeFound)
            throw std::exception();

        vk::ExportMemoryAllocateInfo exportAllocInfo;
        exportAllocInfo.setHandleTypes(vk::ExternalMemoryHandleTypeFlagBits::eOpaqueWin32);

        vk::MemoryAllocateInfo allocateInfo;
        allocateInfo.setPNext(&exportAllocInfo); // Remove this line and the allocation won't fail
        allocateInfo.setAllocationSize(requirements.size);
        allocateInfo.setMemoryTypeIndex(memoryTypeIndex);

        deviceMemory_ = device.allocateMemoryUnique(allocateInfo);

        // Call VkBindBufferMemory or VkBindImageMemory, never reached anyway when allocateInfo.pNext == &exportAllocInfo;
        BindMemory(*deviceMemory_, 0);
}

My system is:

  • Windows 7
  • Nvidia Quadro RTX 4000
  • Driver version 431.02 or 431.94

The validation layer is present in my instance but stays silencious, extensions VK_KHR_external_memory and VK_KHR_external_memory_win32 are available in my device, the allocation size respect the API limitations and the memoryIndexType is correct.

Am I doing something wrong or there is a limitation I missed?

Thanks !

Edit:

I tried to export the handle as a vk::ExternalMemoryHandleTypeFlagBits::eOpaqueWin32Kmt and the allocation worked. The code below is how I test if the allocation require an dedicated allocation to export an handle type.

bool RequireDedicatedAllocation(vk::PhysicalDevice physicalDevice, const vk::ImageCreateInfo& createInfo, vk::ExternalMemoryHandleTypeFlagBits handleType)
{
    vk::PhysicalDeviceExternalImageFormatInfo externalImageFormatInfo;
    externalImageFormatInfo.setHandleType(handleType);

    vk::PhysicalDeviceImageFormatInfo2 imageFormatInfo;
    imageFormatInfo.setUsage(createInfo.usage)
                   .setFormat(createInfo.format)
                   .setTiling(createInfo.tiling)
                   .setType(createInfo.imageType)
                   .setPNext(&externalImageFormatInfo);

    vk::StructureChain<vk::ImageFormatProperties2, vk::ExternalImageFormatProperties> imageFormatPropertiesChain = physicalDevice.getImageFormatProperties2<vk::ImageFormatProperties2, vk::ExternalImageFormatProperties>(imageFormatInfo);
    vk::ExternalImageFormatProperties externalImageProperties = imageFormatPropertiesChain.get<vk::ExternalImageFormatProperties>();

    return static_cast<bool>(externalImageProperties.externalMemoryProperties.externalMemoryFeatures & vk::ExternalMemoryFeatureFlagBits::eDedicatedOnly);
}

On my system, it throws an ErrorFormatNotSupported error (on vk::PhysicalDevice::getImageFormatProperties2) with vk::ExternalMemoryHandleTypeFlagBits::eOpaqueWin32 and return false with vk::ExternalMemoryHandleTypeFlagBits::eOpaqueWin32Kmt.

1
Yes, the problem is the same with driver version 431.94. - Siliace
Please add the code where you check the limits into the question itself. Notably do you check if it requires a Dedicated Allocation? - krOoze
I've edited my post. I checked the allocation limits using NSight (I only allocate one small image of an arbitrary size). - Siliace

1 Answers

0
votes

I finally ended up with a vk::ExternalMemoryHandleTypeFlagBits::eOpaqueWin32Kmt. I don't need to interact with it throught the Windows' API, just OpenGL.