[Bf-blender-cvs] [6dc1d823bab] tmp-vulkan: Ghost: Vulkan: Add surface creation

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


Commit: 6dc1d823babf255656f44a901f498c994dafd450
Author: Clément Foucault
Date:   Thu Jul 23 17:05:17 2020 +0200
Branches: tmp-vulkan
https://developer.blender.org/rB6dc1d823babf255656f44a901f498c994dafd450

Ghost: Vulkan: Add surface creation

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

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

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

diff --git a/intern/ghost/intern/GHOST_ContextVK.cpp b/intern/ghost/intern/GHOST_ContextVK.cpp
index 23f461a2496..0e1e5d518f4 100644
--- a/intern/ghost/intern/GHOST_ContextVK.cpp
+++ b/intern/ghost/intern/GHOST_ContextVK.cpp
@@ -109,7 +109,32 @@ static const char *vulkan_error_as_string(VkResult result)
     } \
   } while (0)
 
-GHOST_ContextVK::GHOST_ContextVK(bool stereoVisual) : GHOST_Context(stereoVisual)
+GHOST_ContextVK::GHOST_ContextVK(bool stereoVisual,
+#ifdef _WIN32
+                                 HWND hwnd,
+                                 HINSTANCE hinstance,
+#else
+                                 Window window,
+                                 Display *display,
+#endif
+                                 int contextMajorVersion,
+                                 int contextMinorVersion,
+                                 int useValidationLayers)
+    : GHOST_Context(stereoVisual),
+#ifdef _WIN32
+      m_hinstance(hinstance),
+      m_hwnd(hwnd),
+#else
+      m_display(display),
+      m_window(window),
+#endif
+      m_contextMajorVersion(contextMajorVersion),
+      m_contextMinorVersion(contextMinorVersion),
+      m_useValidationLayers(useValidationLayers),
+      m_instance(VK_NULL_HANDLE),
+      m_surface(VK_NULL_HANDLE),
+      m_physical_device(VK_NULL_HANDLE),
+      m_device(VK_NULL_HANDLE)
 {
 }
 
@@ -118,6 +143,9 @@ GHOST_ContextVK::~GHOST_ContextVK()
   if (m_device != VK_NULL_HANDLE) {
     vkDestroyDevice(m_device, NULL);
   }
+  if (m_surface != VK_NULL_HANDLE) {
+    vkDestroySurfaceKHR(m_instance, m_surface, NULL);
+  }
   if (m_instance != VK_NULL_HANDLE) {
     vkDestroyInstance(m_instance, NULL);
   }
@@ -293,23 +321,61 @@ static GHOST_TSuccess getGraphicQueueFamily(VkPhysicalDevice device, uint32_t *r
   return GHOST_kFailure;
 }
 
