[Bf-blender-cvs] [78cbcccf341] tmp-vulkan: GHOST: Vulkan: Add physical device & queue family selection

Clément Foucault noreply at git.blender.org
Thu Jul 23 16:21:41 CEST 2020


Commit: 78cbcccf341241a575580c0626f6c37933bb0c54
Author: Clément Foucault
Date:   Mon Jul 20 13:23:41 2020 +0200
Branches: tmp-vulkan
https://developer.blender.org/rB78cbcccf341241a575580c0626f6c37933bb0c54

GHOST: Vulkan: Add physical device & queue family selection

===================================================================

M	intern/ghost/intern/GHOST_ContextVK.cpp
M	intern/ghost/intern/GHOST_ContextVK.h

===================================================================

diff --git a/intern/ghost/intern/GHOST_ContextVK.cpp b/intern/ghost/intern/GHOST_ContextVK.cpp
index a1ab5d17e00..865932dbaf6 100644
--- a/intern/ghost/intern/GHOST_ContextVK.cpp
+++ b/intern/ghost/intern/GHOST_ContextVK.cpp
@@ -28,6 +28,12 @@
 
 #include <vulkan/vulkan.h>
 
+#ifdef _WIN32
+#  include <vulkan/vulkan_win32.h>
+#else
+#  include <vulkan/vulkan_xlib.h>
+#endif
+
 #include <vector>
 
 #include <cassert>
@@ -104,11 +110,11 @@ static const char *vulkan_error_as_string(VkResult result)
 
 GHOST_ContextVK::GHOST_ContextVK(bool stereoVisual) : GHOST_Context(stereoVisual)
 {
-  assert(m_display != NULL);
 }
 
 GHOST_ContextVK::~GHOST_ContextVK()
 {
+  vkDestroyInstance(m_instance, NULL);
 }
 
 GHOST_TSuccess GHOST_ContextVK::swapBuffers()
@@ -128,11 +134,11 @@ GHOST_TSuccess GHOST_ContextVK::releaseDrawingContext()
 
 static vector<VkExtensionProperties> getExtensionsAvailable()
 {
-  uint32_t extensionCount = 0;
-  vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);
+  uint32_t extension_count = 0;
+  vkEnumerateInstanceExtensionProperties(NULL, &extension_count, NULL);
 
-  vector<VkExtensionProperties> extensions(extensionCount);
-  vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.data());
+  vector<VkExtensionProperties> extensions(extension_count);
+  vkEnumerateInstanceExtensionProperties(NULL, &extension_count, extensions.data());
 
   return extensions;
 }
@@ -148,7 +154,7 @@ static bool checkExtensionSupport(vector<VkExtensionProperties> &extensions_avai
   return false;
 }
 
