1 #include <kiba/gpu/vulkan/instance.h>
3 #include <kiba/containers/array.h>
7 #include <kiba/gpu/vulkan/allocator.h>
8 #include <kiba/gpu/vulkan/util.h>
13 array_of(
const char *) extensions;
14 array_of(
const char *) layers;
19 .extensions = array_create(
const char *, 5, &
vk_alloc.kiba_alloc),
20 .layers = array_create(
const char *, 4, &
vk_alloc.kiba_alloc),
22 KB_ASSERT(req.extensions !=
KB_NULL,
"instance extension array creation must be successful");
23 KB_ASSERT(req.layers !=
KB_NULL,
"instance layer array creation must be successful");
25 array_push(req.extensions, VK_KHR_SURFACE_EXTENSION_NAME);
27 array_push(req.extensions,
"VK_KHR_xcb_surface");
30 array_push(req.extensions, VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
31 array_push(req.layers,
"VK_LAYER_KHRONOS_validation");
36 b8 vk_verify_extension_availability(array_of(
const char *) names);
37 b8 vk_verify_layer_availability(array_of(
const char *) names);
39 b8 vk_debug_messenger_create(
void);
40 void vk_debug_messenger_destroy(
void);
42 b8 vk_instance_initialize(
void) {
43 VkApplicationInfo app_info = {
44 .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
45 .pApplicationName =
"kiba-vulkan-backend",
46 .applicationVersion = VK_MAKE_VERSION(1, 0, 0),
47 .pEngineName =
"kiba",
48 .engineVersion = VK_MAKE_VERSION(0, 0, 1),
49 .apiVersion = VK_API_VERSION_1_0,
54 if (!vk_verify_extension_availability(requirements.extensions)) {
55 KB_ERROR(
"not all required extensions available");
59 if (!vk_verify_layer_availability(requirements.layers)) {
60 KB_ERROR(
"not all required layers available");
65 VkValidationFeatureEnableEXT enabled[] = {VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT};
66 VkValidationFeaturesEXT features = {
67 .sType = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT,
68 .disabledValidationFeatureCount = 0,
69 .enabledValidationFeatureCount = 1,
70 .pDisabledValidationFeatures = VK_NULL_HANDLE,
71 .pEnabledValidationFeatures = enabled,
75 VkInstanceCreateInfo instance_info = {
76 .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
77 .pApplicationInfo = &app_info,
78 .enabledLayerCount = (u32) array_size(requirements.layers),
79 .ppEnabledLayerNames = requirements.layers,
80 .enabledExtensionCount = (u32) array_size(requirements.extensions),
81 .ppEnabledExtensionNames = requirements.extensions,
87 VK_CALL_B8(vkCreateInstance(&instance_info, &
vk_alloc.vulkan_callbacks, &vk_instance.raw));
90 if (!vk_debug_messenger_create()) {
91 KB_ERROR(
"could not create vulkan debug messenger");
94 vk_instance.setDebugUtilsObjectName =
95 (PFN_vkSetDebugUtilsObjectNameEXT) vkGetInstanceProcAddr(vk_instance.raw,
"vkSetDebugUtilsObjectNameEXT");
96 vk_instance.cmdBeginDebugUtilsLabel =
97 (PFN_vkCmdBeginDebugUtilsLabelEXT) vkGetInstanceProcAddr(vk_instance.raw,
"vkCmdBeginDebugUtilsLabelEXT");
98 vk_instance.cmdEndDebugUtilsLabel =
99 (PFN_vkCmdEndDebugUtilsLabelEXT) vkGetInstanceProcAddr(vk_instance.raw,
"vkCmdEndDebugUtilsLabelEXT");
100 vk_instance.cmdInsertDebugUtilsLabel =
101 (PFN_vkCmdInsertDebugUtilsLabelEXT) vkGetInstanceProcAddr(vk_instance.raw,
"vkCmdInsertDebugUtilsLabelEXT");
107 void vk_instance_shutdown(
void) {
108 if (vk_instance.raw != VK_NULL_HANDLE) {
109 #ifdef KB_DEBUG_BUILD
110 vk_debug_messenger_destroy();
112 vkDestroyInstance(vk_instance.raw, &
vk_alloc.vulkan_callbacks);
113 vk_instance.raw = VK_NULL_HANDLE;
115 KB_WARN(
"tried to destroy uninitialized vulkan instance");
119 b8 vk_verify_extension_availability(array_of(
const char *) names) {
120 u32 avail_extension_count = 0;
121 VK_CALL_B8(vkEnumerateInstanceExtensionProperties(0, &avail_extension_count, 0))
122 if (avail_extension_count < array_size(names)) {
123 KB_INFO(
"not all required extensions available");
126 array_of(VkExtensionProperties) available_extensions =
127 array_create(VkExtensionProperties, avail_extension_count, array_alloc(names));
128 array_resize(&available_extensions, avail_extension_count);
129 if (available_extensions ==
KB_NULL) {
130 KB_INFO(
"could not allocate enough memory for list of available extensions");
134 VK_CALL_B8(vkEnumerateInstanceExtensionProperties(0, &avail_extension_count, available_extensions));
136 b8 has_extensions =
true;
137 array_for_each(
const char *, name, names) {
139 for (u32 j = 0; j < avail_extension_count; ++j) {
146 KB_ERROR(
"could not find required extension {raw_string}", *name);
147 has_extensions =
false;
150 array_destroy(&available_extensions);
151 return has_extensions;
154 b8 vk_verify_layer_availability(array_of(
const char *) names) {
155 u32 avail_layer_count = 0;
156 VK_CALL_B8(vkEnumerateInstanceLayerProperties(&avail_layer_count, 0));
157 if (avail_layer_count < array_size(names)) {
158 KB_INFO(
"not all required extensions available");
161 array_of(VkLayerProperties) avail_layers = array_create(VkLayerProperties, avail_layer_count, array_alloc(names));
162 array_resize(&avail_layers, avail_layer_count);
164 KB_INFO(
"could not allocate enough memory for list of available layers");
169 VK_CALL_B8(vkEnumerateInstanceLayerProperties(&avail_layer_count, avail_layers));
171 b8 has_layers =
true;
172 array_for_each(
const char *, name, names) {
174 for (u32 j = 0; j < avail_layer_count; ++j) {
181 KB_ERROR(
"could not find required validation layer {raw_string}", *name);
185 array_destroy(&avail_layers);
189 VkDebugUtilsMessengerEXT vk_debug_messenger = {0};
190 VKAPI_ATTR VkBool32 VKAPI_CALL vk_debug_callback(VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,
191 VkDebugUtilsMessageTypeFlagsEXT message_types,
192 const VkDebugUtilsMessengerCallbackDataEXT *callback_data,
195 b8 vk_debug_messenger_create(
void) {
197 VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT
198 | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
199 u32 message_types = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT
200 | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT;
201 VkDebugUtilsMessengerCreateInfoEXT debug_create_info = {
202 .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
203 .messageSeverity = log_severities,
204 .messageType = message_types,
205 .pfnUserCallback = vk_debug_callback,
207 PFN_vkCreateDebugUtilsMessengerEXT messenger_add_func =
208 (PFN_vkCreateDebugUtilsMessengerEXT) vkGetInstanceProcAddr(vk_instance.raw,
"vkCreateDebugUtilsMessengerEXT");
209 if (messenger_add_func ==
KB_NULL) {
210 KB_ERROR(
"could not create vulkan debug messenger");
214 messenger_add_func(vk_instance.raw, &debug_create_info, &
vk_alloc.vulkan_callbacks, &vk_debug_messenger));
218 void vk_debug_messenger_destroy(
void) {
219 PFN_vkDestroyDebugUtilsMessengerEXT messenger_remove_func =
220 (PFN_vkDestroyDebugUtilsMessengerEXT) vkGetInstanceProcAddr(vk_instance.raw,
"vkDestroyDebugUtilsMessengerEXT");
221 if (messenger_remove_func ==
KB_NULL) {
222 KB_ERROR(
"received invalid function to destroy debug messenger");
225 messenger_remove_func(vk_instance.raw, vk_debug_messenger, &
vk_alloc.vulkan_callbacks);
228 VKAPI_ATTR VkBool32 VKAPI_CALL vk_debug_callback(VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,
229 VkDebugUtilsMessageTypeFlagsEXT message_types,
230 const VkDebugUtilsMessengerCallbackDataEXT *callback_data,
234 switch (message_severity) {
235 case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT:
238 case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT:
239 KB_INFO(callback_data->pMessage);
241 case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT:
242 KB_WARN(callback_data->pMessage);
244 case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT:
Lightweight layer between platform and other engine components to enable tracing/monitoring.
b8 string_equal(const string lhs, const string rhs)
Check if the contents of two strings are equal.
string string_from_raw(const char *raw)
Construct a string from a raw string.
Custom library for interactions with strings using string views.
#define UNUSED(x)
Mark parameter as unused.
#define KB_NULL
Value of an invalid ptr (nullptr).
#define KB_ASSERT(expr,...)
Perform runtime assertion and log failures.
#define KB_WARN(...)
Log entry with warn log level.
#define KB_ERROR(...)
Log entry with error log level.
#define KB_TRACE(...)
Log entry with trace log level.
#define KB_INFO(...)
Log entry with info log level.