layer: improve how layer handles Vulkan extensions
[platform/core/uifw/vulkan-wsi-tizen.git] / wsi / wsi_factory.cpp
index 44fc91b..4d015b6 100644 (file)
@@ -1,6 +1,5 @@
-
 /*
- * Copyright (c) 2019 Arm Limited.
+ * Copyright (c) 2019-2021 Arm Limited.
  *
  * SPDX-License-Identifier: MIT
  *
  */
 
 #include "wsi_factory.hpp"
+#include "headless/surface_properties.hpp"
+#include "headless/swapchain.hpp"
+
 #include <cassert>
 #include <cstdlib>
-#include <cstdio>
+#include <cstring>
 #include <new>
 #include <vulkan/vk_icd.h>
 
-#include "headless/surface_properties.hpp"
-#include "headless/swapchain.hpp"
-
 namespace wsi
 {
 
-surface_properties *get_surface_properties(VkSurfaceKHR surface)
+static struct wsi_extension
 {
-   VkIcdSurfaceBase *surface_base = reinterpret_cast<VkIcdSurfaceBase *>(surface);
+   VkExtensionProperties extension;
+   VkIcdWsiPlatform platform;
+} const supported_wsi_extensions[] = {
+   { { VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME, VK_EXT_HEADLESS_SURFACE_SPEC_VERSION }, VK_ICD_WSI_PLATFORM_HEADLESS }
+};
 
-   switch (surface_base->platform)
+static surface_properties *get_surface_properties(VkIcdWsiPlatform platform)
+{
+   switch (platform)
    {
    case VK_ICD_WSI_PLATFORM_HEADLESS:
       return &headless::surface_properties::get_instance();
@@ -54,6 +59,13 @@ surface_properties *get_surface_properties(VkSurfaceKHR surface)
    }
 }
 
+surface_properties *get_surface_properties(VkSurfaceKHR surface)
+{
+   VkIcdSurfaceBase *surface_base = reinterpret_cast<VkIcdSurfaceBase *>(surface);
+
+   return get_surface_properties(surface_base->platform);
+}
+
 template <typename swapchain_type>
 static swapchain_base *allocate_swapchain(layer::device_private_data &dev_data, const VkAllocationCallbacks *pAllocator)
 {
@@ -80,6 +92,64 @@ swapchain_base *allocate_surface_swapchain(VkSurfaceKHR surface, layer::device_p
    }
 }
 
+util::wsi_platform_set find_enabled_layer_platforms(const VkInstanceCreateInfo *pCreateInfo)
+{
+   util::wsi_platform_set ret;
+   for (const auto &ext_provided_by_layer : supported_wsi_extensions)
+   {
+      for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++)
+      {
+         const char* ext_requested_by_user = pCreateInfo->ppEnabledExtensionNames[i];
+         if (strcmp(ext_requested_by_user, ext_provided_by_layer.extension.extensionName) == 0)
+         {
+            ret.add(ext_provided_by_layer.platform);
+         }
+      }
+   }
+   return ret;
+}
+
+VkResult add_extensions_required_by_layer(VkPhysicalDevice phys_dev, const util::wsi_platform_set enabled_platforms,
+                                          util::extension_list &extensions_to_enable)
+{
+   util::allocator allocator{extensions_to_enable.get_allocator(), VK_SYSTEM_ALLOCATION_SCOPE_COMMAND};
+   util::extension_list device_extensions{allocator};
+   VkResult res = device_extensions.add(phys_dev);
+   if (res != VK_SUCCESS)
+   {
+      return res;
+   }
+
+   for (const auto &wsi_ext : supported_wsi_extensions)
+   {
+      /* Skip iterating over platforms not enabled in the instance. */
+      if (!enabled_platforms.contains(wsi_ext.platform))
+      {
+         continue;
+      }
+
+      surface_properties *props = get_surface_properties(wsi_ext.platform);
+      const auto &extensions_required_by_layer = props->get_required_device_extensions();
+      bool supported = device_extensions.contains(extensions_required_by_layer);
+      if (!supported)
+      {
+         /* Can we accept failure? The layer unconditionally advertises support for this platform and the loader uses
+          * this information to enable its own support of the vkCreate*SurfaceKHR entrypoints. The rest of the Vulkan
+          * stack may not support this extension so we cannot blindly fall back to it.
+          * For now treat this as an error.
+          */
+         return VK_ERROR_INITIALIZATION_FAILED;
+      }
+
+      res = extensions_to_enable.add(extensions_required_by_layer);
+      if (res != VK_SUCCESS)
+      {
+         return res;
+      }
+   }
+   return VK_SUCCESS;
+}
+
 void destroy_surface_swapchain(swapchain_base *swapchain, const VkAllocationCallbacks *pAllocator)
 {
    assert(swapchain);