implemented vulkan instance creation

This commit is contained in:
Lorenzo Torres 2025-11-02 22:06:45 +01:00
parent 84ee267b5d
commit 89edee7249
11 changed files with 208 additions and 10 deletions

View file

@ -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

View file

@ -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}

View file

@ -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

6
rgfw.h
View file

@ -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
}

View file

@ -1,6 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause
#include <stdio.h>
#include "core/vector.h"
#include "platform.h"
int main(int argc, char **argv)

106
vk/instance.c Normal file
View file

@ -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);
}

8
vk/instance.h Normal file
View file

@ -0,0 +1,8 @@
#ifndef INSTANCE_H
#define INSTANCE_H
#include "../rendering/renderer.h"
void vk_instance_init(struct renderer_context *context);
#endif

0
vk/physical_device.c Normal file
View file

41
vk/platform.c Normal file
View file

@ -0,0 +1,41 @@
// SPDX-License-Identifier: BSD-3-Clause
#define RGFW_VULKAN
#define RGFW_IMPLEMENTATION
#include "../rgfw.h"
#include <vulkan/vulkan.h>
#include "../core/log.h"
#ifdef PLATFORM_MACOS
#include <vulkan/vulkan_macos.h>
#include <vulkan/vulkan_metal.h>
#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;
}

29
vk/renderer.c Normal file
View file

@ -0,0 +1,29 @@
// SPDX-License-Identifier: BSD-3-Clause
#include "../rendering/renderer.h"
#include <vulkan/vulkan.h>
#include "instance.h"
#include "vk.h"
#include <stdlib.h>
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;
}

10
vk/vk.h Normal file
View file

@ -0,0 +1,10 @@
#ifndef VK_H
#define VK_H
#include <vulkan/vulkan.h>
struct renderer_context {
VkInstance instance;
VkPhysicalDevice physical_device;
};
#endif