diff --git a/run.sh b/run.sh index e8a700e..980e7ca 100755 --- a/run.sh +++ b/run.sh @@ -1,6 +1,14 @@ #!/bin/bash -mkdir -p build -gcc `pkg-config --static --libs glfw3` -c src/window.c -o build/window.o -gcc `pkg-config --static --libs glfw3` build/window.o -o main src/main.c +echo "Building..." +rm -rf ./build +mkdir -p ./build +gcc -c src/log.c -o build/log.o || exit +gcc `pkg-config --static --libs glfw3` -c src/window.c -o build/window.o || exit +gcc `pkg-config --static --libs glfw3` \ + `pkg-config --static --libs vulkan` \ + build/log.o \ + build/window.o \ + -o main src/main.c || exit +echo "Done. Starting app..." ./main diff --git a/src/log.c b/src/log.c new file mode 100644 index 0000000..217f0d0 --- /dev/null +++ b/src/log.c @@ -0,0 +1,37 @@ +#include "log.h" +#include +#include +#include + +int logLevel = 0; + +// TODO +/*const char* timeStr() { + time_t now = time(NULL); + struct tm * p = localtime(&now); + char buffer[25]; + strftime(buffer, 25, "%Y-%m-%d %H:%M:%S", p); + //buffer[24] = '\0'; + const char* str = buffer; + return str; +}*/ + +void vkeSetLogLevel(int level) { + logLevel = level; +} + +void vkeLogDebug(const char* message) { + if(logLevel == 0) { + time_t now; + time(&now); + printf("%s [DEBUG] %s\n", ctime(&now), message); + } +} + +void vkeLogError(const char* message) { + if(logLevel > 0) { + time_t now; + time(&now); + printf("%s [ERROR] %s\n", ctime(&now), message); + } +} diff --git a/src/log.h b/src/log.h new file mode 100644 index 0000000..8923468 --- /dev/null +++ b/src/log.h @@ -0,0 +1,16 @@ +#ifndef VKE_LOG_H +#define VKE_LOG_H + +#define VKE_LOG_DEBUG = 0 +#define VKE_LOG_ERROR = 1 + +// Sets the global log level (VKE_LOG_DEBUG by default). +void vkeSetLogLevel(int level); + +// Logs the given message with the DEBUG tag. +void vkeLogDebug(const char* message); + +// Logs the given message with the ERROR tag. +void vkeLogError(const char* message); + +#endif diff --git a/src/main.c b/src/main.c index a2c850d..8e6e690 100644 --- a/src/main.c +++ b/src/main.c @@ -1,7 +1,97 @@ #include +#include +#include #include +#include +#include "log.h" #include "window.h" +struct VKEContext { + VkInstance instance; +}; + +struct VKEConfig { + const char* title; + int validationLayerCount; + const char** validationLayers; +}; + +bool vkeCheckValidationLayerSupport(const char** validationLayers, int n) { + if(n == 0) { + return true; + } + + uint32_t layerCount; + vkEnumerateInstanceLayerProperties(&layerCount, NULL); + VkLayerProperties availableLayers[layerCount]; + vkEnumerateInstanceLayerProperties(&layerCount, availableLayers); + + for(int i = 0; i < n; i++) { + bool layerFound = false; + + for(int j = 0; j < layerCount; j++) { + if(strcmp(validationLayers[i], availableLayers[j].layerName) == 0) { + layerFound = true; + break; + } + } + + if(!layerFound) { + // log supported validation layers + for(int j = 0; j < layerCount; j++) { + vkeLogDebug(availableLayers[j].layerName); + } + + return false; + } + } + + return true; +} + +int vkeInit(struct VKEContext* ctx, struct VKEConfig* config) { + if(!vkeCheckValidationLayerSupport(config->validationLayers, config->validationLayerCount)) { + vkeLogError("validation layer not supported\n"); + return -1; + } + + uint32_t glfwExtensionCount = 0; + const char** glfwExtensions; + glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount); + VkApplicationInfo appInfo = { + .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, + .pApplicationName = config->title, + .applicationVersion = VK_MAKE_VERSION(1, 0, 0), + .pEngineName = "No Engine", + .engineVersion = VK_MAKE_VERSION(1, 0, 0), + .apiVersion = VK_API_VERSION_1_0 + }; + VkInstanceCreateInfo createInfo = { + .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, + .enabledExtensionCount = glfwExtensionCount, + .ppEnabledExtensionNames = glfwExtensions, + .enabledLayerCount = 0, + .pApplicationInfo = &appInfo + }; + + // TODO + /*if(config->validationLayerCount > 0) { + createInfo.enabledLayerCount = config->validationLayerCount; + createInfo.ppEnabledExtensionNames = config->validationLayers; + }*/ + + if(vkCreateInstance(&createInfo, NULL, &ctx->instance) != VK_SUCCESS) { + vkeLogError("error creating vulkan instance\n"); + return -2; + } + + return 0; +} + +void vkeDestroy(struct VKEContext* ctx) { + vkDestroyInstance(ctx->instance, NULL); +} + void loop(GLFWwindow* window) { while(!glfwWindowShouldClose(window)) { // ... @@ -10,13 +100,30 @@ void loop(GLFWwindow* window) { } int main(int argc, const char *argv[]) { - GLFWwindow* window = vkeCreateWindow("Test", 800, 600); + vkeSetLogLevel(0); + const char* title = "Test"; + GLFWwindow* window = vkeCreateWindow(title, 800, 600); if(window == NULL) { return -1; } + struct VKEContext ctx; + const char* validationLayers[] = { + "VK_LAYER_KHRONOS_validation" + }; + struct VKEConfig config = { + .title = title, + .validationLayerCount = 1, + .validationLayers = validationLayers + }; + + if(vkeInit(&ctx, &config) != 0) { + return -1; + } + loop(window); vkeDestroyWindow(window); + vkeDestroy(&ctx); return 0; }