فهرست منبع

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

Kajetan Johannes Hammerle 10 ماه پیش
والد
کامیت
11050fdae3
6فایلهای تغییر یافته به همراه339 افزوده شده و 142 حذف شده
  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
+}