gfxstream: Fix precedence and ownership issues on Linux for imported FD
and the VirtGpuResource
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33451>
diff --git a/src/gfxstream/guest/vulkan_enc/ResourceTracker.cpp b/src/gfxstream/guest/vulkan_enc/ResourceTracker.cpp
index d7837d0..bbdbec3 100644
--- a/src/gfxstream/guest/vulkan_enc/ResourceTracker.cpp
+++ b/src/gfxstream/guest/vulkan_enc/ResourceTracker.cpp
@@ -1348,7 +1348,8 @@
void ResourceTracker::setDeviceMemoryInfo(VkDevice device, VkDeviceMemory memory,
VkDeviceSize allocationSize, uint8_t* ptr,
uint32_t memoryTypeIndex, void* ahw, bool imported,
- zx_handle_t vmoHandle, VirtGpuResourcePtr blobPtr) {
+ zx_handle_t vmoHandle, VirtGpuResourcePtr blobPtr,
+ int importedFd) {
std::lock_guard<std::recursive_mutex> lock(mLock);
auto& info = info_VkDeviceMemory[memory];
@@ -1362,6 +1363,7 @@
info.imported = imported;
info.vmoHandle = vmoHandle;
info.blobPtr = blobPtr;
+ info.importedFd = importedFd;
}
void ResourceTracker::setImageInfo(VkImage image, VkDevice device,
@@ -3333,13 +3335,6 @@
void* ahw = nullptr;
#endif
-#ifdef LINUX_GUEST_BUILD
- const VkImportMemoryFdInfoKHR* importFdInfoPtr =
- vk_find_struct_const(pAllocateInfo, IMPORT_MEMORY_FD_INFO_KHR);
-#else
- const VkImportMemoryFdInfoKHR* importFdInfoPtr = nullptr;
-#endif
-
#ifdef VK_USE_PLATFORM_FUCHSIA
const VkImportMemoryBufferCollectionFUCHSIA* importBufferCollectionInfoPtr =
vk_find_struct_const(pAllocateInfo, IMPORT_MEMORY_BUFFER_COLLECTION_FUCHSIA);
@@ -3413,6 +3408,8 @@
importVmo = true;
}
+ const VkImportMemoryFdInfoKHR* importFdInfoPtr =
+ vk_find_struct_const(pAllocateInfo, IMPORT_MEMORY_FD_INFO_KHR);
if (importFdInfoPtr) {
importDmabuf =
(importFdInfoPtr->handleType & (VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT |
@@ -3788,8 +3785,27 @@
#endif
VirtGpuResourcePtr bufferBlob = nullptr;
+ int importedFd = -1;
#if defined(LINUX_GUEST_BUILD)
- if (exportDmabuf) {
+ // Check for import first; this takes precedence over exportDmabuf in creating the
+ // VirtGpuResource
+ if (importDmabuf) {
+ VirtGpuExternalHandle importHandle = {};
+ // importBlob impl may close the receivedFd after it creates an GEM handle from it. dup()
+ // the FD here for input to that impl, then manage the original FD at the Vulkan level
+ importHandle.osHandle = dup(importFdInfoPtr->fd);
+ importHandle.type = kMemHandleDmabuf;
+
+ auto instance = VirtGpuDevice::getInstance();
+ bufferBlob = instance->importBlob(importHandle);
+ if (!bufferBlob) {
+ mesa_loge("%s: Failed to import colorBuffer resource\n", __func__);
+ return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+ }
+ // As per the Vulkan spec, the ownership of this FD has been transferred
+ // to the implementation
+ importedFd = importFdInfoPtr->fd;
+ } else if (exportDmabuf) {
VirtGpuDevice* instance = VirtGpuDevice::getInstance();
hasDedicatedImage =
dedicatedAllocInfoPtr && (dedicatedAllocInfoPtr->image != VK_NULL_HANDLE);
@@ -3959,19 +3975,6 @@
}
}
- if (importDmabuf) {
- VirtGpuExternalHandle importHandle = {};
- importHandle.osHandle = importFdInfoPtr->fd;
- importHandle.type = kMemHandleDmabuf;
-
- auto instance = VirtGpuDevice::getInstance();
- bufferBlob = instance->importBlob(importHandle);
- if (!bufferBlob) {
- mesa_loge("%s: Failed to import colorBuffer resource\n", __func__);
- return VK_ERROR_OUT_OF_DEVICE_MEMORY;
- }
- }
-
if (bufferBlob) {
if (hasDedicatedBuffer) {
importBufferInfo.buffer = bufferBlob->getResourceHandle();
@@ -3990,7 +3993,7 @@
if (input_result != VK_SUCCESS) _RETURN_FAILURE_WITH_DEVICE_MEMORY_REPORT(input_result);
setDeviceMemoryInfo(device, *pMemory, 0, nullptr, finalAllocInfo.memoryTypeIndex, ahw,
- isImport, vmo_handle, bufferBlob);
+ isImport, vmo_handle, bufferBlob, importedFd);
uint64_t memoryObjectId = (uint64_t)(void*)*pMemory;
#ifdef VK_USE_PLATFORM_ANDROID_KHR
@@ -4037,7 +4040,8 @@
setDeviceMemoryInfo(device, *pMemory, finalAllocInfo.allocationSize,
reinterpret_cast<uint8_t*>(addr), finalAllocInfo.memoryTypeIndex,
- /*ahw=*/nullptr, isImport, vmo_handle, /*blobPtr=*/nullptr);
+ /*ahw=*/nullptr, isImport, vmo_handle, /*blobPtr=*/nullptr,
+ /*importedFd=*/-1);
return VK_SUCCESS;
}
#endif
@@ -4076,6 +4080,10 @@
memoryObjectId = getAHardwareBufferId(info.ahw);
}
#endif
+ if (info.importedFd >= 0) {
+ close(info.importedFd);
+ info.importedFd = -1;
+ }
emitDeviceMemoryReport(info_VkDevice[device],
info.imported ? VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_UNIMPORT_EXT
diff --git a/src/gfxstream/guest/vulkan_enc/ResourceTracker.h b/src/gfxstream/guest/vulkan_enc/ResourceTracker.h
index f6631d1..22cea51 100644
--- a/src/gfxstream/guest/vulkan_enc/ResourceTracker.h
+++ b/src/gfxstream/guest/vulkan_enc/ResourceTracker.h
@@ -640,7 +640,7 @@
void setDeviceMemoryInfo(VkDevice device, VkDeviceMemory memory, VkDeviceSize allocationSize,
uint8_t* ptr, uint32_t memoryTypeIndex, void* ahw, bool imported,
- zx_handle_t vmoHandle, VirtGpuResourcePtr blobPtr);
+ zx_handle_t vmoHandle, VirtGpuResourcePtr blobPtr, int importedFd);
void setImageInfo(VkImage image, VkDevice device, const VkImageCreateInfo* pCreateInfo);
@@ -774,6 +774,7 @@
#endif // DETECT_OS_ANDROID
CoherentMemoryPtr coherentMemory = nullptr;
VirtGpuResourcePtr blobPtr = nullptr;
+ int importedFd = -1;
};
struct VkCommandBuffer_Info {