VulkanWrapper.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. #define IMPORT_CORE
  2. #include "core/VulkanWrapper.h"
  3. #define GLFW_INCLUDE_VULKAN
  4. #include <GLFW/glfw3.h>
  5. #include <core/Logger.h>
  6. #include <core/Utility.h>
  7. #include <limits.h>
  8. #include <stdio.h>
  9. #include <uchar.h>
  10. typedef struct {
  11. VkInstance instance;
  12. VkPhysicalDevice physicalDevice;
  13. VkDevice device;
  14. } VulkanData;
  15. static VulkanData vk = {0};
  16. #define VK_ERROR_CASE(error) \
  17. case error: return #error
  18. static const char* getVulkanErrorString(VkResult r) {
  19. switch(r) {
  20. VK_ERROR_CASE(VK_ERROR_OUT_OF_HOST_MEMORY);
  21. VK_ERROR_CASE(VK_ERROR_OUT_OF_DEVICE_MEMORY);
  22. VK_ERROR_CASE(VK_ERROR_INITIALIZATION_FAILED);
  23. VK_ERROR_CASE(VK_ERROR_LAYER_NOT_PRESENT);
  24. VK_ERROR_CASE(VK_ERROR_EXTENSION_NOT_PRESENT);
  25. VK_ERROR_CASE(VK_ERROR_INCOMPATIBLE_DRIVER);
  26. default: return "unknown";
  27. }
  28. }
  29. #define VK_ASSERT(a) \
  30. do { \
  31. VkResult vkResult = (a); \
  32. if(vkResult != VK_SUCCESS) { \
  33. printf("Vulkan error at [%s:%d]: %s\n", \
  34. getShortFileName(__FILE__), __LINE__, \
  35. getVulkanErrorString(vkResult)); \
  36. return true; \
  37. } \
  38. } while(false)
  39. static bool initInstance() {
  40. VkApplicationInfo i = {.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
  41. .pApplicationName = "Vulkan",
  42. .applicationVersion = VK_MAKE_VERSION(1, 0, 0),
  43. .pEngineName = "Kajetan",
  44. .engineVersion = VK_MAKE_VERSION(0, 0, 1),
  45. .apiVersion = VK_API_VERSION_1_1};
  46. VkInstanceCreateInfo ci = {
  47. .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
  48. .pApplicationInfo = &i,
  49. .enabledLayerCount = 1,
  50. .ppEnabledLayerNames = (const char*[]){"VK_LAYER_KHRONOS_validation"},
  51. .enabledExtensionCount = 4,
  52. .ppEnabledExtensionNames =
  53. (const char*[]){"VK_KHR_surface", "VK_KHR_xcb_surface",
  54. VK_EXT_DEBUG_UTILS_EXTENSION_NAME,
  55. VK_EXT_DEBUG_REPORT_EXTENSION_NAME}};
  56. VK_ASSERT(vkCreateInstance(&ci, nullptr, &vk.instance));
  57. return false;
  58. }
  59. static bool choosePhysicalDevice(VkPhysicalDevice* devices, u32 amount) {
  60. VK_ASSERT(vkEnumeratePhysicalDevices(vk.instance, &amount, devices));
  61. int bestPoints = 0;
  62. LOG_INFO("Found %u devices", amount);
  63. for(u32 i = 0; i < amount; i++) {
  64. int points = 0;
  65. VkPhysicalDeviceProperties p;
  66. vkGetPhysicalDeviceProperties(devices[i], &p);
  67. if(p.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) {
  68. points += 100;
  69. } else if(p.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU) {
  70. points += 50;
  71. } else if(p.deviceType == VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU) {
  72. points += 20;
  73. }
  74. if(points > bestPoints) {
  75. bestPoints = points;
  76. vk.physicalDevice = devices[i];
  77. LOG_INFO("Best Device: %s", p.deviceName);
  78. }
  79. }
  80. return bestPoints == 0;
  81. }
  82. static bool initPhysicalDevice() {
  83. u32 deviceCount = 0;
  84. VK_ASSERT(vkEnumeratePhysicalDevices(vk.instance, &deviceCount, nullptr));
  85. if(deviceCount == 0) {
  86. LOG_ERROR("No physical device was found");
  87. return true;
  88. }
  89. VkPhysicalDevice* devices =
  90. cAllocate(sizeof(VkPhysicalDevice) * deviceCount);
  91. bool r = choosePhysicalDevice(devices, deviceCount);
  92. cFree(devices);
  93. return r;
  94. }
  95. static u32 findQueueFamilies(VkPhysicalDevice pd, VkQueueFlags flags) {
  96. u32 count = 0;
  97. vkGetPhysicalDeviceQueueFamilyProperties(pd, &count, nullptr);
  98. VkQueueFamilyProperties* properties =
  99. cAllocate(sizeof(VkQueueFamilyProperties) * count);
  100. vkGetPhysicalDeviceQueueFamilyProperties(pd, &count, properties);
  101. for(u32 i = 0; i < count; i++) {
  102. if(properties[i].queueCount != 0 &&
  103. (properties[i].queueFlags & flags) == flags) {
  104. cFree(properties);
  105. return i;
  106. }
  107. }
  108. cFree(properties);
  109. return (u32)-1;
  110. }
  111. static bool initDevice() {
  112. VkPhysicalDeviceFeatures deviceFeatures = {0};
  113. vkGetPhysicalDeviceFeatures(vk.physicalDevice, &deviceFeatures);
  114. u32 graphicsFamily =
  115. findQueueFamilies(vk.physicalDevice, VK_QUEUE_GRAPHICS_BIT);
  116. if(graphicsFamily == (u32)-1) {
  117. LOG_ERROR("Cannot find queue family");
  118. return true;
  119. }
  120. VkDeviceQueueCreateInfo dqInfo = {
  121. .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
  122. .queueFamilyIndex = graphicsFamily,
  123. .queueCount = 1,
  124. .pQueuePriorities = (float[]){1.0f}};
  125. VkDeviceCreateInfo deviceCreateInfo = {
  126. .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
  127. .queueCreateInfoCount = 1,
  128. .pQueueCreateInfos = &dqInfo,
  129. .enabledExtensionCount = 1,
  130. .ppEnabledExtensionNames =
  131. (const char*[]){VK_KHR_SWAPCHAIN_EXTENSION_NAME},
  132. .pEnabledFeatures = &deviceFeatures};
  133. VK_ASSERT(vkCreateDevice(vk.physicalDevice, &deviceCreateInfo, nullptr,
  134. &vk.device));
  135. return false;
  136. }
  137. bool coreInitVulkan() {
  138. return initInstance() || initPhysicalDevice() || initDevice();
  139. }
  140. void coreDestroyVulkan(void) {
  141. vkDestroyDevice(vk.device, nullptr);
  142. vkDestroyInstance(vk.instance, nullptr);
  143. }