vulkan: Split out factory functions into a new component

This adds a new component //gpu/vulkan/init that fills the same role as
//ui/gl/init. It will allow ozone ports to provide the factory functions
for surface types while still having a centralized entry point for
initializing vulkan.

Certain factory functions (e.g. VulkanSurface::CreateViewSurface) moved
into a new VulkanImplementation factory object; platforms override those
functions in order to build the right surface type.

Common code for surface creation moved into VulkanSurface from its single
anonymous subclass (VulkanWSISurface). This means VulkanSurface is not a
pure interface anymore, but neither are any of the other wrapper classes.
We could alternatively keep the pure interface and provide a "base"
subclass to inherit from, but it's not clear that such a separation is
useful.

This also removes the VkInstance from the global scope. Nothing depended
heavily on the fact that it was global, and since the vulkan API supports
instancing of vulkan itself, it seems better to pass the instance
directly into any components where it is needed. This makes any sharing
explicit and makes instancing possible. Also, the VkInstance could not
previously be destroyed, but now this is supported and exercised by the
test suite.

The Android code is also moved into this scheme, although it seems
incomplete prior to this change, does not compile, and is therefore
untested.

Bug: 581471
Test: vulkan_tests

Change-Id: Icefe29b0bfd4fe5ff2c951cefc47b0472250bce7
Reviewed-on: https://chromium-review.googlesource.com/1055824
Commit-Queue: Michael Spang <[email protected]>
Reviewed-by: Antoine Labour <[email protected]>
Cr-Commit-Position: refs/heads/master@{#559152}
diff --git a/gpu/vulkan/vulkan_implementation.cc b/gpu/vulkan/vulkan_implementation.cc
index b90ff1c2..cee1aaf4 100644
--- a/gpu/vulkan/vulkan_implementation.cc
+++ b/gpu/vulkan/vulkan_implementation.cc
@@ -4,203 +4,29 @@
 
 #include "gpu/vulkan/vulkan_implementation.h"
 
-#include <unordered_set>
-#include <vector>
-#include "base/logging.h"
-#include "base/macros.h"
-#include "gpu/vulkan/vulkan_platform.h"
-
-#if defined(VK_USE_PLATFORM_XLIB_KHR)
-#include "ui/gfx/x/x11_types.h"
-#endif  // defined(VK_USE_PLATFORM_XLIB_KHR)
-
-VKAPI_ATTR VkBool32 VKAPI_CALL VulkanErrorCallback(
-    VkDebugReportFlagsEXT       flags,
-    VkDebugReportObjectTypeEXT  objectType,
-    uint64_t                    object,
-    size_t                      location,
-    int32_t                     messageCode,
-    const char*                 pLayerPrefix,
-    const char*                 pMessage,
-    void*                       pUserData) {
-  LOG(ERROR) << pMessage;
-  return VK_TRUE;
-}
-
-VKAPI_ATTR VkBool32 VKAPI_CALL VulkanWarningCallback(
-    VkDebugReportFlagsEXT       flags,
-    VkDebugReportObjectTypeEXT  objectType,
-    uint64_t                    object,
-    size_t                      location,
-    int32_t                     messageCode,
-    const char*                 pLayerPrefix,
-    const char*                 pMessage,
-    void*                       pUserData) {
-  LOG(WARNING) << pMessage;
-  return VK_TRUE;
-}
+#include "base/bind.h"
+#include "gpu/vulkan/vulkan_device_queue.h"
 
 namespace gpu {
 
-struct VulkanInstance {
-  VulkanInstance() {}
+VulkanImplementation::VulkanImplementation() {}
 
-  void Initialize() { valid = InitializeVulkanInstance(); }
+VulkanImplementation::~VulkanImplementation() {}
 
-  bool InitializeVulkanInstance() {
-    VkResult result = VK_SUCCESS;
-
-    VkApplicationInfo app_info = {};
-    app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
-    app_info.pApplicationName = "Chromium";
-    app_info.apiVersion = VK_MAKE_VERSION(1, 0, 2);
-
-    std::vector<const char*> enabled_ext_names;
-    enabled_ext_names.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
-
-#if defined(VK_USE_PLATFORM_XLIB_KHR)
-    enabled_ext_names.push_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
-#elif defined(VK_USE_PLATFORM_ANDROID_KHR)
-    enabled_ext_names.push_back(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME);
-#endif
-
-    uint32_t num_instance_exts = 0;
-    result = vkEnumerateInstanceExtensionProperties(nullptr, &num_instance_exts,
-                                                    nullptr);
-    if (VK_SUCCESS != result) {
-      DLOG(ERROR) << "vkEnumerateInstanceExtensionProperties(NULL) failed: "
-                  << result;
-      return false;
-    }
-
-    std::vector<VkExtensionProperties> instance_exts(num_instance_exts);
-    result = vkEnumerateInstanceExtensionProperties(nullptr, &num_instance_exts,
-                                                    instance_exts.data());
-    if (VK_SUCCESS != result) {
-      DLOG(ERROR) << "vkEnumerateInstanceExtensionProperties() failed: "
-                  << result;
-      return false;
-    }
-
-    bool debug_report_enabled = false;
-    for (const VkExtensionProperties& ext_property : instance_exts) {
-      if (strcmp(ext_property.extensionName,
-                 VK_EXT_DEBUG_REPORT_EXTENSION_NAME) == 0) {
-        debug_report_enabled = true;
-        enabled_ext_names.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
-      }
-    }
-
-    std::vector<const char*> enabled_layer_names;
-#if DCHECK_IS_ON()
-    uint32_t num_instance_layers = 0;
-    result = vkEnumerateInstanceLayerProperties(&num_instance_layers, nullptr);
-    if (VK_SUCCESS != result) {
-      DLOG(ERROR) << "vkEnumerateInstanceLayerProperties(NULL) failed: "
-                  << result;
-      return false;
-    }
-
-    std::vector<VkLayerProperties> instance_layers(num_instance_layers);
-    result = vkEnumerateInstanceLayerProperties(&num_instance_layers,
-                                                instance_layers.data());
-    if (VK_SUCCESS != result) {
-      DLOG(ERROR) << "vkEnumerateInstanceLayerProperties() failed: " << result;
-      return false;
-    }
-
-    std::unordered_set<std::string> desired_layers({
-#if !defined(VK_USE_PLATFORM_XLIB_KHR)
-      // TODO(crbug.com/843346): Make validation work in combination with
-      // VK_KHR_xlib_surface or switch to VK_KHR_xcb_surface.
-      "VK_LAYER_LUNARG_standard_validation",
-#endif
-    });
-
-    for (const VkLayerProperties& layer_property : instance_layers) {
-      if (desired_layers.find(layer_property.layerName) != desired_layers.end())
-        enabled_layer_names.push_back(layer_property.layerName);
-    }
-#endif
-
-    VkInstanceCreateInfo instance_create_info = {};
-    instance_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
-    instance_create_info.pApplicationInfo = &app_info;
-    instance_create_info.enabledLayerCount = enabled_layer_names.size();
-    instance_create_info.ppEnabledLayerNames = enabled_layer_names.data();
-    instance_create_info.enabledExtensionCount = enabled_ext_names.size();
-    instance_create_info.ppEnabledExtensionNames = enabled_ext_names.data();
-
-    result = vkCreateInstance(&instance_create_info, nullptr, &vk_instance);
-    if (VK_SUCCESS != result) {
-      DLOG(ERROR) << "vkCreateInstance() failed: " << result;
-      return false;
-    }
-
-#if DCHECK_IS_ON()
-    // Register our error logging function.
-    if (debug_report_enabled) {
-      PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT =
-          reinterpret_cast<PFN_vkCreateDebugReportCallbackEXT>
-              (vkGetInstanceProcAddr(vk_instance,
-                                     "vkCreateDebugReportCallbackEXT"));
-      DCHECK(vkCreateDebugReportCallbackEXT);
-
-      VkDebugReportCallbackCreateInfoEXT cb_create_info = {};
-      cb_create_info.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
-
-      cb_create_info.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT;
-      cb_create_info.pfnCallback = &VulkanErrorCallback;
-      result = vkCreateDebugReportCallbackEXT(vk_instance, &cb_create_info,
-                                              nullptr, &error_callback);
-      if (VK_SUCCESS != result) {
-        DLOG(ERROR) << "vkCreateDebugReportCallbackEXT(ERROR) failed: "
-                    << result;
-        return false;
-      }
-
-      cb_create_info.flags = VK_DEBUG_REPORT_WARNING_BIT_EXT |
-                             VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
-      cb_create_info.pfnCallback = &VulkanWarningCallback;
-      result = vkCreateDebugReportCallbackEXT(vk_instance, &cb_create_info,
-                                              nullptr, &warning_callback);
-      if (VK_SUCCESS != result) {
-        DLOG(ERROR) << "vkCreateDebugReportCallbackEXT(WARN) failed: "
-                    << result;
-        return false;
-      }
-    }
-#endif
-
-    return true;
+std::unique_ptr<VulkanDeviceQueue> CreateVulkanDeviceQueue(
+    VulkanImplementation* vulkan_implementation,
+    uint32_t option) {
+  auto device_queue = std::make_unique<VulkanDeviceQueue>(
+      vulkan_implementation->GetVulkanInstance());
+  auto callback = base::BindRepeating(
+      &VulkanImplementation::GetPhysicalDevicePresentationSupport,
+      base::Unretained(vulkan_implementation));
+  if (!device_queue->Initialize(option, callback)) {
+    device_queue->Destroy();
+    return nullptr;
   }
 
-  bool valid = false;
-  VkInstance vk_instance = VK_NULL_HANDLE;
-#if DCHECK_IS_ON()
-  VkDebugReportCallbackEXT error_callback = VK_NULL_HANDLE;
-  VkDebugReportCallbackEXT warning_callback = VK_NULL_HANDLE;
-#endif
-};
-
-static VulkanInstance* vulkan_instance = nullptr;
-
-bool InitializeVulkan() {
-  DCHECK(!vulkan_instance);
-  vulkan_instance = new VulkanInstance;
-  vulkan_instance->Initialize();
-  return vulkan_instance->valid;
-}
-
-bool VulkanSupported() {
-  DCHECK(vulkan_instance);
-  return vulkan_instance->valid;
-}
-
-VkInstance GetVulkanInstance() {
-  DCHECK(vulkan_instance);
-  DCHECK(vulkan_instance->valid);
-  return vulkan_instance->vk_instance;
+  return device_queue;
 }
 
 }  // namespace gpu