#ifndef _VKSETUP_H
#define _VKSETUP_H
/* Start header file */
/**
vulkan setup and basic vector math
Single header file with included implementation in the spirit of
stb_* <https://github.com/nothings/stb>
ASSUMPTIONS:
~~~~~~~~~~~~
- Using SDL2 for the window
- Using cglm for maths
- Using shaderc for compiling glsl
- Using vulkan(!)
USAGE:
~~~~~~
Do this:
#define VKSETUP_IMPLEMENTATION
before you include this file in *one* C or C++ file to create the implementation.
// i.e. it should look like this:
#include ...
#include ...
#include ...
#define VKSETUP_IMPLEMENTATION
#include "vksetup.h"
*/
#define SDL_MAIN_HANDLED
#define VK_USE_PLATFORM_XCB_KHR
#include <SDL2/SDL.h>
#include <SDL2/SDL_vulkan.h>
#include <vulkan/vulkan.h>
#include <shaderc/shaderc.h>
#include "../lib/cglm/include/cglm/cglm.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifndef VKSETUPDEF
#ifdef VKSETUP_STATIC
#define VKSETUPDEF static
#else
#define VKSETUPDEF extern
#endif
#endif
// TODO Create structs for vulkan data
typedef struct {void * a;} vksetup_vulkan;
typedef struct {void * a;} vksetup_image;
typedef struct {void * a;} vksetup_;
// need abstraction with the
/**
Create a VkInstance
*/
VKSETUPDEF VkInstance vksetup_create_instance(bool validation_layers_toggle, const char * const validation_layers[], uint32_t validation_layer_count, SDL_Window *window);
/* VKSETUPDEF void vulkan_create_surface(); */
/* VKSETUPDEF void vulkan_pick_physical_device(); */
/* VKSETUPDEF void vulkan_create_logical_device(); */
/* VKSETUPDEF void vulkan_create_swap_chain(); */
/* VKSETUPDEF void vulkan_create_image_views(); */
/* VKSETUPDEF void vulkan_create_descriptor_set_layout(); */
/* VKSETUPDEF void vulkan_create_graphics_pipeline(); */
/* VKSETUPDEF void vulkan_create_command_pool(); */
/* VKSETUPDEF void vulkan_create_depth_resources(); */
/* VKSETUPDEF void vulkan_create_texture_image(); */
/* VKSETUPDEF void vulkan_create_texture_image_view(); */
/* VKSETUPDEF void vulkan_create_texture_sampler(); */
/* VKSETUPDEF void vulkan_create_vertex_buffer(); */
/* VKSETUPDEF void vulkan_create_index_buffer(); */
/* VKSETUPDEF void vulkan_create_uniform_buffers(); */
/* VKSETUPDEF void vulkan_create_descriptor_pool(); */
/* VKSETUPDEF void vulkan_create_descriptor_sets(); */
/* VKSETUPDEF void vulkan_create_command_buffer(); */
/* VKSETUPDEF void vulkan_create_sync_objects(); */
#ifdef __cplusplus
}
#endif
/* End header file */
#endif /* _VKSETUP_H */
#ifdef VKSETUP_IMPLEMENTATION
#include <stddef.h>
#include <stdlib.h>
#include <time.h>
#include "vkutil.h"
bool
_checkValidationLayerSupport(const char * const validation_layers[], uint32_t validation_layer_count)
{
uint32_t layerCount;
vkEnumerateInstanceLayerProperties(&layerCount, NULL);
VkLayerProperties availableLayers[layerCount];
vkEnumerateInstanceLayerProperties(&layerCount, availableLayers);
for (uint32_t i = 0; i < validation_layer_count; i++) {
bool layerFound = false;
for (uint32_t j = 0; j < layerCount; j++) {
if (strcmp(validation_layers[i], availableLayers[j].layerName) == 0) {
layerFound = true;
break;
}
}
if (!layerFound) {
return false;
}
}
return true;
}
VKSETUPDEF VkInstance
vksetup_create_instance(bool validation_layers_toggle, const char * const validation_layers[], uint32_t validation_layer_count, SDL_Window *window)
{
if (validation_layers_toggle && !_checkValidationLayerSupport(validation_layers, validation_layer_count)) {
vk_log(VK_ERROR, "validation layers requested, but not available!\n");
}
uint32_t instanceVersion;
VkResult result = vkEnumerateInstanceVersion(&instanceVersion);
if (result == VK_SUCCESS) {
if (instanceVersion < VK_MAKE_API_VERSION(0, 1, 3, 0)) {
vk_log(VK_ERROR, "Vulkan version 1.3 or greater required!\n");
exit(1);
}
vk_log(VK_INFO, "Vulkan version found (%d) %d.%d.%d\n",
VK_API_VERSION_VARIANT(instanceVersion),
VK_API_VERSION_MAJOR(instanceVersion),
VK_API_VERSION_MINOR(instanceVersion),
VK_API_VERSION_PATCH(instanceVersion));
} else {
vk_log(VK_ERROR, "Failed to retrieve vulkan version, is vulkan supported in this system?\n");
exit(1);
}
// Load Vulkan and create instance
VkApplicationInfo appInfo = {
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
.pApplicationName = "Vulkan Application",
.applicationVersion = VK_MAKE_API_VERSION(0, 1, 3, 0),
.pEngineName = NULL,
.engineVersion = VK_MAKE_API_VERSION(0, 1, 3, 0),
.apiVersion = VK_MAKE_API_VERSION(0, 1, 3, 0),
};
uint32_t sdlExtensionCount = 0;
if (SDL_Vulkan_GetInstanceExtensions(window, &sdlExtensionCount, NULL) == SDL_FALSE) {
vk_log(VK_ERROR, "SDL_Vulkan_GetInstanceExtensions failed: %s\n", SDL_GetError());
}
// make space for debug extenetion
if (validation_layers_toggle) {
sdlExtensionCount++;
}
const char* sdlExtensions[sdlExtensionCount];
if (SDL_Vulkan_GetInstanceExtensions(window, &sdlExtensionCount, sdlExtensions) == SDL_FALSE) {
vk_log(VK_ERROR, "SDL_Vulkan_GetInstanceExtensions failed: %s\n", SDL_GetError());
}
// add debug extenetion
if (validation_layers_toggle) {
sdlExtensions[sdlExtensionCount] = VK_EXT_DEBUG_UTILS_EXTENSION_NAME;
}
vk_log(VK_INFO, "The sdl extensions:\n");
for (uint32_t i = 0; i < sdlExtensionCount; i++) {
vk_log(VK_INFO, "\t%s\n", sdlExtensions[i]);
}
VkInstanceCreateInfo createInfo = {
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
.pApplicationInfo = &appInfo,
.enabledExtensionCount = sdlExtensionCount,
.ppEnabledExtensionNames = sdlExtensions,
.enabledLayerCount = 0,
};
if (validation_layers_toggle) {
createInfo.enabledLayerCount = validation_layer_count;
createInfo.ppEnabledLayerNames = validation_layers;
}
VkInstance instance;
if (vkCreateInstance(&createInfo, NULL, &instance) != VK_SUCCESS) {
vk_log(VK_ERROR, "Can't start vulkan instance\n");
}
vk_log(VK_INFO, "Vulkan instance created\n");
return instance;
}
#endif /* VKSETUP_IMPLEMENTATION */