|
@@ -8,6 +8,8 @@
|
|
|
|
|
|
typedef struct {
|
|
typedef struct {
|
|
VkInstance instance;
|
|
VkInstance instance;
|
|
|
|
+ VkDebugUtilsMessengerEXT debugMessenger;
|
|
|
|
+ VkDebugReportCallbackEXT debugReportCallback;
|
|
u32 graphicsFamily;
|
|
u32 graphicsFamily;
|
|
VkPhysicalDevice physicalDevice;
|
|
VkPhysicalDevice physicalDevice;
|
|
VkDevice device;
|
|
VkDevice device;
|
|
@@ -50,6 +52,12 @@ static const char* getVulkanErrorString(VkResult r) {
|
|
} \
|
|
} \
|
|
} while(false)
|
|
} while(false)
|
|
|
|
|
|
|
|
+static PFN_vkVoidFunction getVulkanFunction(const char* name) {
|
|
|
|
+ return vkGetInstanceProcAddr(vk.instance, name);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+#define GET_VULKAN_FUNCTION(name) ((PFN_##name)getVulkanFunction(#name))
|
|
|
|
+
|
|
static bool initInstance() {
|
|
static bool initInstance() {
|
|
VkApplicationInfo i = {.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
|
|
VkApplicationInfo i = {.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
|
|
.pApplicationName = "Vulkan",
|
|
.pApplicationName = "Vulkan",
|
|
@@ -71,6 +79,84 @@ static bool initInstance() {
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static VKAPI_ATTR VkBool32 onVulkanDebugMessenger VKAPI_CALL(
|
|
|
|
+ VkDebugUtilsMessageSeverityFlagBitsEXT, VkDebugUtilsMessageTypeFlagsEXT,
|
|
|
|
+ const VkDebugUtilsMessengerCallbackDataEXT* data, void*) {
|
|
|
|
+ LOG_WARNING("Vulkan validation layer message: %s", data->pMessage);
|
|
|
|
+ return false;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static bool initDebugMessenger() {
|
|
|
|
+ VkDebugUtilsMessengerCreateInfoEXT info = {
|
|
|
|
+ .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
|
|
|
|
+ .messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
|
|
|
|
+ VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT,
|
|
|
|
+ .messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
|
|
|
|
+ VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
|
|
|
|
+ VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT,
|
|
|
|
+ .pfnUserCallback = onVulkanDebugMessenger};
|
|
|
|
+ auto f = GET_VULKAN_FUNCTION(vkCreateDebugUtilsMessengerEXT);
|
|
|
|
+ if(f == nullptr) {
|
|
|
|
+ LOG_WARNING("Could not find debug util messenger function");
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ VK_ASSERT(f(vk.instance, &info, nullptr, &vk.debugMessenger));
|
|
|
|
+ return false;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static VKAPI_ATTR VkBool32 onVulkanDebugReport
|
|
|
|
+VKAPI_CALL(VkDebugReportFlagsEXT, VkDebugReportObjectTypeEXT, uint64_t, size_t,
|
|
|
|
+ int32_t, const char* pLayerPrefix, const char* pMessage, void*) {
|
|
|
|
+ LOG_WARNING("Vulkan debug message '%s': %s", pLayerPrefix, pMessage);
|
|
|
|
+ return false;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static bool initDebugReportCallback() {
|
|
|
|
+ VkDebugReportCallbackCreateInfoEXT info = {
|
|
|
|
+ .sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT,
|
|
|
|
+ .flags = VK_DEBUG_REPORT_WARNING_BIT_EXT |
|
|
|
|
+ VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT |
|
|
|
|
+ VK_DEBUG_REPORT_ERROR_BIT_EXT,
|
|
|
|
+ .pfnCallback = onVulkanDebugReport};
|
|
|
|
+ auto f = GET_VULKAN_FUNCTION(vkCreateDebugReportCallbackEXT);
|
|
|
|
+ if(f == nullptr) {
|
|
|
|
+ LOG_WARNING("Could not find debug report function");
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ VK_ASSERT(f(vk.instance, &info, nullptr, &vk.debugReportCallback));
|
|
|
|
+ return false;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static bool initDebugging() {
|
|
|
|
+ return initDebugMessenger() || initDebugReportCallback();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void destroyDebugMessenger() {
|
|
|
|
+ auto f = GET_VULKAN_FUNCTION(vkDestroyDebugUtilsMessengerEXT);
|
|
|
|
+ if(f == nullptr) {
|
|
|
|
+ LOG_WARNING("Could not find debug util messenger destroy function");
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ f(vk.instance, vk.debugMessenger, nullptr);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void destroyDebugReportCallback() {
|
|
|
|
+ auto f = GET_VULKAN_FUNCTION(vkDestroyDebugReportCallbackEXT);
|
|
|
|
+ if(f == nullptr) {
|
|
|
|
+ LOG_WARNING("Could not find debug report destroy function");
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ f(vk.instance, vk.debugReportCallback, nullptr);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void destroyDebugging() {
|
|
|
|
+ if(vk.instance == VK_NULL_HANDLE) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ destroyDebugMessenger();
|
|
|
|
+ destroyDebugReportCallback();
|
|
|
|
+}
|
|
|
|
+
|
|
static bool choosePhysicalDevice(VkPhysicalDevice* devices, u32 amount) {
|
|
static bool choosePhysicalDevice(VkPhysicalDevice* devices, u32 amount) {
|
|
VK_ASSERT(vkEnumeratePhysicalDevices(vk.instance, &amount, devices));
|
|
VK_ASSERT(vkEnumeratePhysicalDevices(vk.instance, &amount, devices));
|
|
int bestPoints = 0;
|
|
int bestPoints = 0;
|
|
@@ -288,8 +374,8 @@ static bool createSwapchainImages(SwapchainImages* i) {
|
|
bool initVulkan() {
|
|
bool initVulkan() {
|
|
vk.width = 400;
|
|
vk.width = 400;
|
|
vk.height = 300;
|
|
vk.height = 300;
|
|
- if(initInstance() || initPhysicalDevice() || initDevice() ||
|
|
|
|
- initSurface() || initSwapchain()) {
|
|
|
|
|
|
+ if(initInstance() || initDebugging() || initPhysicalDevice() ||
|
|
|
|
+ initDevice() || initSurface() || initSwapchain()) {
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
SwapchainImages images;
|
|
SwapchainImages images;
|
|
@@ -308,5 +394,6 @@ void destroyVulkan(void) {
|
|
vkDestroySurfaceKHR(vk.instance, vk.surface, nullptr);
|
|
vkDestroySurfaceKHR(vk.instance, vk.surface, nullptr);
|
|
}
|
|
}
|
|
vkDestroyDevice(vk.device, nullptr);
|
|
vkDestroyDevice(vk.device, nullptr);
|
|
|
|
+ destroyDebugging();
|
|
vkDestroyInstance(vk.instance, nullptr);
|
|
vkDestroyInstance(vk.instance, nullptr);
|
|
}
|
|
}
|