-static bool requireExtension(vector<VkExtensionProperties> &extensions_available,
+static void requireExtension(vector<VkExtensionProperties> &extensions_available,
                              vector<const char *> &extensions_enabled,
                              const char *extension_name)
 {
@@ -156,23 +162,141 @@ static bool requireExtension(vector<VkExtensionProperties> &extensions_available
     extensions_enabled.push_back(extension_name);
   }
   else {
-    cout << "Error : " << extension.extensionName << " not found\n";
+    cout << "Error : " << extension_name << " not found\n";
   }
 }
 
-GHOST_TSuccess GHOST_ContextVK::initializeDrawingContext()
+static vector<VkLayerProperties> getLayersAvailable()
 {
-  VkApplicationInfo app_info = {
-      .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
-      .pApplicationName = "Blender",
-      .applicationVersion = VK_MAKE_VERSION(1, 0, 0),
-      .pEngineName = "Blender",
-      .engineVersion = VK_MAKE_VERSION(1, 0, 0),
-      .apiVersion = VK_API_VERSION_1_0,
-  };
+  uint32_t layer_count = 0;
+  vkEnumerateInstanceLayerProperties(&layer_count, NULL);
+
+  vector<VkLayerProperties> layers(layer_count);
+  vkEnumerateInstanceLayerProperties(&layer_count, layers.data());
+
+  return layers;
+}
+
+static bool checkLayerSupport(vector<VkLayerProperties> &layers_available, const char *layer_name)
+{
+  for (const auto &layer : layers_available) {
+    if (strcmp(layer_name, layer.layerName) == 0) {
+      return true;
+    }
+  }
+  return false;
+}
+
+static void enableLayer(vector<VkLayerProperties> &layers_available,
+                        vector<const char *> &layers_enabled,
+                        const char *layer_name)
+{
+  if (checkLayerSupport(layers_available, layer_name)) {
+    layers_enabled.push_back(layer_name);
+  }
+  else {
+    cout << "Info : " << layer_name << " not supported.\n";
+  }
+}
+
+static VkPhysicalDevice pickPhysicalDevice(VkInstance instance)
+{
+  uint32_t device_count = 0;
+  vkEnumeratePhysicalDevices(instance, &device_count, NULL);
+
+  if (device_count == 0) {
+    return VK_NULL_HANDLE;
+  }
+
+  vector<VkPhysicalDevice> devices(device_count);
+  vkEnumeratePhysicalDevices(instance, &device_count, devices.data());
+
+  // TODO Pick the best GPU by default OR by name from user settings.
+  // For now we just select the first suitable gpu.
+  VkPhysicalDevice best_device = VK_NULL_HANDLE;
+  int best_device_score = -1;
+
+  for (const auto &device : devices) {
+    VkPhysicalDeviceProperties device_properties;
+    vkGetPhysicalDeviceProperties(device, &device_properties);
 
+    VkPhysicalDeviceFeatures device_features;
+    vkGetPhysicalDeviceFeatures(device, &device_features);
+
+    // List of REQUIRED features.
+    if (device_features.geometryShader &&  // Needed for wide lines
+        device_features.dualSrcBlend &&    // Needed by EEVEE
+        device_features.logicOp            // Needed by EEVEE
+    ) {
+      int device_score = 0;
+      switch (device_properties.deviceType) {
+        case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU:
+          device_score = 400;
+          break;
+        case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU:
+          device_score = 300;
+          break;
+        case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU:
+          device_score = 200;
+          break;
+        case VK_PHYSICAL_DEVICE_TYPE_CPU:
+          device_score = 100;
+          break;
+        default:
+          break;
+      }
+      cout << "Found Vulkan Device : " << device_properties.deviceName << "\n";
+      if (device_score > best_device_score) {
+        best_device = device;
+        best_device_score = device_score;
+      }
+    }
+  }
+
+  if (best_device == VK_NULL_HANDLE) {
+    // TODO debug output of devices and features.
+    cout << "Error: No suitable Vulkan Device found!\n";
+  }
+  else {
+    VkPhysicalDeviceProperties device_properties;
+    vkGetPhysicalDeviceProperties(best_device, &device_properties);
+    cout << "Selected Vulkan Device : " << device_properties.deviceName << "\n";
+  }
+
+  return best_device;
+}
+
+static GHOST_TSuccess getGraphicQueueFamily(VkPhysicalDevice device, uint32_t *r_queue_index)
+{
+  uint32_t queue_family_count = 0;
+  vkGetPhysicalDeviceQueueFamilyProperties(device, &queue_family_count, NULL);
+
+  vector<VkQueueFamilyProperties> queue_families(queue_family_count);
+  vkGetPhysicalDeviceQueueFamilyProperties(device, &queue_family_count, queue_families.data());
+
+  *r_queue_index = 0;
+  for (const auto &queue_family : queue_families) {
+    if (queue_family.queueFlags & VK_QUEUE_GRAPHICS_BIT) {
+      return GHOST_kSuccess;
+    }
+    (*r_queue_index)++;
+  }
+
+  cout << "Couldn't find any Graphic queue familly on selected device\n";
+
+  return GHOST_kFailure;
+}
+
+GHOST_TSuccess GHOST_ContextVK::initializeDrawingContext()
+{
+  auto layers_available = getLayersAvailable();
   auto extensions_available = getExtensionsAvailable();
 
+  vector<const char *> layers_enabled;
+  if (true) {
+    enableLayer(layers_available, layers_enabled, "VK_LAYER_KHRONOS_validation");
+  }
+
   vector<const char *> extensions_enabled;
 #ifdef _WIN32
   requireExtension(extensions_available, extensions_enabled, VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
@@ -180,18 +304,31 @@ GHOST_TSuccess GHOST_ContextVK::initializeDrawingContext()
   requireExtension(extensions_available, extensions_enabled, VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
 #endif
 
+  VkApplicationInfo app_info = {
+      .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
+      .pApplicationName = "Blender",
+      .applicationVersion = VK_MAKE_VERSION(1, 0, 0),
+      .pEngineName = "Blender",
+      .engineVersion = VK_MAKE_VERSION(1, 0, 0),
+      .apiVersion = VK_API_VERSION_1_0,
+  };
+
   VkInstanceCreateInfo create_info = {
       .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
       .pApplicationInfo = &app_info,
-      .enabledLayerCount = 0,
-      .ppEnabledLayerNames = NULL,
+      .enabledLayerCount = static_cast<uint32_t>(layers_enabled.size()),
+      .ppEnabledLayerNames = layers_enabled.data(),
       .enabledExtensionCount = static_cast<uint32_t>(extensions_enabled.size()),
       .ppEnabledExtensionNames = extensions_enabled.data(),
   };
 
   VK_CHECK(vkCreateInstance(&create_info, NULL, &m_instance));
 
-  vkDestroyInstance(m_instance, NULL);
+  m_physical_device = pickPhysicalDevice(m_instance);
+
+  if (!getGraphicQueueFamily(m_physical_device, &m_queue_family_graphic)) {
+    return GHOST_kFailure;
+  }
 
   return GHOST_kFailure;
 }
diff --git a/intern/ghost/intern/GHOST_ContextVK.h b/intern/ghost/intern/GHOST_ContextVK.h
index c12d6885e73..303edbde510 100644
--- a/intern/ghost/intern/GHOST_ContextVK.h
+++ b/intern/ghost/intern/GHOST_ContextVK.h
@@ -99,6 +99,8 @@ class GHOST_ContextVK : public GHOST_Context {
 
  private:
   VkInstance m_instance;
+  VkPhysicalDevice m_physical_device;
+  uint32_t m_queue_family_graphic;
 };
 
 #endif  // __GHOST_CONTEXTVK_H__



More information about the Bf-blender-cvs mailing list