diff options
| author | kartofen <mladenovnasko0@gmail.com> | 2023-10-16 23:46:15 +0300 | 
|---|---|---|
| committer | kartofen <mladenovnasko0@gmail.com> | 2023-10-16 23:46:15 +0300 | 
| commit | 5e910c7e41d18dab95e34ceb6e620a8958197ae6 (patch) | |
| tree | bf49c8ca6dd123d0765beef63d5858445dcf24aa | |
things done
| -rw-r--r-- | Makefile | 83 | ||||
| -rw-r--r-- | files/shaders/shader1.frag | 7 | ||||
| -rw-r--r-- | files/shaders/shader1.vert | 10 | ||||
| -rw-r--r-- | src/common.c | 33 | ||||
| -rw-r--r-- | src/common.h | 34 | ||||
| -rw-r--r-- | src/device.c | 395 | ||||
| -rw-r--r-- | src/device.h | 33 | ||||
| -rw-r--r-- | src/main.c | 88 | ||||
| -rw-r--r-- | src/window.c | 36 | ||||
| -rw-r--r-- | src/window.h | 23 | 
10 files changed, 742 insertions, 0 deletions
| diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..0009173 --- /dev/null +++ b/Makefile @@ -0,0 +1,83 @@ +CC := gcc +GLSLC := glslc + +ifeq ($(PROD),1) +CFLAGS := -O2 # production flags +else +CFLAGS := -Wall -Wextra -Wpedantic -g -DDEBUG # debug flags +endif + +CFLAGS += -std=c99 -lm -lvulkan `sdl2-config --cflags --libs` + +SRCD := src +OBJD := obj +BIND := bin +FILD := files +SHDR := shaders + +SFILE = $(shell find $(SRCD)/ -type f 2> /dev/null) +CSRCS = $(filter %.c, $(SFILE)) +COBJS = $(CSRCS:$(SRCD)/%.c=$(OBJD)/%.o) + +FILES = $(shell find $(FILD) -type f 2> /dev/null) +SHDRS = $(filter %.vert %.frag, $(FILES)) +SHOBJ = $(SHDRS:$(FILD)/$(SHDR)/%=$(BIND)/$(SHDR)/%.spv) + +CDEPS = $(COBJS:%.o=%.d) +-include $(CDEPS) + +NAME := test + +all: clean $(NAME) +$(NAME): $(BIND)/$(NAME) $(SHOBJ) + +clean: +	rm -rf $(BIND) +	rm -rf $(OBJD) + +$(OBJD)/%.o: $(SRCD)/%.c +	@mkdir -p $(dir $@) +	$(CC) $(CFLAGS) -MMD -MF $(@:%.o=%.d) -c $< -o $@ + +$(BIND)/$(SHDR)/%.spv: $(FILD)/$(SHDR)/% +	@mkdir -p $(dir $@) +	$(GLSLC) $< -o $@ + +$(BIND)/$(NAME): $(COBJS) +	@mkdir -p $(dir $@) +	$(CC) $(CFLAGS) $^ -o $@ + +# Extra Tools + +RUN_CMD := $(BIND)/$(NAME) +UNITY := unity + +$(BIND)/$(UNITY): $(CSRCS) +	@mkdir -p $(dir $@) + +	for src in $^; do \ +		cat $${src} >> $(SRCD)/$(UNITY).c; \ +	done + +	$(CC) $(CFLAGS) $(SRCD)/$(UNITY).c -o $@ +	@rm $(SRCD)/$(UNITY).c + +analyze: clean +	scan-build \ +		-enable-checker alpha \ +		-enable-checker core \ +		-enable-checker deadcode \ +		-enable-checker security \ +		-enable-checker unix \ +		make $(BIND)/$(UNITY) + +sanitize: clean +	$(MAKE) CC="clang -fsanitize=address" run + +run: $(NAME) +	$(RUN_CMD) + +valgrind: all +	valgrind -s --leak-check=full --show-leak-kinds=all $(RUN_CMD) + + diff --git a/files/shaders/shader1.frag b/files/shaders/shader1.frag new file mode 100644 index 0000000..f30417b --- /dev/null +++ b/files/shaders/shader1.frag @@ -0,0 +1,7 @@ +#version 450 + +layout (location = 0) out vec4 outColor; + +void main() { +    outColor = vec4(1.0, 0.0, 0.0, 1.0); +} diff --git a/files/shaders/shader1.vert b/files/shaders/shader1.vert new file mode 100644 index 0000000..c5d117f --- /dev/null +++ b/files/shaders/shader1.vert @@ -0,0 +1,10 @@ +#version 450 + +vec2 positions[3] = vec2[]( +    vec2(0.0, -0.5), +    vec2(0.5, 0.5), +    vec2(-0.5, 0.5)); + +void main() { +    gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0); +} diff --git a/src/common.c b/src/common.c new file mode 100644 index 0000000..084c584 --- /dev/null +++ b/src/common.c @@ -0,0 +1,33 @@ +#include <string.h> +#include <errno.h> +#include "common.h" + +void *xmalloc(size_t size) +{ +    void *ret; +    if(!(ret = malloc(size))) { +        die("malloc: %s", strerror(errno)); +    } + +    return ret; +} + +void *xcalloc(size_t nmemb, size_t size) +{ +    void *ret; +    if(!(ret = calloc(nmemb, size))) { +        die("calloc: %s", strerror(errno)); +    } + +    return ret; +} + +void *xrealloc(void *ptr, size_t size) +{ +    void *ret; +    if(!(ret = realloc(ptr, size))) { +        die("realloc: %s", strerror(errno)); +    } + +    return ret; +} diff --git a/src/common.h b/src/common.h new file mode 100644 index 0000000..e10649a --- /dev/null +++ b/src/common.h @@ -0,0 +1,34 @@ +#ifndef LOG_H +#define LOG_H + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> + +#define ARR_SIZE(a) (sizeof(a)/sizeof(*(a))) + +#define __RED__    "\033[0;31m" +#define __GREEN__  "\033[0;32m" +#define __YELLOW__ "\033[0;33m" +#define __RESET__  "\033[0m" + +#define STR(x) #x +#define XSTR(x) STR(x) + +#define info(...) do { fprintf(stdout, __GREEN__"[INFO]"__RESET__"  "__VA_ARGS__); fprintf(stdout, "\n"); } while(0) +#define err(...)  do { fprintf(stderr, __RED__"[ERROR]"__RESET__" "__FILE__":"XSTR(__LINE__)": "__VA_ARGS__); fprintf(stderr, "\n"); } while(0) +#define warn(...) do { fprintf(stderr, __YELLOW__"[WARN]"__RESET__"  "__FILE__":"XSTR(__LINE__)": "__VA_ARGS__); fprintf(stderr, "\n"); } while(0) + +#define die(...) do {     \ +        err(__VA_ARGS__); \ +        abort();          \ +    } while(0) + +#define MAKE_VERSION(major, minor, patch) \ +    ((((uint32_t)(major)) << 22U) | (((uint32_t)(minor)) << 12U) | ((uint32_t)(patch))) + +void *xmalloc(size_t size); +void *xcalloc(size_t nmemb, size_t size); +void *xrealloc(void *ptr, size_t size); + +#endif diff --git a/src/device.c b/src/device.c new file mode 100644 index 0000000..fdcc7ad --- /dev/null +++ b/src/device.c @@ -0,0 +1,395 @@ +#include <string.h> +#include <vulkan/vulkan.h> + +#include "device.h" +#include "common.h" + +// TODO: rename device.c/.h +// TODO: add error checking +// TODO: add log output + +#ifdef DEBUG +char *validation_layers[] = { +    "VK_LAYER_KHRONOS_validation" +}; +#endif + +enum { +    QUEUE_FAMILY_COUNT = 2, +     +    QUEUE_FAMILY_GRAPHICS_FAMILY = 1 << 0, +    QUEUE_FAMILY_PRESENT_FAMILY  = 1 << 1, +     +    QUEUE_FAMILY_ALL = QUEUE_FAMILY_GRAPHICS_FAMILY | +                       QUEUE_FAMILY_PRESENT_FAMILY, +}; + +struct queue_family_idx { +    uint32_t graphics_family; +    uint32_t present_family; +}; + +// most function that return an int follow this scheme: +// 0 - success; 1 - error; (sometimes -1 - fatal error) + +// if the function has 'has' or 'is', then +// 0 - fail; 1 - success (sometimes -1 - fatal error) + +static int create_instance(device_t device, struct device_info *info); +static int create_surface(device_t device, struct device_info *info); +static int create_physical_device(device_t device, struct device_info *info); +static int create_logical_device(device_t device, struct device_info *info); + +static int is_device_suitable(VkPhysicalDevice phy_device, VkSurfaceKHR surface); + +// does not follow the general scheme, see implementation for details +static int find_queue_families(VkPhysicalDevice phy_device, VkSurfaceKHR surface, struct queue_family_idx *queue_family); + +#ifdef DEBUG +static int create_debug_messenger(device_t device, struct device_info* info); +static int has_validation_layer_support(const char * const *layers, uint32_t nlayers); +static void populate_debug_messenger_info(VkDebugUtilsMessengerCreateInfoEXT *info); + +VkResult CreateDebugUtilsMessengerEXT( +    VkInstance instance, +    const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, +    const VkAllocationCallbacks* pAllocator, +    VkDebugUtilsMessengerEXT* pDebugMessenger); +void DestroyDebugUtilsMessengerEXT( +    VkInstance instance, +    VkDebugUtilsMessengerEXT debugMessenger, +    const VkAllocationCallbacks* pAllocator); +static VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback( +    VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, +    VkDebugUtilsMessageTypeFlagsEXT messageType, +    const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, +    void* pUserData); +#endif + +#define CHECK(func) if(func(device, info)) { goto fail; } + +device_t device_create(struct device_info *info) +{ +    device_t device = xmalloc(sizeof(struct device)); +    +    CHECK(create_instance); +    CHECK(create_surface); +#ifdef DEBUG +    CHECK(create_debug_messenger); +#endif +    CHECK(create_physical_device); +    CHECK(create_logical_device); +     +    return device;     +fail: +    device_destroy(device); +    return NULL; +} + +void device_destroy(device_t device) +{ +    if(!device) return; + +    vkDestroyDevice(device->logical_device, NULL); +     +    #ifdef DEBUG +    DestroyDebugUtilsMessengerEXT(device->instance, device->debug_messenger, NULL); +    #endif + +    vkDestroySurfaceKHR(device->instance, device->surface, NULL); + +    vkDestroyInstance(device->instance, NULL); +     +    free(device); +} + +static int create_instance(device_t device, struct device_info *info) +{ +    VkApplicationInfo app_info = {0}; +    app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; +    app_info.pEngineName = "Engine"; +    app_info.engineVersion = VK_MAKE_VERSION(1, 0, 0); +    app_info.apiVersion = VK_API_VERSION_1_0; + +    app_info.pApplicationName = info->name; +    app_info.applicationVersion = info->version; + +    VkInstanceCreateInfo create_info = {0}; +    create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; +    create_info.pApplicationInfo = &app_info; +    create_info.enabledLayerCount = 0; +             +#ifdef DEBUG +    // add debug utils extensions for debug callback +    char **extensions = xcalloc(info->ext_count+1, sizeof(char *)); +    extensions[info->ext_count] = VK_EXT_DEBUG_UTILS_EXTENSION_NAME; +         +    for(uint32_t i = 0; i < info->ext_count; i++) { +        extensions[i] = (char *)info->extensions[i]; +    } +         +    free((void *)info->extensions); +         +    // we just added one more extension +    create_info.enabledExtensionCount = info->ext_count+1; +    create_info.ppEnabledExtensionNames = (const char * const *)extensions; + +    // validation layer support +    char *validation_layers[] = { +        "VK_LAYER_KHRONOS_validation" +    }; +     +    uint32_t nlayers = ARR_SIZE(validation_layers); + +    if(!has_validation_layer_support((const char * const *)validation_layers, nlayers)) { +        err("validation_layer_support: failed"); +        goto fail; +    } +         +    create_info.ppEnabledLayerNames = (const char * const *)validation_layers; +    create_info.enabledLayerCount = nlayers; + +    // add the debug messenger for instance creation and destruction +    VkDebugUtilsMessengerCreateInfoEXT msg_info = {0}; +    populate_debug_messenger_info(&msg_info); +         +    create_info.pNext = &msg_info; +#endif  + +    if(vkCreateInstance(&create_info, NULL, &device->instance) != VK_SUCCESS) { +        err("vkCreateInstance: failed"); +        goto fail; +    } +     +#ifdef DEBUG +    free(extensions); +#endif + +    return 0; +fail: +    return 1; +} + +static int create_surface(device_t device, struct device_info *info) +{ +    if(info->surface_func(device->instance, &device->surface)) { +        err("Couldn't create a VkSurfaceKHR"); +        return 1; +    } +     +    return 0; +} + +static int create_physical_device(device_t device, struct device_info *info) +{ +    (void)info; +         +    device->physical_device = VK_NULL_HANDLE; +     +    uint32_t dev_count = 0; +    vkEnumeratePhysicalDevices(device->instance, &dev_count, NULL); + +    if(dev_count == 0) { +        err("No physical devices could be found!"); +        goto fail; +    } + +    VkPhysicalDevice *devices = xcalloc(dev_count, sizeof(VkPhysicalDevice)); +    vkEnumeratePhysicalDevices(device->instance, &dev_count, devices); + +    for(uint32_t i = 0; i < dev_count; i++) { +        if(is_device_suitable(devices[i], device->surface)) { +            device->physical_device = devices[i]; +            break; +        } +    } + +    free(devices); + +    if(device->physical_device == VK_NULL_HANDLE) { +        err("No suitable physical device could be found"); +        goto fail; +    } +     +    return 0; +fail: +    return 1; +} + +static int create_logical_device(device_t device, struct device_info *info) +{ +    (void)info; + +    // queue family data +    struct queue_family_idx indices = {0}; +    find_queue_families(device->physical_device, device->surface, &indices); + +    // queue infos +    VkDeviceQueueCreateInfo *queue_infos = xcalloc(QUEUE_FAMILY_COUNT, sizeof(VkDeviceQueueCreateInfo)); +    memset(queue_infos, 0, QUEUE_FAMILY_COUNT * sizeof(VkDeviceQueueCreateInfo)); +     +    uint32_t *queue_indices = xcalloc(QUEUE_FAMILY_COUNT, sizeof(uint32_t)); +    queue_indices[0] = indices.graphics_family; +    queue_indices[1] = indices.present_family; + +    float queue_priority = 1.0f; +    for(int i = 0; i < QUEUE_FAMILY_COUNT; i++) +    { +        queue_infos[i].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; +        queue_infos[i].queueFamilyIndex = queue_indices[i]; +        queue_infos[i].queueCount = 1; +        queue_infos[i].pQueuePriorities = &queue_priority; +    } + +    // device features +    VkPhysicalDeviceFeatures device_features = {0}; + +    // logical device create info +    VkDeviceCreateInfo create_info = {0}; +    create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; +     +    create_info.pQueueCreateInfos = queue_infos; +    create_info.queueCreateInfoCount = QUEUE_FAMILY_COUNT; + +    create_info.pEnabledFeatures = &device_features; +     +    create_info.enabledExtensionCount = 0; +  +    // validation layers can be set, but +    // newer implementations will ignore them +    // so i wont bother adding them +    create_info.enabledLayerCount = 0; + +    if(vkCreateDevice(device->physical_device, &create_info, NULL, &device->logical_device) != VK_SUCCESS) { +        err("vkCreateDevice: failed"); +        goto fail; +    } + +    // vkGetDeviceQueue(device->logical_device, indices.graphics_family, 0, &device->graphics_queue); + +    free(queue_infos); +    free(queue_indices); + +    return 0; +fail: +    return 1; +} + +// returns a bitmask if a given family is set, or not +static int find_queue_families(VkPhysicalDevice phy_device, VkSurfaceKHR surface, struct queue_family_idx *queue_family) +{ +    int ret = 0; +     +    uint32_t count = 0; +    vkGetPhysicalDeviceQueueFamilyProperties(phy_device, &count, NULL); + +    VkQueueFamilyProperties *properties = xcalloc(count, sizeof(VkQueueFamilyProperties)); +    vkGetPhysicalDeviceQueueFamilyProperties(phy_device, &count, properties); + +    for(uint32_t i = 0; i < count; i++) { +        if(properties[i].queueFlags & VK_QUEUE_COMPUTE_BIT) { +            ret |= QUEUE_FAMILY_GRAPHICS_FAMILY; +            if(queue_family != NULL) { +                queue_family->graphics_family = i; +            } +        } + +        VkBool32 present_support = 0; +        vkGetPhysicalDeviceSurfaceSupportKHR(phy_device, i, surface, &present_support); +        if(present_support) { +            ret |= QUEUE_FAMILY_PRESENT_FAMILY; +            if(queue_family != NULL){ +                queue_family->present_family = i; +            } +        } +    } + +    free(properties); +    return ret; +} + +static int is_device_suitable(VkPhysicalDevice phy_device, VkSurfaceKHR surface) +{ +    if(find_queue_families(phy_device, surface, NULL) == QUEUE_FAMILY_ALL) { +        return 1; +    } + +    return 0; +} + + +#ifdef DEBUG + +static int create_debug_messenger(device_t device, struct device_info *info) +{ +    (void)info; +     +    VkDebugUtilsMessengerCreateInfoEXT cinfo = {0}; +    populate_debug_messenger_info(&cinfo); + +    if(CreateDebugUtilsMessengerEXT(device->instance, &cinfo, NULL, &device->debug_messenger) != VK_SUCCESS) { +        info("CreateDebugUtilMessengerEXT: failed"); +        return 1; +    } + +    return 0; +} + +static void populate_debug_messenger_info(VkDebugUtilsMessengerCreateInfoEXT *info) +{ +    info->sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; +    info->messageSeverity = +        VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | +        VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | +        VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; +    info->messageType = +        VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | +        VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | +        VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT; +    info->pfnUserCallback = debug_callback; +} + +static int has_validation_layer_support(const char * const *layers, uint32_t nlayers) +{ +    (void)layers; +    (void)nlayers; +     +    // uint32_t navaliable = 0; +    // vkEnumerateInstanceLayerProperties(&navaliable, NULL); + +    // VkLayerProperties *available_layers = xcalloc(navaliable, sizeof(VkLayerProperties)); +    // vkEnumerateInstanceLayerProperties(&navaliable, available_layers); +    return 1; +} + +static VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback( +    VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, +    VkDebugUtilsMessageTypeFlagsEXT messageType, +    const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, +    void* pUserData) +{ +    (void)messageSeverity; +    (void)messageType; +    (void)pUserData; +     +    warn("Validation Layer: %s", pCallbackData->pMessage); +    return VK_FALSE; +} + +VkResult CreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugUtilsMessengerEXT* pDebugMessenger) { +    PFN_vkCreateDebugUtilsMessengerEXT f = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT"); +    if (f != NULL) { +        return f(instance, pCreateInfo, pAllocator, pDebugMessenger); +    } else { +        return VK_ERROR_EXTENSION_NOT_PRESENT; +    } +} + +void DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT debugMessenger, const VkAllocationCallbacks* pAllocator) { +    PFN_vkDestroyDebugUtilsMessengerEXT f = (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT"); +    if (f != NULL) { +        f(instance, debugMessenger, pAllocator); +    } +} + +#endif diff --git a/src/device.h b/src/device.h new file mode 100644 index 0000000..d6768e1 --- /dev/null +++ b/src/device.h @@ -0,0 +1,33 @@ +#ifndef DEVICE_H +#define DEVICE_H + +#include <vulkan/vulkan.h> +#include "common.h" + +typedef struct device { +    VkInstance instance; +    VkDebugUtilsMessengerEXT debug_messenger; +     +    VkPhysicalDevice physical_device;     +    VkDevice logical_device; +    VkQueue graphics_queue; + +    VkSurfaceKHR surface; +} * device_t; + +typedef int (*surface_func_t)(VkInstance instance, VkSurfaceKHR *surface); + +struct device_info { +    char *name; +    uint32_t version; +     +    const char* const* extensions; +    uint32_t ext_count; + +    surface_func_t surface_func; +}; + +device_t device_create(struct device_info *info); +void device_destroy(device_t device); + +#endif diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..90985be --- /dev/null +++ b/src/main.c @@ -0,0 +1,88 @@ +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> + +#include "device.h" +#include "window.h" +#include "common.h" + +// TODO: rename device.c/.h +// TODO: fix fail gotos + +window_t window; +device_t device; + +int _create_surface(VkInstance instance, VkSurfaceKHR *surface); + +int main(void) +{ +    int ret = 1; + +    if(SDL_Init(0)) { +        err("SDL_Init: failed"); +        goto sf; +    } + +    // populate window info +    struct window_info win_info = {0}; +    win_info.title = "Test App"; +    win_info.w = 1200; +    win_info.h = 800; +     +    // create window +    window = window_create(&win_info); +    if(!window) { +        err("window_create: failed"); +        goto wf; +    } +     +    // get extensions +    unsigned int ext_count = 0; +    window_extension_info(window, &ext_count, NULL); +     +    // populate the device info +    struct device_info dev_info = {0}; +    dev_info.name = "Test App"; +    dev_info.version = MAKE_VERSION(1, 0, 0); + +    if(ext_count == 0){ +        dev_info.ext_count = 0; +        dev_info.extensions = NULL; +    } else { +        char **extensions = xcalloc(ext_count, sizeof(char *)); +        window_extension_info(window, &ext_count, (const char **)extensions); +     +        dev_info.ext_count = ext_count; +        dev_info.extensions = (const char * const *)extensions; +    } + +    dev_info.surface_func = _create_surface; + +    // create the device +    device = device_create(&dev_info); +    if(!device) { +        err("device_create: failed"); +        goto df; +    } +     +    int running = 1; +    while(running) { +        SDL_Event windowEvent; +        while(SDL_PollEvent(&windowEvent)) +            if(windowEvent.type == SDL_QUIT) { +                running = 0; +                break; +            } +    } +     +    ret = 0; +df: device_destroy(device); +wf: window_destroy(window); +sf: SDL_Quit(); +    return ret; +} + +int _create_surface(VkInstance instance, VkSurfaceKHR *surface) +{ +    return window_create_surface(window, instance, surface); +} diff --git a/src/window.c b/src/window.c new file mode 100644 index 0000000..4a498e6 --- /dev/null +++ b/src/window.c @@ -0,0 +1,36 @@ +#include "window.h" +#include "common.h" + +window_t window_create(struct window_info *info) +{ +    info->flags |= SDL_WINDOW_SHOWN | SDL_WINDOW_VULKAN; +    SDL_Vulkan_LoadLibrary(NULL); +     +    window_t window = SDL_CreateWindow(info->title, info->x, info->y, +                                       info->w, info->h, info->flags); +    return window; +} + +void window_destroy(window_t window) +{ +    SDL_DestroyWindow((SDL_Window *)window); +    SDL_Vulkan_UnloadLibrary(); +} + +int window_extension_info(window_t window, unsigned int *ext_count, const char **extensions) +{ +    if(SDL_Vulkan_GetInstanceExtensions((SDL_Window *)window, ext_count, extensions) == SDL_FALSE) { +        return 1; +    } +     +    return 0; +} + +int window_create_surface(window_t window, VkInstance instance, VkSurfaceKHR *surface) +{ +    if(SDL_Vulkan_CreateSurface((SDL_Window *)window, instance, surface) == SDL_FALSE) { +        return 1; +    } +     +    return 0; +} diff --git a/src/window.h b/src/window.h new file mode 100644 index 0000000..01ecbb3 --- /dev/null +++ b/src/window.h @@ -0,0 +1,23 @@ +#ifndef WINDOW_H +#define WINDOW_H + +#include <SDL2/SDL.h> +#include <SDL2/SDL_vulkan.h> +#include <vulkan/vulkan.h> + +typedef SDL_Window * window_t; + +struct window_info { +    char *title; +    int x; int y; +    int w; int h; +    Uint32 flags; +}; + +window_t window_create(struct window_info *info); +void window_destroy(window_t window); + +int window_extension_info(window_t window, unsigned int *ext_count, const char **extensions); +int window_create_surface(window_t window, VkInstance instance, VkSurfaceKHR *surface); + +#endif | 
