Browse Source

Move Vulkan code into own files, Vulkan resource cleanup, suppression
file for system libs

Kajetan Johannes Hammerle 4 months ago
parent
commit
11050fdae3
6 changed files with 339 additions and 142 deletions
  1. 8 6
      CMakeLists.txt
  2. 5 0
      include/core/VulkanWrapper.h
  3. 156 0
      src/VulkanWrapper.c
  4. 3 135
      src/WindowManager.c
  5. 5 1
      tasks
  6. 162 0
      valgrind.supp

+ 8 - 6
CMakeLists.txt

@@ -8,6 +8,7 @@ set(CMAKE_C_STANDARD 23)
 set(SRC
     "src/Image.c"
     "src/Network.c"
+    "src/VulkanWrapper.c"
     "src/WindowManager.c"
 )
 
@@ -55,28 +56,29 @@ target_compile_options(gaming_core PUBLIC
     ${WARNINGS}
     -fdiagnostics-color=always
 )
-target_compile_definitions(gaming_core 
+target_compile_definitions(gaming_core
     PUBLIC CORE_LOG_LEVEL=${LOG_LEVEL}
     PUBLIC ${DEFINITIONS}
 )
-target_link_libraries(gaming_core 
+target_link_libraries(gaming_core
     PRIVATE m core glfw vulkan ${LINK_OPTIONS}
 )
-target_include_directories(gaming_core SYSTEM 
+target_include_directories(gaming_core SYSTEM
     PUBLIC ${CMAKE_INSTALL_PREFIX}/include
     PUBLIC enet/include
     PUBLIC stb
     PUBLIC glfw/include
 )
-target_link_directories(gaming_core SYSTEM 
+target_link_directories(gaming_core SYSTEM
     PUBLIC ${CMAKE_INSTALL_PREFIX}/lib
 )
-target_sources(gaming_core PUBLIC 
+target_sources(gaming_core PUBLIC
     FILE_SET HEADERS
     BASE_DIRS include
-    FILES 
+    FILES
         ./include/core/Image.h
         ./include/core/Network.h
+        ./include/core/VulkanWrapper.h
         ./include/core/WindowManager.h
 )
 install(TARGETS gaming_core FILE_SET HEADERS)

+ 5 - 0
include/core/VulkanWrapper.h

@@ -0,0 +1,5 @@
+#define GLFW_INCLUDE_VULKAN
+#include <GLFW/glfw3.h>
+
+bool coreInitVulkan(void);
+void coreDestroyVulkan(void);

+ 156 - 0
src/VulkanWrapper.c

@@ -0,0 +1,156 @@
+#define IMPORT_CORE
+#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>
+
+typedef struct {
+    VkInstance instance;
+    VkPhysicalDevice physicalDevice;
+    VkDevice device;
+} VulkanData;
+static VulkanData vk = {0};
+
+#define VK_ERROR_CASE(error)                                                   \
+    case error: return #error
+
+static const char* getVulkanErrorString(VkResult r) {
+    switch(r) {
+        VK_ERROR_CASE(VK_ERROR_OUT_OF_HOST_MEMORY);
+        VK_ERROR_CASE(VK_ERROR_OUT_OF_DEVICE_MEMORY);
+        VK_ERROR_CASE(VK_ERROR_INITIALIZATION_FAILED);
+        VK_ERROR_CASE(VK_ERROR_LAYER_NOT_PRESENT);
+        VK_ERROR_CASE(VK_ERROR_EXTENSION_NOT_PRESENT);
+        VK_ERROR_CASE(VK_ERROR_INCOMPATIBLE_DRIVER);
+        default: return "unknown";
+    }
+}
+
+#define VK_ASSERT(a)                                                           \
+    do {                                                                       \
+        VkResult vkResult = (a);                                               \
+        if(vkResult != VK_SUCCESS) {                                           \
+            printf("Vulkan error at [%s:%d]: %s\n",                            \
+                   getShortFileName(__FILE__), __LINE__,                       \
+                   getVulkanErrorString(vkResult));                            \
+            return true;                                                       \
+        }                                                                      \
+    } while(false)
+
+static bool initInstance() {
+    VkApplicationInfo i = {.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
+                           .pApplicationName = "Vulkan",
+                           .applicationVersion = VK_MAKE_VERSION(1, 0, 0),
+                           .pEngineName = "Kajetan",
+                           .engineVersion = VK_MAKE_VERSION(0, 0, 1),
+                           .apiVersion = VK_API_VERSION_1_1};
+    VkInstanceCreateInfo ci = {
+        .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
+        .pApplicationInfo = &i,
+        .enabledLayerCount = 1,
+        .ppEnabledLayerNames = (const char*[]){"VK_LAYER_KHRONOS_validation"},
+        .enabledExtensionCount = 4,
+        .ppEnabledExtensionNames =
+            (const char*[]){"VK_KHR_surface", "VK_KHR_xcb_surface",
+                            VK_EXT_DEBUG_UTILS_EXTENSION_NAME,
+                            VK_EXT_DEBUG_REPORT_EXTENSION_NAME}};
+    VK_ASSERT(vkCreateInstance(&ci, nullptr, &vk.instance));
+    return false;
+}
+
+static bool choosePhysicalDevice(VkPhysicalDevice* devices, u32 amount) {
+    VK_ASSERT(vkEnumeratePhysicalDevices(vk.instance, &amount, devices));
+    int bestPoints = 0;
+    LOG_INFO("Found %u devices", amount);
+    for(u32 i = 0; i < amount; i++) {
+        int points = 0;
+        VkPhysicalDeviceProperties p;
+        vkGetPhysicalDeviceProperties(devices[i], &p);
+        if(p.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) {
+            points += 100;
+        } else if(p.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU) {
+            points += 50;
+        } else if(p.deviceType == VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU) {
+            points += 20;
+        }
+        if(points > bestPoints) {
+            bestPoints = points;
+            vk.physicalDevice = devices[i];
+            LOG_INFO("Best Device: %s", p.deviceName);
+        }
+    }
+    return bestPoints == 0;
+}
+
+static bool initPhysicalDevice() {
+    u32 deviceCount = 0;
+    VK_ASSERT(vkEnumeratePhysicalDevices(vk.instance, &deviceCount, nullptr));
+    if(deviceCount == 0) {
+        LOG_ERROR("No physical device was found");
+        return true;
+    }
+    VkPhysicalDevice* devices =
+        cAllocate(sizeof(VkPhysicalDevice) * deviceCount);
+    bool r = choosePhysicalDevice(devices, deviceCount);
+    cFree(devices);
+    return r;
+}
+
+static u32 findQueueFamilies(VkPhysicalDevice pd, VkQueueFlags flags) {
+    u32 count = 0;
+    vkGetPhysicalDeviceQueueFamilyProperties(pd, &count, nullptr);
+    VkQueueFamilyProperties* properties =
+        cAllocate(sizeof(VkQueueFamilyProperties) * count);
+    vkGetPhysicalDeviceQueueFamilyProperties(pd, &count, properties);
+    for(u32 i = 0; i < count; i++) {
+        if(properties[i].queueCount != 0 &&
+           (properties[i].queueFlags & flags) == flags) {
+            cFree(properties);
+            return i;
+        }
+    }
+    cFree(properties);
+    return (u32)-1;
+}
+
+static bool initDevice() {
+    VkPhysicalDeviceFeatures deviceFeatures = {0};
+    vkGetPhysicalDeviceFeatures(vk.physicalDevice, &deviceFeatures);
+
+    u32 graphicsFamily =
+        findQueueFamilies(vk.physicalDevice, VK_QUEUE_GRAPHICS_BIT);
+    if(graphicsFamily == (u32)-1) {
+        LOG_ERROR("Cannot find queue family");
+        return true;
+    }
+    VkDeviceQueueCreateInfo dqInfo = {
+        .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
+        .queueFamilyIndex = graphicsFamily,
+        .queueCount = 1,
+        .pQueuePriorities = (float[]){1.0f}};
+    VkDeviceCreateInfo deviceCreateInfo = {
+        .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
+        .queueCreateInfoCount = 1,
+        .pQueueCreateInfos = &dqInfo,
+        .enabledExtensionCount = 1,
+        .ppEnabledExtensionNames =
+            (const char*[]){VK_KHR_SWAPCHAIN_EXTENSION_NAME},
+        .pEnabledFeatures = &deviceFeatures};
+    VK_ASSERT(vkCreateDevice(vk.physicalDevice, &deviceCreateInfo, nullptr,
+                             &vk.device));
+    return false;
+}
+
+bool coreInitVulkan() {
+    return initInstance() || initPhysicalDevice() || initDevice();
+}
+
+void coreDestroyVulkan(void) {
+    vkDestroyDevice(vk.device, nullptr);
+    vkDestroyInstance(vk.instance, nullptr);
+}

+ 3 - 135
src/WindowManager.c

@@ -1,11 +1,9 @@
 #define IMPORT_CORE
 #include "core/WindowManager.h"
 
-#define GLFW_INCLUDE_VULKAN
-#include <GLFW/glfw3.h>
-#include <core/HashMap.h>
 #include <core/Logger.h>
 #include <core/Utility.h>
+#include <core/VulkanWrapper.h>
 #include <limits.h>
 #include <stdio.h>
 #include <uchar.h>
@@ -174,89 +172,6 @@ static void onMouseMove(GLFWwindow*, double x, double y) {
     mousePosition.data[1] = (float)y;
 }
 
-#define VK_ERROR_CASE(error)                                                   \
-    case error: return #error
-
-static const char* getVulkanErrorString(VkResult r) {
-    switch(r) {
-        VK_ERROR_CASE(VK_ERROR_OUT_OF_HOST_MEMORY);
-        VK_ERROR_CASE(VK_ERROR_OUT_OF_DEVICE_MEMORY);
-        VK_ERROR_CASE(VK_ERROR_INITIALIZATION_FAILED);
-        VK_ERROR_CASE(VK_ERROR_LAYER_NOT_PRESENT);
-        VK_ERROR_CASE(VK_ERROR_EXTENSION_NOT_PRESENT);
-        VK_ERROR_CASE(VK_ERROR_INCOMPATIBLE_DRIVER);
-        default: return "unknown";
-    }
-}
-
-#define VK_ASSERT(a)                                                           \
-    do {                                                                       \
-        VkResult vkResult = (a);                                               \
-        if(vkResult != VK_SUCCESS) {                                           \
-            printf("Vulkan error at [%s:%d]: %s\n",                            \
-                   getShortFileName(__FILE__), __LINE__,                       \
-                   getVulkanErrorString(vkResult));                            \
-            return true;                                                       \
-        }                                                                      \
-    } while(false)
-
-static VkResult findSuitablePhysicalDevice(VkInstance instance,
-                                           VkPhysicalDevice* pd) {
-    u32 deviceCount = 0;
-    VkResult r = vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr);
-    if(r != VK_SUCCESS) {
-        return r;
-    } else if(deviceCount == 0) {
-        return VK_ERROR_INITIALIZATION_FAILED;
-    }
-    VkPhysicalDevice* devices =
-        cAllocate(sizeof(VkPhysicalDevice) * deviceCount);
-    r = vkEnumeratePhysicalDevices(instance, &deviceCount, devices);
-    if(r != VK_SUCCESS) {
-        cFree(devices);
-        return r;
-    }
-    int bestPoints = 0;
-    LOG_INFO("Found %u devices", deviceCount);
-    for(u32 i = 0; i < deviceCount; i++) {
-        int points = 0;
-        VkPhysicalDeviceProperties p;
-        vkGetPhysicalDeviceProperties(devices[i], &p);
-        if(p.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) {
-            points += 100;
-        } else if(p.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU) {
-            points += 50;
-        } else if(p.deviceType == VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU) {
-            points += 20;
-        }
-        if(points > bestPoints) {
-            bestPoints = points;
-            *pd = devices[i];
-            LOG_INFO("Best Device: %s", p.deviceName);
-        }
-    }
-    cFree(devices);
-    return bestPoints > 0 ? VK_SUCCESS : VK_ERROR_INITIALIZATION_FAILED;
-}
-
-static u32 findQueueFamilies(VkPhysicalDevice pd, VkQueueFlags flags) {
-    u32 count = 0;
-    vkGetPhysicalDeviceQueueFamilyProperties(pd, &count, nullptr);
-    VkQueueFamilyProperties* properties =
-        cAllocate(sizeof(VkQueueFamilyProperties) * count);
-    vkGetPhysicalDeviceQueueFamilyProperties(pd, &count, properties);
-    for(u32 i = 0; i < count; i++) {
-        if(properties[i].queueCount != 0 &&
-           (properties[i].queueFlags & flags) == flags) {
-            LOG_INFO("Queue family bits: %x", properties[i].queueFlags);
-            cFree(properties);
-            return i;
-        }
-    }
-    cFree(properties);
-    return (u32)-1;
-}
-
 bool openWindow(const WindowOptions* o) {
     if(!glfwInit()) {
         LOG_ERROR("could not initialize GLFW");
@@ -284,59 +199,12 @@ bool openWindow(const WindowOptions* o) {
     glfwSetFramebufferSizeCallback(window, onResize);
     glfwSetMouseButtonCallback(window, onMouse);
     glfwSetCursorPosCallback(window, onMouseMove);
-
-    VkInstance instance = {0};
-    VkApplicationInfo info = {.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
-                              .pApplicationName = "Vulkan",
-                              .applicationVersion = VK_MAKE_VERSION(1, 0, 0),
-                              .pEngineName = "Kajetan",
-                              .engineVersion = VK_MAKE_VERSION(0, 0, 1),
-                              .apiVersion = VK_API_VERSION_1_1};
-    VkInstanceCreateInfo instanceCreateInfo = {
-        .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
-        .pApplicationInfo = &info,
-        .enabledLayerCount = 1,
-        .ppEnabledLayerNames = (const char*[]){"VK_LAYER_KHRONOS_validation"},
-        .enabledExtensionCount = 4,
-        .ppEnabledExtensionNames =
-            (const char*[]){"VK_KHR_surface", "VK_KHR_xcb_surface",
-                            VK_EXT_DEBUG_UTILS_EXTENSION_NAME,
-                            VK_EXT_DEBUG_REPORT_EXTENSION_NAME}};
-    VK_ASSERT(vkCreateInstance(&instanceCreateInfo, nullptr, &instance));
-
-    VkPhysicalDevice physicalDevice = {0};
-    VK_ASSERT(findSuitablePhysicalDevice(instance, &physicalDevice));
-    VkPhysicalDeviceFeatures deviceFeatures = {0};
-    vkGetPhysicalDeviceFeatures(physicalDevice, &deviceFeatures);
-
-    u32 graphicsFamily =
-        findQueueFamilies(physicalDevice, VK_QUEUE_GRAPHICS_BIT);
-    if(graphicsFamily == (u32)-1) {
-        LOG_ERROR("Cannot find queue family");
-        return true;
-    }
-    VkDeviceQueueCreateInfo dqInfo = {
-        .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
-        .queueFamilyIndex = graphicsFamily,
-        .queueCount = 1,
-        .pQueuePriorities = (float[]){1.0f}};
-    VkDeviceCreateInfo deviceCreateInfo = {
-        .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
-        .queueCreateInfoCount = 1,
-        .pQueueCreateInfos = &dqInfo,
-        .enabledExtensionCount = 1,
-        .ppEnabledExtensionNames =
-            (const char*[]){VK_KHR_SWAPCHAIN_EXTENSION_NAME},
-        .pEnabledFeatures = &deviceFeatures};
-    VkDevice device = {0};
-    VK_ASSERT(
-        vkCreateDevice(physicalDevice, &deviceCreateInfo, nullptr, &device));
-
-    return false;
+    return coreInitVulkan();
 }
 
 void closeWindow(void) {
     if(window != nullptr) {
+        coreDestroyVulkan();
         glfwDestroyWindow(window);
         window = nullptr;
     }

+ 5 - 1
tasks

@@ -106,7 +106,11 @@ elif [ "$task" = "valgrind" ]; then
         echo "Valid valgrind types are: debug, release, window, all"
         printHelpExit
     fi
-    valgrind="valgrind --leak-check=full --show-leak-kinds=all"
+    valgrind="valgrind \
+        --leak-check=full \
+        --show-leak-kinds=all \
+        --suppressions=../valgrind.supp
+        "
 elif [ "$task" = "time" ]; then
     build_release=true
     time=true

+ 162 - 0
valgrind.supp

@@ -0,0 +1,162 @@
+{
+  glfwInit 1
+  Memcheck:Leak
+  match-leak-kinds: reachable
+  fun:calloc
+  fun:calloc
+  fun:_dl_new_object
+}
+{
+  glfwInit 2
+  Memcheck:Leak
+  match-leak-kinds: reachable
+  fun:calloc
+  ...
+  fun:_dl_catch_exception
+}
+{
+  glfwInit 3
+  Memcheck:Leak
+  match-leak-kinds: reachable
+  fun:malloc
+  ...
+  fun:_dl_catch_exception
+}
+{
+  glfwInit 4
+  Memcheck:Leak
+  match-leak-kinds: reachable
+  fun:realloc
+  ...
+  fun:_dl_catch_exception
+}
+{
+  glfwInit 5
+  Memcheck:Leak
+  match-leak-kinds: reachable
+  ...
+  obj:/usr/lib/x86_64-linux-gnu/libdbus-1.so.3.32.4
+}
+{
+  glfwInit 6
+  Memcheck:Leak
+  match-leak-kinds: reachable
+  ...
+  fun:_dl_init
+  ...
+  fun:_dl_catch_exception
+}
+{
+  glfwinit 7
+  Memcheck:Leak
+  match-leak-kinds: reachable
+  fun:realloc
+  ...
+  fun:g_hash_table_insert
+  ...
+  fun:call_init
+}
+{
+  glfwShowWindow
+  Memcheck:Leak
+  match-leak-kinds: definite
+  fun:calloc
+  ...
+  fun:createLibdecorFrame
+  fun:createShellObjects
+}
+{
+  libcairo font stuff
+  Memcheck:Leak
+  match-leak-kinds: reachable
+  ...
+  obj:/usr/lib/x86_64-linux-gnu/libcairo.so.2.11600.0
+}
+{
+  libpangocairo font stuff
+  Memcheck:Leak
+  match-leak-kinds: reachable
+  ...
+  obj:/usr/lib/x86_64-linux-gnu/libpangocairo-1.0.so.0.5000.12
+}
+{
+  libpango font stuff
+  Memcheck:Leak
+  ...
+  obj:/usr/lib/x86_64-linux-gnu/libpango-1.0.so.0.5000.12
+}
+{
+  libexpat font stuff
+  Memcheck:Leak
+  match-leak-kinds: reachable
+  ...
+  obj:/usr/lib/x86_64-linux-gnu/libexpat.so.1.8.10
+}
+{
+  libfontconfig font stuff
+  Memcheck:Leak
+  ...
+  obj:/usr/lib/x86_64-linux-gnu/libfontconfig.so.1.12.0
+}
+{
+  libharfbuzz font stuff
+  Memcheck:Leak
+  ...
+  obj:/usr/lib/x86_64-linux-gnu/libharfbuzz.so.0.60000.0
+}
+{
+  libfreetype font stuff
+  Memcheck:Leak
+  ...
+  obj:/usr/lib/x86_64-linux-gnu/libfreetype.so.6.18.3
+}
+{
+  libgobject 1
+  Memcheck:Leak
+  match-leak-kinds: reachable
+  fun:realloc
+  ...
+  fun:g_hash_table_insert
+  ...
+  fun:g_type_class_ref
+}
+{
+  libgobject 2
+  Memcheck:Leak
+  match-leak-kinds: reachable
+  fun:malloc
+  ...
+  fun:g_type_class_ref
+}
+{
+  libgobject 3
+  Memcheck:Leak
+  match-leak-kinds: reachable
+  fun:realloc
+  ...
+  fun:g_type_class_ref
+}
+{
+  libgobject 4
+  Memcheck:Leak
+  match-leak-kinds: reachable
+  fun:calloc
+  ...
+  fun:g_type_class_ref
+}
+{
+  libglib
+  Memcheck:Leak
+  match-leak-kinds: reachable
+  fun:malloc
+  ...
+  fun:start_thread
+  fun:clone
+}
+{
+  dl_init
+  Memcheck:Leak
+  match-leak-kinds: reachable
+  ...
+  fun:_dl_init
+}