Browse Source

Bump suppress versions, create vulkan swapchain and surface

Kajetan Johannes Hammerle 2 months ago
parent
commit
e60bae3c7e
5 changed files with 138 additions and 15 deletions
  1. 4 2
      include/core/VulkanWrapper.h
  2. 9 0
      include/core/internal/GLFW.h
  3. 106 9
      src/VulkanWrapper.c
  4. 7 1
      src/WindowManager.c
  5. 12 3
      valgrind.supp

+ 4 - 2
include/core/VulkanWrapper.h

@@ -1,5 +1,7 @@
-#define GLFW_INCLUDE_VULKAN
-#include <GLFW/glfw3.h>
+#ifndef CORE_VULKAN_WRAPPER_H
+#define CORE_VULKAN_WRAPPER_H
 
 bool initVulkan(void);
 void destroyVulkan(void);
+
+#endif

+ 9 - 0
include/core/internal/GLFW.h

@@ -0,0 +1,9 @@
+#ifndef CORE_GLFW_H
+#define CORE_GLFW_H
+
+#define GLFW_INCLUDE_VULKAN
+#include <GLFW/glfw3.h>
+
+GLFWwindow* getWindow(void);
+
+#endif

+ 106 - 9
src/VulkanWrapper.c

@@ -1,17 +1,20 @@
 #include "core/VulkanWrapper.h"
 
-#define GLFW_INCLUDE_VULKAN
-#include <GLFW/glfw3.h>
 #include <core/Logger.h>
 #include <core/Utility.h>
-#include <limits.h>
 #include <stdio.h>
-#include <uchar.h>
+
+#include "core/internal/GLFW.h"
 
 typedef struct {
     VkInstance instance;
+    u32 graphicsFamily;
     VkPhysicalDevice physicalDevice;
     VkDevice device;
+    VkSurfaceKHR surface;
+    VkSwapchainKHR swapchain;
+    u32 width;
+    u32 height;
 } VulkanData;
 static VulkanData vk = {0};
 
