topaz/rendering/vk/instance.c

106 lines
2.9 KiB
C

/* SPDX-License-Identifier:BSD-3-Clause */
#include "vk.h"
#include "instance.h"
#include "../../core/log.h"
const char *extensions[] = {
#ifdef PLATFORM_MACOS
VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME,
VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
#endif
NULL
};
#ifdef DEBUG
const char *layers[] = {
"VK_LAYER_KHRONOS_validation"
};
#define LAYER_COUNT (sizeof(layers)/sizeof(layers[0]))
#else
#define LAYER_COUNT 0
const char *layers[] = {NULL};
#endif
/*
* Vulkan is modular by design. This means that some features that might not be
* always needed are not enabled by default. To enable those features (like
* macOS platform compatibility or windowing) extensions are needed. This
* function checks which extensions are required by RGFW and adds extensions
* required by the game itself.
*/
const char **vk_instance_extensions(usize * count)
{
usize rgfw_extension_count = 0;
const char **rgfw_extensions = RGFW_getRequiredInstanceExtensions_Vulkan(&rgfw_extension_count);
usize extension_count = sizeof(extensions) / sizeof(extensions[0]) - 1;
*count = rgfw_extension_count + extension_count;
const char **instance_extensions = malloc(*count * sizeof(char *));
log_info("Required Vulkan extensions: ");
for (usize i = 0; i < rgfw_extension_count; i++) {
printf("%s ", rgfw_extensions[i]);
instance_extensions[i] = rgfw_extensions[i];
}
for (usize i = 0; i < extension_count; i++) {
printf("%s ", extensions[i]);
instance_extensions[rgfw_extension_count + i] = extensions[i];
}
printf("\n");
return instance_extensions;
}
void vk_instance_init(struct renderer_context *context)
{
VkApplicationInfo application_info = {
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
.pApplicationName = "topaz",
.applicationVersion = 0,
.pEngineName = "topaz",
.engineVersion = 0,
.apiVersion = VK_API_VERSION_1_4
};
usize extension_count = 0;
const char **extension_names = vk_instance_extensions(&extension_count);
u32 flags = 0;
#ifdef PLATFORM_MACOS
flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
#endif
VkInstanceCreateInfo instance_info = {
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
.pApplicationInfo = &application_info,
.flags = flags,
.enabledLayerCount = LAYER_COUNT,
.ppEnabledLayerNames = layers,
.enabledExtensionCount = extension_count,
.ppEnabledExtensionNames = extension_names,
};
VkResult result = vkCreateInstance(&instance_info, NULL, &context->instance);
switch (result) {
case VK_ERROR_INCOMPATIBLE_DRIVER:
free(extension_names);
fatal("Incompatible driver.\n");
case VK_ERROR_LAYER_NOT_PRESENT:
free(extension_names);
fatal("Requested vulkan layers are not present.\n");
case VK_SUCCESS:
log_info("Vulkan instance created.\n");
break;
default:
fatal("Can't create Vulkan instance.\n");
}
free(extension_names);
}
void vk_instance_deinit(struct renderer_context *context)
{
vkDestroyInstance(context->instance, NULL);
}