diff --git a/src/main.c b/src/main.c index 4e73a07..4f3fb41 100644 --- a/src/main.c +++ b/src/main.c @@ -1,25 +1,146 @@ #define GLFW_INCLUDE_VULKAN #include +#include #include +#include +#include +#include -int main() { +#define WIDTH 2560 +#define HEIGHT 1440 +#define VALIDATE true + +#define ARRSIZE(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x]))))) + +const char* validation_layers[] = { + "VK_LAYER_KHRONOS_validation", +}; + +typedef struct ApplicationState { + GLFWwindow* window; + //information about the connection between application and vulkan itself + VkInstance instance; +} ApplicationState; + +void create_window(ApplicationState* state) { glfwInit(); glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); - GLFWwindow* window = glfwCreateWindow(2560, 1440, "vulkan learning example", NULL, NULL); + state->window = glfwCreateWindow(WIDTH, HEIGHT, "vulkan learning example", NULL, NULL); +} + +//check if all of our validation layers are supported +bool check_validation_layer_support() { + uint32_t layer_count; + vkEnumerateInstanceLayerProperties(&layer_count, NULL); + + VkLayerProperties* available_layers = malloc(sizeof(VkLayerProperties) * layer_count); + vkEnumerateInstanceLayerProperties(&layer_count, available_layers); + + printf("supported validation layers:\n"); + for (int i = 0; i < layer_count; i++) { + printf("\t%s\n", available_layers[i].layerName); + } + + for (int i = 0; i < ARRSIZE(validation_layers); i++) { + bool found = false; + for (int j = 0; j < layer_count; j++) { + if (!strcmp(available_layers[j].layerName, validation_layers[i])) { + found = true; + } + } + + if (!found) { + return false; + } + } + + return true; +} + +//we first create an instance, filling it in with our application information. +void create_instance(ApplicationState* state) { + if (VALIDATE && !check_validation_layer_support()) { + printf("Requested validation layers but they're not supported"); + exit(1); + } + + VkApplicationInfo appinfo = {0}; + + appinfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; + appinfo.pApplicationName = "Vulkan learning triangle example"; + appinfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0); + appinfo.pEngineName = "No Engine"; + appinfo.engineVersion = VK_MAKE_VERSION(1, 0, 0); + appinfo.apiVersion = VK_API_VERSION_1_0; + + VkInstanceCreateInfo create_info = {0}; + create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; + create_info.pApplicationInfo = &appinfo; - uint32_t num_extensions = 0; - vkEnumerateInstanceExtensionProperties(NULL, &num_extensions, NULL); + //now let's require the global extensions that are required for GLFW to work + uint32_t glfw_extension_num = 0; + const char** glfw_extensions; - printf("number of supported extensions %Xh\n", num_extensions); + glfw_extensions = glfwGetRequiredInstanceExtensions(&glfw_extension_num); - while(!glfwWindowShouldClose(window)) { + create_info.enabledExtensionCount = glfw_extension_num; + create_info.ppEnabledExtensionNames = glfw_extensions; + + if (VALIDATE) { + create_info.enabledLayerCount = ARRSIZE(validation_layers); + create_info.ppEnabledLayerNames = validation_layers; + } else { + create_info.enabledLayerCount = 0; + } + + //now we actually create the instance + if (vkCreateInstance(&create_info, NULL, &state->instance) != VK_SUCCESS) { + printf("error creating instance\n"); + exit(1); + } + + printf("Instance successfully created\n"); + + //let's just list all supported vulkan instance extensions + uint32_t extension_num = 0; + vkEnumerateInstanceExtensionProperties(NULL, &extension_num, NULL); + VkExtensionProperties* extensions = malloc(sizeof(VkExtensionProperties) * extension_num); + vkEnumerateInstanceExtensionProperties(NULL, &extension_num, extensions); + + printf("instance extensions:\n"); + + for (int i = 0; i < extension_num; i++) { + printf("\t%s\n", extensions[i].extensionName); + } + + free(extensions); +} + +void init_vulkan(ApplicationState* state) { + create_instance(state); +} + +void main_loop(ApplicationState* state) { + while(!glfwWindowShouldClose(state->window)) { glfwPollEvents(); } +} - glfwDestroyWindow(window); +void terminate(ApplicationState* state) { + vkDestroyInstance(state->instance, NULL); + glfwDestroyWindow(state->window); glfwTerminate(); +} + +int main() { + ApplicationState state = {0}; + create_window(&state); + init_vulkan(&state); + + main_loop(&state); + terminate(&state); return 0; }