+static GHOST_TSuccess getPresetQueueFamily(VkPhysicalDevice device,
+                                           VkSurfaceKHR surface,
+                                           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());
+
+  /* TODO(fclem) Prefer using the familly who also has graphic ability.
+   * These may not be the same. */
+  *r_queue_index = 0;
+  for (int i = 0; i < queue_family_count; i++) {
+    VkBool32 present_support = false;
+    vkGetPhysicalDeviceSurfaceSupportKHR(device, *r_queue_index, surface, &present_support);
+
+    if (present_support) {
+      return GHOST_kSuccess;
+    }
+    (*r_queue_index)++;
+  }
+
+  cout << "Couldn't find any Present queue familly on selected device\n";
+
+  return GHOST_kFailure;
+}
+
 GHOST_TSuccess GHOST_ContextVK::initializeDrawingContext()
 {
+#ifdef _WIN32
+  const bool use_window_surface = (m_hwnd != NULL);
+#else
+  const bool use_window_surface = (m_display != NULL);
+#endif
+
   auto layers_available = getLayersAvailable();
   auto extensions_available = getExtensionsAvailable();
 
   vector<const char *> layers_enabled;
-  if (true) {
+  if (m_useValidationLayers) {
     enableLayer(layers_available, layers_enabled, "VK_LAYER_KHRONOS_validation");
   }
 
   vector<const char *> extensions_enabled;
-  requireExtension(extensions_available, extensions_enabled, "VK_KHR_surface");
+
+  if (use_window_surface) {
 #ifdef _WIN32
-  requireExtension(extensions_available, extensions_enabled, VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
+    const char *native_surface_extension_name = VK_KHR_WIN32_SURFACE_EXTENSION_NAME;
 #else
-  requireExtension(extensions_available, extensions_enabled, VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
+    const char *native_surface_extension_name = VK_KHR_XLIB_SURFACE_EXTENSION_NAME;
 #endif
+    requireExtension(extensions_available, extensions_enabled, "VK_KHR_surface");
+    requireExtension(extensions_available, extensions_enabled, native_surface_extension_name);
+  }
 
   VkApplicationInfo app_info = {
       .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
@@ -333,28 +399,69 @@ GHOST_TSuccess GHOST_ContextVK::initializeDrawingContext()
 
   m_physical_device = pickPhysicalDevice(m_instance);
 
-  if (!getGraphicQueueFamily(m_physical_device, &m_queue_family_graphic)) {
-    return GHOST_kFailure;
+  vector<VkDeviceQueueCreateInfo> queue_create_infos;
+
+  if (use_window_surface) {
+#ifdef _WIN32
+    VkWin32SurfaceCreateInfoKHR surface_create_info = {
+        .sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR,
+        hinstance = m_hinstance,
+        hwnd = m_hwnd,
+    };
+    VK_CHECK(vkCreateWin32SurfaceKHR(m_instance, &surface_create_info, NULL, &m_surface));
+#else
+    VkXlibSurfaceCreateInfoKHR surface_create_info = {
+        .sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR,
+        .dpy = m_display,
+        .window = m_window,
+    };
+    VK_CHECK(vkCreateXlibSurfaceKHR(m_instance, &surface_create_info, NULL, &m_surface));
+#endif
+
+    /* A present queue is required only if we render to a window. */
+    if (!getPresetQueueFamily(m_physical_device, m_surface, &m_queue_family_present)) {
+      return GHOST_kFailure;
+    }
+
+    float queue_priorities[] = {1.0f};
+    VkDeviceQueueCreateInfo present_queue_create_info = {
+        .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
+        .queueFamilyIndex = m_queue_family_present,
+        .queueCount = 1,
+        .pQueuePriorities = queue_priorities,
+    };
+    queue_create_infos.push_back(present_queue_create_info);
   }
 
-  float queue_priorities[] = {1.0f};
-  VkDeviceQueueCreateInfo queue_create_info = {
-      .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
-      .queueFamilyIndex = m_queue_family_graphic,
-      .queueCount = 1,
-      .pQueuePriorities = queue_priorities,
-  };
+  {
+    /* A graphic queue is required to draw anything. */
+    if (!getGraphicQueueFamily(m_physical_device, &m_queue_family_graphic)) {
+      return GHOST_kFailure;
+    }
+
+    float queue_priorities[] = {1.0f};
+    VkDeviceQueueCreateInfo graphic_queue_create_info = {
+        .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
+        .queueFamilyIndex = m_queue_family_graphic,
+        .queueCount = 1,
+        .pQueuePriorities = queue_priorities,
+    };
+    /* Eash queue must be unique. */
+    if (m_queue_family_graphic != m_queue_family_present) {
+      queue_create_infos.push_back(graphic_queue_create_info);
+    }
+  }
 
   VkPhysicalDeviceFeatures device_features = {
-      .geometryShader = VK_TRUE,  // Needed for wide lines
+      .geometryShader = VK_TRUE,  // Needed for wide lines & EEVEE barycentric support
       .dualSrcBlend = VK_TRUE,    // Needed by EEVEE
       .logicOp = VK_TRUE,         // Needed by UI
   };
 
   VkDeviceCreateInfo device_create_info = {
       .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
-      .queueCreateInfoCount = 1,
-      .pQueueCreateInfos = &queue_create_info,
+      .queueCreateInfoCount = static_cast<uint32_t>(queue_create_infos.size()),
+      .pQueueCreateInfos = queue_create_infos.data(),
       // Same as instance extensions. Only needed for 1.0 implementations.
       .enabledLayerCount = static_cast<uint32_t>(layers_enabled.size()),
       .ppEnabledLayerNames = layers_enabled.data(),
@@ -365,6 +472,10 @@ GHOST_TSuccess GHOST_ContextVK::initializeDrawingContext()
 
   vkGetDeviceQueue(m_device, m_queue_family_graphic, 0, &m_graphic_queue);
 
+  if (use_window_surface) {
+    vkGetDeviceQueue(m_device, m_queue_family_present, 0, &m_present_queue);
+  }
+
   return GHOST_kFailure;
 }
 
diff --git a/intern/ghost/intern/GHOST_ContextVK.h b/intern/ghost/intern/GHOST_ContextVK.h
index b157744bdf4..a6707ac4fe6 100644
--- a/intern/ghost/intern/GHOST_ContextVK.h
+++ b/intern/ghost/intern/GHOST_ContextVK.h
@@ -26,6 +26,12 @@
 
 #include "GHOST_Context.h"
 
+#ifdef _WIN32
+#  include "GHOST_SystemWin32.h"
+#else
+#  include "GHOST_SystemX11.h"
+#endif
+
 #include <vulkan/vulkan.h>
 
 #ifndef GHOST_OPENGL_VK_CONTEXT_FLAGS
@@ -45,7 +51,17 @@ class GHOST_ContextVK : public GHOST_Context {
   /**
    * Constructor.
    */
-  GHOST_ContextVK(bool stereoVisual);
+  GHOST_ContextVK(bool stereoVisual,
+#ifdef _WIN32
+                  HWND hwnd,
+                  HINSTANCE hinstance,
+#else
+                  Window window,
+                  Display *display,
+#endif
+                  int contextMajorVersion,
+                  int contextMinorVersion,
+                  int useValidationLayers);
 
   /**
    * Destructor.
@@ -98,12 +114,27 @@ class GHOST_ContextVK : public GHOST_Context {
   GHOST_TSuccess getSwapInterval(int &intervalOut);
 
  private:
+#ifdef _WIN32
+  HWND hwnd;
+  HINSTANCE hinstance;
+#else
+  Display *m_display;
+  Window m_window;
+#endif
+
+  const int m_contextMajorVersion;
+  const int m_contextMinorVersion;
+  const int m_useValidationLayers;
+
   VkInstance m_instance;
+  VkSurfaceKHR m_surface;
   VkPhysicalDevice m_physical_device;
   uint32_t m_queue_family_graphic;
+  uint32_t m_queue_family_present;
 
   VkDevice m_device;
   VkQueue m_graphic_queue;
+  VkQueue m_present_queue;
 };
 
 #endif  // __GHOST_CONTEXTVK_H__
diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp
index 1f25ca3c1b9..a1ddf9de6fb 100644
--- a/intern/ghost/intern/GHOST_SystemX11.cpp
+++ b/intern/ghost/intern/GHOST_SystemX11.cpp
@@ -443,7 +443,7 @@ GHOST_IContext *GHOST_SystemX11::createOffscreenContext()
 
 #if defined(WITH_VULKAN)
   {
-    context = new GHOST_ContextVK(false);
+    context = new GHOST_ContextVK(false, (Window)NULL, NULL, 1, 0, 0);
 
     if (context->initializeDrawingContext())
       return context;
diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp
index 3b642a77b6c..87a889433d0 100644
--- a/intern/ghost/intern/GHOST_WindowX11.cpp
+++ b/intern/ghost/intern/GHOST_WindowX11.cpp
@@ -1362,7 +1362,8 @@ GHOST_Context *GHOST_WindowX11::newDrawingContext(GHOST_TDrawingContextType type
     //   try vulkan
     //   fallback to OGL
 #if defined(WITH_VULKAN)
-    context = new GHOST_ContextVK(m_wantStereoVisual)

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list