summaryrefslogblamecommitdiffstats
path: root/src/vksetup.h
blob: 2feb533d1188d0a3400087e490e4c66e8ce5b0df (plain) (tree)























































































































































































































                                                                                                                                                                          
#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 */