ref, feat: Restructure
- The renderer backend is now its own library, loaded at runtime. - Removed GLFW dependency, instead use win32 directly. - Broke linux window creation, because it's not implemented yet. - Maybe use GLFW for linux?
This commit is contained in:
parent
63e3f973b2
commit
81798df3e9
@ -1,60 +0,0 @@
|
|||||||
#ifndef VY_FIO_H
|
|
||||||
#define VY_FIO_H
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include "voyage.h"
|
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
VY_FILE_BUFFER_FLAG_FILE_NOT_FOUND = 0x1,
|
|
||||||
VY_FILE_BUFFER_FLAG_READ_FAILED = 0x2,
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
void *data;
|
|
||||||
size_t size;
|
|
||||||
uint32_t flags;
|
|
||||||
} vy_file_buffer;
|
|
||||||
|
|
||||||
inline bool vyWasFileBufferSuccessful(const vy_file_buffer *fb) {
|
|
||||||
return fb->flags == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* used to identify a file (XXH3 hash of the path) */
|
|
||||||
typedef uint64_t vy_file_id;
|
|
||||||
|
|
||||||
typedef unsigned int vy_fio_handle;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
unsigned int queue_size;
|
|
||||||
unsigned int max_file_count;
|
|
||||||
} vy_fio_config;
|
|
||||||
|
|
||||||
bool vyInitFIO(const vy_fio_config *config);
|
|
||||||
|
|
||||||
void vyShutdownFIO(void);
|
|
||||||
|
|
||||||
vy_file_id vyGetFileId(const char *path);
|
|
||||||
|
|
||||||
vy_file_id vyGetFileIdFromSpan(vy_text_span path);
|
|
||||||
|
|
||||||
vy_file_id vyAddFile(const char *path);
|
|
||||||
|
|
||||||
vy_file_id vyAddFileFromSpan(vy_text_span path);
|
|
||||||
|
|
||||||
const char *vyGetFilePath(vy_file_id fid);
|
|
||||||
|
|
||||||
vy_fio_handle vyEnqueueRead(vy_file_id fid);
|
|
||||||
|
|
||||||
void vyAbortFIO(vy_fio_handle fio);
|
|
||||||
|
|
||||||
bool vyIsFIOFinished(vy_fio_handle fio);
|
|
||||||
|
|
||||||
bool vyRetrieveReadBuffer(vy_fio_handle fio, vy_file_buffer *buffer);
|
|
||||||
|
|
||||||
void vyFreeFileBuffer(vy_file_buffer buffer);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,29 +0,0 @@
|
|||||||
#ifndef VY_GFX_BACKEND_H
|
|
||||||
#define VY_GFX_BACKEND_H
|
|
||||||
|
|
||||||
/* Backend functions and types. */
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
#include "gfx.h"
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
const char *compute_source;
|
|
||||||
size_t compute_source_length;
|
|
||||||
} vy_compute_pipeline_info;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
const char *vertex_source;
|
|
||||||
size_t vertex_source_length;
|
|
||||||
|
|
||||||
const char *fragment_source;
|
|
||||||
size_t fragment_source_length;
|
|
||||||
} vy_graphics_pipeline_info;
|
|
||||||
|
|
||||||
vy_gfx_pipeline_id
|
|
||||||
vyCompileComputePipeline(const vy_compute_pipeline_info *info);
|
|
||||||
|
|
||||||
vy_gfx_pipeline_id
|
|
||||||
vyCompileGraphicsPipeline(const vy_graphics_pipeline_info *info);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,18 +0,0 @@
|
|||||||
#ifndef VY_THREADING_H
|
|
||||||
#define VY_THREADING_H
|
|
||||||
|
|
||||||
/* platform independent threading */
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
typedef struct vy_mutex_s vy_mutex;
|
|
||||||
|
|
||||||
vy_mutex *vyCreateMutex(void);
|
|
||||||
|
|
||||||
void vyDestroyMutex(vy_mutex *mutex);
|
|
||||||
|
|
||||||
bool vyLockMutex(vy_mutex *mutex);
|
|
||||||
|
|
||||||
bool vyUnlockMutex(vy_mutex *mutex);
|
|
||||||
|
|
||||||
#endif
|
|
74
meson.build
74
meson.build
@ -22,42 +22,64 @@ elif compiler.get_argument_syntax() == 'msvc'
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
# Debug specific flags
|
# Debug specific flags
|
||||||
if buildtype == 'debug'
|
if buildtype == 'debug' or buildtype == 'debugoptimized'
|
||||||
add_project_arguments([ '-DDEBUG'], language : 'c')
|
add_project_arguments([ '-DDEBUG'], language : 'c')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# "Select" renderer backend
|
|
||||||
# Currently only OpenGL is supported
|
|
||||||
add_project_arguments([ '-DRENDERER_GL'], language : 'c')
|
|
||||||
|
|
||||||
# Gather dependencies
|
# Gather dependencies
|
||||||
thread_dep = dependency('threads')
|
thread_dep = dependency('threads')
|
||||||
m_dep = compiler.find_library('m', required : false)
|
m_dep = compiler.find_library('m', required : false)
|
||||||
glfw_proj = subproject('glfw', default_options : 'default_library=static')
|
vk_dep = dependency('vulkan', required : false)
|
||||||
glfw_dep = glfw_proj.get_variable('glfw_dep')
|
|
||||||
|
|
||||||
incdir = include_directories(['contrib', 'include'])
|
# glfw_proj = subproject('glfw', default_options : 'default_library=static')
|
||||||
|
# glfw_dep = glfw_proj.get_variable('glfw_dep')
|
||||||
|
|
||||||
executable('voyage',
|
incdir = include_directories(['contrib', 'src'])
|
||||||
|
|
||||||
|
runtime_lib = library('vyrt',
|
||||||
# Project Sources
|
# Project Sources
|
||||||
'include/voyage.h',
|
'src/runtime/runtime.h',
|
||||||
'include/gfx.h',
|
'src/runtime/gfx.h',
|
||||||
'include/gfx_backend.h',
|
'src/runtime/renderer_api.h',
|
||||||
'include/fio.h',
|
'src/runtime/fio.h',
|
||||||
'include/config.h',
|
'src/runtime/config.h',
|
||||||
'include/threading.h',
|
'src/runtime/threading.h',
|
||||||
|
'src/runtime/app.h',
|
||||||
|
'src/runtime/dynamic_libs.h',
|
||||||
|
|
||||||
'src/voyage.c',
|
'src/runtime/error_report.c',
|
||||||
'src/fio.c',
|
'src/runtime/gfx_main.c',
|
||||||
'src/error_report.c',
|
'src/runtime/gfx_shader_loading.c',
|
||||||
'src/gfx_main.c',
|
'src/runtime/config.c',
|
||||||
'src/gfx_shader_loading.c',
|
'src/runtime/runtime_cvars.c',
|
||||||
'src/gfx_pipelines.c',
|
'src/runtime/threading.c',
|
||||||
'src/config.c',
|
'src/runtime/fio.c',
|
||||||
'src/threading.c',
|
'src/runtime/app.c',
|
||||||
|
'src/runtime/dynamic_libs.c',
|
||||||
|
|
||||||
# Contrib Sources
|
# Contrib Sources
|
||||||
'contrib/glad/glad.c',
|
|
||||||
'contrib/xxhash/xxhash.c',
|
'contrib/xxhash/xxhash.c',
|
||||||
dependencies : [thread_dep, m_dep, glfw_dep],
|
dependencies : [thread_dep, m_dep],
|
||||||
include_directories: incdir)
|
include_directories : incdir,
|
||||||
|
c_pch : 'pch/rt_pch.h')
|
||||||
|
|
||||||
|
if vk_dep.found()
|
||||||
|
vk_renderer_lib = library('vyvk',
|
||||||
|
# Project Sources
|
||||||
|
'src/renderer/vk/gpu.h',
|
||||||
|
|
||||||
|
'src/renderer/vk/init.c',
|
||||||
|
'src/renderer/vk/gfx_pipelines.c',
|
||||||
|
dependencies : [m_dep, vk_dep],
|
||||||
|
include_directories : incdir,
|
||||||
|
link_with : [runtime_lib],
|
||||||
|
c_pch : 'pch/vk_pch.h')
|
||||||
|
endif
|
||||||
|
|
||||||
|
executable('voyage',
|
||||||
|
'src/game/voyage.c',
|
||||||
|
include_directories : incdir,
|
||||||
|
link_with : [runtime_lib],
|
||||||
|
win_subsystem : 'windows')
|
||||||
|
|
||||||
|
|
||||||
|
1
pch/rt_pch.h
Normal file
1
pch/rt_pch.h
Normal file
@ -0,0 +1 @@
|
|||||||
|
#include <Windows.h>
|
1
pch/vk_pch.h
Normal file
1
pch/vk_pch.h
Normal file
@ -0,0 +1 @@
|
|||||||
|
#include <vulkan/vulkan.h>
|
15
src/game/voyage.c
Normal file
15
src/game/voyage.c
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#include "runtime/app.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
int WINAPI wWinMain(HINSTANCE hInstance,
|
||||||
|
HINSTANCE hPrevInstance,
|
||||||
|
PWSTR pCmdLine,
|
||||||
|
int nCmdShow) {
|
||||||
|
return vyWin32Entry(hInstance, hPrevInstance, pCmdLine, nCmdShow);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -1,23 +0,0 @@
|
|||||||
#include <glad/glad.h>
|
|
||||||
|
|
||||||
#include "gfx.h"
|
|
||||||
|
|
||||||
/* Attributes are used to bind buffers (or textures) to symbolic values.
|
|
||||||
* For example, an attribute might be bound to "CELL_GRID", which would be
|
|
||||||
* replaced with the (at the time of the invoke) grid buffer of the current
|
|
||||||
* world cell.
|
|
||||||
*/
|
|
||||||
|
|
||||||
bool vyLoadShaders(const char **paths, vy_shader *shaders, unsigned int count);
|
|
||||||
|
|
||||||
bool vyInitRenderer(void) {
|
|
||||||
/* Init shader programs */
|
|
||||||
const char *shader_files[] = {"shader/cell.shader"};
|
|
||||||
vy_shader shaders[1];
|
|
||||||
if (!vyLoadShaders(shader_files, shaders, 1))
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void vyShutdownRenderer(void) {
|
|
||||||
}
|
|
@ -1,11 +1,11 @@
|
|||||||
#include <glad/glad.h>
|
#include "runtime/runtime.h"
|
||||||
|
#include "runtime/gfx.h"
|
||||||
|
|
||||||
#include "gfx.h"
|
#include "runtime/renderer_api.h"
|
||||||
#include "gfx_backend.h"
|
|
||||||
#include "voyage.h"
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
GLuint prog;
|
|
||||||
|
unsigned int prog;
|
||||||
} vy_gl_pipeline;
|
} vy_gl_pipeline;
|
||||||
|
|
||||||
#define NUM_SLOTS 256
|
#define NUM_SLOTS 256
|
||||||
@ -52,8 +52,9 @@ static void ReleasePipelineSlot(vy_gfx_pipeline_id id) {
|
|||||||
_storage.generation_in_use[slot] &= ~0x1;
|
_storage.generation_in_use[slot] &= ~0x1;
|
||||||
}
|
}
|
||||||
|
|
||||||
vy_gfx_pipeline_id
|
VY_DLLEXPORT vy_gfx_pipeline_id
|
||||||
vyCompileComputePipeline(const vy_compute_pipeline_info *info) {
|
vyCompileComputePipeline(const vy_compute_pipeline_info *info) {
|
||||||
|
#if 0
|
||||||
char info_log[512];
|
char info_log[512];
|
||||||
|
|
||||||
GLuint prog = glCreateProgram();
|
GLuint prog = glCreateProgram();
|
||||||
@ -86,16 +87,18 @@ vyCompileComputePipeline(const vy_compute_pipeline_info *info) {
|
|||||||
return (vy_gfx_pipeline_id){0};
|
return (vy_gfx_pipeline_id){0};
|
||||||
}
|
}
|
||||||
glDeleteShader(shader);
|
glDeleteShader(shader);
|
||||||
|
#endif
|
||||||
|
|
||||||
vy_gl_pipeline pipeline;
|
vy_gl_pipeline pipeline;
|
||||||
pipeline.prog = prog;
|
pipeline.prog = 0;
|
||||||
return StorePipeline(pipeline);
|
return StorePipeline(pipeline);
|
||||||
}
|
}
|
||||||
|
|
||||||
vy_gfx_pipeline_id
|
VY_DLLEXPORT vy_gfx_pipeline_id
|
||||||
vyCompileGraphicsPipeline(const vy_graphics_pipeline_info *info) {
|
vyCompileGraphicsPipeline(const vy_graphics_pipeline_info *info) {
|
||||||
char info_log[512];
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
char info_log[512];
|
||||||
GLuint prog = glCreateProgram();
|
GLuint prog = glCreateProgram();
|
||||||
GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER);
|
GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER);
|
||||||
GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
|
GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||||
@ -148,8 +151,9 @@ vyCompileGraphicsPipeline(const vy_graphics_pipeline_info *info) {
|
|||||||
|
|
||||||
glDeleteShader(vertex_shader);
|
glDeleteShader(vertex_shader);
|
||||||
glDeleteShader(fragment_shader);
|
glDeleteShader(fragment_shader);
|
||||||
|
#endif
|
||||||
|
|
||||||
vy_gl_pipeline pipeline;
|
vy_gl_pipeline pipeline;
|
||||||
pipeline.prog = prog;
|
pipeline.prog = 0;
|
||||||
return StorePipeline(pipeline);
|
return StorePipeline(pipeline);
|
||||||
}
|
}
|
15
src/renderer/vk/gpu.h
Normal file
15
src/renderer/vk/gpu.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#ifndef VY_VK_GPU_H
|
||||||
|
#define VY_VK_GPU_H
|
||||||
|
|
||||||
|
#include <vulkan/vulkan.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
VkInstance instance;
|
||||||
|
VkAllocationCallbacks *alloc_cb;
|
||||||
|
} vy_vk_gpu;
|
||||||
|
|
||||||
|
#ifndef VY_VK_DONT_DEFINE_GPU_GLOBAL
|
||||||
|
extern vy_vk_gpu g_gpu;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
137
src/renderer/vk/init.c
Normal file
137
src/renderer/vk/init.c
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
|
||||||
|
#define VY_VK_DONT_DEFINE_GPU_GLOBAL
|
||||||
|
#include "gpu.h"
|
||||||
|
|
||||||
|
#include "runtime/runtime.h"
|
||||||
|
#include "runtime/renderer_api.h"
|
||||||
|
#include "runtime/config.h"
|
||||||
|
|
||||||
|
VY_CVAR_I(r_EnableAPIAllocTracking,
|
||||||
|
"Enable tracking of allocations done by the vulkan api. [0/1] Default: 0",
|
||||||
|
0);
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
size_t allocated;
|
||||||
|
size_t reallocated;
|
||||||
|
size_t freed;
|
||||||
|
size_t max_alignment;
|
||||||
|
} vy_vk_alloc_stats;
|
||||||
|
|
||||||
|
vy_vk_gpu g_gpu;
|
||||||
|
|
||||||
|
static VkAllocationCallbacks _tracking_alloc_cbs;
|
||||||
|
static vy_vk_alloc_stats _alloc_stats;
|
||||||
|
|
||||||
|
static const char *AllocationScopeToString(VkSystemAllocationScope scope)
|
||||||
|
{
|
||||||
|
switch (scope) {
|
||||||
|
case VK_SYSTEM_ALLOCATION_SCOPE_COMMAND:
|
||||||
|
return "COMMAND";
|
||||||
|
case VK_SYSTEM_ALLOCATION_SCOPE_OBJECT:
|
||||||
|
return "OBJECT";
|
||||||
|
case VK_SYSTEM_ALLOCATION_SCOPE_CACHE:
|
||||||
|
return "CACHE";
|
||||||
|
case VK_SYSTEM_ALLOCATION_SCOPE_DEVICE:
|
||||||
|
return "DEVICE";
|
||||||
|
case VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE:
|
||||||
|
return "INSTANCE";
|
||||||
|
default:
|
||||||
|
return "UNKNOWN";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void LogAllocationStats(const vy_vk_alloc_stats *stats) {
|
||||||
|
vyLog("vk",
|
||||||
|
"Allocated: %zu bytes. Reallocated: %zu bytes. Max. requested "
|
||||||
|
"alignment: %zu bytes",
|
||||||
|
stats->allocated,
|
||||||
|
stats->reallocated,
|
||||||
|
stats->max_alignment);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *TrackAllocation(void *userData, size_t size, size_t alignment, VkSystemAllocationScope scope) {
|
||||||
|
vy_vk_alloc_stats *stats = userData;
|
||||||
|
if (alignment > stats->max_alignment)
|
||||||
|
stats->max_alignment = alignment;
|
||||||
|
stats->allocated += size;
|
||||||
|
vyLog("vk",
|
||||||
|
"Allocation. Size: %zu, Alignment: %zu, Scope: %s",
|
||||||
|
size,
|
||||||
|
alignment,
|
||||||
|
AllocationScopeToString(scope));
|
||||||
|
LogAllocationStats(stats);
|
||||||
|
return _aligned_malloc(size, alignment);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *TrackReallocation(void *userData,
|
||||||
|
void *original,
|
||||||
|
size_t size,
|
||||||
|
size_t alignment,
|
||||||
|
VkSystemAllocationScope scope) {
|
||||||
|
vy_vk_alloc_stats *stats = userData;
|
||||||
|
if (alignment > stats->max_alignment)
|
||||||
|
stats->max_alignment = alignment;
|
||||||
|
stats->reallocated += size;
|
||||||
|
vyLog("vk",
|
||||||
|
"Reallocation. Size: %zu, Alignment: %zu, Scope: %s",
|
||||||
|
size,
|
||||||
|
alignment,
|
||||||
|
AllocationScopeToString(scope));
|
||||||
|
LogAllocationStats(stats);
|
||||||
|
return _aligned_realloc(original, size, alignment);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void TrackFree(void *userData, void *memory) {
|
||||||
|
vy_vk_alloc_stats *stats = userData;
|
||||||
|
vyLog("vk", "Free.");
|
||||||
|
LogAllocationStats(stats);
|
||||||
|
free(memory);
|
||||||
|
}
|
||||||
|
|
||||||
|
VY_DLLEXPORT int vyInit(const vy_renderer_init_info *info) {
|
||||||
|
vyLog("vk", "Init");
|
||||||
|
|
||||||
|
vyRegisterCVAR(&r_EnableAPIAllocTracking);
|
||||||
|
|
||||||
|
_tracking_alloc_cbs.pUserData = &_alloc_stats;
|
||||||
|
_tracking_alloc_cbs.pfnAllocation = TrackAllocation;
|
||||||
|
_tracking_alloc_cbs.pfnReallocation = TrackReallocation;
|
||||||
|
_tracking_alloc_cbs.pfnFree = TrackFree;
|
||||||
|
|
||||||
|
if (r_EnableAPIAllocTracking.i) {
|
||||||
|
g_gpu.alloc_cb = &_tracking_alloc_cbs;
|
||||||
|
} else {
|
||||||
|
g_gpu.alloc_cb = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkResult result;
|
||||||
|
|
||||||
|
VkApplicationInfo app_info = {
|
||||||
|
.apiVersion = VK_API_VERSION_1_0,
|
||||||
|
.applicationVersion = 0x00001000,
|
||||||
|
.engineVersion = 0x00001000,
|
||||||
|
.pEngineName = "voyage",
|
||||||
|
.pApplicationName = "Voyage",
|
||||||
|
};
|
||||||
|
|
||||||
|
VkInstanceCreateInfo instance_info = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
|
||||||
|
.pApplicationInfo = &app_info,
|
||||||
|
};
|
||||||
|
result = vkCreateInstance(&instance_info, g_gpu.alloc_cb, &g_gpu.instance);
|
||||||
|
if (result != VK_SUCCESS) {
|
||||||
|
vyReportError("vk", "Failed to create the vulkan instance!");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
VY_DLLEXPORT void vyShutdown(void) {
|
||||||
|
vyLog("vk", "Shutdown");
|
||||||
|
|
||||||
|
vkDestroyInstance(g_gpu.instance, g_gpu.alloc_cb);
|
||||||
|
}
|
130
src/runtime/app.c
Normal file
130
src/runtime/app.c
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
#include "app.h"
|
||||||
|
#include "fio.h"
|
||||||
|
#include "gfx.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include "renderer_api.h"
|
||||||
|
|
||||||
|
extern void __RegisterRuntimeCVars(void);
|
||||||
|
|
||||||
|
VY_CVAR_I(rt_Fullscreen, "Show window in fullscreen mode. [0/1] Default: 0", 0);
|
||||||
|
VY_CVAR_I(rt_WindowWidth, "Window width. Default: 1024", 1024);
|
||||||
|
VY_CVAR_I(rt_WindowHeight, "Window height. Default: 768", 768);
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
static LRESULT CALLBACK win32WndProc(HWND hWnd,
|
||||||
|
UINT uMsg,
|
||||||
|
WPARAM wParam,
|
||||||
|
LPARAM lParam) {
|
||||||
|
switch (uMsg) {
|
||||||
|
case WM_CLOSE:
|
||||||
|
PostQuitMessage(0);
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
return DefWindowProcW(hWnd, uMsg, wParam, lParam);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VY_DLLEXPORT int vyWin32Entry(HINSTANCE hInstance,
|
||||||
|
HINSTANCE hPrevInstance,
|
||||||
|
PWSTR pCmdLine,
|
||||||
|
int nCmdShow) {
|
||||||
|
|
||||||
|
__RegisterRuntimeCVars();
|
||||||
|
|
||||||
|
vy_fio_config fio_config = {0};
|
||||||
|
if (!vyInitFIO(&fio_config)) {
|
||||||
|
vyReportError("FIO", "Init failed.");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WNDCLASSEXW wndclass = {
|
||||||
|
.cbSize = sizeof(wndclass),
|
||||||
|
.hInstance = hInstance,
|
||||||
|
.lpszClassName = L"vyWndClass",
|
||||||
|
.style = CS_OWNDC,
|
||||||
|
.lpfnWndProc = win32WndProc,
|
||||||
|
};
|
||||||
|
if (!RegisterClassExW(&wndclass)) {
|
||||||
|
vyReportError("CORE", "RegisterClassEx failed: %u", GetLastError());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
HWND wnd = NULL;
|
||||||
|
if (rt_Fullscreen.i) {
|
||||||
|
/* Fullscreen window */
|
||||||
|
int w = GetSystemMetrics(SM_CXSCREEN);
|
||||||
|
int h = GetSystemMetrics(SM_CYSCREEN);
|
||||||
|
wnd = CreateWindowExW(WS_EX_APPWINDOW,
|
||||||
|
L"vyWndClass",
|
||||||
|
L"Voyage",
|
||||||
|
WS_POPUP,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
w,
|
||||||
|
h,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
hInstance,
|
||||||
|
NULL);
|
||||||
|
ShowWindow(wnd, SW_SHOW);
|
||||||
|
} else {
|
||||||
|
/* Windowed mode */
|
||||||
|
int w = rt_WindowWidth.i;
|
||||||
|
int h = rt_WindowHeight.i;
|
||||||
|
wnd = CreateWindowExW(WS_EX_APPWINDOW,
|
||||||
|
L"vyWndClass",
|
||||||
|
L"Voyage",
|
||||||
|
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU,
|
||||||
|
CW_USEDEFAULT,
|
||||||
|
CW_USEDEFAULT,
|
||||||
|
w,
|
||||||
|
h,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
hInstance,
|
||||||
|
NULL);
|
||||||
|
ShowWindow(wnd, SW_SHOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wnd) {
|
||||||
|
vyReportError("CORE",
|
||||||
|
"Failed to create the game window: %u",
|
||||||
|
GetLastError());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
vy_renderer_init_info renderer_info = {.hWnd = wnd, .hInstance = hInstance};
|
||||||
|
if (!vyInitGFX(&renderer_info)) {
|
||||||
|
vyReportError("GFX", "Init failed.");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Main Loop */
|
||||||
|
bool keep_running = true;
|
||||||
|
while (keep_running) {
|
||||||
|
MSG msg;
|
||||||
|
while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) {
|
||||||
|
if (msg.message == WM_QUIT) {
|
||||||
|
keep_running = false;
|
||||||
|
} else {
|
||||||
|
TranslateMessage(&msg);
|
||||||
|
DispatchMessageW(&msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vyShutdownGFX();
|
||||||
|
|
||||||
|
DestroyWindow(wnd);
|
||||||
|
UnregisterClassW(L"vyWndClass", hInstance);
|
||||||
|
|
||||||
|
vyShutdownFIO();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
20
src/runtime/app.h
Normal file
20
src/runtime/app.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#ifndef VY_APP_H
|
||||||
|
#define VY_APP_H
|
||||||
|
|
||||||
|
/* Platform specific application entry point */
|
||||||
|
|
||||||
|
#include "runtime.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
/* Forward declared here, to avoid including windows.h */
|
||||||
|
struct HINSTANCE__;
|
||||||
|
|
||||||
|
VY_DLLEXPORT int vyWin32Entry(struct HINSTANCE__ *hInstance,
|
||||||
|
struct HINSTANCE__ *hPrevInstance,
|
||||||
|
wchar_t *pCmdLine,
|
||||||
|
int nCmdShow);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
@ -1,6 +1,6 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "threading.h"
|
#include "threading.h"
|
||||||
#include "voyage.h"
|
#include "runtime.h"
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
@ -1,6 +1,8 @@
|
|||||||
#ifndef VY_CONFIG_H
|
#ifndef VY_CONFIG_H
|
||||||
#define VY_CONFIG_H
|
#define VY_CONFIG_H
|
||||||
|
|
||||||
|
#include "runtime.h"
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
VY_CVAR_TYPE_INT,
|
VY_CVAR_TYPE_INT,
|
||||||
@ -36,8 +38,8 @@ typedef struct
|
|||||||
.s = (v), \
|
.s = (v), \
|
||||||
.type = VY_CVAR_TYPE_STRING}
|
.type = VY_CVAR_TYPE_STRING}
|
||||||
|
|
||||||
void vyRegisterCVAR(vy_cvar *cvar);
|
VY_DLLEXPORT void vyRegisterCVAR(vy_cvar *cvar);
|
||||||
|
|
||||||
vy_cvar *vyGetCVAR(const char *name);
|
VY_DLLEXPORT vy_cvar *vyGetCVAR(const char *name);
|
||||||
|
|
||||||
#endif
|
#endif
|
43
src/runtime/dynamic_libs.c
Normal file
43
src/runtime/dynamic_libs.c
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#include "dynamic_libs.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
VY_DLLEXPORT vy_dynlib vyOpenLib(const char *libname) {
|
||||||
|
wchar_t libname_w[MAX_PATH];
|
||||||
|
MultiByteToWideChar(CP_UTF8,
|
||||||
|
MB_PRECOMPOSED,
|
||||||
|
libname,
|
||||||
|
-1,
|
||||||
|
libname_w,
|
||||||
|
MAX_PATH);
|
||||||
|
HMODULE mod = LoadLibraryW(libname_w);
|
||||||
|
return (vy_dynlib)mod;
|
||||||
|
}
|
||||||
|
|
||||||
|
VY_DLLEXPORT void *vyGetSymbol(vy_dynlib lib, const char *symbol) {
|
||||||
|
return (void*)GetProcAddress((HMODULE)lib, symbol);
|
||||||
|
}
|
||||||
|
|
||||||
|
VY_DLLEXPORT void vyCloseLib(vy_dynlib lib) {
|
||||||
|
FreeLibrary((HMODULE)lib);
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(__linux__)
|
||||||
|
#include <dlfcn.h>
|
||||||
|
|
||||||
|
VY_DLLEXPORT vy_dynlib vyOpenLib(const char *libname) {
|
||||||
|
return dlopen(libname, RTLD_NOW | RTLD_LOCAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
VY_DLLEXPORT void *vyGetSymbol(vy_dynlib lib, const char *symbol) {
|
||||||
|
return dlsym(lib, symbol);
|
||||||
|
}
|
||||||
|
|
||||||
|
VY_DLLEXPORT void vyCloseLib(vy_dynlib lib) {
|
||||||
|
dlclose(lib);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
20
src/runtime/dynamic_libs.h
Normal file
20
src/runtime/dynamic_libs.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#ifndef VY_DYNAMIC_LIBS_H
|
||||||
|
#define VY_DYNAMIC_LIBS_H
|
||||||
|
|
||||||
|
#include "runtime.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define VY_DLLNAME(s) (s".dll")
|
||||||
|
#elif defined(__linux__)
|
||||||
|
#define VY_DLLNAME(s) ("lib"s".so")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef void *vy_dynlib;
|
||||||
|
|
||||||
|
VY_DLLEXPORT vy_dynlib vyOpenLib(const char *libname);
|
||||||
|
|
||||||
|
VY_DLLEXPORT void *vyGetSymbol(vy_dynlib lib, const char *symbol);
|
||||||
|
|
||||||
|
VY_DLLEXPORT void vyCloseLib(vy_dynlib lib);
|
||||||
|
|
||||||
|
#endif
|
@ -1,7 +1,7 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "voyage.h"
|
#include "runtime.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
@ -40,7 +40,7 @@ static void LogOut(const char *text)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void vyReportError(const char *subsystem, const char *fmt, ...) {
|
VY_DLLEXPORT void vyReportError(const char *subsystem, const char *fmt, ...) {
|
||||||
char buf[256];
|
char buf[256];
|
||||||
|
|
||||||
int at = snprintf(buf, VY_ARRAY_COUNT(buf) - 1, "[%s] ", subsystem);
|
int at = snprintf(buf, VY_ARRAY_COUNT(buf) - 1, "[%s] ", subsystem);
|
||||||
@ -54,7 +54,7 @@ void vyReportError(const char *subsystem, const char *fmt, ...) {
|
|||||||
DisplayErrorBox(buf);
|
DisplayErrorBox(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void vyLog(const char *subsystem, const char *fmt, ...) {
|
VY_DLLEXPORT void vyLog(const char *subsystem, const char *fmt, ...) {
|
||||||
char buf[256];
|
char buf[256];
|
||||||
|
|
||||||
int at = snprintf(buf, VY_ARRAY_COUNT(buf) - 1, "[%s] ", subsystem);
|
int at = snprintf(buf, VY_ARRAY_COUNT(buf) - 1, "[%s] ", subsystem);
|
@ -139,7 +139,7 @@ static void *linuxFIOThreadProc(void *);
|
|||||||
static DWORD WINAPI win32FIOThreadProc(_In_ LPVOID);
|
static DWORD WINAPI win32FIOThreadProc(_In_ LPVOID);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool vyInitFIO(const vy_fio_config *config) {
|
VY_DLLEXPORT bool vyInitFIO(const vy_fio_config *config) {
|
||||||
unsigned int queue_size = (config->queue_size) ? config->queue_size : 512;
|
unsigned int queue_size = (config->queue_size) ? config->queue_size : 512;
|
||||||
unsigned int max_file_count =
|
unsigned int max_file_count =
|
||||||
(config->max_file_count) ? config->max_file_count : 512;
|
(config->max_file_count) ? config->max_file_count : 512;
|
||||||
@ -165,7 +165,7 @@ bool vyInitFIO(const vy_fio_config *config) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void vyShutdownFIO(void) {
|
VY_DLLEXPORT void vyShutdownFIO(void) {
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
pthread_cancel(_thread);
|
pthread_cancel(_thread);
|
||||||
pthread_join(_thread, NULL);
|
pthread_join(_thread, NULL);
|
||||||
@ -199,7 +199,7 @@ vy_file_id vyGetFileIdFromSpan(vy_text_span path) {
|
|||||||
return fid;
|
return fid;
|
||||||
}
|
}
|
||||||
|
|
||||||
vy_file_id vyAddFileFromSpan(vy_text_span path) {
|
VY_DLLEXPORT vy_file_id vyAddFileFromSpan(vy_text_span path) {
|
||||||
vy_file_id fid = vyGetFileIdFromSpan(path);
|
vy_file_id fid = vyGetFileIdFromSpan(path);
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
@ -246,14 +246,14 @@ vy_file_id vyAddFileFromSpan(vy_text_span path) {
|
|||||||
return fid;
|
return fid;
|
||||||
}
|
}
|
||||||
|
|
||||||
vy_file_id vyAddFile(const char *path) {
|
VY_DLLEXPORT vy_file_id vyAddFile(const char *path) {
|
||||||
vy_text_span span;
|
vy_text_span span;
|
||||||
span.start = path;
|
span.start = path;
|
||||||
span.length = (unsigned int)strlen(path);
|
span.length = (unsigned int)strlen(path);
|
||||||
return vyAddFileFromSpan(span);
|
return vyAddFileFromSpan(span);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *vyGetFilePath(vy_file_id fid) {
|
VY_DLLEXPORT const char *vyGetFilePath(vy_file_id fid) {
|
||||||
/* Hash Lookup */
|
/* Hash Lookup */
|
||||||
if (fid == 0)
|
if (fid == 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -286,7 +286,7 @@ const char *vyGetFilePath(vy_file_id fid) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
vy_fio_handle vyEnqueueRead(vy_file_id fid) {
|
VY_DLLEXPORT vy_fio_handle vyEnqueueRead(vy_file_id fid) {
|
||||||
vy_fio_handle handle = 0;
|
vy_fio_handle handle = 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
@ -326,7 +326,7 @@ vy_fio_handle vyEnqueueRead(vy_file_id fid) {
|
|||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
void vyAbortFIO(vy_fio_handle fio) {
|
VY_DLLEXPORT void vyAbortFIO(vy_fio_handle fio) {
|
||||||
if (fio == 0)
|
if (fio == 0)
|
||||||
return;
|
return;
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
@ -346,7 +346,7 @@ void vyAbortFIO(vy_fio_handle fio) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool vyIsFIOFinished(vy_fio_handle fio) {
|
VY_DLLEXPORT bool vyIsFIOFinished(vy_fio_handle fio) {
|
||||||
if (fio == 0)
|
if (fio == 0)
|
||||||
return false;
|
return false;
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
@ -363,7 +363,8 @@ bool vyIsFIOFinished(vy_fio_handle fio) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool vyRetrieveReadBuffer(vy_fio_handle fio, vy_file_buffer *buffer) {
|
VY_DLLEXPORT bool vyRetrieveReadBuffer(vy_fio_handle fio,
|
||||||
|
vy_file_buffer *buffer) {
|
||||||
if (fio == 0)
|
if (fio == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -394,7 +395,7 @@ bool vyRetrieveReadBuffer(vy_fio_handle fio, vy_file_buffer *buffer) {
|
|||||||
return is_finished;
|
return is_finished;
|
||||||
}
|
}
|
||||||
|
|
||||||
void vyFreeFileBuffer(vy_file_buffer buffer) {
|
VY_DLLEXPORT void vyFreeFileBuffer(vy_file_buffer buffer) {
|
||||||
free(buffer.data);
|
free(buffer.data);
|
||||||
}
|
}
|
||||||
|
|
61
src/runtime/fio.h
Normal file
61
src/runtime/fio.h
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#ifndef VY_FIO_H
|
||||||
|
#define VY_FIO_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "runtime.h"
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
VY_FILE_BUFFER_FLAG_FILE_NOT_FOUND = 0x1,
|
||||||
|
VY_FILE_BUFFER_FLAG_READ_FAILED = 0x2,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
void *data;
|
||||||
|
size_t size;
|
||||||
|
uint32_t flags;
|
||||||
|
} vy_file_buffer;
|
||||||
|
|
||||||
|
inline bool vyWasFileBufferSuccessful(const vy_file_buffer *fb) {
|
||||||
|
return fb->flags == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* used to identify a file (XXH3 hash of the path) */
|
||||||
|
typedef uint64_t vy_file_id;
|
||||||
|
|
||||||
|
typedef unsigned int vy_fio_handle;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned int queue_size;
|
||||||
|
unsigned int max_file_count;
|
||||||
|
} vy_fio_config;
|
||||||
|
|
||||||
|
VY_DLLEXPORT bool vyInitFIO(const vy_fio_config *config);
|
||||||
|
|
||||||
|
VY_DLLEXPORT void vyShutdownFIO(void);
|
||||||
|
|
||||||
|
VY_DLLEXPORT vy_file_id vyGetFileId(const char *path);
|
||||||
|
|
||||||
|
VY_DLLEXPORT vy_file_id vyGetFileIdFromSpan(vy_text_span path);
|
||||||
|
|
||||||
|
VY_DLLEXPORT vy_file_id vyAddFile(const char *path);
|
||||||
|
|
||||||
|
VY_DLLEXPORT vy_file_id vyAddFileFromSpan(vy_text_span path);
|
||||||
|
|
||||||
|
VY_DLLEXPORT const char *vyGetFilePath(vy_file_id fid);
|
||||||
|
|
||||||
|
VY_DLLEXPORT vy_fio_handle vyEnqueueRead(vy_file_id fid);
|
||||||
|
|
||||||
|
VY_DLLEXPORT void vyAbortFIO(vy_fio_handle fio);
|
||||||
|
|
||||||
|
VY_DLLEXPORT bool vyIsFIOFinished(vy_fio_handle fio);
|
||||||
|
|
||||||
|
VY_DLLEXPORT bool vyRetrieveReadBuffer(vy_fio_handle fio,
|
||||||
|
vy_file_buffer *buffer);
|
||||||
|
|
||||||
|
VY_DLLEXPORT void vyFreeFileBuffer(vy_file_buffer buffer);
|
||||||
|
|
||||||
|
#endif
|
@ -1,8 +1,6 @@
|
|||||||
#ifndef VY_GFX_H
|
#ifndef VY_GFX_H
|
||||||
#define VY_GFX_H
|
#define VY_GFX_H
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
/* graphics system. this is the interface of the rendering code.
|
/* graphics system. this is the interface of the rendering code.
|
||||||
*
|
*
|
||||||
* we need (at least) three different renderers:
|
* we need (at least) three different renderers:
|
||||||
@ -11,11 +9,17 @@
|
|||||||
* - object renderer (for static models)
|
* - object renderer (for static models)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
bool vyInitRenderer(void);
|
#include "runtime.h"
|
||||||
|
|
||||||
void vyShutdownRenderer(void);
|
/* In renderer_api.h -> Not necessary for almost all gfx usage */
|
||||||
|
typedef struct vy_renderer_init_info_s vy_renderer_init_info;
|
||||||
|
|
||||||
|
VY_DLLEXPORT bool vyInitGFX(vy_renderer_init_info *renderer_info);
|
||||||
|
|
||||||
|
VY_DLLEXPORT void vyShutdownGFX(void);
|
||||||
|
|
||||||
/* Generational indices for backend objects */
|
/* Generational indices for backend objects */
|
||||||
typedef struct {
|
typedef struct {
|
75
src/runtime/gfx_main.c
Normal file
75
src/runtime/gfx_main.c
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define VY_DONT_DEFINE_RENDERER_GLOBAL
|
||||||
|
|
||||||
|
#include "gfx.h"
|
||||||
|
#include "renderer_api.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include "dynamic_libs.h"
|
||||||
|
|
||||||
|
/* Attributes are used to bind buffers (or textures) to symbolic values.
|
||||||
|
* For example, an attribute might be bound to "CELL_GRID", which would be
|
||||||
|
* replaced with the (at the time of the invoke) grid buffer of the current
|
||||||
|
* world cell.
|
||||||
|
*/
|
||||||
|
|
||||||
|
vy_renderer_api g_renderer;
|
||||||
|
static vy_dynlib _renderer_lib;
|
||||||
|
|
||||||
|
VY_CVAR_S(rt_Renderer,
|
||||||
|
"Select the render backend. Available options: [vk], Default: vk",
|
||||||
|
"vk");
|
||||||
|
|
||||||
|
extern bool vyLoadShaders(const char **paths, vy_shader *shaders, unsigned int count);
|
||||||
|
|
||||||
|
static bool LoadRenderer(void)
|
||||||
|
{
|
||||||
|
#define RETRIEVE_SYMBOL(name, type) \
|
||||||
|
g_renderer.name = (type *)vyGetSymbol(_renderer_lib, "vy" #name); \
|
||||||
|
if (!g_renderer.name) { \
|
||||||
|
vyReportError( \
|
||||||
|
"GFX", \
|
||||||
|
"Unable to retrieve renderer function %s from backend %s", \
|
||||||
|
#name, rt_Renderer.s); \
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(rt_Renderer.s, "vk") == 0) {
|
||||||
|
_renderer_lib = vyOpenLib(VY_DLLNAME("vyvk"));
|
||||||
|
if (!_renderer_lib) {
|
||||||
|
vyReportError("GFX",
|
||||||
|
"Unable to load renderer backend: %s",
|
||||||
|
VY_DLLNAME("vyvk"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
RETRIEVE_SYMBOL(Init, vy_init_renderer_fn);
|
||||||
|
RETRIEVE_SYMBOL(Shutdown, vy_shutdown_renderer_fn);
|
||||||
|
RETRIEVE_SYMBOL(CompileComputePipeline, vy_compile_compute_pipeline_fn);
|
||||||
|
RETRIEVE_SYMBOL(CompileGraphicsPipeline,
|
||||||
|
vy_compile_graphics_pipeline_fn);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
vyReportError("GFX", "Unsupported renderer backend: (%s) %s", rt_Renderer.name, rt_Renderer.s);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#undef RETRIEVE_SYMBOL
|
||||||
|
}
|
||||||
|
|
||||||
|
VY_DLLEXPORT bool vyInitGFX(vy_renderer_init_info *renderer_info) {
|
||||||
|
|
||||||
|
if (!LoadRenderer())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (g_renderer.Init(renderer_info) != 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* Init shader programs */
|
||||||
|
const char *shader_files[] = {"shader/cell.shader"};
|
||||||
|
vy_shader shaders[1];
|
||||||
|
if (!vyLoadShaders(shader_files, shaders, 1))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
VY_DLLEXPORT void vyShutdownGFX(void) {
|
||||||
|
g_renderer.Shutdown();
|
||||||
|
}
|
@ -6,10 +6,10 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "runtime.h"
|
||||||
#include "fio.h"
|
#include "fio.h"
|
||||||
#include "gfx.h"
|
#include "gfx.h"
|
||||||
#include "gfx_backend.h"
|
#include "renderer_api.h"
|
||||||
#include "voyage.h"
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
VY_STMT_FORM_VALUE,
|
VY_STMT_FORM_VALUE,
|
||||||
@ -289,9 +289,9 @@ static vy_fio_handle DispatchShaderRead(const char *shader,
|
|||||||
return DispatchFileRead(path->value);
|
return DispatchFileRead(path->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static vy_gfx_pipeline_id LinkProgram(vy_parse_state *state,
|
static vy_gfx_pipeline_id CreatePipeline(vy_parse_state *state,
|
||||||
const char *file_path,
|
const char *file_path,
|
||||||
unsigned int root_list) {
|
unsigned int root_list) {
|
||||||
/* Process the data */
|
/* Process the data */
|
||||||
vy_fio_handle vertex_read =
|
vy_fio_handle vertex_read =
|
||||||
DispatchShaderRead("vertex", state, root_list, file_path);
|
DispatchShaderRead("vertex", state, root_list, file_path);
|
||||||
@ -324,7 +324,7 @@ static vy_gfx_pipeline_id LinkProgram(vy_parse_state *state,
|
|||||||
vy_compute_pipeline_info info;
|
vy_compute_pipeline_info info;
|
||||||
info.compute_source = compute_code.data;
|
info.compute_source = compute_code.data;
|
||||||
info.compute_source_length = compute_code.size;
|
info.compute_source_length = compute_code.size;
|
||||||
vy_gfx_pipeline_id pipeline = vyCompileComputePipeline(&info);
|
vy_gfx_pipeline_id pipeline = g_renderer.CompileComputePipeline(&info);
|
||||||
vyFreeFileBuffer(compute_code);
|
vyFreeFileBuffer(compute_code);
|
||||||
return pipeline;
|
return pipeline;
|
||||||
} else if (vertex_read || fragment_read) {
|
} else if (vertex_read || fragment_read) {
|
||||||
@ -386,7 +386,7 @@ static vy_gfx_pipeline_id LinkProgram(vy_parse_state *state,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vy_gfx_pipeline_id pipeline = vyCompileGraphicsPipeline(&info);
|
vy_gfx_pipeline_id pipeline = g_renderer.CompileGraphicsPipeline(&info);
|
||||||
vyFreeFileBuffer(vertex_code);
|
vyFreeFileBuffer(vertex_code);
|
||||||
vyFreeFileBuffer(fragment_code);
|
vyFreeFileBuffer(fragment_code);
|
||||||
return pipeline;
|
return pipeline;
|
||||||
@ -515,7 +515,7 @@ ParseShaderFile(vy_file_id fid, vy_file_buffer fbuf, vy_shader *shader) {
|
|||||||
|
|
||||||
DbgPrintShaderFile(&state, root_list, 0);
|
DbgPrintShaderFile(&state, root_list, 0);
|
||||||
|
|
||||||
shader->pipeline = LinkProgram(&state, file_path, root_list);
|
shader->pipeline = CreatePipeline(&state, file_path, root_list);
|
||||||
if (!VY_IS_GFX_ID_VALID(shader->pipeline)) {
|
if (!VY_IS_GFX_ID_VALID(shader->pipeline)) {
|
||||||
result = false;
|
result = false;
|
||||||
goto out;
|
goto out;
|
53
src/runtime/renderer_api.h
Normal file
53
src/runtime/renderer_api.h
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
#ifndef VY_GFX_BACKEND_H
|
||||||
|
#define VY_GFX_BACKEND_H
|
||||||
|
|
||||||
|
/* Backend functions and types. */
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include "gfx.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
struct HINSTANCE__;
|
||||||
|
struct HWND__;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct vy_renderer_init_info_s {
|
||||||
|
#ifdef _WIN32
|
||||||
|
struct HINSTANCE__ *hInstance;
|
||||||
|
struct HWND__ *hWnd;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char *compute_source;
|
||||||
|
size_t compute_source_length;
|
||||||
|
} vy_compute_pipeline_info;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char *vertex_source;
|
||||||
|
size_t vertex_source_length;
|
||||||
|
|
||||||
|
const char *fragment_source;
|
||||||
|
size_t fragment_source_length;
|
||||||
|
} vy_graphics_pipeline_info;
|
||||||
|
|
||||||
|
typedef int vy_init_renderer_fn(const vy_renderer_init_info *info);
|
||||||
|
typedef void vy_shutdown_renderer_fn(void);
|
||||||
|
typedef vy_gfx_pipeline_id
|
||||||
|
vy_compile_compute_pipeline_fn(const vy_compute_pipeline_info *info);
|
||||||
|
typedef vy_gfx_pipeline_id
|
||||||
|
vy_compile_graphics_pipeline_fn(const vy_graphics_pipeline_info *info);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
vy_init_renderer_fn *Init;
|
||||||
|
vy_shutdown_renderer_fn *Shutdown;
|
||||||
|
vy_compile_compute_pipeline_fn *CompileComputePipeline;
|
||||||
|
vy_compile_graphics_pipeline_fn *CompileGraphicsPipeline;
|
||||||
|
} vy_renderer_api;
|
||||||
|
|
||||||
|
#ifndef VY_DONT_DEFINE_RENDERER_GLOBAL
|
||||||
|
extern vy_renderer_api g_renderer;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
@ -5,6 +5,12 @@
|
|||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define VY_DLLEXPORT __declspec(dllexport)
|
||||||
|
#else
|
||||||
|
#define VY_DLLEXPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
#define VY_UNUSED(x) ((void)sizeof((x)))
|
#define VY_UNUSED(x) ((void)sizeof((x)))
|
||||||
#define VY_ARRAY_COUNT(x) (sizeof((x)) / sizeof((x)[0]))
|
#define VY_ARRAY_COUNT(x) (sizeof((x)) / sizeof((x)[0]))
|
||||||
|
|
||||||
@ -13,8 +19,8 @@ typedef struct {
|
|||||||
unsigned int length;
|
unsigned int length;
|
||||||
} vy_text_span;
|
} vy_text_span;
|
||||||
|
|
||||||
void vyReportError(const char *subsystem, const char *fmt, ...);
|
VY_DLLEXPORT void vyReportError(const char *subsystem, const char *fmt, ...);
|
||||||
|
|
||||||
void vyLog(const char *subsystem, const char *fmt, ...);
|
VY_DLLEXPORT void vyLog(const char *subsystem, const char *fmt, ...);
|
||||||
|
|
||||||
#endif
|
#endif
|
14
src/runtime/runtime_cvars.c
Normal file
14
src/runtime/runtime_cvars.c
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
extern vy_cvar rt_Renderer;
|
||||||
|
extern vy_cvar rt_Fullscreen;
|
||||||
|
extern vy_cvar rt_WindowWidth;
|
||||||
|
extern vy_cvar rt_WindowHeight;
|
||||||
|
|
||||||
|
void __RegisterRuntimeCVars(void)
|
||||||
|
{
|
||||||
|
vyRegisterCVAR(&rt_Renderer);
|
||||||
|
vyRegisterCVAR(&rt_Fullscreen);
|
||||||
|
vyRegisterCVAR(&rt_WindowWidth);
|
||||||
|
vyRegisterCVAR(&rt_WindowHeight);
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
#include "threading.h"
|
#include "threading.h"
|
||||||
#include "voyage.h"
|
#include "runtime.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
@ -15,7 +15,7 @@ static vy_mutex _mutex[MAX_MUTEX];
|
|||||||
static ptrdiff_t _first_reusable = MAX_MUTEX;
|
static ptrdiff_t _first_reusable = MAX_MUTEX;
|
||||||
static ptrdiff_t _next = 0;
|
static ptrdiff_t _next = 0;
|
||||||
|
|
||||||
vy_mutex *vyCreateMutex(void) {
|
VY_DLLEXPORT vy_mutex *vyCreateMutex(void) {
|
||||||
if (_first_reusable < MAX_MUTEX) {
|
if (_first_reusable < MAX_MUTEX) {
|
||||||
vy_mutex *mtx = &_mutex[_first_reusable];
|
vy_mutex *mtx = &_mutex[_first_reusable];
|
||||||
_first_reusable = mtx->next_reusable;
|
_first_reusable = mtx->next_reusable;
|
||||||
@ -35,18 +35,18 @@ vy_mutex *vyCreateMutex(void) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void vyDestroyMutex(vy_mutex *mutex) {
|
VY_DLLEXPORT void vyDestroyMutex(vy_mutex *mutex) {
|
||||||
ptrdiff_t index = mutex - &_mutex[0];
|
ptrdiff_t index = mutex - &_mutex[0];
|
||||||
mutex->next_reusable = _first_reusable;
|
mutex->next_reusable = _first_reusable;
|
||||||
_first_reusable = index;
|
_first_reusable = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool vyLockMutex(vy_mutex *mutex) {
|
VY_DLLEXPORT bool vyLockMutex(vy_mutex *mutex) {
|
||||||
return WaitForSingleObject(mutex->handle, INFINITE) == WAIT_OBJECT_0;
|
return WaitForSingleObject(mutex->handle, INFINITE) == WAIT_OBJECT_0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool vyUnlockMutex(vy_mutex *mutex) {
|
VY_DLLEXPORT bool vyUnlockMutex(vy_mutex *mutex) {
|
||||||
return ReleaseMutex(mutex) != 0;
|
return ReleaseMutex(mutex->handle) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(__linux__)
|
#elif defined(__linux__)
|
||||||
@ -62,7 +62,7 @@ static vy_mutex _mutex[MAX_MUTEX];
|
|||||||
static ptrdiff_t _first_reusable = MAX_MUTEX;
|
static ptrdiff_t _first_reusable = MAX_MUTEX;
|
||||||
static ptrdiff_t _next = 0;
|
static ptrdiff_t _next = 0;
|
||||||
|
|
||||||
vy_mutex *vyCreateMutex(void) {
|
VY_DLLEXPORT vy_mutex *vyCreateMutex(void) {
|
||||||
if (_first_reusable < MAX_MUTEX) {
|
if (_first_reusable < MAX_MUTEX) {
|
||||||
vy_mutex *mtx = &_mutex[_first_reusable];
|
vy_mutex *mtx = &_mutex[_first_reusable];
|
||||||
_first_reusable = mtx->next_reusable;
|
_first_reusable = mtx->next_reusable;
|
||||||
@ -81,17 +81,17 @@ vy_mutex *vyCreateMutex(void) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void vyDestroyMutex(vy_mutex *mutex) {
|
VY_DLLEXPORT void vyDestroyMutex(vy_mutex *mutex) {
|
||||||
ptrdiff_t index = mutex - &_mutex[0];
|
ptrdiff_t index = mutex - &_mutex[0];
|
||||||
mutex->next_reusable = _first_reusable;
|
mutex->next_reusable = _first_reusable;
|
||||||
_first_reusable = index;
|
_first_reusable = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool vyLockMutex(vy_mutex *mutex) {
|
VY_DLLEXPORT bool vyLockMutex(vy_mutex *mutex) {
|
||||||
return pthread_mutex_lock(&mutex->handle) == 0;
|
return pthread_mutex_lock(&mutex->handle) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool vyUnlockMutex(vy_mutex *mutex) {
|
VY_DLLEXPORT bool vyUnlockMutex(vy_mutex *mutex) {
|
||||||
return pthread_mutex_unlock(&mutex->handle) == 0;
|
return pthread_mutex_unlock(&mutex->handle) == 0;
|
||||||
}
|
}
|
||||||
|
|
20
src/runtime/threading.h
Normal file
20
src/runtime/threading.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#ifndef VY_THREADING_H
|
||||||
|
#define VY_THREADING_H
|
||||||
|
|
||||||
|
/* platform independent threading */
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "runtime.h"
|
||||||
|
|
||||||
|
typedef struct vy_mutex_s vy_mutex;
|
||||||
|
|
||||||
|
VY_DLLEXPORT vy_mutex *vyCreateMutex(void);
|
||||||
|
|
||||||
|
VY_DLLEXPORT void vyDestroyMutex(vy_mutex *mutex);
|
||||||
|
|
||||||
|
VY_DLLEXPORT bool vyLockMutex(vy_mutex *mutex);
|
||||||
|
|
||||||
|
VY_DLLEXPORT bool vyUnlockMutex(vy_mutex *mutex);
|
||||||
|
|
||||||
|
#endif
|
115
src/voyage.c
115
src/voyage.c
@ -1,115 +0,0 @@
|
|||||||
#include <glad/glad.h>
|
|
||||||
|
|
||||||
#include <GLFW/glfw3.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "fio.h"
|
|
||||||
#include "gfx.h"
|
|
||||||
#include "threading.h"
|
|
||||||
|
|
||||||
static void glfw_error_cb(int err, const char *description) {
|
|
||||||
fprintf(stderr, "[GLFW] %u: %s\n", err, description);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void make_window_windowed_fullscreen(GLFWwindow *window,
|
|
||||||
GLFWmonitor *monitor) {
|
|
||||||
const GLFWvidmode *mode = glfwGetVideoMode(monitor);
|
|
||||||
glfwSetWindowMonitor(window,
|
|
||||||
monitor,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
mode->width,
|
|
||||||
mode->height,
|
|
||||||
mode->refreshRate);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void make_window_windowed(GLFWwindow *window, int w, int h) {
|
|
||||||
glfwSetWindowMonitor(window, NULL, 0, 0, w, h, GLFW_DONT_CARE);
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int f1;
|
|
||||||
int esc;
|
|
||||||
} key_states;
|
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
|
||||||
glfwSetErrorCallback(glfw_error_cb);
|
|
||||||
if (!glfwInit()) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
printf("[GFLW] Version: %s\n", glfwGetVersionString());
|
|
||||||
|
|
||||||
/* Create a windowed full screen window */
|
|
||||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API);
|
|
||||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
|
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);
|
|
||||||
GLFWwindow *window = glfwCreateWindow(640, 480, "Voyage", NULL, NULL);
|
|
||||||
if (!window) {
|
|
||||||
fprintf(stderr, "[GFX] Window creation failed.\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
glfwMakeContextCurrent(window);
|
|
||||||
glfwSwapInterval(1);
|
|
||||||
|
|
||||||
if (!gladLoadGL()) {
|
|
||||||
fprintf(stderr, "[GFX] OpenGL load failed.\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
vy_fio_config fio_config = {0};
|
|
||||||
if (!vyInitFIO(&fio_config)) {
|
|
||||||
fprintf(stderr, "[FIO] Init failed.\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!vyInitRenderer()) {
|
|
||||||
fprintf(stderr, "[GFX] Init failed.\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
printf("GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS: %u\n",
|
|
||||||
GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS);
|
|
||||||
printf("GL_MAX_UNIFORM_BUFFER_BINDINGS: %u\n",
|
|
||||||
GL_MAX_UNIFORM_BUFFER_BINDINGS);
|
|
||||||
|
|
||||||
key_states prev_keys = {0};
|
|
||||||
int window_state = 0;
|
|
||||||
|
|
||||||
while (!glfwWindowShouldClose(window)) {
|
|
||||||
/* Gather input */
|
|
||||||
key_states keys;
|
|
||||||
keys.f1 = glfwGetKey(window, GLFW_KEY_F1);
|
|
||||||
keys.esc = glfwGetKey(window, GLFW_KEY_ESCAPE);
|
|
||||||
|
|
||||||
if (keys.f1 && !prev_keys.f1) {
|
|
||||||
if (window_state)
|
|
||||||
make_window_windowed(window, 640, 480);
|
|
||||||
else
|
|
||||||
make_window_windowed_fullscreen(window,
|
|
||||||
glfwGetPrimaryMonitor());
|
|
||||||
window_state = !window_state;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (keys.esc)
|
|
||||||
glfwSetWindowShouldClose(window, GLFW_TRUE);
|
|
||||||
|
|
||||||
int fbw, fbh;
|
|
||||||
glfwGetFramebufferSize(window, &fbw, &fbh);
|
|
||||||
glViewport(0, 0, fbw, fbh);
|
|
||||||
glClearColor(0, 0, 0, 0);
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
|
||||||
|
|
||||||
glfwSwapBuffers(window);
|
|
||||||
glfwPollEvents();
|
|
||||||
prev_keys = keys;
|
|
||||||
}
|
|
||||||
|
|
||||||
vyShutdownRenderer();
|
|
||||||
vyShutdownFIO();
|
|
||||||
|
|
||||||
glfwDestroyWindow(window);
|
|
||||||
glfwTerminate();
|
|
||||||
return 0;
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user