@@ -55,7 +58,7 @@ static bool initInstance() {
         .ppEnabledLayerNames = (const char*[]){"VK_LAYER_KHRONOS_validation"},
         .enabledExtensionCount = 4,
         .ppEnabledExtensionNames =
-            (const char*[]){"VK_KHR_surface", "VK_KHR_xcb_surface",
+            (const char*[]){"VK_KHR_surface", "VK_KHR_wayland_surface",
                             VK_EXT_DEBUG_UTILS_EXTENSION_NAME,
                             VK_EXT_DEBUG_REPORT_EXTENSION_NAME}};
     VK_ASSERT(vkCreateInstance(&ci, nullptr, &vk.instance));
@@ -121,15 +124,15 @@ static bool initDevice() {
     VkPhysicalDeviceFeatures deviceFeatures = {0};
     vkGetPhysicalDeviceFeatures(vk.physicalDevice, &deviceFeatures);
 
-    u32 graphicsFamily =
+    vk.graphicsFamily =
         findQueueFamilies(vk.physicalDevice, VK_QUEUE_GRAPHICS_BIT);
-    if(graphicsFamily == (u32)-1) {
+    if(vk.graphicsFamily == (u32)-1) {
         LOG_ERROR("Cannot find queue family");
         return true;
     }
     VkDeviceQueueCreateInfo dqInfo = {
         .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
-        .queueFamilyIndex = graphicsFamily,
+        .queueFamilyIndex = vk.graphicsFamily,
         .queueCount = 1,
         .pQueuePriorities = (float[]){1.0f}};
     VkDeviceCreateInfo deviceCreateInfo = {
@@ -145,11 +148,105 @@ static bool initDevice() {
     return false;
 }
 
+static bool initSurface() {
+    VK_ASSERT(glfwCreateWindowSurface(vk.instance, getWindow(), nullptr,
+                                      &vk.surface));
+    return false;
+}
+
+static u32 getSwapImageCount(const VkSurfaceCapabilitiesKHR* caps) {
+    u32 c = caps->minImageCount + 1;
+    // according to VkSurfaceCapabilitiesKHR doc:
+    // maxImageCount is 0 when there is no strict limit
+    if(caps->maxImageCount != 0 && c > caps->maxImageCount) {
+        return caps->maxImageCount;
+    }
+    return c;
+}
+
+static bool getSurfaceFormat(VkSurfaceFormatKHR* sf) {
+    u32 c = 0;
+    VK_ASSERT(vkGetPhysicalDeviceSurfaceFormatsKHR(vk.physicalDevice,
+                                                   vk.surface, &c, nullptr));
+    VkSurfaceFormatKHR* formats = coreAllocate(sizeof(VkSurfaceFormatKHR) * c);
+    VK_ASSERT(vkGetPhysicalDeviceSurfaceFormatsKHR(vk.physicalDevice,
+                                                   vk.surface, &c, formats));
+    for(u32 i = 0; i < c; i++) {
+        if(formats[i].format == VK_FORMAT_B8G8R8A8_UNORM &&
+           formats[i].colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
+            *sf = formats[i];
+            coreFree(formats);
+            return false;
+        }
+    }
+    coreFree(formats);
+    LOG_ERROR("Could not find any matching surface format");
+    return true;
+}
+
+static bool getPresentMode(VkPresentModeKHR* pm) {
+    u32 c = 0;
+    VK_ASSERT(vkGetPhysicalDeviceSurfacePresentModesKHR(
+        vk.physicalDevice, vk.surface, &c, nullptr));
+    VkPresentModeKHR* modes = coreAllocate(sizeof(VkPresentModeKHR) * c);
+    VK_ASSERT(vkGetPhysicalDeviceSurfacePresentModesKHR(vk.physicalDevice,
+                                                        vk.surface, &c, modes));
+    for(u32 i = 0; i < c; i++) {
+        if(modes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
+            *pm = modes[i];
+            coreFree(modes);
+            return false;
+        }
+    }
+    coreFree(modes);
+    LOG_ERROR("Could not find any matching present modes");
+    return true;
+}
+
+static bool initSwapchain() {
+    VkSurfaceCapabilitiesKHR caps = {0};
+    VK_ASSERT(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(vk.physicalDevice,
+                                                        vk.surface, &caps));
+    VkSurfaceFormatKHR sf = {0};
+    if(getSurfaceFormat(&sf)) {
+        return true;
+    }
+    VkPresentModeKHR pm = {0};
+    if(getPresentMode(&pm)) {
+        return true;
+    }
+    VkSwapchainCreateInfoKHR ci = {
+        .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
+        .surface = vk.surface,
+        .minImageCount = getSwapImageCount(&caps),
+        .imageFormat = sf.format,
+        .imageColorSpace = sf.colorSpace,
+        .imageExtent = {.width = vk.width, .height = vk.height},
+        .imageArrayLayers = 1,
+        .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
+                      VK_IMAGE_USAGE_TRANSFER_DST_BIT,
+        .imageSharingMode = VK_SHARING_MODE_EXCLUSIVE,
+        .queueFamilyIndexCount = 1,
+        .pQueueFamilyIndices = &vk.graphicsFamily,
+        .preTransform = caps.currentTransform,
+        .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
+        .presentMode = pm,
+        .clipped = VK_TRUE,
+        .oldSwapchain = VK_NULL_HANDLE};
+    VK_ASSERT(vkCreateSwapchainKHR(vk.device, &ci, nullptr, &vk.swapchain));
+    return false;
+}
+
 bool initVulkan() {
-    return initInstance() || initPhysicalDevice() || initDevice();
+    vk.width = 400;
+    vk.height = 300;
+    return initInstance() || initPhysicalDevice() || initDevice() ||
+           initSurface() || initSwapchain();
 }
 
 void destroyVulkan(void) {
+    vkDestroySwapchainKHR(vk.device, vk.swapchain, nullptr);
+    vkDestroySurfaceKHR(vk.instance, vk.surface, nullptr);
     vkDestroyDevice(vk.device, nullptr);
     vkDestroyInstance(vk.instance, nullptr);
 }

+ 7 - 1
src/WindowManager.c

@@ -2,11 +2,13 @@
 
 #include <core/Logger.h>
 #include <core/Utility.h>
-#include <core/VulkanWrapper.h>
 #include <limits.h>
 #include <stdio.h>
 #include <uchar.h>
 
+#include "core/VulkanWrapper.h"
+#include "core/internal/GLFW.h"
+
 static bool dummyWindowRunHandler(void*) {
     return !shouldWindowClose();
 }
@@ -483,3 +485,7 @@ bool wasButtonReleased(Button b) {
 const char* getButtonName(Button b) {
     return getButton(b)->name;
 }
+
+GLFWwindow* getWindow(void) {
+    return window;
+}

+ 12 - 3
valgrind.supp

@@ -70,7 +70,7 @@
   Memcheck:Leak
   match-leak-kinds: reachable
   ...
-  obj:/usr/lib/x86_64-linux-gnu/libcairo.so.2.11800.0
+  obj:/usr/lib/x86_64-linux-gnu/libcairo.so.2.11802.2
 }
 {
   libpangocairo font stuff
@@ -102,13 +102,13 @@
   libharfbuzz font stuff
   Memcheck:Leak
   ...
-  obj:/usr/lib/x86_64-linux-gnu/libharfbuzz.so.0.60830.0
+  obj:/usr/lib/x86_64-linux-gnu/libharfbuzz.so.0.60900.0
 }
 {
   libfreetype font stuff
   Memcheck:Leak
   ...
-  obj:/usr/lib/x86_64-linux-gnu/libfreetype.so.6.20.1
+  obj:/usr/lib/x86_64-linux-gnu/libfreetype.so.6.20.2
 }
 {
   libgobject 1
@@ -153,6 +153,15 @@
   fun:start_thread
   fun:clone
 }
+{
+  libglib 2
+  Memcheck:Leak
+  match-leak-kinds: reachable
+  fun:calloc
+  ...
+  fun:start_thread
+  fun:clone
+}
 {
   dl_init
   Memcheck:Leak