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.