kiba-engine
instance.c
1 #include <kiba/renderer/vulkan/instance.h>
2 
3 #include <kiba/containers/array.h>
4 #include <kiba/core/string.h>
5 
6 b8 verify_extension_availability(array_of(const char *) names);
7 
8 b8 verify_layer_availability(array_of(const char *) names);
9 
10 b8 vulkan_instance_create(vulkan_context *context) {
11  VkApplicationInfo app_info = {
12  .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
13  .pApplicationName = "Vulkan POC", // TODO pass that and other app info into backend creation
14  .applicationVersion = VK_MAKE_VERSION(1, 0, 0),
15  .pEngineName = "kiba",
16  .engineVersion = VK_MAKE_VERSION(0, 0, 1),
17  .apiVersion = VK_API_VERSION_1_0,
18  };
19 
20  if (!verify_extension_availability(context->instance.extensions)) {
21  KB_ERROR("not all required extensions available");
22  return false;
23  }
24 
25  if (!verify_layer_availability(context->instance.layers)) {
26  KB_ERROR("not all required layers available");
27  return false;
28  }
29 
30 #ifdef KB_DEBUG_BUILD
31  VkValidationFeatureEnableEXT enabled[] = {VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT};
32  VkValidationFeaturesEXT features = {
33  .sType = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT,
34  .disabledValidationFeatureCount = 0,
35  .enabledValidationFeatureCount = 1,
36  .pDisabledValidationFeatures = VK_NULL_HANDLE,
37  .pEnabledValidationFeatures = enabled,
38  };
39 #endif
40 
41  VkInstanceCreateInfo instance_info = {
42  .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
43  .pApplicationInfo = &app_info,
44  .enabledLayerCount = (u32) array_size(context->instance.layers),
45  .ppEnabledLayerNames = context->instance.layers,
46  .enabledExtensionCount = (u32) array_size(context->instance.extensions),
47  .ppEnabledExtensionNames = context->instance.extensions,
48 #ifdef KB_DEBUG_BUILD
49  .pNext = &features,
50 #endif
51  };
52 
53  VK_CALL_B8(vkCreateInstance(&instance_info, &context->alloc.vulkan_callbacks, &context->instance.instance));
54 
55  return true;
56 }
57 
58 void vulkan_instance_destroy(vulkan_context *context) {
59  vkDestroyInstance(context->instance.instance, &context->alloc.vulkan_callbacks);
60 }
61 
62 b8 verify_extension_availability(array_of(const char *) names) {
63  u32 avail_extension_count = 0;
64  VK_CALL_B8(vkEnumerateInstanceExtensionProperties(0, &avail_extension_count, 0))
65  if (avail_extension_count < array_size(names)) {
66  KB_INFO("not all required extensions available");
67  return false;
68  }
69  array_of(VkExtensionProperties) available_extensions =
70  array_create(VkExtensionProperties, avail_extension_count, array_alloc(names));
71  if (available_extensions == KB_NULL) {
72  KB_INFO("could not allocate enough memory for list of available extensions");
73  return false;
74  }
75  // NOTE: this leaks in case it is unsuccessful
76  VK_CALL_B8(vkEnumerateInstanceExtensionProperties(0, &avail_extension_count, available_extensions));
77  array_resize(&available_extensions, avail_extension_count);
78 
79  b8 has_extensions = true;
80  array_for_each(const char *, name, names) {
81  b8 found = false;
82  for (u32 j = 0; j < avail_extension_count; ++j) {
83  if (string_equal(string_from_raw(*name), string_from_raw(available_extensions[j].extensionName))) {
84  found = true;
85  break;
86  }
87  }
88  if (!found) {
89  KB_ERROR("could not find required extension {raw_string}", *name);
90  has_extensions = false;
91  }
92  }
93  array_destroy(&available_extensions);
94  return has_extensions;
95 }
96 
97 b8 verify_layer_availability(array_of(const char *) names) {
98  u32 avail_layer_count = 0;
99  VK_CALL_B8(vkEnumerateInstanceLayerProperties(&avail_layer_count, 0));
100  if (avail_layer_count < array_size(names)) {
101  KB_INFO("not all required extensions available");
102  return false;
103  }
104  array_of(VkLayerProperties) avail_layers = array_create(VkLayerProperties, avail_layer_count, array_alloc(names));
105  if (avail_layers == KB_NULL) {
106  KB_INFO("could not allocate enough memory for list of available layers");
107  return false;
108  }
109 
110  // NOTE: this leaks in case it is unsuccessful
111  VK_CALL_B8(vkEnumerateInstanceLayerProperties(&avail_layer_count, avail_layers));
112  array_resize(&avail_layers, avail_layer_count);
113 
114  b8 has_layers = true;
115  array_for_each(const char *, name, names) {
116  b8 found = false;
117  for (u32 j = 0; j < avail_layer_count; ++j) {
118  if (string_equal(string_from_raw(*name), string_from_raw(avail_layers[j].layerName))) {
119  found = true;
120  break;
121  }
122  }
123  if (!found) {
124  KB_ERROR("could not find required validation layer {raw_string}", *name);
125  has_layers = false;
126  }
127  }
128  array_destroy(&avail_layers);
129  return has_layers;
130 }
b8 string_equal(const string lhs, const string rhs)
Check if the contents of two strings are equal.
Definition: string.c:118
string string_from_raw(const char *raw)
Construct a string from a raw string.
Definition: string.c:13
Custom library for interactions with strings using string views.
#define KB_NULL
Value of an invalid ptr (nullptr).
Definition: defines.h:18
#define KB_ERROR(...)
Log entry with error log level.
Definition: log.h:142
#define KB_INFO(...)
Log entry with info log level.
Definition: log.h:162