From 89edee7249764e329b3f662d6a1706bd79c7f062 Mon Sep 17 00:00:00 2001 From: Lorenzo Torres Date: Sun, 2 Nov 2025 22:06:45 +0100 Subject: [PATCH] implemented vulkan instance creation --- config.mk | 6 +-- makefile | 3 +- rendering/renderer.h | 8 ++-- rgfw.h | 6 ++- topaz.c | 1 + vk/instance.c | 106 +++++++++++++++++++++++++++++++++++++++++++ vk/instance.h | 8 ++++ vk/physical_device.c | 0 vk/platform.c | 41 +++++++++++++++++ vk/renderer.c | 29 ++++++++++++ vk/vk.h | 10 ++++ 11 files changed, 208 insertions(+), 10 deletions(-) create mode 100644 vk/instance.c create mode 100644 vk/instance.h create mode 100644 vk/physical_device.c create mode 100644 vk/platform.c create mode 100644 vk/renderer.c create mode 100644 vk/vk.h diff --git a/config.mk b/config.mk index f425614..a4724b6 100644 --- a/config.mk +++ b/config.mk @@ -1,10 +1,10 @@ # SPDX-License-Identifier: BSD-3-Clause CC := cc -CFLAGS := -Wall -Wextra -std=c99 -pedantic -ggdb -O2 +CFLAGS := -Wall -Wextra -std=c99 -pedantic -ggdb -O2 -DDEBUG LIBS := -lm # can be gl or vk -BACKEND := gl +BACKEND := vk PLATFORM := $(shell uname) @@ -22,7 +22,7 @@ endif ifeq (${PLATFORM},Darwin) CFLAGS += -DPLATFORM_MACOS - LIBS += -framework Cocoa -framework CoreVideo -framework IOKit + LIBS += -framework Cocoa -framework CoreVideo -framework Metal -framework IOKit else ifeq (${PLATFORM},Linux) CFLAGS += -DPLATFORM_LINUX endif diff --git a/makefile b/makefile index 688a2ad..4eab902 100644 --- a/makefile +++ b/makefile @@ -14,7 +14,8 @@ ifeq (${BACKEND},gl) endif ifeq (${BACKEND},vk) SRC += vk/platform.c\ - vk/renderer.c + vk/renderer.c\ + vk/instance.c endif OBJ:=${SRC:.c=.o} diff --git a/rendering/renderer.h b/rendering/renderer.h index fc7dc31..7e59dd4 100644 --- a/rendering/renderer.h +++ b/rendering/renderer.h @@ -11,9 +11,9 @@ struct mesh { struct renderer_context; -struct renderer_context *renderer_create_context(void); -struct mesh renderer_build_chunk_mesh(); -void renderer_draw_mesh(struct mesh); -void renderer_draw_chunk(struct mesh); +struct renderer_context *renderer_context_init(void); +struct mesh *renderer_build_chunk_mesh(void); +void renderer_draw_mesh(struct mesh mesh); +void renderer_draw_chunk(struct mesh mesh); #endif diff --git a/rgfw.h b/rgfw.h index 1ca98f3..5e5f44d 100644 --- a/rgfw.h +++ b/rgfw.h @@ -2379,7 +2379,7 @@ RGFWDEF RGFW_bool RGFW_extensionSupportedPlatform_EGL(const char* extension, siz * @param count [OUTPUT] A pointer that will receive the number of required extensions (typically 2). * @return A pointer to a static array of required Vulkan instance extension names. */ -RGFWDEF const char** RGFW_getRequiredInstanceExtensions_Vulkan(size_t* count); +const char** RGFW_getRequiredInstanceExtensions_Vulkan(size_t* count); /**! * @brief Creates a Vulkan surface for the specified window. @@ -4613,7 +4613,7 @@ VkResult RGFW_window_createSurface_Vulkan(RGFW_window* win, VkInstance instance, return vkCreateWin32SurfaceKHR(instance, &win32, NULL, surface); #elif defined(RGFW_MACOS) && !defined(RGFW_MACOS_X11) void* contentView = ((void* (*)(id, SEL))objc_msgSend)((id)win->src.window, sel_getUid("contentView")); - VkMacOSSurfaceCreateSurfaceMVK macos = { VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK, 0, 0, 0, (void*)contentView }; + VkMacOSSurfaceCreateInfoMVK macos = { VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK, 0, 0, (void*)contentView }; return vkCreateMacOSSurfaceMVK(instance, &macos, NULL, surface); #endif } @@ -4634,6 +4634,8 @@ RGFW_bool RGFW_getPresentationSupport_Vulkan(VkInstance instance, VkPhysicalDevi return wlout; #elif defined(RGFW_WINDOWS) #elif defined(RGFW_MACOS) && !defined(RGFW_MACOS_X11) + (void) physicalDevice; + (void) queueFamilyIndex; return RGFW_FALSE; /* TODO */ #endif } diff --git a/topaz.c b/topaz.c index b2dd92d..bdf4d41 100644 --- a/topaz.c +++ b/topaz.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: BSD-3-Clause #include +#include "core/vector.h" #include "platform.h" int main(int argc, char **argv) diff --git a/vk/instance.c b/vk/instance.c new file mode 100644 index 0000000..25340d2 --- /dev/null +++ b/vk/instance.c @@ -0,0 +1,106 @@ +#include "instance.h" +#include "../core/log.h" +#define RGFW_VULKAN +#include "../rgfw.h" +#include "vk.h" + +const char *extensions[] = { +#ifdef PLATFORM_MACOS + VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME, + VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME +#endif +}; + +#ifdef DEBUG +const char *layers[] = { + "VK_LAYER_KHRONOS_validation" +}; +#define LAYER_COUNT (sizeof(layers)/sizeof(layers[0])) +#else +#define LAYER_COUNT 0 +const char *layers[] = {NULL}; +#endif + +/* + * Vulkan is modular by design. This means that + * some features that might not be always needed + * are not enabled by default. To enable those + * features (like macOS platform compatibility + * or windowing) extensions are needed. This + * function checks which extensions are required + * by RGFW and adds extensions required by the + * game itself. + */ +const char **vk_instance_extensions(usize *count) +{ + usize rgfw_extension_count = 0; + const char **rgfw_extensions = RGFW_getRequiredInstanceExtensions_Vulkan(&rgfw_extension_count); + + usize extension_count = sizeof(extensions)/sizeof(extensions[0]); + *count = rgfw_extension_count + extension_count; + const char **instance_extensions = malloc(*count * sizeof(char *)); + + #ifdef DEBUG + log_info("Required Vulkan extensions: "); + #endif + + for (usize i = 0; i < rgfw_extension_count; i++) { + #ifdef DEBUG + printf("%s ", rgfw_extensions[i]); + #endif + instance_extensions[i] = rgfw_extensions[i]; + } + + for (usize i = 0; i < extension_count; i++) { + #ifdef DEBUG + printf("%s ", extensions[i]); + #endif + instance_extensions[rgfw_extension_count + i] = extensions[i]; + } + + #ifdef DEBUG + printf("\n"); + #endif + + return instance_extensions; +} + +void vk_instance_init(struct renderer_context *context) +{ + VkApplicationInfo application_info = { + .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, + .pApplicationName = "topaz", + .applicationVersion = 0, + .pEngineName = "topaz", + .engineVersion = 0, + .apiVersion = VK_API_VERSION_1_4 + }; + + usize extension_count = 0; + const char **extension_names = vk_instance_extensions(&extension_count); + + VkInstanceCreateInfo instance_info = { + .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, + .pApplicationInfo = &application_info, + .flags = VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR, + .enabledLayerCount = LAYER_COUNT, + .ppEnabledLayerNames = layers, + .enabledExtensionCount = extension_count, + .ppEnabledExtensionNames = extension_names, + }; + + VkResult result = vkCreateInstance(&instance_info, NULL, &context->instance); + switch(result) { + case VK_ERROR_INCOMPATIBLE_DRIVER: + fatal("Incompatible driver.\n"); + case VK_ERROR_LAYER_NOT_PRESENT: + fatal("Requested vulkan layers are not present.\n"); + case VK_SUCCESS: + log_info("Vulkan instance created.\n"); + break; + default: + fatal("Can't create Vulkan instance.\n"); + } + + free(extension_names); +} diff --git a/vk/instance.h b/vk/instance.h new file mode 100644 index 0000000..729c778 --- /dev/null +++ b/vk/instance.h @@ -0,0 +1,8 @@ +#ifndef INSTANCE_H +#define INSTANCE_H + +#include "../rendering/renderer.h" + +void vk_instance_init(struct renderer_context *context); + +#endif diff --git a/vk/physical_device.c b/vk/physical_device.c new file mode 100644 index 0000000..e69de29 diff --git a/vk/platform.c b/vk/platform.c new file mode 100644 index 0000000..de73672 --- /dev/null +++ b/vk/platform.c @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#define RGFW_VULKAN +#define RGFW_IMPLEMENTATION +#include "../rgfw.h" +#include +#include "../core/log.h" + +#ifdef PLATFORM_MACOS +#include +#include +#endif + +#include "../rendering/renderer.h" + +/* + * This function is the entrypoint for the whole + * game. Its role is to initialize Vulkan, create + * the renderer and start the game loop. + */ +int platform_run(i32 argc, u8 **argv) +{ + (void) argc; + (void) argv; + + log_info("Using Vulkan as rendering backend.\n"); + + RGFW_window* win = RGFW_createWindow("topaz", 0, 0, 800, 600, RGFW_windowCenter | RGFW_windowNoResize | RGFW_windowHide); + RGFW_window_show(win); + RGFW_window_setExitKey(win, RGFW_escape); + + struct renderer_context *context = renderer_context_init(); + + while (RGFW_window_shouldClose(win) == RGFW_FALSE) { + RGFW_event event; + while (RGFW_window_checkEvent(win, &event)); + } + + RGFW_window_close(win); + return 0; +} diff --git a/vk/renderer.c b/vk/renderer.c new file mode 100644 index 0000000..8381d3c --- /dev/null +++ b/vk/renderer.c @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: BSD-3-Clause +#include "../rendering/renderer.h" +#include +#include "instance.h" +#include "vk.h" +#include + +struct renderer_context *renderer_context_init(void) +{ + struct renderer_context *context = (struct renderer_context *) malloc(sizeof(struct renderer_context)); + + vk_instance_init(context); + return context; +} + +struct mesh *renderer_build_chunk_mesh(void) +{ + return NULL; +} + +void renderer_draw_mesh(struct mesh mesh) +{ + (void) mesh; +} + +void renderer_draw_chunk(struct mesh mesh) +{ + (void) mesh; +} diff --git a/vk/vk.h b/vk/vk.h new file mode 100644 index 0000000..5454737 --- /dev/null +++ b/vk/vk.h @@ -0,0 +1,10 @@ +#ifndef VK_H +#define VK_H + +#include +struct renderer_context { + VkInstance instance; + VkPhysicalDevice physical_device; +}; + +#endif