cfl997
cfl997

Reputation: 43

vkGetMemoryFdKHR is return the same fd?

In WIN32:

I'm sure that if the handle is the same, the memory may not be the same, and the same handle will be returned no matter how many times getMemoryWin32HandleKHR is executed.

This is consistent with vulkan's official explanation: Vulkan shares memory.

It doesn't seem to work properly in Linux.

In my program,

getMemoryWin32HandleKHR works normally and can return a different handle for each different memory.

The same memory returns the same handle.

But in getMemoryFdKHR, different memories return the same fd.

Or the same memory executes getMemoryFdKHR twice, it can return two different handles.

This causes me to fail the device memory allocation during subsequent imports.

I don't understand why this is?

Thanks!

#ifdef WIN32
        texGl.handle = device.getMemoryWin32HandleKHR({ info.memory, vk::ExternalMemoryHandleTypeFlagBits::eOpaqueWin32 });
#else
        VkDeviceMemory memory=VkDeviceMemory(info.memory);

        int file_descriptor=-1;

        VkMemoryGetFdInfoKHR get_fd_info{
            VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR, nullptr, memory,
            VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT
        };
        VkResult result= vkGetMemoryFdKHR(device,&get_fd_info,&file_descriptor);
        assert(result==VK_SUCCESS);

        texGl.handle=file_descriptor;
//        texGl.handle = device.getMemoryFdKHR({ info.memory, vk::ExternalMemoryHandleTypeFlagBits::eOpaqueFd });

Win32 is nomal.

Linux is bad.

It will return VK_ERROR_OUT_OF_DEVICE_MEMORY.

#ifdef _WIN32
        VkImportMemoryWin32HandleInfoKHR import_allocate_info{
            VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR, nullptr,
            VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT, sharedHandle, nullptr };
#elif __linux__
        VkImportMemoryFdInfoKHR import_allocate_info{
            VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR, nullptr,
            VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT,
                    sharedHandle};
#endif

        VkMemoryAllocateInfo allocate_info{
            VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,  // sType
            &import_allocate_info,                   // pNext
            aligned_data_size_,         // allocationSize
            memory_index };



        VkDeviceMemory device_memory=VK_NULL_HANDLE;
        VkResult result = vkAllocateMemory(m_device, &allocate_info, nullptr, &device_memory);
        NVVK_CHECK(result);

I think it has something to do with fd.

In my some test: if I try to get fd twice. use the next fd that vkAllocateMemory is work current......but I think is error .

The fd obtained in this way is different from the previous one.

Because each acquisition will be a different fd.

This makes it impossible for me to distinguish, and the following fd does vkAllocateMemory.
Still get an error.

So this test cannot be used.

I still think it should have the same process as win32. When the fd is obtained for the first time, vkAllocateMemory can be performed correctly.

thanks very much!

Upvotes: 0

Views: 501

Answers (1)

Nicol Bolas
Nicol Bolas

Reputation: 473447

The Vulkan specifications for the Win32 handle and POSIX file descriptor interfaces explicitly state different things about their importing behavior.

For HANDLEs:

Importing memory object payloads from Windows handles does not transfer ownership of the handle to the Vulkan implementation. For handle types defined as NT handles, the application must release handle ownership using the CloseHandle system call when the handle is no longer needed.

For FDs:

Importing memory from a file descriptor transfers ownership of the file descriptor from the application to the Vulkan implementation. The application must not perform any operations on the file descriptor after a successful import.

So HANDLE importation leaves the HANLDE in a valid state, still referencing the memory object. File descriptor importation claims ownership of the FD, leaving it in a place where you cannot use it.

What this means is that the FD may have been released by the internal implementation. If that is the case, later calls to create a new FD may use the same FD index as a previous call.

The safest way to use both of these APIs is to have the Win32 version emulate the functionality of the FD version. Don't try to do any kinds of comparisons of handles. If you need some kind of comparison logic, then you'll have to implement it yourself. When you import a HANDLE, close it immediately afterwards.

Upvotes: 1

Related Questions