[PATCH] gfxstream: follow the semantics desired by distro VK loader
authorGurchetan Singh <gurchetansingh@google.com>
Fri, 21 Mar 2025 15:07:20 +0000 (08:07 -0700)
committerTimo Aaltonen <tjaalton@debian.org>
Thu, 3 Apr 2025 10:47:45 +0000 (13:47 +0300)
- vkCreateInstance should return VK_SUCCESS absent a few specific
  conditions
- just don't add any physical devices later

Cc: mesa-stable
Reviewed-by: Aaron Ruby <aruby@qnx.com>
Gbp-Pq: Name gfxstream-follow-the-semantics-desired-by-distro-VK.diff

src/gfxstream/guest/vulkan/gfxstream_vk_device.cpp
src/gfxstream/guest/vulkan_enc/gfxstream_vk_private.h

index ef874b9f43d8761a4a9d860b4f294cd884525122..abd078010ea8edbe52f02c74c56c88fe57a45ec8 100644 (file)
@@ -77,7 +77,7 @@ static VkResult SetupInstanceForProcess(void) {
     auto mgr = getConnectionManager();
     if (!mgr) {
         mesa_logd("vulkan: Failed to get host connection\n");
-        return VK_ERROR_DEVICE_LOST;
+        return VK_ERROR_INITIALIZATION_FAILED;
     }
 
     gfxstream::vk::ResourceTracker::get()->setupCaps(gNoRenderControlEnc);
@@ -231,6 +231,11 @@ static void gfxstream_vk_destroy_physical_device(struct vk_physical_device* phys
 static VkResult gfxstream_vk_enumerate_devices(struct vk_instance* vk_instance) {
     VkResult result = VK_SUCCESS;
     gfxstream_vk_instance* gfxstream_instance = (gfxstream_vk_instance*)vk_instance;
+
+    if (gfxstream_instance->init_failed) {
+        return VK_SUCCESS;
+    }
+
     uint32_t deviceCount = 0;
     auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
     auto resources = gfxstream::vk::ResourceTracker::get();
@@ -315,24 +320,48 @@ VkResult gfxstream_vk_CreateInstance(const VkInstanceCreateInfo* pCreateInfo,
     MESA_TRACE_SCOPE("vkCreateInstance");
 
     struct gfxstream_vk_instance* instance;
+    VkResult result = VK_SUCCESS;
 
     pAllocator = pAllocator ?: vk_default_allocator();
-    instance = (struct gfxstream_vk_instance*)vk_zalloc(pAllocator, sizeof(*instance), GFXSTREAM_DEFAULT_ALIGN,
-                                                        VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
-    if (NULL == instance) {
+    instance = (struct gfxstream_vk_instance*)vk_zalloc(
+        pAllocator, sizeof(*instance), GFXSTREAM_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+
+    if (!instance) {
         return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
     }
 
-    VkResult result = VK_SUCCESS;
+    instance->init_failed = (SetupInstanceForProcess() == VK_ERROR_INITIALIZATION_FAILED);
+    auto extensions = instance->init_failed ? &gfxstream_vk_instance_extensions_supported
+                                            : get_instance_extensions();
+    struct vk_instance_dispatch_table dispatch_table;
+    memset(&dispatch_table, 0, sizeof(struct vk_instance_dispatch_table));
+    vk_instance_dispatch_table_from_entrypoints(&dispatch_table, &gfxstream_vk_instance_entrypoints,
+                                                false);
+#if !DETECT_OS_FUCHSIA
+    vk_instance_dispatch_table_from_entrypoints(&dispatch_table, &wsi_instance_entrypoints, false);
+#endif
+
+    result = vk_instance_init(&instance->vk, extensions, &dispatch_table, pCreateInfo, pAllocator);
+
+    if (result != VK_SUCCESS) {
+        vk_free(pAllocator, instance);
+        return vk_error(NULL, result);
+    }
+
+    // Note: Do not support try_create_for_drm. virtio_gpu DRM device opened in
+    // init_renderer above, which can still enumerate multiple physical devices on the host.
+    instance->vk.physical_devices.enumerate = gfxstream_vk_enumerate_devices;
+    instance->vk.physical_devices.destroy = gfxstream_vk_destroy_physical_device;
+
+    if (instance->init_failed) {
+        goto out;
+    }
+
     /* Encoder call */
     {
-        result = SetupInstanceForProcess();
-        if (VK_SUCCESS != result) {
-            vk_free(pAllocator, instance);
-            return vk_error(NULL, result);
-        }
         uint32_t initialEnabledExtensionCount = pCreateInfo->enabledExtensionCount;
         const char* const* initialPpEnabledExtensionNames = pCreateInfo->ppEnabledExtensionNames;
+
         std::vector<const char*> filteredExts = filteredInstanceExtensionNames(
             pCreateInfo->enabledExtensionCount, pCreateInfo->ppEnabledExtensionNames);
         // Temporarily modify createInfo for the encoder call
@@ -352,27 +381,7 @@ VkResult gfxstream_vk_CreateInstance(const VkInstanceCreateInfo* pCreateInfo,
         mutableCreateInfo->ppEnabledExtensionNames = initialPpEnabledExtensionNames;
     }
 
-    struct vk_instance_dispatch_table dispatch_table;
-    memset(&dispatch_table, 0, sizeof(struct vk_instance_dispatch_table));
-    vk_instance_dispatch_table_from_entrypoints(&dispatch_table, &gfxstream_vk_instance_entrypoints,
-                                                false);
-#if !DETECT_OS_FUCHSIA
-    vk_instance_dispatch_table_from_entrypoints(&dispatch_table, &wsi_instance_entrypoints, false);
-#endif
-
-    result = vk_instance_init(&instance->vk, get_instance_extensions(), &dispatch_table,
-                              pCreateInfo, pAllocator);
-
-    if (result != VK_SUCCESS) {
-        vk_free(pAllocator, instance);
-        return vk_error(NULL, result);
-    }
-
-    // Note: Do not support try_create_for_drm. virtio_gpu DRM device opened in
-    // init_renderer above, which can still enumerate multiple physical devices on the host.
-    instance->vk.physical_devices.enumerate = gfxstream_vk_enumerate_devices;
-    instance->vk.physical_devices.destroy = gfxstream_vk_destroy_physical_device;
-
+out:
     *pInstance = gfxstream_vk_instance_to_handle(instance);
     return VK_SUCCESS;
 }
@@ -383,8 +392,10 @@ void gfxstream_vk_DestroyInstance(VkInstance _instance, const VkAllocationCallba
 
     VK_FROM_HANDLE(gfxstream_vk_instance, instance, _instance);
 
-    auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
-    vkEnc->vkDestroyInstance(instance->internal_object, pAllocator, true /* do lock */);
+    if (!instance->init_failed) {
+        auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
+        vkEnc->vkDestroyInstance(instance->internal_object, pAllocator, true /* do lock */);
+    }
 
     vk_instance_finish(&instance->vk);
     vk_free(&instance->vk.alloc, instance);
index 164c227d6fbcd31ebac32189391754cdf124cdef..b9dc22cc036d0946ea95bfdb389a42d752d25d9f 100644 (file)
@@ -62,6 +62,7 @@
 struct gfxstream_vk_instance {
     struct vk_instance vk;
     uint32_t api_version;
+    bool init_failed;
     VkInstance internal_object;
 };