rename the engine to recreational.tech

This commit is contained in:
Kevin Trogant 2024-01-16 16:10:56 +01:00
parent 448d448430
commit abb367dffc
69 changed files with 1759 additions and 1756 deletions

3
.gitignore vendored
View File

@ -5,3 +5,6 @@
# assetc directories
/actemp/*
/data/*
/.cache/*
/.vs/*

View File

@ -22,16 +22,16 @@ elif compiler.get_argument_syntax() == 'msvc'
endif
if get_option('default_library') == 'static'
add_project_arguments(['-DVY_STATIC_LIB'], language : 'c')
add_project_arguments(['-DRT_STATIC_LIB'], language : 'c')
endif
if get_option('error_report_debugbreak')
add_project_arguments(['-DVY_ERROR_REPORT_DEBUGBREAK'], language : 'c')
add_project_arguments(['-DRT_ERROR_REPORT_DEBUGBREAK'], language : 'c')
endif
# Debug specific flags
if buildtype == 'debug' or buildtype == 'debugoptimized'
add_project_arguments([ '-DVY_DEBUG'], language : 'c')
add_project_arguments([ '-DRT_DEBUG'], language : 'c')
endif
# Gather dependencies
@ -42,12 +42,12 @@ vk_dep = dependency('vulkan', required : false)
windowing_dep = []
if get_option('use_xlib')
windowing_dep = dependency('x11', required : true)
add_project_arguments(['-DVY_USE_XLIB'], language : 'c')
add_project_arguments(['-DRT_USE_XLIB'], language : 'c')
endif
incdir = include_directories(['contrib', 'src'])
runtime_lib = library('vyrt',
runtime_lib = library('rt',
# Project Sources
'src/runtime/aio.h',
'src/runtime/app.h',
@ -107,7 +107,7 @@ if vk_dep.found()
endif
vk_inc_dep = vk_dep.partial_dependency(compile_args : true, includes : true)
vk_renderer_lib = library('vyvk',
vk_renderer_lib = library('rtvk',
# Project Sources
'src/renderer/vk/gpu.h',
'src/renderer/vk/swapchain.h',
@ -177,7 +177,7 @@ executable('assetc',
link_args : ['-L'+shaderc_libdir, '-lshaderc_combined'],
win_subsystem : 'console')
# Game
executable('voyage',
'src/game/voyage.c',
include_directories : incdir,

View File

@ -6,13 +6,13 @@
#include <Windows.h>
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow) {
return vyWin32Entry(hInstance, hPrevInstance, pCmdLine, nCmdShow);
return rtWin32Entry(hInstance, hPrevInstance, pCmdLine, nCmdShow);
}
#elif defined(__linux__)
int main(int argc, char **argv) {
return vyXlibEntry(argc, argv);
return rtXlibEntry(argc, argv);
}
#endif

View File

@ -1,22 +1,22 @@
#ifndef VY_VK_FRAMEBUFFER_H
#define VY_VK_FRAMEBUFFER_H
#ifndef RT_VK_FRAMEBUFFER_H
#define RT_VK_FRAMEBUFFER_H
#include <volk/volk.h>
typedef struct {
VkFramebuffer framebuffer;
uint32_t pass_idx;
} vy_framebuffer;
} rt_framebuffer;
typedef struct {
uint32_t index;
} vy_framebuffer_handle;
} rt_framebuffer_handle;
/* Reserve a slot, but don't actually create the framebuffer yet.
* We can use this if we are unsure if the framebuffer will really be needed.
*/
vy_framebuffer_handle vy_reserve_framebuffer(void);
rt_framebuffer_handle rt_reserve_framebuffer(void);
vy_framebuffer *vy_get_framebuffer(vy_framebuffer_handle handle);
rt_framebuffer *rt_get_framebuffer(rt_framebuffer_handle handle);
#endif

View File

@ -1,12 +1,12 @@
#ifndef VY_VK_GPU_H
#define VY_VK_GPU_H
#ifndef RT_VK_GPU_H
#define RT_VK_GPU_H
#include <volk/volk.h>
#ifdef _WIN32
struct HINSTANCE__;
struct HWND__;
#elif defined(VY_USE_XLIB)
#elif defined(RT_USE_XLIB)
struct _XDisplay;
#endif
@ -14,11 +14,11 @@ typedef struct {
#ifdef _WIN32
struct HINSTANCE__ *hInstance;
struct HWND__ *hWnd;
#elif defined(VY_USE_XLIB)
#elif defined(RT_USE_XLIB)
struct _XDisplay *display;
unsigned long window;
#endif
} vy_native_window;
} rt_native_window;
typedef struct {
VkInstance instance;
@ -34,14 +34,14 @@ typedef struct {
uint32_t compute_family;
uint32_t present_family;
vy_native_window native_window;
rt_native_window native_window;
VkPhysicalDeviceDescriptorIndexingProperties descriptor_indexing_props;
VkPhysicalDeviceProperties phys_device_props;
} vy_vk_gpu;
} rt_vk_gpu;
#ifndef VY_VK_DONT_DEFINE_GPU_GLOBAL
extern vy_vk_gpu g_gpu;
#ifndef RT_VK_DONT_DEFINE_GPU_GLOBAL
extern rt_vk_gpu g_gpu;
#endif
#endif

View File

@ -2,7 +2,7 @@
#include <stdlib.h>
#include <string.h>
#define VY_VK_DONT_DEFINE_GPU_GLOBAL
#define RT_VK_DONT_DEFINE_GPU_GLOBAL
#include "gpu.h"
#include "swapchain.h"
@ -10,13 +10,13 @@
#include "runtime/renderer_api.h"
#include "runtime/runtime.h"
VY_CVAR_I(r_VkEnableAPIAllocTracking,
RT_CVAR_I(r_VkEnableAPIAllocTracking,
"Enable tracking of allocations done by the vulkan api. [0/1] Default: 0",
0);
VY_CVAR_S(r_VkPhysDeviceName, "Name of the selected physical device. Default: \"\"", "");
RT_CVAR_S(r_VkPhysDeviceName, "Name of the selected physical device. Default: \"\"", "");
vy_vk_gpu g_gpu;
rt_vk_gpu g_gpu;
static VkAllocationCallbacks _tracking_alloc_cbs;
@ -39,7 +39,7 @@ static const char *AllocationScopeToString(VkSystemAllocationScope scope) {
static void *
TrackAllocation(void *userData, size_t size, size_t alignment, VkSystemAllocationScope scope) {
vyLog("vk",
rtLog("vk",
"Allocation. Size: %zu, Alignment: %zu, Scope: %s",
size,
alignment,
@ -56,7 +56,7 @@ static void *TrackReallocation(void *userData,
size_t size,
size_t alignment,
VkSystemAllocationScope scope) {
vyLog("vk",
rtLog("vk",
"Reallocation. Size: %zu, Alignment: %zu, Scope: %s",
size,
alignment,
@ -77,20 +77,20 @@ DebugUtilsMessengerCb(VkDebugUtilsMessageSeverityFlagBitsEXT severity,
return VK_FALSE;
}
extern vy_cvar r_VkPreferredSwapchainImages;
extern vy_cvar r_VkPreferMailboxMode;
extern rt_cvar r_VkPreferredSwapchainImages;
extern rt_cvar r_VkPreferMailboxMode;
void VY_RENDERER_API_FN(RegisterCVars)(void) {
vyRegisterCVAR(&r_VkEnableAPIAllocTracking);
vyRegisterCVAR(&r_VkPhysDeviceName);
vyRegisterCVAR(&r_VkPreferredSwapchainImages);
vyRegisterCVAR(&r_VkPreferMailboxMode);
void RT_RENDERER_API_FN(RegisterCVars)(void) {
rtRegisterCVAR(&r_VkEnableAPIAllocTracking);
rtRegisterCVAR(&r_VkPhysDeviceName);
rtRegisterCVAR(&r_VkPreferredSwapchainImages);
rtRegisterCVAR(&r_VkPreferMailboxMode);
}
static vy_result CreateInstance(void) {
static rt_result CreateInstance(void) {
VkResult result = volkInitialize();
if (result != VK_SUCCESS) {
vyReportError("vk", "Initialization failed: volkInitialize()");
rtReportError("vk", "Initialization failed: volkInitialize()");
return 1;
}
@ -106,18 +106,18 @@ static vy_result CreateInstance(void) {
VK_KHR_SURFACE_EXTENSION_NAME,
#ifdef _WIN32
"VK_KHR_win32_surface",
#elif defined(VY_USE_XLIB)
#elif defined(RT_USE_XLIB)
"VK_KHR_xlib_surface",
#endif
#ifdef VY_DEBUG
#ifdef RT_DEBUG
VK_EXT_DEBUG_UTILS_EXTENSION_NAME,
#endif
};
const char *layers[1];
unsigned int layer_count = 0;
#ifdef VY_DEBUG
#ifdef RT_DEBUG
/* Search for layers we want to enable */
uint32_t available_layer_count = 0;
result = vkEnumerateInstanceLayerProperties(&available_layer_count, NULL);
@ -134,10 +134,10 @@ static vy_result CreateInstance(void) {
}
free(props);
} else {
vyLog("vk", "Failed to allocate storage for instance layer properties.");
rtLog("vk", "Failed to allocate storage for instance layer properties.");
}
} else {
vyLog("vk", "vkEnumerateInstanceLayerProperties failed.");
rtLog("vk", "vkEnumerateInstanceLayerProperties failed.");
}
#endif
@ -145,18 +145,18 @@ static vy_result CreateInstance(void) {
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
.pApplicationInfo = &app_info,
.ppEnabledExtensionNames = extensions,
.enabledExtensionCount = VY_ARRAY_COUNT(extensions),
.enabledExtensionCount = RT_ARRAY_COUNT(extensions),
.ppEnabledLayerNames = layers,
.enabledLayerCount = layer_count,
};
result = vkCreateInstance(&instance_info, g_gpu.alloc_cb, &g_gpu.instance);
if (result != VK_SUCCESS) {
vyReportError("vk", "Failed to create the vulkan instance.");
rtReportError("vk", "Failed to create the vulkan instance.");
return 1;
}
volkLoadInstance(g_gpu.instance);
#ifdef VY_DEBUG
#ifdef RT_DEBUG
/* Create the debug utils messenger */
VkDebugUtilsMessengerCreateInfoEXT messenger_info = {
.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
@ -171,10 +171,10 @@ static vy_result CreateInstance(void) {
g_gpu.alloc_cb,
&g_gpu.messenger);
#endif
return VY_SUCCESS;
return RT_SUCCESS;
}
static vy_result CreateSurface(const vy_renderer_init_info *info) {
static rt_result CreateSurface(const rt_renderer_init_info *info) {
#ifdef _WIN32
g_gpu.native_window.hInstance = info->hInstance;
g_gpu.native_window.hWnd = info->hWnd;
@ -185,10 +185,10 @@ static vy_result CreateSurface(const vy_renderer_init_info *info) {
};
if (vkCreateWin32SurfaceKHR(g_gpu.instance, &surface_info, g_gpu.alloc_cb, &g_gpu.surface) ==
VK_SUCCESS)
return VY_SUCCESS;
return RT_SUCCESS;
else
return 100;
#elif defined(VY_USE_XLIB_KHR)
#elif defined(RT_USE_XLIB_KHR)
g_gpu.native_window.display = info->display;
g_gpu.native_window.window = info->window;
VkXlibSurfaceCreateInfoKHR surface_info = {
@ -198,7 +198,7 @@ static vy_result CreateSurface(const vy_renderer_init_info *info) {
};
if (vkCreateXlibSurfaceKHR(g_gpu.instance, &surface_info, &g_gpu.alloc_cb, &g_gpu.surface) ==
VK_SUCCESS)
return VY_SUCCESS;
return RT_SUCCESS;
else
return 100;
#endif
@ -208,10 +208,10 @@ typedef struct {
uint32_t graphics;
uint32_t compute;
uint32_t present;
} vy_queue_indices;
} rt_queue_indices;
static vy_queue_indices RetrieveQueueIndices(VkPhysicalDevice phys_dev, VkSurfaceKHR surface) {
vy_queue_indices indices = {.graphics = UINT32_MAX,
static rt_queue_indices RetrieveQueueIndices(VkPhysicalDevice phys_dev, VkSurfaceKHR surface) {
rt_queue_indices indices = {.graphics = UINT32_MAX,
.compute = UINT32_MAX,
.present = UINT32_MAX};
@ -254,7 +254,7 @@ static bool CheckDeviceExtensionSupported(VkPhysicalDevice phys_dev) {
vkEnumerateDeviceExtensionProperties(phys_dev, NULL, &extension_count, supported_extensions);
bool supported = true;
for (uint32_t i = 0; i < VY_ARRAY_COUNT(required_extensions); ++i) {
for (uint32_t i = 0; i < RT_ARRAY_COUNT(required_extensions); ++i) {
bool found = false;
for (uint32_t j = 0; j < extension_count; ++j) {
if (strncmp(supported_extensions[j].extensionName,
@ -275,18 +275,18 @@ out:
return supported;
}
static vy_result ChoosePhysicalDevice(void) {
static rt_result ChoosePhysicalDevice(void) {
g_gpu.phys_device = VK_NULL_HANDLE;
uint32_t phys_device_count = 0;
VkResult result = vkEnumeratePhysicalDevices(g_gpu.instance, &phys_device_count, NULL);
if (result != VK_SUCCESS) {
vyReportError("vk", "Failed to enumerate the physical devices.");
rtReportError("vk", "Failed to enumerate the physical devices.");
return 2;
}
VkPhysicalDevice *phys_devices = calloc(phys_device_count, sizeof(VkPhysicalDevice));
if (!phys_devices) {
vyReportError("vk", "Failed to enumerate the physical devices: Out of memory.");
rtReportError("vk", "Failed to enumerate the physical devices: Out of memory.");
return 2;
}
vkEnumeratePhysicalDevices(g_gpu.instance, &phys_device_count, phys_devices);
@ -307,7 +307,7 @@ static vy_result ChoosePhysicalDevice(void) {
if (!CheckDeviceExtensionSupported(phys_devices[i]))
continue;
vy_queue_indices indices = RetrieveQueueIndices(phys_devices[i], g_gpu.surface);
rt_queue_indices indices = RetrieveQueueIndices(phys_devices[i], g_gpu.surface);
if (indices.compute == UINT32_MAX || indices.present == UINT32_MAX ||
indices.graphics == UINT32_MAX)
continue;
@ -354,18 +354,18 @@ static vy_result ChoosePhysicalDevice(void) {
free(phys_devices);
if (g_gpu.phys_device == VK_NULL_HANDLE) {
vyReportError("vk", "Failed to find a suitable physical device.");
rtReportError("vk", "Failed to find a suitable physical device.");
return 3;
}
return VY_SUCCESS;
return RT_SUCCESS;
}
static vy_result CreateDevice(void) {
static rt_result CreateDevice(void) {
const char *extensions[] = {
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
};
vy_queue_indices queue_indices = RetrieveQueueIndices(g_gpu.phys_device, g_gpu.surface);
rt_queue_indices queue_indices = RetrieveQueueIndices(g_gpu.phys_device, g_gpu.surface);
g_gpu.compute_family = queue_indices.compute;
g_gpu.graphics_family = queue_indices.graphics;
@ -402,14 +402,14 @@ static vy_result CreateDevice(void) {
VkDeviceCreateInfo device_info = {
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
.enabledExtensionCount = VY_ARRAY_COUNT(extensions),
.enabledExtensionCount = RT_ARRAY_COUNT(extensions),
.ppEnabledExtensionNames = extensions,
.pQueueCreateInfos = queue_info,
.queueCreateInfoCount = distinct_queue_count,
};
if (vkCreateDevice(g_gpu.phys_device, &device_info, g_gpu.alloc_cb, &g_gpu.device) !=
VK_SUCCESS) {
vyReportError("vk", "Device creation failed.");
rtReportError("vk", "Device creation failed.");
return 10;
}
@ -417,14 +417,14 @@ static vy_result CreateDevice(void) {
vkGetDeviceQueue(g_gpu.device, queue_indices.compute, 0, &g_gpu.compute_queue);
vkGetDeviceQueue(g_gpu.device, queue_indices.present, 0, &g_gpu.present_queue);
return VY_SUCCESS;
return RT_SUCCESS;
}
extern vy_result InitPipelineManagement(void);
extern rt_result InitPipelineManagement(void);
extern void ShutdownPipelineManagement(void);
vy_result VY_RENDERER_API_FN(Init)(const vy_renderer_init_info *info) {
vyLog("vk", "Init");
rt_result RT_RENDERER_API_FN(Init)(const rt_renderer_init_info *info) {
rtLog("vk", "Init");
_tracking_alloc_cbs.pUserData = NULL;
_tracking_alloc_cbs.pfnAllocation = TrackAllocation;
@ -438,31 +438,31 @@ vy_result VY_RENDERER_API_FN(Init)(const vy_renderer_init_info *info) {
}
int res = CreateInstance();
if (res != VY_SUCCESS)
if (res != RT_SUCCESS)
return res;
res = CreateSurface(info);
if (res != VY_SUCCESS)
if (res != RT_SUCCESS)
return res;
res = ChoosePhysicalDevice();
if (res != VY_SUCCESS)
if (res != RT_SUCCESS)
return res;
res = CreateDevice();
if (res != VY_SUCCESS)
if (res != RT_SUCCESS)
return res;
res = InitPipelineManagement();
if (res != VY_SUCCESS)
if (res != RT_SUCCESS)
return res;
res = vyCreateSwapchain();
if (res != VY_SUCCESS)
res = rtCreateSwapchain();
if (res != RT_SUCCESS)
return res;
return VY_SUCCESS;
return RT_SUCCESS;
}
void VY_RENDERER_API_FN(Shutdown)(void) {
vyLog("vk", "Shutdown");
void RT_RENDERER_API_FN(Shutdown)(void) {
rtLog("vk", "Shutdown");
vkDeviceWaitIdle(g_gpu.device);
vyDestroySwapchain();
rtDestroySwapchain();
ShutdownPipelineManagement();
vkDestroyDevice(g_gpu.device, g_gpu.alloc_cb);
vkDestroySurfaceKHR(g_gpu.instance, g_gpu.surface, g_gpu.alloc_cb);

View File

@ -9,38 +9,38 @@
#include <volk/volk.h>
#include <stdlib.h>
VY_CVAR_I(r_VkMaxPipelineCount, "Maximum number of pipeline objects. Default: 1024", 1024);
RT_CVAR_I(r_VkMaxPipelineCount, "Maximum number of pipeline objects. Default: 1024", 1024);
typedef struct vy_pipeline_s {
typedef struct rt_pipeline_s {
uint32_t version;
vy_pipeline pipeline;
struct vy_pipeline_s *next_free;
} vy_pipeline_slot;
rt_pipeline pipeline;
struct rt_pipeline_s *next_free;
} rt_pipeline_slot;
static vy_pipeline_slot *_pipelines;
static vy_pipeline_slot *_first_free;
static vy_rwlock _lock;
static rt_pipeline_slot *_pipelines;
static rt_pipeline_slot *_first_free;
static rt_rwlock _lock;
vy_result InitPipelineManagement(void) {
vy_create_rwlock_result lock_res = vyCreateRWLock();
rt_result InitPipelineManagement(void) {
rt_create_rwlock_result lock_res = rtCreateRWLock();
if (!lock_res.ok)
return VY_UNKNOWN_ERROR;
return RT_UNKNOWN_ERROR;
_lock = lock_res.lock;
_pipelines = calloc(r_VkMaxPipelineCount.i, sizeof(vy_pipeline_slot));
_pipelines = calloc(r_VkMaxPipelineCount.i, sizeof(rt_pipeline_slot));
if (!_pipelines) {
vyDestroyRWLock(&_lock);
return VY_OUT_OF_MEMORY;
rtDestroyRWLock(&_lock);
return RT_OUT_OF_MEMORY;
}
/* Keep [0] unused to preserve 0 as the invalid handle */
_first_free = &_pipelines[1];
for (int i = 1; i < r_VkMaxPipelineCount.i - 1; ++i) {
_pipelines[i].next_free = &_pipelines[i + 1];
}
return VY_SUCCESS;
return RT_SUCCESS;
}
static void DestroyPipeline(vy_pipeline_slot *slot) {
static void DestroyPipeline(rt_pipeline_slot *slot) {
if (slot->pipeline.pipeline) {
vkDestroyPipeline(g_gpu.device, slot->pipeline.pipeline, g_gpu.alloc_cb);
}
@ -53,22 +53,22 @@ void ShutdownPipelineManagement(void) {
DestroyPipeline(&_pipelines[i]);
}
free(_pipelines);
vyDestroyRWLock(&_lock);
rtDestroyRWLock(&_lock);
_first_free = NULL;
}
vy_pipeline_handle VY_RENDERER_API_FN(CompilePipeline)(const vy_pipeline_info *info) {
vy_pipeline_handle handle = VY_INVALID_HANDLE;
vyLockWrite(&_lock);
rt_pipeline_handle RT_RENDERER_API_FN(CompilePipeline)(const rt_pipeline_info *info) {
rt_pipeline_handle handle = RT_INVALID_HANDLE;
rtLockWrite(&_lock);
if (!_first_free) {
vyLog("VK", "No free pipeline slots!");
vyUnlockWrite(&_lock);
rtLog("VK", "No free pipeline slots!");
rtUnlockWrite(&_lock);
return handle;
}
vy_pipeline_slot *slot = _first_free;
rt_pipeline_slot *slot = _first_free;
_first_free = slot->next_free;
slot->version = (slot->version + 1) & VY_GFX_HANDLE_MAX_VERSION;
vyUnlockWrite(&_lock);
slot->version = (slot->version + 1) & RT_GFX_HANDLE_MAX_VERSION;
rtUnlockWrite(&_lock);
/* No other thread that calls compile gets the same slot.
* Another thread accessing the slot via GetPipeline would get a version mismatch.
@ -78,26 +78,26 @@ vy_pipeline_handle VY_RENDERER_API_FN(CompilePipeline)(const vy_pipeline_info *i
return handle;
}
void VY_RENDERER_API_FN(DestroyPipeline)(vy_pipeline_handle handle) {
void RT_RENDERER_API_FN(DestroyPipeline)(rt_pipeline_handle handle) {
if (handle.index >= (uint32_t)r_VkMaxPipelineCount.i)
return;
vyLockWrite(&_lock);
rtLockWrite(&_lock);
if (_pipelines[handle.index].version == handle.version)
DestroyPipeline(&_pipelines[handle.index]);
else
vyLog("VK", "Tried to destroy a pipeline using an outdated handle.");
vyUnlockWrite(&_lock);
rtLog("VK", "Tried to destroy a pipeline using an outdated handle.");
rtUnlockWrite(&_lock);
}
const vy_pipeline *vyGetPipeline(vy_pipeline_handle handle) {
const rt_pipeline *rtGetPipeline(rt_pipeline_handle handle) {
if (handle.index >= (uint32_t)r_VkMaxPipelineCount.i)
return NULL;
vyLockRead(&_lock);
vy_pipeline *res = NULL;
rtLockRead(&_lock);
rt_pipeline *res = NULL;
if (_pipelines[handle.index].version == handle.version)
res = &_pipelines[handle.index].pipeline;
else
vyLog("VK", "Tried to access a pipeline using an outdated handle.");
vyUnlockRead(&_lock);
rtLog("VK", "Tried to access a pipeline using an outdated handle.");
rtUnlockRead(&_lock);
return res;
}

View File

@ -1,5 +1,5 @@
#ifndef VY_VK_PIPELINES_H
#define VY_VK_PIPELINES_H
#ifndef RT_VK_PIPELINES_H
#define RT_VK_PIPELINES_H
#include <volk/volk.h>
@ -7,9 +7,9 @@
typedef struct {
VkPipeline pipeline;
} vy_pipeline;
} rt_pipeline;
/* A pipeline is immutable after creation. */
const vy_pipeline *vyGetPipeline(vy_pipeline_handle handle);
const rt_pipeline *rtGetPipeline(rt_pipeline_handle handle);
#endif

View File

@ -1,4 +1,4 @@
#define VY_VK_DONT_DEFINE_SWAPCHAIN_GLOBAL
#define RT_VK_DONT_DEFINE_SWAPCHAIN_GLOBAL
#include "swapchain.h"
#include "gpu.h"
@ -9,24 +9,24 @@
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#elif defined(VY_USE_XLIB)
#elif defined(RT_USE_XLIB)
#include <X11/Xlib.h>
#endif
VY_CVAR_I(r_VkPreferredSwapchainImages,
RT_CVAR_I(r_VkPreferredSwapchainImages,
"Preferred number of swapchain iamges. [2/3] Default: 2",
2);
VY_CVAR_I(r_VkPreferMailboxMode, "Prefer mailbox present mode over fifo mode. [0/1] Default: 0", 1);
RT_CVAR_I(r_VkPreferMailboxMode, "Prefer mailbox present mode over fifo mode. [0/1] Default: 0", 1);
typedef struct {
VkPresentModeKHR present_mode;
VkSurfaceFormatKHR surface_format;
VkExtent2D extent;
VkSurfaceTransformFlagsKHR pre_transform;
} vy_device_swapchain_parameters;
} rt_device_swapchain_parameters;
static vy_device_swapchain_parameters DetermineSwapchainParameters(void) {
vy_device_swapchain_parameters params;
static rt_device_swapchain_parameters DetermineSwapchainParameters(void) {
rt_device_swapchain_parameters params;
/* determine presentation mode. FIFO should always be available */
params.present_mode = VK_PRESENT_MODE_FIFO_KHR;
@ -76,10 +76,10 @@ static vy_device_swapchain_parameters DetermineSwapchainParameters(void) {
return params;
}
vy_swapchain g_swapchain;
rt_swapchain g_swapchain;
vy_result vyCreateSwapchain(void) {
vy_device_swapchain_parameters device_params = DetermineSwapchainParameters();
rt_result rtCreateSwapchain(void) {
rt_device_swapchain_parameters device_params = DetermineSwapchainParameters();
uint32_t image_count = r_VkPreferredSwapchainImages.i;
if (image_count < 2)
@ -117,7 +117,7 @@ vy_result vyCreateSwapchain(void) {
&swapchain_info,
g_gpu.alloc_cb,
&g_swapchain.swapchain) != VK_SUCCESS) {
vyReportError("vk", "Failed to create the swapchain");
rtReportError("vk", "Failed to create the swapchain");
return 50;
}
g_swapchain.format = device_params.surface_format.format;
@ -125,8 +125,8 @@ vy_result vyCreateSwapchain(void) {
/* Retrieve images */
g_swapchain.image_count = 0;
vkGetSwapchainImagesKHR(g_gpu.device, g_swapchain.swapchain, &g_swapchain.image_count, NULL);
if (g_swapchain.image_count > VY_VK_MAX_SWAPCHAIN_IMAGES) {
vyReportError("vk", "Unsupported number of swapchain images: %u", g_swapchain.image_count);
if (g_swapchain.image_count > RT_VK_MAX_SWAPCHAIN_IMAGES) {
rtReportError("vk", "Unsupported number of swapchain images: %u", g_swapchain.image_count);
return 51;
}
vkGetSwapchainImagesKHR(g_gpu.device,
@ -161,21 +161,21 @@ vy_result vyCreateSwapchain(void) {
&view_info,
g_gpu.alloc_cb,
&g_swapchain.image_views[i]) != VK_SUCCESS) {
vyReportError("vk", "Failed to create an image view for the swapchain.");
rtReportError("vk", "Failed to create an image view for the swapchain.");
return 52;
}
}
return VY_SUCCESS;
return RT_SUCCESS;
}
vy_result vyRecreateSwapchain(void) {
rt_result rtRecreateSwapchain(void) {
/* TODO(Kevin): Old swapchain in swapchain create info */
vyDestroySwapchain();
return vyCreateSwapchain();
rtDestroySwapchain();
return rtCreateSwapchain();
}
void vyDestroySwapchain(void) {
void rtDestroySwapchain(void) {
for (uint32_t i = 0; i < g_swapchain.image_count; ++i) {
vkDestroyImageView(g_gpu.device, g_swapchain.image_views[i], g_gpu.alloc_cb);
}

View File

@ -1,28 +1,28 @@
#ifndef VY_VK_SWAPCHAIN_H
#define VY_VK_SWAPCHAIN_H
#ifndef RT_VK_SWAPCHAIN_H
#define RT_VK_SWAPCHAIN_H
#include <volk/volk.h>
#include "runtime/runtime.h"
#define VY_VK_MAX_SWAPCHAIN_IMAGES 3
#define RT_VK_MAX_SWAPCHAIN_IMAGES 3
typedef struct {
VkSwapchainKHR swapchain;
VkImage images[VY_VK_MAX_SWAPCHAIN_IMAGES];
VkImageView image_views[VY_VK_MAX_SWAPCHAIN_IMAGES];
VkImage images[RT_VK_MAX_SWAPCHAIN_IMAGES];
VkImageView image_views[RT_VK_MAX_SWAPCHAIN_IMAGES];
uint32_t image_count;
VkFormat format;
} vy_swapchain;
} rt_swapchain;
#ifndef VY_VK_DONT_DEFINE_SWAPCHAIN_GLOBAL
extern vy_swapchain g_swapchain;
#ifndef RT_VK_DONT_DEFINE_SWAPCHAIN_GLOBAL
extern rt_swapchain g_swapchain;
#endif
vy_result vyCreateSwapchain(void);
rt_result rtCreateSwapchain(void);
vy_result vyRecreateSwapchain(void);
rt_result rtRecreateSwapchain(void);
void vyDestroySwapchain(void);
void rtDestroySwapchain(void);
#endif

View File

@ -21,33 +21,33 @@ typedef struct {
HANDLE file_handle;
OVERLAPPED overlapped;
#endif
volatile vy_aio_state state;
} vy_aio;
volatile rt_aio_state state;
} rt_aio;
typedef struct {
vy_mutex *guard;
rt_mutex *guard;
vy_aio *storage;
rt_aio *storage;
uint32_t capacity;
uint32_t head;
uint32_t tail;
} vy_aio_ringbuffer;
} rt_aio_ringbuffer;
typedef struct {
vy_aio *a;
vy_aio *b;
rt_aio *a;
rt_aio *b;
uint32_t a_count;
} vy_ringbuffer_space;
} rt_ringbuffer_space;
static vy_aio_ringbuffer _ringbuffer;
static rt_aio_ringbuffer _ringbuffer;
static vy_ringbuffer_space ReserveRingbufferSpace(uint32_t count) {
if (!vyLockMutex(_ringbuffer.guard)) {
vy_ringbuffer_space failed = {NULL, NULL, 0};
static rt_ringbuffer_space ReserveRingbufferSpace(uint32_t count) {
if (!rtLockMutex(_ringbuffer.guard)) {
rt_ringbuffer_space failed = {NULL, NULL, 0};
return failed;
}
vy_ringbuffer_space result = {NULL, NULL, 0};
rt_ringbuffer_space result = {NULL, NULL, 0};
if (_ringbuffer.head >= _ringbuffer.tail) {
if (_ringbuffer.head + count <= _ringbuffer.capacity) {
@ -66,7 +66,7 @@ static vy_ringbuffer_space ReserveRingbufferSpace(uint32_t count) {
_ringbuffer.head = b_count;
} else {
/* Not enough space, we would overwrite the tail */
vyLog("aio", "Ringbuffer is full.");
rtLog("aio", "Ringbuffer is full.");
}
}
} else {
@ -78,78 +78,78 @@ static vy_ringbuffer_space ReserveRingbufferSpace(uint32_t count) {
_ringbuffer.head = (_ringbuffer.head + count) % _ringbuffer.capacity;
} else {
/* Not enough space, we would overwrite the tail */
vyLog("aio", "Ringbuffer is full.");
rtLog("aio", "Ringbuffer is full.");
}
}
vyUnlockMutex(_ringbuffer.guard);
rtUnlockMutex(_ringbuffer.guard);
return result;
}
#ifdef _WIN32
static void
win32CompletionRoutine(DWORD error_code, DWORD num_bytes_transfered, LPOVERLAPPED overlapped) {
vy_aio *op = (vy_aio *)overlapped->hEvent;
assert(op->state == VY_AIO_STATE_PENDING);
rt_aio *op = (rt_aio *)overlapped->hEvent;
assert(op->state == RT_AIO_STATE_PENDING);
if (error_code != ERROR_SUCCESS) {
op->state = VY_AIO_STATE_FAILED;
vyLog("aio", "Async io failed: %u", error_code);
op->state = RT_AIO_STATE_FAILED;
rtLog("aio", "Async io failed: %u", error_code);
} else {
op->state = VY_AIO_STATE_FINISHED;
op->state = RT_AIO_STATE_FINISHED;
}
CloseHandle(op->file_handle);
}
#endif
VY_CVAR_I(rt_MaxConcurrentAsyncIO,
RT_CVAR_I(rt_MaxConcurrentAsyncIO,
"Maximum number of concurrent async. I/O operations. Default: 1024",
1024);
vy_result InitAIO(void) {
rt_result InitAIO(void) {
unsigned int max_concurrent_operations = rt_MaxConcurrentAsyncIO.i;
_ringbuffer.guard = vyCreateMutex();
_ringbuffer.guard = rtCreateMutex();
if (!_ringbuffer.guard) {
return VY_AIO_OUT_OF_MEMORY;
return RT_AIO_OUT_OF_MEMORY;
}
if (max_concurrent_operations == 0)
max_concurrent_operations = 1024;
_ringbuffer.storage = calloc(max_concurrent_operations, sizeof(vy_aio));
_ringbuffer.storage = calloc(max_concurrent_operations, sizeof(rt_aio));
if (!_ringbuffer.storage)
return VY_AIO_OUT_OF_MEMORY;
return RT_AIO_OUT_OF_MEMORY;
_ringbuffer.head = 0;
_ringbuffer.tail = 0;
_ringbuffer.capacity = max_concurrent_operations;
return VY_SUCCESS;
return RT_SUCCESS;
}
void ShutdownAIO(void) {
vyDestroyMutex(_ringbuffer.guard);
rtDestroyMutex(_ringbuffer.guard);
free(_ringbuffer.storage);
_ringbuffer.capacity = 0;
}
VY_DLLEXPORT vy_result vySubmitLoadBatch(const vy_load_batch *batch, vy_aio_handle *handles) {
if (batch->num_loads > VY_LOAD_BATCH_MAX_SIZE) {
return VY_AIO_LOAD_TOO_LARGE;
RT_DLLEXPORT rt_result rtSubmitLoadBatch(const rt_load_batch *batch, rt_aio_handle *handles) {
if (batch->num_loads > RT_LOAD_BATCH_MAX_SIZE) {
return RT_AIO_LOAD_TOO_LARGE;
}
vy_ringbuffer_space rbspace = ReserveRingbufferSpace(batch->num_loads);
rt_ringbuffer_space rbspace = ReserveRingbufferSpace(batch->num_loads);
if (!rbspace.a) {
vyReportError("aio", "Too many pending file operations");
return VY_AIO_TOO_MANY_OPERATIONS;
rtReportError("aio", "Too many pending file operations");
return RT_AIO_TOO_MANY_OPERATIONS;
}
for (unsigned int i = 0; i < batch->num_loads; ++i) {
vy_aio *op = (i < rbspace.a_count) ? &rbspace.a[i] : &rbspace.b[i - rbspace.a_count];
op->state = VY_AIO_STATE_PENDING;
const char *file_path = vyGetFilePath(batch->loads[i].file);
rt_aio *op = (i < rbspace.a_count) ? &rbspace.a[i] : &rbspace.b[i - rbspace.a_count];
op->state = RT_AIO_STATE_PENDING;
const char *file_path = rtGetFilePath(batch->loads[i].file);
if (!file_path) {
vyReportError("aio", "Failed to resolve file path for a batched load");
op->state = VY_AIO_STATE_INVALID;
handles[i] = VY_AIO_INVALID_HANDLE;
rtReportError("aio", "Failed to resolve file path for a batched load");
op->state = RT_AIO_STATE_INVALID;
handles[i] = RT_AIO_INVALID_HANDLE;
continue;
}
#ifdef _WIN32
@ -168,10 +168,10 @@ VY_DLLEXPORT vy_result vySubmitLoadBatch(const vy_load_batch *batch, vy_aio_hand
file_path,
-1,
wpath,
VY_ARRAY_COUNT(wpath)) == 0) {
vyReportError("aio", "MultiByteToWideChar failed with error code: %u", GetLastError());
op->state = VY_AIO_STATE_FINISHED;
handles[i] = VY_AIO_INVALID_HANDLE;
RT_ARRAY_COUNT(wpath)) == 0) {
rtReportError("aio", "MultiByteToWideChar failed with error code: %u", GetLastError());
op->state = RT_AIO_STATE_FINISHED;
handles[i] = RT_AIO_INVALID_HANDLE;
continue;
}
@ -183,12 +183,12 @@ VY_DLLEXPORT vy_result vySubmitLoadBatch(const vy_load_batch *batch, vy_aio_hand
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
NULL);
if (file_handle == INVALID_HANDLE_VALUE) {
vyReportError("aio",
rtReportError("aio",
"CreateFileW failed for file: %s with error code: %u",
file_path,
GetLastError());
op->state = VY_AIO_STATE_INVALID;
handles[i] = VY_AIO_INVALID_HANDLE;
op->state = RT_AIO_STATE_INVALID;
handles[i] = RT_AIO_INVALID_HANDLE;
continue;
}
op->file_handle = file_handle;
@ -199,9 +199,9 @@ VY_DLLEXPORT vy_result vySubmitLoadBatch(const vy_load_batch *batch, vy_aio_hand
win32CompletionRoutine);
DWORD err = GetLastError();
if (!result || err != ERROR_SUCCESS) {
vyReportError("aio", "ReadFileEx failed with error code: %u", err);
op->state = VY_AIO_STATE_FINISHED;
handles[i] = VY_AIO_INVALID_HANDLE;
rtReportError("aio", "ReadFileEx failed with error code: %u", err);
op->state = RT_AIO_STATE_FINISHED;
handles[i] = RT_AIO_INVALID_HANDLE;
CloseHandle(file_handle);
op->file_handle = NULL;
}
@ -212,69 +212,69 @@ VY_DLLEXPORT vy_result vySubmitLoadBatch(const vy_load_batch *batch, vy_aio_hand
#endif
}
return VY_SUCCESS;
return RT_SUCCESS;
}
VY_DLLEXPORT volatile vy_aio_state vyGetAIOState(vy_aio_handle handle) {
if (handle == VY_AIO_INVALID_HANDLE || handle > _ringbuffer.capacity)
return VY_AIO_STATE_INVALID;
RT_DLLEXPORT volatile rt_aio_state rtGetAIOState(rt_aio_handle handle) {
if (handle == RT_AIO_INVALID_HANDLE || handle > _ringbuffer.capacity)
return RT_AIO_STATE_INVALID;
#ifdef _WIN32
/* Give the compation function an opportunity to run */
SleepEx(0, TRUE);
#endif
vyLockMutex(_ringbuffer.guard);
vy_aio_state state = _ringbuffer.storage[handle - 1].state;
vyUnlockMutex(_ringbuffer.guard);
rtLockMutex(_ringbuffer.guard);
rt_aio_state state = _ringbuffer.storage[handle - 1].state;
rtUnlockMutex(_ringbuffer.guard);
return state;
}
VY_DLLEXPORT void vyReleaseAIO(vy_aio_handle handle) {
if (handle == VY_AIO_INVALID_HANDLE || handle > _ringbuffer.capacity) {
RT_DLLEXPORT void rtReleaseAIO(rt_aio_handle handle) {
if (handle == RT_AIO_INVALID_HANDLE || handle > _ringbuffer.capacity) {
return;
}
vyLockMutex(_ringbuffer.guard);
_ringbuffer.storage[handle - 1].state = VY_AIO_STATE_INVALID;
rtLockMutex(_ringbuffer.guard);
_ringbuffer.storage[handle - 1].state = RT_AIO_STATE_INVALID;
if (handle - 1 == _ringbuffer.tail) {
/* Advance the tail such that it points to the last used slot. (Or to head, if the
* ringbuffer is now empty) */
uint32_t i = _ringbuffer.tail;
while ((_ringbuffer.storage[i].state == VY_AIO_STATE_INVALID) && i != _ringbuffer.head) {
while ((_ringbuffer.storage[i].state == RT_AIO_STATE_INVALID) && i != _ringbuffer.head) {
i = (i + 1) % _ringbuffer.capacity;
}
_ringbuffer.tail = i;
}
vyUnlockMutex(_ringbuffer.guard);
rtUnlockMutex(_ringbuffer.guard);
}
VY_DLLEXPORT vy_aio_state vyWaitForAIOCompletion(vy_aio_handle handle) {
if (handle == VY_AIO_INVALID_HANDLE || handle > _ringbuffer.capacity)
return VY_AIO_STATE_INVALID;
vy_aio_state state;
RT_DLLEXPORT rt_aio_state rtWaitForAIOCompletion(rt_aio_handle handle) {
if (handle == RT_AIO_INVALID_HANDLE || handle > _ringbuffer.capacity)
return RT_AIO_STATE_INVALID;
rt_aio_state state;
do {
state = vyGetAIOState(handle);
state = rtGetAIOState(handle);
/* NOTE(Kevin): This is where we could temporarily run a job. */
#ifdef _WIN32
YieldProcessor();
#elif defined(__linux__)
sched_yield();
#endif
} while (state == VY_AIO_STATE_PENDING);
} while (state == RT_AIO_STATE_PENDING);
return state;
}
VY_DLLEXPORT vy_result vySubmitSingleLoad(vy_file_load load, vy_aio_handle *handle) {
vy_load_batch batch;
RT_DLLEXPORT rt_result rtSubmitSingleLoad(rt_file_load load, rt_aio_handle *handle) {
rt_load_batch batch;
batch.loads[0] = load;
batch.num_loads = 1;
return vySubmitLoadBatch(&batch, handle);
return rtSubmitLoadBatch(&batch, handle);
}
VY_DLLEXPORT vy_aio_state vySubmitSingleLoadSync(vy_file_load load) {
vy_aio_handle handle;
if (vySubmitSingleLoad(load, &handle) != VY_SUCCESS)
return VY_AIO_STATE_FAILED;
vy_aio_state state = vyWaitForAIOCompletion(handle);
vyReleaseAIO(handle);
RT_DLLEXPORT rt_aio_state rtSubmitSingleLoadSync(rt_file_load load) {
rt_aio_handle handle;
if (rtSubmitSingleLoad(load, &handle) != RT_SUCCESS)
return RT_AIO_STATE_FAILED;
rt_aio_state state = rtWaitForAIOCompletion(handle);
rtReleaseAIO(handle);
return state;
}

View File

@ -1,5 +1,5 @@
#ifndef VY_AIO_H
#define VY_AIO_H
#ifndef RT_AIO_H
#define RT_AIO_H
#include <stdint.h>
@ -13,57 +13,57 @@ typedef struct {
* Must be valid until the load is finished.
*/
void *dest;
vy_file_id file; /**< Unique identifier for the file */
} vy_file_load;
rt_file_id file; /**< Unique identifier for the file */
} rt_file_load;
#define VY_LOAD_BATCH_MAX_SIZE 64
#define RT_LOAD_BATCH_MAX_SIZE 64
/** A batch of loads that will be started together.
*
* The aio system will hand these to the OS.
*/
typedef struct {
vy_file_load loads[VY_LOAD_BATCH_MAX_SIZE];
rt_file_load loads[RT_LOAD_BATCH_MAX_SIZE];
/** Must be smaller or equal to @c VY_LOAD_BATCH_MAX_SIZE */
/** Must be smaller or equal to @c RT_LOAD_BATCH_MAX_SIZE */
unsigned int num_loads;
} vy_load_batch;
} rt_load_batch;
#define VY_AIO_INVALID_HANDLE 0
#define RT_AIO_INVALID_HANDLE 0
/** Handle for an async io operation. Can be used to query the state and result. */
typedef uint32_t vy_aio_handle;
typedef uint32_t rt_aio_handle;
enum {
VY_AIO_LOAD_TOO_LARGE = (VY_SUCCESS + 1),
VY_AIO_TOO_MANY_OPERATIONS,
VY_AIO_OUT_OF_MEMORY,
RT_AIO_LOAD_TOO_LARGE = (RT_SUCCESS + 1),
RT_AIO_TOO_MANY_OPERATIONS,
RT_AIO_OUT_OF_MEMORY,
};
typedef enum {
VY_AIO_STATE_INVALID,
VY_AIO_STATE_PENDING,
VY_AIO_STATE_FINISHED,
VY_AIO_STATE_FAILED,
} vy_aio_state;
RT_AIO_STATE_INVALID,
RT_AIO_STATE_PENDING,
RT_AIO_STATE_FINISHED,
RT_AIO_STATE_FAILED,
} rt_aio_state;
VY_DLLEXPORT vy_result vySubmitLoadBatch(const vy_load_batch *batch, vy_aio_handle *handles);
RT_DLLEXPORT rt_result rtSubmitLoadBatch(const rt_load_batch *batch, rt_aio_handle *handles);
VY_DLLEXPORT volatile vy_aio_state vyGetAIOState(vy_aio_handle handle);
RT_DLLEXPORT volatile rt_aio_state rtGetAIOState(rt_aio_handle handle);
/* Blocks until the given operation is no longer pending.
* Returns the state that caused the wait to end. The handle is still valid after this function returned. */
VY_DLLEXPORT vy_aio_state vyWaitForAIOCompletion(vy_aio_handle handle);
RT_DLLEXPORT rt_aio_state rtWaitForAIOCompletion(rt_aio_handle handle);
/* Releases the internal storage for the operation.
* The system is allowed to re-use the same handle value for new operations after this was called.
*/
VY_DLLEXPORT void vyReleaseAIO(vy_aio_handle handle);
RT_DLLEXPORT void rtReleaseAIO(rt_aio_handle handle);
VY_DLLEXPORT vy_result vySubmitSingleLoad(vy_file_load load, vy_aio_handle *handle);
RT_DLLEXPORT rt_result rtSubmitSingleLoad(rt_file_load load, rt_aio_handle *handle);
/* Convenience wrapper for a single synchronous file load.
* Returns the state that caused the wait for completion to return. */
VY_DLLEXPORT vy_aio_state vySubmitSingleLoadSync(vy_file_load load);
RT_DLLEXPORT rt_aio_state rtSubmitSingleLoadSync(rt_file_load load);
#endif

View File

@ -5,9 +5,9 @@
#include "gfx.h"
#include "renderer_api.h"
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);
RT_CVAR_I(rt_Fullscreen, "Show window in fullscreen mode. [0/1] Default: 0", 0);
RT_CVAR_I(rt_WindowWidth, "Window width. Default: 1024", 1024);
RT_CVAR_I(rt_WindowHeight, "Window height. Default: 768", 768);
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
@ -23,22 +23,22 @@ static LRESULT CALLBACK win32WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM
}
}
VY_DLLEXPORT int
vyWin32Entry(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow) {
if (vyInitRuntime() != VY_SUCCESS)
RT_DLLEXPORT int
rtWin32Entry(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow) {
if (rtInitRuntime() != RT_SUCCESS)
return 1;
vyRegisterRendererCVars();
rtRegisterRendererCVars();
WNDCLASSEXW wndclass = {
.cbSize = sizeof(wndclass),
.hInstance = hInstance,
.lpszClassName = L"vyWndClass",
.lpszClassName = L"rtWndClass",
.style = CS_OWNDC,
.lpfnWndProc = win32WndProc,
};
if (!RegisterClassExW(&wndclass)) {
vyReportError("CORE", "RegisterClassEx failed: %u", GetLastError());
rtReportError("CORE", "RegisterClassEx failed: %u", GetLastError());
return 1;
}
@ -48,7 +48,7 @@ vyWin32Entry(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int n
int w = GetSystemMetrics(SM_CXSCREEN);
int h = GetSystemMetrics(SM_CYSCREEN);
wnd = CreateWindowExW(WS_EX_APPWINDOW,
L"vyWndClass",
L"rtWndClass",
L"Voyage",
WS_POPUP,
0,
@ -65,7 +65,7 @@ vyWin32Entry(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int n
int w = rt_WindowWidth.i;
int h = rt_WindowHeight.i;
wnd = CreateWindowExW(WS_EX_APPWINDOW,
L"vyWndClass",
L"rtWndClass",
L"Voyage",
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU,
CW_USEDEFAULT,
@ -80,13 +80,13 @@ vyWin32Entry(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int n
}
if (!wnd) {
vyReportError("CORE", "Failed to create the game window: %u", GetLastError());
rtReportError("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.");
rt_renderer_init_info renderer_info = {.hWnd = wnd, .hInstance = hInstance};
if (!rtInitGFX(&renderer_info)) {
rtReportError("GFX", "Init failed.");
return 1;
}
@ -104,17 +104,17 @@ vyWin32Entry(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int n
}
}
vyShutdownGFX();
rtShutdownGFX();
DestroyWindow(wnd);
UnregisterClassW(L"vyWndClass", hInstance);
UnregisterClassW(L"rtWndClass", hInstance);
vyShutdownRuntime();
rtShutdownRuntime();
return 0;
}
#elif defined(VY_USE_XLIB)
#elif defined(RT_USE_XLIB)
#include <X11/Xlib.h>
#include <assert.h>
@ -123,7 +123,7 @@ static void xlibSetFullscreen(Display *dpy, int screen, Window window, bool enab
Atom wm_state = XInternAtom(dpy, "_NET_W_STATE", False);
Atom wm_fullscreen = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False);
if (wm_state == None || wm_fullscreen == None) {
vyLog("CORE", "Window manager does not support fullscreen mode.");
rtLog("CORE", "Window manager does not support fullscreen mode.");
return;
}
@ -146,7 +146,7 @@ static void xlibSetFullscreen(Display *dpy, int screen, Window window, bool enab
long ev_mask = SubstructureRedirectMask;
if (!XSendEvent(dpy, root_window, False, ev_mask, &ev)) {
vyReportError("CORE", "Failed to send x11 fullscreen event.");
rtReportError("CORE", "Failed to send x11 fullscreen event.");
}
#undef _NET_WM_STATE_ADD
@ -154,16 +154,16 @@ static void xlibSetFullscreen(Display *dpy, int screen, Window window, bool enab
#undef EVENT_SOURCE_APPLICATION
}
VY_DLLEXPORT int vyXlibEntry(int argc, char **argv) {
if (vyInitRuntime() != VY_SUCCESS)
RT_DLLEXPORT int rtXlibEntry(int argc, char **argv) {
if (rtInitRuntime() != RT_SUCCESS)
return 1;
vyRegisterRendererCVars();
rtRegisterRendererCVars();
Display *dpy = XOpenDisplay(NULL);
if (!dpy) {
vyReportError("CORE", "Failed to open default display");
rtReportError("CORE", "Failed to open default display");
return 1;
}
int screen = DefaultScreen(dpy);
@ -185,7 +185,7 @@ VY_DLLEXPORT int vyXlibEntry(int argc, char **argv) {
Atom wm_close = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
if (!wm_close) {
vyReportError("CORE", "Failed to find WM_DELETE_WINDOW atom.");
rtReportError("CORE", "Failed to find WM_DELETE_WINDOW atom.");
XDestroyWindow(dpy, window);
XCloseDisplay(dpy);
return 1;
@ -195,9 +195,9 @@ VY_DLLEXPORT int vyXlibEntry(int argc, char **argv) {
if (rt_Fullscreen.i)
xlibSetFullscreen(dpy, screen, window, true);
vy_renderer_init_info renderer_info = {.display = dpy, .window = window};
if (!vyInitGFX(&renderer_info)) {
vyReportError("GFX", "Init failed.");
rt_renderer_init_info renderer_info = {.display = dpy, .window = window};
if (!rtInitGFX(&renderer_info)) {
rtReportError("GFX", "Init failed.");
return 1;
}
@ -218,7 +218,7 @@ VY_DLLEXPORT int vyXlibEntry(int argc, char **argv) {
break;
case ClientMessage:
if (event.xclient.data.l[0] == (long)wm_close) {
vyLog("CORE", "Received WM_DELETE_WINDOW");
rtLog("CORE", "Received WM_DELETE_WINDOW");
keep_running = false;
}
break;
@ -226,10 +226,10 @@ VY_DLLEXPORT int vyXlibEntry(int argc, char **argv) {
}
}
vyShutdownGFX();
rtShutdownGFX();
XDestroyWindow(dpy, window);
XCloseDisplay(dpy);
vyShutdownRuntime();
rtShutdownRuntime();
return 0;
}

View File

@ -1,5 +1,5 @@
#ifndef VY_APP_H
#define VY_APP_H
#ifndef RT_APP_H
#define RT_APP_H
/* Platform specific application entry point */
@ -10,14 +10,14 @@
/* Forward declared here, to avoid including windows.h */
struct HINSTANCE__;
VY_DLLEXPORT int vyWin32Entry(struct HINSTANCE__ *hInstance,
RT_DLLEXPORT int rtWin32Entry(struct HINSTANCE__ *hInstance,
struct HINSTANCE__ *hPrevInstance,
wchar_t *pCmdLine,
int nCmdShow);
#elif defined(VY_USE_XLIB)
#elif defined(RT_USE_XLIB)
VY_DLLEXPORT int vyXlibEntry(int argc, char **argv);
RT_DLLEXPORT int rtXlibEntry(int argc, char **argv);
#endif

View File

@ -9,10 +9,10 @@
#include <assert.h>
#include <stdlib.h>
VY_CVAR_I(rt_AssetCacheSize, "Number of asset cache entries. Default: 1024.", 1024);
RT_CVAR_I(rt_AssetCacheSize, "Number of asset cache entries. Default: 1024.", 1024);
/* asset_loading.c */
extern vy_result DecompressAsset(void *compressed_buffer,
extern rt_result DecompressAsset(void *compressed_buffer,
size_t compressed_buffer_size,
void **p_decompressed,
size_t *p_decompressed_size);
@ -21,63 +21,63 @@ typedef enum {
CACHE_ENTRY_STATE_FREE,
CACHE_ENTRY_STATE_LOADING,
CACHE_ENTRY_STATE_LOADED,
} vy_asset_cache_entry_state;
} rt_asset_cache_entry_state;
typedef struct vy_asset_cache_entry_s {
vy_asset_cache_entry_state state;
vy_aio_handle load;
typedef struct rt_asset_cache_entry_s {
rt_asset_cache_entry_state state;
rt_aio_handle load;
void *buffer;
size_t size;
int refcount;
/* Reclaim list */
struct vy_asset_cache_entry_s *prev_reclaim;
struct vy_asset_cache_entry_s *next_reclaim;
} vy_asset_cache_entry;
struct rt_asset_cache_entry_s *prev_reclaim;
struct rt_asset_cache_entry_s *next_reclaim;
} rt_asset_cache_entry;
static vy_uid *_uids;
static vy_asset_cache_entry *_entries;
static vy_asset_cache_entry *_first_reclaim;
static vy_asset_cache_entry *_last_reclaim;
static rt_uid *_uids;
static rt_asset_cache_entry *_entries;
static rt_asset_cache_entry *_first_reclaim;
static rt_asset_cache_entry *_last_reclaim;
/* Locked as writer when modifiying entries, as reader when searching */
static vy_rwlock _lock;
static rt_rwlock _lock;
vy_result InitAssetCache(void) {
_entries = calloc((size_t)rt_AssetCacheSize.i, sizeof(vy_asset_cache_entry));
rt_result InitAssetCache(void) {
_entries = calloc((size_t)rt_AssetCacheSize.i, sizeof(rt_asset_cache_entry));
if (!_entries) {
return VY_BUFFER_ALLOC_FAILED;
return RT_BUFFER_ALLOC_FAILED;
}
_uids = calloc((size_t)rt_AssetCacheSize.i, sizeof(vy_uid));
_uids = calloc((size_t)rt_AssetCacheSize.i, sizeof(rt_uid));
if (!_uids) {
free(_entries);
return VY_BUFFER_ALLOC_FAILED;
return RT_BUFFER_ALLOC_FAILED;
}
vy_create_rwlock_result lock_res = vyCreateRWLock();
rt_create_rwlock_result lock_res = rtCreateRWLock();
if (!lock_res.ok) {
free(_entries);
free(_uids);
return VY_UNKNOWN_ERROR;
return RT_UNKNOWN_ERROR;
}
_lock = lock_res.lock;
return VY_SUCCESS;
return RT_SUCCESS;
}
void ShutdownAssetCache(void) {
free(_entries);
free(_uids);
vyDestroyRWLock(&_lock);
rtDestroyRWLock(&_lock);
_first_reclaim = NULL;
_last_reclaim = NULL;
}
static void ReleaseEntry(vy_asset_cache_entry *entry) {
if (entry->load != VY_AIO_INVALID_HANDLE) {
vyWaitForAIOCompletion(entry->load);
vyReleaseAIO(entry->load);
entry->load = VY_AIO_INVALID_HANDLE;
static void ReleaseEntry(rt_asset_cache_entry *entry) {
if (entry->load != RT_AIO_INVALID_HANDLE) {
rtWaitForAIOCompletion(entry->load);
rtReleaseAIO(entry->load);
entry->load = RT_AIO_INVALID_HANDLE;
}
vyReleaseBuffer(entry->buffer, entry->size);
rtReleaseBuffer(entry->buffer, entry->size);
entry->buffer = NULL;
entry->size = 0;
entry->next_reclaim = NULL;
@ -85,28 +85,28 @@ static void ReleaseEntry(vy_asset_cache_entry *entry) {
}
static void GarbageCollect(void) {
vyLockWrite(&_lock);
vy_asset_cache_entry *entry = _first_reclaim;
rtLockWrite(&_lock);
rt_asset_cache_entry *entry = _first_reclaim;
while (entry) {
assert(entry->refcount == 0);
vy_asset_cache_entry *next = entry->next_reclaim;
rt_asset_cache_entry *next = entry->next_reclaim;
if (entry->state == CACHE_ENTRY_STATE_LOADED) {
ReleaseEntry(entry);
_first_reclaim = next;
}
entry = next;
}
vyUnlockWrite(&_lock);
rtUnlockWrite(&_lock);
}
static vy_asset_cache_entry *GetEntry(vy_uid uid) {
static rt_asset_cache_entry *GetEntry(rt_uid uid) {
/* Hash lookup */
unsigned int mod = (unsigned int)rt_AssetCacheSize.i - 1;
for (unsigned int i = 0; i < (unsigned int)rt_AssetCacheSize.i; ++i) {
unsigned int slot = (uid + i) & mod;
if (_uids[slot] == uid) {
return &_entries[slot];
} else if (_uids[slot] == VY_INVALID_UID) {
} else if (_uids[slot] == RT_INVALID_UID) {
break;
}
}
@ -114,8 +114,8 @@ static vy_asset_cache_entry *GetEntry(vy_uid uid) {
}
static bool IsAssetLoaded(vy_uid uid) {
const vy_asset_cache_entry *entry = GetEntry(uid);
static bool IsAssetLoaded(rt_uid uid) {
const rt_asset_cache_entry *entry = GetEntry(uid);
if (entry)
return entry->state == CACHE_ENTRY_STATE_LOADED ||
entry->state == CACHE_ENTRY_STATE_LOADING;
@ -123,7 +123,7 @@ static bool IsAssetLoaded(vy_uid uid) {
return false;
}
static int InsertEntry(vy_uid uid) {
static int InsertEntry(rt_uid uid) {
unsigned int mod = (unsigned int)rt_AssetCacheSize.i - 1;
for (unsigned int i = 0; i < (unsigned int)rt_AssetCacheSize.i; ++i) {
unsigned int slot = (uid + i) & mod;
@ -133,58 +133,58 @@ static int InsertEntry(vy_uid uid) {
}
return -1;
}
static vy_result InsertAndLoadAssets(const vy_uid *uids, size_t count) {
vy_load_batch batch = {.num_loads = 0};
static rt_result InsertAndLoadAssets(const rt_uid *uids, size_t count) {
rt_load_batch batch = {.num_loads = 0};
vy_result res = VY_SUCCESS;
rt_result res = RT_SUCCESS;
count = (count < VY_LOAD_BATCH_MAX_SIZE) ? count : VY_LOAD_BATCH_MAX_SIZE;
vy_asset_cache_entry *load_entries[VY_LOAD_BATCH_MAX_SIZE];
count = (count < RT_LOAD_BATCH_MAX_SIZE) ? count : RT_LOAD_BATCH_MAX_SIZE;
rt_asset_cache_entry *load_entries[RT_LOAD_BATCH_MAX_SIZE];
for (size_t i = 0; i < count; ++i) {
vyLockRead(&_lock);
rtLockRead(&_lock);
bool needs_load = !IsAssetLoaded(uids[i]);
vyUnlockRead(&_lock);
rtUnlockRead(&_lock);
if (!needs_load)
continue;
vyLockWrite(&_lock);
rtLockWrite(&_lock);
/* It's possible that another thread loaded the asset in the meantime */
if (!IsAssetLoaded(uids[i])) {
const vy_uid_data *data = vyGetUIDData(uids[i]);
const rt_uid_data *data = rtGetUIDData(uids[i]);
if (!data) {
vyUnlockWrite(&_lock);
vyLog("ASSET_CACHE", "Failed to get uid data for uid %u", uids[i]);
res = VY_UNKNOWN_ASSET;
rtUnlockWrite(&_lock);
rtLog("ASSET_CACHE", "Failed to get uid data for uid %u", uids[i]);
res = RT_UNKNOWN_ASSET;
continue;
}
void *compressed_data = vyAllocBuffer(data->size);
void *compressed_data = rtAllocBuffer(data->size);
if (!compressed_data) {
/* Try again after garbage collection */
vyUnlockWrite(&_lock);
rtUnlockWrite(&_lock);
GarbageCollect();
compressed_data = vyAllocBuffer(data->size);
compressed_data = rtAllocBuffer(data->size);
if (!compressed_data) {
vyLog("ASSET_CACHE",
rtLog("ASSET_CACHE",
"Failed to allocate intermediate buffer for uid %u",
uids[i]);
res = VY_BUFFER_ALLOC_FAILED;
res = RT_BUFFER_ALLOC_FAILED;
continue;
}
vyLockWrite(&_lock);
rtLockWrite(&_lock);
}
int slot = InsertEntry(uids[i]);
if (slot == -1) {
vyUnlockWrite(&_lock);
vyLog("ASSET_CACHE", "Failed to insert new entry for uid %u", uids[i]);
res = VY_ASSET_CACHE_FULL;
rtUnlockWrite(&_lock);
rtLog("ASSET_CACHE", "Failed to insert new entry for uid %u", uids[i]);
res = RT_ASSET_CACHE_FULL;
break;
}
vy_asset_cache_entry *entry = &_entries[slot];
rt_asset_cache_entry *entry = &_entries[slot];
load_entries[batch.num_loads] = entry;
/* We set the refcount to 0, but don't insert the entry
@ -197,7 +197,7 @@ static vy_result InsertAndLoadAssets(const vy_uid *uids, size_t count) {
entry->size = data->size;
entry->next_reclaim = NULL;
entry->prev_reclaim = NULL;
entry->load = VY_AIO_INVALID_HANDLE;
entry->load = RT_AIO_INVALID_HANDLE;
batch.loads[batch.num_loads].file = data->pkg_file;
batch.loads[batch.num_loads].num_bytes = data->size;
@ -206,45 +206,45 @@ static vy_result InsertAndLoadAssets(const vy_uid *uids, size_t count) {
++batch.num_loads;
}
}
vyUnlockWrite(&_lock);
rtUnlockWrite(&_lock);
/* Dispatch the load */
vy_aio_handle handles[VY_LOAD_BATCH_MAX_SIZE];
if ((res = vySubmitLoadBatch(&batch, handles)) != VY_SUCCESS) {
vyLog("ASSET_CACHE", "Failed to submit %u asset loads.", batch.num_loads);
rt_aio_handle handles[RT_LOAD_BATCH_MAX_SIZE];
if ((res = rtSubmitLoadBatch(&batch, handles)) != RT_SUCCESS) {
rtLog("ASSET_CACHE", "Failed to submit %u asset loads.", batch.num_loads);
return res;
}
/* Set the aio handles of the inserted entries */
vyLockWrite(&_lock);
rtLockWrite(&_lock);
for (unsigned int i = 0; i < batch.num_loads; ++i) {
load_entries[batch.num_loads]->load = handles[i];
}
vyUnlockWrite(&_lock);
rtUnlockWrite(&_lock);
return res;
}
static bool DecompressEntry(vy_uid uid, vy_asset_cache_entry *entry) {
vyReleaseAIO(entry->load);
entry->load = VY_AIO_INVALID_HANDLE;
static bool DecompressEntry(rt_uid uid, rt_asset_cache_entry *entry) {
rtReleaseAIO(entry->load);
entry->load = RT_AIO_INVALID_HANDLE;
void *decompressed_buffer;
size_t decompressed_size;
vy_result dec_res =
rt_result dec_res =
DecompressAsset(entry->buffer, entry->size, &decompressed_buffer, &decompressed_size);
if (dec_res == VY_SUCCESS) {
vyReleaseBuffer(entry->buffer, entry->size);
if (dec_res == RT_SUCCESS) {
rtReleaseBuffer(entry->buffer, entry->size);
entry->buffer = decompressed_buffer;
entry->size = decompressed_size;
entry->state = CACHE_ENTRY_STATE_LOADED;
return true;
} else if (dec_res == VY_BUFFER_ALLOC_FAILED) {
} else if (dec_res == RT_BUFFER_ALLOC_FAILED) {
GarbageCollect();
/* Try again */
if (DecompressAsset(entry->buffer, entry->size, &decompressed_buffer, &decompressed_size) ==
VY_SUCCESS) {
vyReleaseBuffer(entry->buffer, entry->size);
RT_SUCCESS) {
rtReleaseBuffer(entry->buffer, entry->size);
entry->buffer = decompressed_buffer;
entry->size = decompressed_size;
entry->state = CACHE_ENTRY_STATE_LOADED;
@ -252,74 +252,74 @@ static bool DecompressEntry(vy_uid uid, vy_asset_cache_entry *entry) {
}
/* Don't do anything yet. We might be able to to do this later, once some
* buffers become free. */
vyLog("ASSET_CACHE", "Failed to decompress asset %u", uid);
rtLog("ASSET_CACHE", "Failed to decompress asset %u", uid);
return false;
} else {
vyLog("ASSET_CACHE", "Failed to decompress asset %u", uid);
rtLog("ASSET_CACHE", "Failed to decompress asset %u", uid);
ReleaseEntry(entry);
ptrdiff_t idx = entry - _entries;
_uids[idx] = VY_INVALID_UID;
_uids[idx] = RT_INVALID_UID;
return false;
}
}
static void CheckCompletedLoads(const vy_uid *uids, size_t count) {
static void CheckCompletedLoads(const rt_uid *uids, size_t count) {
for (size_t i = 0; i < count; ++i) {
vyLockRead(&_lock);
volatile vy_asset_cache_entry *entry = (volatile vy_asset_cache_entry *)GetEntry(uids[i]);
rtLockRead(&_lock);
volatile rt_asset_cache_entry *entry = (volatile rt_asset_cache_entry *)GetEntry(uids[i]);
if (!entry) {
vyUnlockRead(&_lock);
vyLog("ASSET_CACHE", "Passed unknown uid %u to CheckCompletedLoads()", uids[i]);
rtUnlockRead(&_lock);
rtLog("ASSET_CACHE", "Passed unknown uid %u to CheckCompletedLoads()", uids[i]);
continue;
}
if (entry->state != CACHE_ENTRY_STATE_LOADING) {
vyUnlockRead(&_lock);
rtUnlockRead(&_lock);
continue;
}
bool load_finished = vyGetAIOState(entry->load) == VY_AIO_STATE_FINISHED;
vyUnlockRead(&_lock);
bool load_finished = rtGetAIOState(entry->load) == RT_AIO_STATE_FINISHED;
rtUnlockRead(&_lock);
if (load_finished) {
vyLockWrite(&_lock);
rtLockWrite(&_lock);
/* Ensure that no-one else handled this */
if (entry->state == CACHE_ENTRY_STATE_LOADING) {
DecompressEntry(uids[i], (vy_asset_cache_entry *)entry);
DecompressEntry(uids[i], (rt_asset_cache_entry *)entry);
}
vyUnlockWrite(&_lock);
rtUnlockWrite(&_lock);
}
}
}
VY_DLLEXPORT vy_get_asset_result vyGetAsset(vy_uid uid) {
vy_get_asset_result result = {
.result = VY_SUCCESS,
RT_DLLEXPORT rt_get_asset_result rtGetAsset(rt_uid uid) {
rt_get_asset_result result = {
.result = RT_SUCCESS,
};
vyLockRead(&_lock);
rtLockRead(&_lock);
bool needs_load = !IsAssetLoaded(uid);
vyUnlockRead(&_lock);
rtUnlockRead(&_lock);
if (needs_load) {
vy_uid load_uids[VY_LOAD_BATCH_MAX_SIZE];
rt_uid load_uids[RT_LOAD_BATCH_MAX_SIZE];
size_t load_count = 1;
load_uids[0] = uid;
vy_asset_dependency_list deps = vyGetAssetDependencies(uid);
for (size_t i = 0; i < deps.count && i < VY_LOAD_BATCH_MAX_SIZE - 1; ++i) {
rt_asset_dependency_list deps = rtGetAssetDependencies(uid);
for (size_t i = 0; i < deps.count && i < RT_LOAD_BATCH_MAX_SIZE - 1; ++i) {
load_uids[i + 1] = deps.dependencies[i];
++load_count;
}
result.result = InsertAndLoadAssets(load_uids, load_count);
if (result.result == VY_SUCCESS) {
if (result.result == RT_SUCCESS) {
CheckCompletedLoads(load_uids, load_count);
}
}
vyLockWrite(&_lock);
vy_asset_cache_entry *entry = GetEntry(uid);
rtLockWrite(&_lock);
rt_asset_cache_entry *entry = GetEntry(uid);
if (entry) {
if (entry->state == CACHE_ENTRY_STATE_LOADED) {
++entry->refcount;
@ -327,19 +327,19 @@ VY_DLLEXPORT vy_get_asset_result vyGetAsset(vy_uid uid) {
result.size = entry->size;
} else if (entry->state == CACHE_ENTRY_STATE_LOADING) {
if (entry->state == CACHE_ENTRY_STATE_LOADING) {
assert(entry->load != VY_AIO_INVALID_HANDLE);
assert(entry->load != RT_AIO_INVALID_HANDLE);
++entry->refcount;
if (vyWaitForAIOCompletion(entry->load) == VY_AIO_STATE_FINISHED) {
if (rtWaitForAIOCompletion(entry->load) == RT_AIO_STATE_FINISHED) {
if (DecompressEntry(uid, entry)) {
result.data = entry->buffer;
result.size = entry->size;
} else {
result.result = VY_LOAD_FAILED;
result.result = RT_LOAD_FAILED;
}
} else {
ReleaseEntry(entry);
vyLog("ASSET_CACHE", "Failed to load asset %u", uid);
result.result = VY_LOAD_FAILED;
rtLog("ASSET_CACHE", "Failed to load asset %u", uid);
result.result = RT_LOAD_FAILED;
}
}
}
@ -354,14 +354,14 @@ VY_DLLEXPORT vy_get_asset_result vyGetAsset(vy_uid uid) {
if (entry->prev_reclaim)
entry->prev_reclaim->next_reclaim = entry->next_reclaim;
}
vyUnlockWrite(&_lock);
rtUnlockWrite(&_lock);
return result;
}
VY_DLLEXPORT void vyReleaseAsset(vy_uid uid) {
vyLockWrite(&_lock);
vy_asset_cache_entry *entry = GetEntry(uid);
RT_DLLEXPORT void rtReleaseAsset(rt_uid uid) {
rtLockWrite(&_lock);
rt_asset_cache_entry *entry = GetEntry(uid);
if (entry && entry->refcount > 0) {
--entry->refcount;
if (entry->refcount == 0) {
@ -375,5 +375,5 @@ VY_DLLEXPORT void vyReleaseAsset(vy_uid uid) {
_last_reclaim = entry;
}
}
vyUnlockWrite(&_lock);
rtUnlockWrite(&_lock);
}

View File

@ -1,4 +1,4 @@
#define VY_DEFINE_DEPENDENCY_FILE_STRUCTURES
#define RT_DEFINE_DEPENDENCY_FILE_STRUCTURES
#include "asset_dependencies.h"
#include "aio.h"
@ -12,87 +12,87 @@
typedef struct {
uint32_t begin;
uint32_t count;
} vy_dep_list;
} rt_dep_list;
typedef struct {
vy_uid *uids;
vy_dep_list *lists;
rt_uid *uids;
rt_dep_list *lists;
uint32_t capacity;
} vy_dep_map;
} rt_dep_map;
static vy_dep_map _map;
static vy_uid *_list_mem;
static rt_dep_map _map;
static rt_uid *_list_mem;
vy_result LoadAssetDependencies(void) {
vy_dependency_file_header header;
vy_file_id fid = vyAddFile("data/deps.bin");
rt_result LoadAssetDependencies(void) {
rt_dependency_file_header header;
rt_file_id fid = rtAddFile("data/deps.bin");
if (vySubmitSingleLoadSync((vy_file_load){.dest = &header,
if (rtSubmitSingleLoadSync((rt_file_load){.dest = &header,
.num_bytes = sizeof(header),
.offset = 0,
.file = fid}) != VY_AIO_STATE_FINISHED) {
vyReportError("core", "Failed to load deps.bin");
return VY_UNKNOWN_ERROR;
.file = fid}) != RT_AIO_STATE_FINISHED) {
rtReportError("core", "Failed to load deps.bin");
return RT_UNKNOWN_ERROR;
}
void *buffer = vyAllocBuffer(header.data_size);
if (vySubmitSingleLoadSync((vy_file_load){.dest = buffer,
void *buffer = rtAllocBuffer(header.data_size);
if (rtSubmitSingleLoadSync((rt_file_load){.dest = buffer,
.num_bytes = header.data_size,
.offset = sizeof(header),
.file = fid}) != VY_AIO_STATE_FINISHED) {
vyReportError("core", "Failed to load deps.bin");
return VY_UNKNOWN_ERROR;
.file = fid}) != RT_AIO_STATE_FINISHED) {
rtReportError("core", "Failed to load deps.bin");
return RT_UNKNOWN_ERROR;
}
/* We know the exact number of list entries */
uint64_t total_list_entries =
(header.data_size - header.num_lists * sizeof(vy_dependency_file_list_header)) /
sizeof(vy_uid);
_list_mem = malloc(total_list_entries * sizeof(vy_uid));
(header.data_size - header.num_lists * sizeof(rt_dependency_file_list_header)) /
sizeof(rt_uid);
_list_mem = malloc(total_list_entries * sizeof(rt_uid));
if (!_list_mem) {
vyReleaseBuffer(buffer, header.data_size);
vyReportError("core", "Failed to allocate dependency list storage.");
return VY_UNKNOWN_ERROR;
rtReleaseBuffer(buffer, header.data_size);
rtReportError("core", "Failed to allocate dependency list storage.");
return RT_UNKNOWN_ERROR;
}
_map.capacity = vyNextPowerOfTwo32(header.num_lists);
_map.uids = calloc(_map.capacity, sizeof(vy_uid));
_map.capacity = rtNextPowerOfTwo32(header.num_lists);
_map.uids = calloc(_map.capacity, sizeof(rt_uid));
if (!_map.uids) {
free(_list_mem);
vyReleaseBuffer(buffer, header.data_size);
vyReportError("core", "Failed to allocate dependency list storage.");
return VY_UNKNOWN_ERROR;
rtReleaseBuffer(buffer, header.data_size);
rtReportError("core", "Failed to allocate dependency list storage.");
return RT_UNKNOWN_ERROR;
}
_map.lists = calloc(_map.capacity, sizeof(vy_dep_list));
_map.lists = calloc(_map.capacity, sizeof(rt_dep_list));
if (!_map.uids) {
free(_list_mem);
free(_map.uids);
vyReleaseBuffer(buffer, header.data_size);
vyReportError("core", "Failed to allocate dependency list storage.");
return VY_UNKNOWN_ERROR;
rtReleaseBuffer(buffer, header.data_size);
rtReportError("core", "Failed to allocate dependency list storage.");
return RT_UNKNOWN_ERROR;
}
uint32_t storage_at = 0;
vy_dependency_file_list_header *list = buffer;
rt_dependency_file_list_header *list = buffer;
for (uint32_t i = 0; i < header.num_lists; ++i) {
const vy_uid *entries = (vy_uid *)(list + 1);
const rt_uid *entries = (rt_uid *)(list + 1);
/* Validate the checksum */
XXH64_hash_t file_hash = XXH64_hashFromCanonical(&list->checksum);
XXH64_hash_t calc_hash = XXH3_64bits(entries, sizeof(vy_uid) * list->num_entries);
XXH64_hash_t calc_hash = XXH3_64bits(entries, sizeof(rt_uid) * list->num_entries);
if (file_hash != calc_hash) {
vyReportError("core", "Checksum mismatch in list %u", i);
vyReleaseBuffer(buffer, header.data_size);
return VY_UNKNOWN_ERROR;
rtReportError("core", "Checksum mismatch in list %u", i);
rtReleaseBuffer(buffer, header.data_size);
return RT_UNKNOWN_ERROR;
}
/* Store the list */
memcpy(_list_mem + storage_at, entries, sizeof(vy_uid) * list->num_entries);
memcpy(_list_mem + storage_at, entries, sizeof(rt_uid) * list->num_entries);
bool inserted = false;
for (uint32_t j = 0; j < _map.capacity; ++j) {
uint32_t slot = (list->uid + j) % _map.capacity;
if (_map.uids[slot] == VY_INVALID_UID) {
if (_map.uids[slot] == RT_INVALID_UID) {
_map.uids[slot] = list->uid;
_map.lists[slot].begin = storage_at;
_map.lists[slot].count = list->num_entries;
@ -104,12 +104,12 @@ vy_result LoadAssetDependencies(void) {
assert(inserted);
assert(storage_at <= total_list_entries);
list = (vy_dependency_file_list_header *)(entries + list->num_entries);
list = (rt_dependency_file_list_header *)(entries + list->num_entries);
}
vyReleaseBuffer(buffer, header.data_size);
rtReleaseBuffer(buffer, header.data_size);
return VY_SUCCESS;
return RT_SUCCESS;
}
void ReleaseAssetDependencies(void) {
@ -118,8 +118,8 @@ void ReleaseAssetDependencies(void) {
free(_map.lists);
}
VY_DLLEXPORT vy_asset_dependency_list vyGetAssetDependencies(vy_uid asset) {
vy_asset_dependency_list result = {
RT_DLLEXPORT rt_asset_dependency_list rtGetAssetDependencies(rt_uid asset) {
rt_asset_dependency_list result = {
.dependencies = NULL,
.count = 0,
};
@ -129,7 +129,7 @@ VY_DLLEXPORT vy_asset_dependency_list vyGetAssetDependencies(vy_uid asset) {
result.dependencies = &_list_mem[_map.lists[slot].begin];
result.count = _map.lists[slot].count;
break;
} else if (_map.uids[slot] == VY_INVALID_UID) {
} else if (_map.uids[slot] == RT_INVALID_UID) {
break;
}
}

View File

@ -1,9 +1,9 @@
#ifndef VY_ASSET_DEPENDENCIES_H
#define VY_ASSET_DEPENDENCIES_H
#ifndef RT_ASSET_DEPENDENCIES_H
#define RT_ASSET_DEPENDENCIES_H
#include "assets.h"
#ifdef VY_DEFINE_DEPENDENCY_FILE_STRUCTURES
#ifdef RT_DEFINE_DEPENDENCY_FILE_STRUCTURES
#include "xxhash/xxhash.h"
@ -11,23 +11,23 @@
typedef struct {
uint64_t data_size;
uint32_t num_lists;
} vy_dependency_file_header;
} rt_dependency_file_header;
typedef struct {
vy_uid uid;
rt_uid uid;
uint32_t num_entries;
XXH64_canonical_t checksum;
} vy_dependency_file_list_header;
} rt_dependency_file_list_header;
#pragma pack(pop)
#endif
typedef struct {
const vy_uid *dependencies;
const rt_uid *dependencies;
uint32_t count;
} vy_asset_dependency_list;
} rt_asset_dependency_list;
VY_DLLEXPORT vy_asset_dependency_list vyGetAssetDependencies(vy_uid asset);
RT_DLLEXPORT rt_asset_dependency_list rtGetAssetDependencies(rt_uid asset);
#endif

View File

@ -3,70 +3,70 @@
#include "aio.h"
#include "buffer_manager.h"
#define VY_DEFINE_PACKAGE_FILE_STRUCTURES
#define RT_DEFINE_PACKAGE_FILE_STRUCTURES
#include "packages.h"
#include "lz4/lz4.h"
vy_result DecompressAsset(void *compressed_buffer,
rt_result DecompressAsset(void *compressed_buffer,
size_t compressed_buffer_size,
void **p_decompressed,
size_t *p_decompressed_size) {
const vy_package_asset_header *header = compressed_buffer;
const rt_package_asset_header *header = compressed_buffer;
size_t compressed_size = (compressed_buffer_size) - sizeof(*header);
XXH64_hash_t calculated_hash = XXH3_64bits((header + 1), compressed_size);
XXH64_hash_t file_hash = XXH64_hashFromCanonical(&header->checksum);
if (calculated_hash != file_hash) {
vyLog("core", "Checksum mismatch for asset");
return VY_LOAD_FAILED;
rtLog("core", "Checksum mismatch for asset");
return RT_LOAD_FAILED;
}
size_t size = (size_t)header->decompressed_size;
void *decompressed_buffer = vyAllocBuffer(size);
void *decompressed_buffer = rtAllocBuffer(size);
if (!decompressed_buffer) {
return VY_BUFFER_ALLOC_FAILED;
return RT_BUFFER_ALLOC_FAILED;
}
if (LZ4_decompress_safe((const char *)(header + 1),
(char *)decompressed_buffer,
(int)compressed_size,
(int)size) < 0) {
return VY_UNKNOWN_ERROR;
return RT_UNKNOWN_ERROR;
}
*p_decompressed = decompressed_buffer;
*p_decompressed_size = size;
return VY_SUCCESS;
return RT_SUCCESS;
}
VY_DLLEXPORT vy_result vyLoadAssetDirect(vy_uid uid, void **p_buffer, size_t *p_size) {
const vy_uid_data *data = vyGetUIDData(uid);
RT_DLLEXPORT rt_result rtLoadAssetDirect(rt_uid uid, void **p_buffer, size_t *p_size) {
const rt_uid_data *data = rtGetUIDData(uid);
if (!data)
return VY_UNKNOWN_ASSET;
return RT_UNKNOWN_ASSET;
void *compressed_buffer = vyAllocBuffer(data->size);
void *compressed_buffer = rtAllocBuffer(data->size);
if (!compressed_buffer) {
return VY_BUFFER_ALLOC_FAILED;
return RT_BUFFER_ALLOC_FAILED;
}
if (vySubmitSingleLoadSync((vy_file_load) {
if (rtSubmitSingleLoadSync((rt_file_load) {
.file = data->pkg_file,
.offset = data->offset,
.num_bytes = data->size,
.dest = compressed_buffer,
}) != VY_AIO_STATE_FINISHED) {
vyReleaseBuffer(compressed_buffer, data->size);
return VY_LOAD_FAILED;
}) != RT_AIO_STATE_FINISHED) {
rtReleaseBuffer(compressed_buffer, data->size);
return RT_LOAD_FAILED;
}
void *decompressed_buffer;
size_t decompressed_size;
vy_result res = DecompressAsset(compressed_buffer, data->size, &decompressed_buffer, &decompressed_size);
rt_result res = DecompressAsset(compressed_buffer, data->size, &decompressed_buffer, &decompressed_size);
vyReleaseBuffer(compressed_buffer, data->size);
rtReleaseBuffer(compressed_buffer, data->size);
*p_buffer = decompressed_buffer;
*p_size = decompressed_size;

View File

@ -1,40 +1,40 @@
#ifndef VY_ASSETS_H
#define VY_ASSETS_H
#ifndef RT_ASSETS_H
#define RT_ASSETS_H
#include <stdint.h>
#include "runtime.h"
/* Unique identifier for an asset. */
typedef uint32_t vy_uid;
typedef uint32_t rt_uid;
#define VY_INVALID_UID 0
#define RT_INVALID_UID 0
/* Used to identify renderer backend dependent assets. */
enum {
VY_INVALID_RENDERER_BACKEND_CODE = 0,
VY_RENDERER_BACKEND_CODE_VK = 1,
RT_INVALID_RENDERER_BACKEND_CODE = 0,
RT_RENDERER_BACKEND_CODE_VK = 1,
VY_RENDERER_BACKEND_CODE_ONE_PAST_LAST,
RT_RENDERER_BACKEND_CODE_ONE_PAST_LAST,
};
typedef uint8_t vy_renderer_backend_code;
typedef uint8_t rt_renderer_backend_code;
enum {
VY_UNKNOWN_ASSET = VY_CUSTOM_ERROR_START,
VY_BUFFER_ALLOC_FAILED,
VY_LOAD_FAILED,
VY_ASSET_CACHE_FULL,
RT_UNKNOWN_ASSET = RT_CUSTOM_ERROR_START,
RT_BUFFER_ALLOC_FAILED,
RT_LOAD_FAILED,
RT_ASSET_CACHE_FULL,
};
/* Load an asset without using the cache */
VY_DLLEXPORT vy_result vyLoadAssetDirect(vy_uid uid, void **buffer, size_t *size);
RT_DLLEXPORT rt_result rtLoadAssetDirect(rt_uid uid, void **buffer, size_t *size);
typedef struct {
void *data;
size_t size;
vy_result result;
} vy_get_asset_result;
rt_result result;
} rt_get_asset_result;
VY_DLLEXPORT vy_get_asset_result vyGetAsset(vy_uid uid);
RT_DLLEXPORT rt_get_asset_result rtGetAsset(rt_uid uid);
#endif

View File

@ -8,13 +8,13 @@
#include <stdint.h>
#include <stdlib.h>
typedef struct vy_buffer_region_s {
typedef struct rt_buffer_region_s {
void *memory;
int16_t *refcounts; // One per block
uint32_t *bitmap;
size_t block_count;
vy_mutex *guard;
} vy_buffer_region;
rt_mutex *guard;
} rt_buffer_region;
/* Count leading zeroes.
* Note that the return value of __builtin_clz(0) is undefined. */
@ -49,17 +49,17 @@ static inline bool IsLZCNTSupported(void) {
#endif
/* NOTE(Kevin): Keep these sorted! */
static size_t _block_sizes[] = {VY_KB(512), VY_MB(1), VY_MB(4), VY_MB(8)};
static size_t _block_sizes[] = {RT_KB(512), RT_MB(1), RT_MB(4), RT_MB(8)};
#define NUM_BLOCK_SIZES (sizeof(_block_sizes) / sizeof(_block_sizes[0]))
static vy_buffer_region _regions[NUM_BLOCK_SIZES];
static rt_buffer_region _regions[NUM_BLOCK_SIZES];
VY_CVAR_SZ(rt_BufferManagerMemory,
RT_CVAR_SZ(rt_BufferManagerMemory,
"Total number of bytes allocated for the buffer manager. Default: 1GB",
VY_GB(1));
RT_GB(1));
vy_result InitBufferManager(void) {
rt_result InitBufferManager(void) {
if ((rt_BufferManagerMemory.sz % NUM_BLOCK_SIZES) != 0)
vyLog("BUFFERMGR",
rtLog("BUFFERMGR",
"Configured memory amount is not dividable by number of block "
"sizes: %u MB/%u",
rt_BufferManagerMemory.sz / (1024 * 1024),
@ -68,7 +68,7 @@ vy_result InitBufferManager(void) {
size_t mem_per_size = rt_BufferManagerMemory.sz / NUM_BLOCK_SIZES;
for (unsigned int i = 0; i < NUM_BLOCK_SIZES; ++i) {
if ((mem_per_size % _block_sizes[i]) != 0)
vyLog("BUFFERMGR",
rtLog("BUFFERMGR",
"Memory per block size is not dividable by block size: %u "
"MB/%u KB",
mem_per_size / (1024 * 1024),
@ -76,46 +76,46 @@ vy_result InitBufferManager(void) {
size_t block_count = mem_per_size / _block_sizes[i];
_regions[i].block_count = block_count;
_regions[i].guard = vyCreateMutex();
_regions[i].guard = rtCreateMutex();
if (!_regions[i].guard) {
vyReportError("BUFFERMGR", "Failed to create guard mutex %u", i);
return VY_BUFFER_MGR_MUTEX_CREATION_FAILED;
rtReportError("BUFFERMGR", "Failed to create guard mutex %u", i);
return RT_BUFFER_MGR_MUTEX_CREATION_FAILED;
}
_regions[i].memory = malloc(mem_per_size);
if (!_regions[i].memory) {
vyDestroyMutex(_regions[i].guard);
vyReportError("BUFFERMGR", "Failed to allocate memory.", i);
return VY_BUFFER_MGR_OUT_OF_MEMORY;
rtDestroyMutex(_regions[i].guard);
rtReportError("BUFFERMGR", "Failed to allocate memory.", i);
return RT_BUFFER_MGR_OUT_OF_MEMORY;
}
_regions[i].bitmap = calloc((block_count + 31) / 32, sizeof(uint32_t));
if (!_regions[i].bitmap) {
vyDestroyMutex(_regions[i].guard);
rtDestroyMutex(_regions[i].guard);
free(_regions[i].memory);
vyReportError("BUFFERMGR", "Failed to allocate memory.", i);
return VY_BUFFER_MGR_OUT_OF_MEMORY;
rtReportError("BUFFERMGR", "Failed to allocate memory.", i);
return RT_BUFFER_MGR_OUT_OF_MEMORY;
}
_regions[i].refcounts = calloc(block_count, sizeof(uint16_t));
if (!_regions[i].refcounts) {
vyDestroyMutex(_regions[i].guard);
rtDestroyMutex(_regions[i].guard);
free(_regions[i].memory);
free(_regions[i].bitmap);
vyReportError("BUFFERMGR", "Failed to allocate memory.", i);
return VY_BUFFER_MGR_OUT_OF_MEMORY;
rtReportError("BUFFERMGR", "Failed to allocate memory.", i);
return RT_BUFFER_MGR_OUT_OF_MEMORY;
}
}
return VY_SUCCESS;
return RT_SUCCESS;
}
void ShutdownBufferManager(void) {
for (unsigned int i = 0; i < NUM_BLOCK_SIZES; ++i) {
vyDestroyMutex(_regions[i].guard);
rtDestroyMutex(_regions[i].guard);
free(_regions[i].memory);
free(_regions[i].bitmap);
free(_regions[i].refcounts);
}
}
VY_DLLEXPORT void *vyAllocBuffer(size_t size) {
RT_DLLEXPORT void *rtAllocBuffer(size_t size) {
assert(IsLZCNTSupported());
// Determine the best block size to use
@ -131,8 +131,8 @@ VY_DLLEXPORT void *vyAllocBuffer(size_t size) {
void *result = NULL;
vy_buffer_region *region = &_regions[best_fit];
vyLockMutex(region->guard);
rt_buffer_region *region = &_regions[best_fit];
rtLockMutex(region->guard);
size_t dword_count = (region->block_count + 31) / 32;
if (required_blocks < 32) {
@ -207,11 +207,11 @@ VY_DLLEXPORT void *vyAllocBuffer(size_t size) {
}
}
vyUnlockMutex(region->guard);
rtUnlockMutex(region->guard);
return result;
}
VY_DLLEXPORT void vyReleaseBuffer(const void *begin, size_t size) {
RT_DLLEXPORT void rtReleaseBuffer(const void *begin, size_t size) {
if (!begin)
return;
uintptr_t begin_addr = (uintptr_t)begin;
@ -223,7 +223,7 @@ VY_DLLEXPORT void vyReleaseBuffer(const void *begin, size_t size) {
size_t block_count = (size + _block_sizes[i] - 1) / _block_sizes[i];
size_t first_block = (begin_addr - region_addr) / _block_sizes[i];
vyLockMutex(_regions[i].guard);
rtLockMutex(_regions[i].guard);
for (size_t j = 0; j < block_count; ++j) {
size_t dword = (first_block + j) / 32;
size_t bit = (first_block + j) % 32;
@ -231,14 +231,14 @@ VY_DLLEXPORT void vyReleaseBuffer(const void *begin, size_t size) {
if (--_regions[i].refcounts[first_block + j] == 0)
_regions[i].bitmap[dword] &= ~(1u << bit);
}
vyUnlockMutex(_regions[i].guard);
rtUnlockMutex(_regions[i].guard);
return;
}
}
vyLog("BUFFERMGR", "Tried to release an invalid buffer");
rtLog("BUFFERMGR", "Tried to release an invalid buffer");
}
VY_DLLEXPORT void vyIncreaseBufferRefCount(const void *begin, size_t size) {
RT_DLLEXPORT void rtIncreaseBufferRefCount(const void *begin, size_t size) {
uintptr_t begin_addr = (uintptr_t)begin;
for (unsigned int i = 0; i < NUM_BLOCK_SIZES; ++i) {
uintptr_t region_addr = (uintptr_t)_regions[i].memory;
@ -248,13 +248,13 @@ VY_DLLEXPORT void vyIncreaseBufferRefCount(const void *begin, size_t size) {
size_t block_count = (size + _block_sizes[i] - 1) / _block_sizes[i];
size_t first_block = (begin_addr - region_addr) / _block_sizes[i];
vyLockMutex(_regions[i].guard);
rtLockMutex(_regions[i].guard);
for (size_t j = 0; j < block_count; ++j) {
++_regions[i].refcounts[first_block + j];
}
vyUnlockMutex(_regions[i].guard);
rtUnlockMutex(_regions[i].guard);
return;
}
}
vyLog("BUFFERMGR", "Tried to increase the refcount of an invalid buffer");
rtLog("BUFFERMGR", "Tried to increase the refcount of an invalid buffer");
}

View File

@ -1,17 +1,17 @@
#ifndef VY_BUFFER_MANAGER_H
#define VY_BUFFER_MANAGER_H
#ifndef RT_BUFFER_MANAGER_H
#define RT_BUFFER_MANAGER_H
#include "runtime.h"
enum {
VY_BUFFER_MGR_OUT_OF_MEMORY = VY_CUSTOM_ERROR_START,
VY_BUFFER_MGR_MUTEX_CREATION_FAILED,
RT_BUFFER_MGR_OUT_OF_MEMORY = RT_CUSTOM_ERROR_START,
RT_BUFFER_MGR_MUTEX_CREATION_FAILED,
};
VY_DLLEXPORT void *vyAllocBuffer(size_t size);
RT_DLLEXPORT void *rtAllocBuffer(size_t size);
VY_DLLEXPORT void vyReleaseBuffer(const void *begin, size_t size);
RT_DLLEXPORT void rtReleaseBuffer(const void *begin, size_t size);
VY_DLLEXPORT void vyIncreaseBufferRefCount(const void *begin, size_t size);
RT_DLLEXPORT void rtIncreaseBufferRefCount(const void *begin, size_t size);
#endif

View File

@ -5,35 +5,35 @@
#include <stddef.h>
#include <string.h>
#define VY_MAX_CVARS 1024
#define RT_MAX_CVARS 1024
static vy_cvar *_vars[VY_MAX_CVARS];
static rt_cvar *_vars[RT_MAX_CVARS];
static unsigned int _next = 0;
static vy_mutex *_mutex = NULL;
static rt_mutex *_mutex = NULL;
void vyRegisterCVAR(vy_cvar *cvar) {
void rtRegisterCVAR(rt_cvar *cvar) {
if (!_mutex)
_mutex = vyCreateMutex();
vyLockMutex(_mutex);
if (_next < VY_MAX_CVARS) {
_mutex = rtCreateMutex();
rtLockMutex(_mutex);
if (_next < RT_MAX_CVARS) {
_vars[_next++] = cvar;
} else {
vyReportError("cvar", "Ran out of space for CVars");
rtReportError("cvar", "Ran out of space for CVars");
}
vyUnlockMutex(_mutex);
rtUnlockMutex(_mutex);
}
vy_cvar *vyGetCVAR(const char *name) {
rt_cvar *rtGetCVAR(const char *name) {
if (!_mutex)
_mutex = vyCreateMutex();
vy_cvar *var = NULL;
vyLockMutex(_mutex);
_mutex = rtCreateMutex();
rt_cvar *var = NULL;
rtLockMutex(_mutex);
for (unsigned int i = 0; i < _next; ++i) {
if (strcmp(name, _vars[i]->name) == 0) {
var = _vars[i];
break;
}
}
vyUnlockMutex(_mutex);
rtUnlockMutex(_mutex);
return var;
}

View File

@ -1,14 +1,14 @@
#ifndef VY_CONFIG_H
#define VY_CONFIG_H
#ifndef RT_CONFIG_H
#define RT_CONFIG_H
#include "runtime.h"
typedef enum {
VY_CVAR_TYPE_INT,
VY_CVAR_TYPE_FLOAT,
VY_CVAR_TYPE_STRING,
VY_CVAR_TYPE_SIZE,
} vy_cvar_type;
RT_CVAR_TYPE_INT,
RT_CVAR_TYPE_FLOAT,
RT_CVAR_TYPE_STRING,
RT_CVAR_TYPE_SIZE,
} rt_cvar_type;
typedef struct {
const char *name;
@ -19,21 +19,21 @@ typedef struct {
const char *s;
size_t sz;
};
vy_cvar_type type;
} vy_cvar;
rt_cvar_type type;
} rt_cvar;
/* n variable name, d description string, v default value*/
#define VY_CVAR_I(n, d, v) \
vy_cvar n = {.name = #n, .description = d, .i = (v), .type = VY_CVAR_TYPE_INT}
#define VY_CVAR_F(n, d, v) \
vy_cvar n = {.name = #n, .description = d, .f = (v), .type = VY_CVAR_TYPE_FLOAT}
#define VY_CVAR_S(n, d, v) \
vy_cvar n = {.name = #n, .description = d, .s = (v), .type = VY_CVAR_TYPE_STRING}
#define VY_CVAR_SZ(n, d, v) \
vy_cvar n = {.name = #n, .description = d, .sz = (v), .type = VY_CVAR_TYPE_SIZE}
#define RT_CVAR_I(n, d, v) \
rt_cvar n = {.name = #n, .description = d, .i = (v), .type = RT_CVAR_TYPE_INT}
#define RT_CVAR_F(n, d, v) \
rt_cvar n = {.name = #n, .description = d, .f = (v), .type = RT_CVAR_TYPE_FLOAT}
#define RT_CVAR_S(n, d, v) \
rt_cvar n = {.name = #n, .description = d, .s = (v), .type = RT_CVAR_TYPE_STRING}
#define RT_CVAR_SZ(n, d, v) \
rt_cvar n = {.name = #n, .description = d, .sz = (v), .type = RT_CVAR_TYPE_SIZE}
VY_DLLEXPORT void vyRegisterCVAR(vy_cvar *cvar);
RT_DLLEXPORT void rtRegisterCVAR(rt_cvar *cvar);
VY_DLLEXPORT vy_cvar *vyGetCVAR(const char *name);
RT_DLLEXPORT rt_cvar *rtGetCVAR(const char *name);
#endif

View File

@ -4,41 +4,41 @@
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
VY_DLLEXPORT vy_dynlib vyOpenCallerLib(void) {
return (vy_dynlib)GetModuleHandleW(NULL);
RT_DLLEXPORT rt_dynlib rtOpenCallerLib(void) {
return (rt_dynlib)GetModuleHandleW(NULL);
}
VY_DLLEXPORT vy_dynlib vyOpenLib(const char *libname) {
RT_DLLEXPORT rt_dynlib rtOpenLib(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;
return (rt_dynlib)mod;
}
VY_DLLEXPORT void *vyGetSymbol(vy_dynlib lib, const char *symbol) {
RT_DLLEXPORT void *rtGetSymbol(rt_dynlib lib, const char *symbol) {
return (void *)GetProcAddress((HMODULE)lib, symbol);
}
VY_DLLEXPORT void vyCloseLib(vy_dynlib lib) {
RT_DLLEXPORT void rtCloseLib(rt_dynlib lib) {
FreeLibrary((HMODULE)lib);
}
#elif defined(__linux__)
#include <dlfcn.h>
VY_DLLEXPORT vy_dynlib vyOpenCallerLib(void) {
RT_DLLEXPORT rt_dynlib rtOpenCallerLib(void) {
return dlopen(NULL, RTLD_NOW | RTLD_LOCAL);
}
VY_DLLEXPORT vy_dynlib vyOpenLib(const char *libname) {
RT_DLLEXPORT rt_dynlib rtOpenLib(const char *libname) {
return dlopen(libname, RTLD_NOW | RTLD_LOCAL);
}
VY_DLLEXPORT void *vyGetSymbol(vy_dynlib lib, const char *symbol) {
RT_DLLEXPORT void *rtGetSymbol(rt_dynlib lib, const char *symbol) {
return dlsym(lib, symbol);
}
VY_DLLEXPORT void vyCloseLib(vy_dynlib lib) {
RT_DLLEXPORT void rtCloseLib(rt_dynlib lib) {
dlclose(lib);
}

View File

@ -1,26 +1,26 @@
#ifndef VY_DYNAMIC_LIBS_H
#define VY_DYNAMIC_LIBS_H
#ifndef RT_DYNAMIC_LIBS_H
#define RT_DYNAMIC_LIBS_H
#include "runtime.h"
#ifdef _WIN32
#define VY_DLLNAME(s) \
#define RT_DLLNAME(s) \
(".\\"s \
".dll")
#elif defined(__linux__)
#define VY_DLLNAME(s) \
#define RT_DLLNAME(s) \
("./lib"s \
".so")
#endif
typedef void *vy_dynlib;
typedef void *rt_dynlib;
VY_DLLEXPORT vy_dynlib vyOpenLib(const char *libname);
RT_DLLEXPORT rt_dynlib rtOpenLib(const char *libname);
VY_DLLEXPORT vy_dynlib vyOpenCallerLib(void);
RT_DLLEXPORT rt_dynlib rtOpenCallerLib(void);
VY_DLLEXPORT void *vyGetSymbol(vy_dynlib lib, const char *symbol);
RT_DLLEXPORT void *rtGetSymbol(rt_dynlib lib, const char *symbol);
VY_DLLEXPORT void vyCloseLib(vy_dynlib lib);
RT_DLLEXPORT void rtCloseLib(rt_dynlib lib);
#endif

View File

@ -22,14 +22,14 @@
static bool DisplayErrorBox(const char *text) {
#ifdef _WIN32
WCHAR msg[256];
vyUTF8ToWStr(text, msg, VY_ARRAY_COUNT(msg));
rtUTF8ToWStr(text, msg, RT_ARRAY_COUNT(msg));
#ifdef VY_ERROR_REPORT_DEBUGBREAK
#ifdef RT_ERROR_REPORT_DEBUGBREAK
return MessageBoxW(NULL, msg, L"Error", MB_OKCANCEL | MB_ICONERROR) == IDCANCEL;
#else
MessageBoxW(NULL, msg, L"Error", MB_ICONERROR);
return false;
#endif /* VY_ERROR_REPORT_DEBUGBREAK */
#endif /* RT_ERROR_REPORT_DEBUGBREAK */
#else
return false;
#endif
@ -38,21 +38,21 @@ static bool DisplayErrorBox(const char *text) {
static void LogOut(const char *text) {
#ifdef _WIN32
WCHAR msg[256];
vyUTF8ToWStr(text, msg, VY_ARRAY_COUNT(msg));
rtUTF8ToWStr(text, msg, RT_ARRAY_COUNT(msg));
OutputDebugStringW(msg);
#endif
fprintf(stderr, "%s", text);
}
VY_DLLEXPORT void vyReportError(const char *subsystem, const char *fmt, ...) {
RT_DLLEXPORT void rtReportError(const char *subsystem, const char *fmt, ...) {
char buf[256];
int at = snprintf(buf, VY_ARRAY_COUNT(buf) - 1, "[%s] ", subsystem);
int at = snprintf(buf, RT_ARRAY_COUNT(buf) - 1, "[%s] ", subsystem);
va_list ap;
va_start(ap, fmt);
at += vsnprintf(&buf[at], VY_ARRAY_COUNT(buf) - at - 1, fmt, ap);
at += vsnprintf(&buf[at], RT_ARRAY_COUNT(buf) - at - 1, fmt, ap);
va_end(ap);
at += snprintf(&buf[at], VY_ARRAY_COUNT(buf) - at - 1, "\n");
at += snprintf(&buf[at], RT_ARRAY_COUNT(buf) - at - 1, "\n");
LogOut(buf);
if (DisplayErrorBox(buf)) {
@ -60,15 +60,15 @@ VY_DLLEXPORT void vyReportError(const char *subsystem, const char *fmt, ...) {
}
}
VY_DLLEXPORT void vyLog(const char *subsystem, const char *fmt, ...) {
RT_DLLEXPORT void rtLog(const char *subsystem, const char *fmt, ...) {
char buf[256];
int at = snprintf(buf, VY_ARRAY_COUNT(buf) - 1, "[%s] ", subsystem);
int at = snprintf(buf, RT_ARRAY_COUNT(buf) - 1, "[%s] ", subsystem);
va_list ap;
va_start(ap, fmt);
at += vsnprintf(&buf[at], VY_ARRAY_COUNT(buf) - at - 1, fmt, ap);
at += vsnprintf(&buf[at], RT_ARRAY_COUNT(buf) - at - 1, fmt, ap);
va_end(ap);
at += snprintf(&buf[at], VY_ARRAY_COUNT(buf) - at - 1, "\n");
at += snprintf(&buf[at], RT_ARRAY_COUNT(buf) - at - 1, "\n");
LogOut(buf);
}

View File

@ -6,22 +6,22 @@
#define NAME_CAP(cap) ((cap)*128)
typedef struct {
vy_file_id *ids;
rt_file_id *ids;
unsigned int *name_offsets;
char *names;
unsigned int capacity;
unsigned int name_head;
vy_mutex *mutex;
} vy_file_tab;
rt_mutex *mutex;
} rt_file_tab;
static vy_file_tab _file_tab;
static rt_file_tab _file_tab;
VY_CVAR_I(rt_FileTabCapacity, "Maximum number of filetab entries. Default: 1024", 1024);
RT_CVAR_I(rt_FileTabCapacity, "Maximum number of filetab entries. Default: 1024", 1024);
vy_result InitFileTab(void) {
rt_result InitFileTab(void) {
unsigned int max_files = (unsigned int)rt_FileTabCapacity.i;
_file_tab.ids = calloc(max_files, sizeof(vy_file_id));
_file_tab.ids = calloc(max_files, sizeof(rt_file_id));
if (!_file_tab.ids)
return 1;
_file_tab.name_offsets = calloc(max_files, sizeof(unsigned int));
@ -33,38 +33,38 @@ vy_result InitFileTab(void) {
_file_tab.capacity = max_files;
_file_tab.name_head = 0;
_file_tab.mutex = vyCreateMutex();
return VY_SUCCESS;
_file_tab.mutex = rtCreateMutex();
return RT_SUCCESS;
}
void ShutdownFileTab(void) {
free(_file_tab.ids);
free(_file_tab.names);
free(_file_tab.name_offsets);
vyDestroyMutex(_file_tab.mutex);
rtDestroyMutex(_file_tab.mutex);
}
VY_DLLEXPORT vy_file_id vyGetFileId(const char *path) {
vy_text_span span;
RT_DLLEXPORT rt_file_id rtGetFileId(const char *path) {
rt_text_span span;
span.start = path;
span.length = (unsigned int)strlen(path);
return vyGetFileIdFromSpan(span);
return rtGetFileIdFromSpan(span);
}
VY_DLLEXPORT vy_file_id vyGetFileIdFromSpan(vy_text_span path) {
RT_DLLEXPORT rt_file_id rtGetFileIdFromSpan(rt_text_span path) {
/* Randomly choosen, aka finger smash keyboard */
XXH64_hash_t seed = 15340978;
vy_file_id fid = (vy_file_id)XXH3_64bits_withSeed(path.start, path.length, seed);
rt_file_id fid = (rt_file_id)XXH3_64bits_withSeed(path.start, path.length, seed);
if (fid == 0)
fid = ~fid;
return fid;
}
VY_DLLEXPORT vy_file_id vyAddFileFromSpan(vy_text_span path) {
vy_file_id fid = vyGetFileIdFromSpan(path);
RT_DLLEXPORT rt_file_id rtAddFileFromSpan(rt_text_span path) {
rt_file_id fid = rtGetFileIdFromSpan(path);
if (!vyLockMutex(_file_tab.mutex)) {
vyReportError("fio", "Failed to lock the guard mutex.");
if (!rtLockMutex(_file_tab.mutex)) {
rtReportError("fio", "Failed to lock the guard mutex.");
return 0;
}
@ -97,24 +97,24 @@ VY_DLLEXPORT vy_file_id vyAddFileFromSpan(vy_text_span path) {
if (i == _file_tab.capacity)
fid = 0;
vyUnlockMutex(_file_tab.mutex);
rtUnlockMutex(_file_tab.mutex);
return fid;
}
VY_DLLEXPORT vy_file_id vyAddFile(const char *path) {
vy_text_span span;
RT_DLLEXPORT rt_file_id rtAddFile(const char *path) {
rt_text_span span;
span.start = path;
span.length = (unsigned int)strlen(path);
return vyAddFileFromSpan(span);
return rtAddFileFromSpan(span);
}
VY_DLLEXPORT const char *vyGetFilePath(vy_file_id fid) {
RT_DLLEXPORT const char *rtGetFilePath(rt_file_id fid) {
/* Hash Lookup */
if (fid == 0)
return NULL;
if (!vyLockMutex(_file_tab.mutex)) {
vyReportError("fio", "Failed to lock the guard mutex.");
if (!rtLockMutex(_file_tab.mutex)) {
rtReportError("fio", "Failed to lock the guard mutex.");
return 0;
}
const char *result = NULL;
@ -130,6 +130,6 @@ VY_DLLEXPORT const char *vyGetFilePath(vy_file_id fid) {
}
++i;
}
vyUnlockMutex(_file_tab.mutex);
rtUnlockMutex(_file_tab.mutex);
return result;
}

View File

@ -1,22 +1,22 @@
#ifndef VY_FILE_TAB_H
#define VY_FILE_TAB_H
#ifndef RT_FILE_TAB_H
#define RT_FILE_TAB_H
#include "runtime.h"
#include <stdint.h>
/* used to identify a file (XXH3 hash of the path) */
typedef uint64_t vy_file_id;
#define VY_INVALID_FILE_ID 0
typedef uint64_t rt_file_id;
#define RT_INVALID_FILE_ID 0
VY_DLLEXPORT vy_file_id vyGetFileId(const char *path);
RT_DLLEXPORT rt_file_id rtGetFileId(const char *path);
VY_DLLEXPORT vy_file_id vyGetFileIdFromSpan(vy_text_span path);
RT_DLLEXPORT rt_file_id rtGetFileIdFromSpan(rt_text_span path);
VY_DLLEXPORT vy_file_id vyAddFile(const char *path);
RT_DLLEXPORT rt_file_id rtAddFile(const char *path);
VY_DLLEXPORT vy_file_id vyAddFileFromSpan(vy_text_span path);
RT_DLLEXPORT rt_file_id rtAddFileFromSpan(rt_text_span path);
VY_DLLEXPORT const char *vyGetFilePath(vy_file_id fid);
RT_DLLEXPORT const char *rtGetFilePath(rt_file_id fid);
#endif

View File

@ -1,5 +1,5 @@
#ifndef VY_GFX_H
#define VY_GFX_H
#ifndef RT_GFX_H
#define RT_GFX_H
/* graphics system. this is the interface of the rendering code.
*
@ -15,22 +15,22 @@
#include "runtime.h"
/* In renderer_api.h -> Not necessary for almost all gfx usage */
typedef struct vy_renderer_init_info_s vy_renderer_init_info;
typedef struct rt_renderer_init_info_s rt_renderer_init_info;
VY_DLLEXPORT void vyRegisterRendererCVars(void);
RT_DLLEXPORT void rtRegisterRendererCVars(void);
VY_DLLEXPORT bool vyInitGFX(vy_renderer_init_info *renderer_info);
RT_DLLEXPORT bool rtInitGFX(rt_renderer_init_info *renderer_info);
VY_DLLEXPORT void vyShutdownGFX(void);
RT_DLLEXPORT void rtShutdownGFX(void);
/* Handles backend objects */
#define VY_GFX_HANDLE_MAX_VERSION 255
#define RT_GFX_HANDLE_MAX_VERSION 255
typedef struct {
uint32_t version : 8;
uint32_t index : 24;
} vy_pipeline_handle;
} rt_pipeline_handle;
/* Attributes are used to bind buffers (or textures) to symbolic values.
* For example, an attribute might be bound to "CELL_GRID", which would be
@ -39,15 +39,15 @@ typedef struct {
*/
typedef enum {
VY_ATTRIBUTE_VALUE_UNDEFINED,
RT_ATTRIBUTE_VALUE_UNDEFINED,
VY_ATTRIBUTE_VALUE_MATERIAL_ALBEDO,
VY_ATTRIBUTE_VALUE_MATERIAL_NORMAL,
} vy_attribute_value;
RT_ATTRIBUTE_VALUE_MATERIAL_ALBEDO,
RT_ATTRIBUTE_VALUE_MATERIAL_NORMAL,
} rt_attribute_value;
typedef struct {
uint32_t index;
vy_attribute_value value;
} vy_attribute_binding;
rt_attribute_value value;
} rt_attribute_binding;
#endif

View File

@ -1,6 +1,6 @@
#include <string.h>
#define VY_DONT_DEFINE_RENDERER_GLOBAL
#define RT_DONT_DEFINE_RENDERER_GLOBAL
#include "config.h"
#include "dynamic_libs.h"
@ -13,45 +13,45 @@
* world cell.
*/
vy_renderer_api g_renderer;
static vy_dynlib _renderer_lib;
rt_renderer_api g_renderer;
static rt_dynlib _renderer_lib;
static bool _renderer_loaded = false;
VY_CVAR_S(rt_Renderer, "Select the render backend. Available options: [vk], Default: vk", "vk");
RT_CVAR_S(rt_Renderer, "Select the render backend. Available options: [vk], Default: vk", "vk");
#ifdef VY_STATIC_LIB
extern void VY_RENDERER_API_FN(RegisterCVars)(void);
extern vy_result VY_RENDERER_API_FN(Init)(const vy_renderer_init_info *);
extern void VY_RENDERER_API_FN(Shutdown)(void);
extern vy_pipeline_handle VY_RENDERER_API_FN(CompilePipeline)(const vy_pipeline_info *);
extern void VY_RENDERER_API_FN(DestroyPipeline)(vy_pipeline_handle handle);
#ifdef RT_STATIC_LIB
extern void RT_RENDERER_API_FN(RegisterCVars)(void);
extern rt_result RT_RENDERER_API_FN(Init)(const rt_renderer_init_info *);
extern void RT_RENDERER_API_FN(Shutdown)(void);
extern rt_pipeline_handle RT_RENDERER_API_FN(CompilePipeline)(const rt_pipeline_info *);
extern void RT_RENDERER_API_FN(DestroyPipeline)(rt_pipeline_handle handle);
#endif
static bool LoadRenderer(void) {
#if !defined(VY_STATIC_LIB)
#if !defined(RT_STATIC_LIB)
#define RETRIEVE_SYMBOL(name, type) \
g_renderer.name = (type *)vyGetSymbol(_renderer_lib, "vyRen" #name); \
g_renderer.name = (type *)rtGetSymbol(_renderer_lib, "rtRen" #name); \
if (!g_renderer.name) { \
vyReportError("GFX", \
rtReportError("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"));
_renderer_lib = rtOpenLib(RT_DLLNAME("rtvk"));
if (!_renderer_lib) {
vyReportError("GFX", "Unable to load renderer backend: %s", VY_DLLNAME("vyvk"));
rtReportError("GFX", "Unable to load renderer backend: %s", RT_DLLNAME("rtvk"));
return false;
}
RETRIEVE_SYMBOL(RegisterCVars, vy_register_renderer_cvars_fn);
RETRIEVE_SYMBOL(Init, vy_init_renderer_fn);
RETRIEVE_SYMBOL(Shutdown, vy_shutdown_renderer_fn);
RETRIEVE_SYMBOL(CompilePipeline, vy_compile_pipeline_fn);
RETRIEVE_SYMBOL(DestroyPipeline, vy_destroy_pipeline_fn);
RETRIEVE_SYMBOL(RegisterCVars, rt_register_renderer_cvars_fn);
RETRIEVE_SYMBOL(Init, rt_init_renderer_fn);
RETRIEVE_SYMBOL(Shutdown, rt_shutdown_renderer_fn);
RETRIEVE_SYMBOL(CompilePipeline, rt_compile_pipeline_fn);
RETRIEVE_SYMBOL(DestroyPipeline, rt_destroy_pipeline_fn);
} else {
vyReportError("GFX",
rtReportError("GFX",
"Unsupported renderer backend: (%s) %s",
rt_Renderer.name,
rt_Renderer.s);
@ -59,16 +59,16 @@ static bool LoadRenderer(void) {
}
#undef RETRIEVE_SYMBOL
#else
g_renderer.RegisterCVars = &vyRenRegisterCVars;
g_renderer.Init = &vyRenInit;
g_renderer.Shutdown = &vyRenShutdown;
g_renderer.CompilePipeline = &vyRenCompilePipeline;
g_renderer.DestroyPipeline = &vyRenDestroyPipeline;
g_renderer.RegisterCVars = &rtRenRegisterCVars;
g_renderer.Init = &rtRenInit;
g_renderer.Shutdown = &rtRenShutdown;
g_renderer.CompilePipeline = &rtRenCompilePipeline;
g_renderer.DestroyPipeline = &rtRenDestroyPipeline;
#endif
return true;
}
VY_DLLEXPORT void vyRegisterRendererCVars(void) {
RT_DLLEXPORT void rtRegisterRendererCVars(void) {
if (!_renderer_loaded) {
if (!LoadRenderer())
return;
@ -77,19 +77,19 @@ VY_DLLEXPORT void vyRegisterRendererCVars(void) {
g_renderer.RegisterCVars();
}
VY_DLLEXPORT bool vyInitGFX(vy_renderer_init_info *renderer_info) {
RT_DLLEXPORT bool rtInitGFX(rt_renderer_init_info *renderer_info) {
if (!_renderer_loaded) {
if (!LoadRenderer())
return false;
g_renderer.RegisterCVars();
}
if (g_renderer.Init(renderer_info) != VY_SUCCESS)
if (g_renderer.Init(renderer_info) != RT_SUCCESS)
return false;
return true;
}
VY_DLLEXPORT void vyShutdownGFX(void) {
RT_DLLEXPORT void rtShutdownGFX(void) {
g_renderer.Shutdown();
}

View File

@ -1,11 +1,11 @@
#ifndef VY_HANDLES_H
#define VY_HANDLES_H
#ifndef RT_HANDLES_H
#define RT_HANDLES_H
/* All handle types should contain a uint32_t index */
#define VY_INVALID_HANDLE \
#define RT_INVALID_HANDLE \
{ .index = 0 }
#define VY_IS_HANDLE_VALID(handle) ((handle).index != 0)
#define RT_IS_HANDLE_VALID(handle) ((handle).index != 0)
#endif

View File

@ -5,85 +5,85 @@
#include "buffer_manager.h"
#include "uidtab.h"
extern vy_cvar rt_Renderer;
extern vy_cvar rt_Fullscreen;
extern vy_cvar rt_WindowWidth;
extern vy_cvar rt_WindowHeight;
extern vy_cvar rt_BufferManagerMemory;
extern vy_cvar rt_FileTabCapacity;
extern vy_cvar rt_MaxConcurrentAsyncIO;
extern vy_cvar rt_AssetCacheSize;
extern rt_cvar rt_Renderer;
extern rt_cvar rt_Fullscreen;
extern rt_cvar rt_WindowWidth;
extern rt_cvar rt_WindowHeight;
extern rt_cvar rt_BufferManagerMemory;
extern rt_cvar rt_FileTabCapacity;
extern rt_cvar rt_MaxConcurrentAsyncIO;
extern rt_cvar rt_AssetCacheSize;
void RegisterRuntimeCVars(void) {
vyRegisterCVAR(&rt_Renderer);
vyRegisterCVAR(&rt_Fullscreen);
vyRegisterCVAR(&rt_WindowWidth);
vyRegisterCVAR(&rt_WindowHeight);
vyRegisterCVAR(&rt_BufferManagerMemory);
vyRegisterCVAR(&rt_FileTabCapacity);
vyRegisterCVAR(&rt_MaxConcurrentAsyncIO);
vyRegisterCVAR(&rt_AssetCacheSize);
rtRegisterCVAR(&rt_Renderer);
rtRegisterCVAR(&rt_Fullscreen);
rtRegisterCVAR(&rt_WindowWidth);
rtRegisterCVAR(&rt_WindowHeight);
rtRegisterCVAR(&rt_BufferManagerMemory);
rtRegisterCVAR(&rt_FileTabCapacity);
rtRegisterCVAR(&rt_MaxConcurrentAsyncIO);
rtRegisterCVAR(&rt_AssetCacheSize);
}
extern void SetMainThreadId(void);
extern vy_result InitBufferManager(void);
extern rt_result InitBufferManager(void);
extern void ShutdownBufferManager(void);
extern vy_result InitFileTab(void);
extern rt_result InitFileTab(void);
extern void ShutdownFileTab(void);
extern vy_result InitAIO(void);
extern rt_result InitAIO(void);
extern void ShutdownAIO(void);
extern vy_result InitAssetCache(void);
extern rt_result InitAssetCache(void);
extern void ShutdownAssetCache(void);
extern vy_result LoadUIDTable(void);
extern rt_result LoadUIDTable(void);
extern void ReleaseUIDTable(void);
extern vy_result LoadAssetDependencies(void);
extern rt_result LoadAssetDependencies(void);
extern void ReleaseAssetDependencies(void);
extern vy_result LoadPackageNames(void);
extern rt_result LoadPackageNames(void);
VY_DLLEXPORT vy_result vyInitRuntime(void) {
RT_DLLEXPORT rt_result rtInitRuntime(void) {
SetMainThreadId();
RegisterRuntimeCVars();
vy_result res;
if ((res = InitBufferManager()) != VY_SUCCESS) {
vyReportError("BUFFERMGR", "Init failed.");
rt_result res;
if ((res = InitBufferManager()) != RT_SUCCESS) {
rtReportError("BUFFERMGR", "Init failed.");
return res;
}
if ((res = InitFileTab()) != VY_SUCCESS) {
vyReportError("FTAB", "Init failed.");
if ((res = InitFileTab()) != RT_SUCCESS) {
rtReportError("FTAB", "Init failed.");
return res;
}
if ((res = InitAIO()) != VY_SUCCESS) {
vyReportError("AIO", "Init failed.");
if ((res = InitAIO()) != RT_SUCCESS) {
rtReportError("AIO", "Init failed.");
return res;
}
if ((res = InitAssetCache()) != VY_SUCCESS) {
vyReportError("ASSETCACHE", "Init failed.");
if ((res = InitAssetCache()) != RT_SUCCESS) {
rtReportError("ASSETCACHE", "Init failed.");
return res;
}
if ((res = LoadUIDTable()) != VY_SUCCESS) {
vyLog("CORE", "LoadUIDTable returned result: %u", res);
if ((res = LoadUIDTable()) != RT_SUCCESS) {
rtLog("CORE", "LoadUIDTable returned result: %u", res);
}
if ((res = LoadAssetDependencies()) != VY_SUCCESS) {
vyReportError("ASSETDEP", "Init failed.");
if ((res = LoadAssetDependencies()) != RT_SUCCESS) {
rtReportError("ASSETDEP", "Init failed.");
return res;
}
if ((res = LoadPackageNames()) != VY_SUCCESS) {
vyLog("CORE", "LoadPackageNames returned result: %u", res);
if ((res = LoadPackageNames()) != RT_SUCCESS) {
rtLog("CORE", "LoadPackageNames returned result: %u", res);
}
return VY_SUCCESS;
return RT_SUCCESS;
}
VY_DLLEXPORT void vyShutdownRuntime(void) {
RT_DLLEXPORT void rtShutdownRuntime(void) {
ReleaseAssetDependencies();
ReleaseUIDTable();
ShutdownAssetCache();

View File

@ -8,27 +8,27 @@
typedef struct {
uint32_t base_iteration;
uint32_t iteration_count;
vy_job_fn *fn;
rt_job_fn *fn;
void *param;
} vy_job_chunk;
} rt_job_chunk;
typedef struct {
/* Queue */
struct {
vy_job_chunk *chunks;
rt_job_chunk *chunks;
unsigned int head;
unsigned int tail;
vy_condition_var *lock;
rt_condition_var *lock;
} job_queue;
/* Thread data */
vy_thread *thread;
} vy_worker_data;
rt_thread *thread;
} rt_worker_data;
static volatile bool _keep_running = true;
static vy_worker_data _worker_data[MAX_WORKERS];
static rt_worker_data _worker_data[MAX_WORKERS];
static void ExecOneJobIfAvailable(vy_worker_data *wd) {
static void ExecOneJobIfAvailable(rt_worker_data *wd) {
if (wd->job_queue.head == wd->job_queue.tail) {
/* No job available.
* TODO: Pick one job queue at random and check if we can steal?
@ -36,7 +36,7 @@ static void ExecOneJobIfAvailable(vy_worker_data *wd) {
return;
}
vy_job_chunk chunk = wd->job_queue.chunks[wd->job_queue.head];
rt_job_chunk chunk = wd->job_queue.chunks[wd->job_queue.head];
wd->job_queue.head = (wd->job_queue.head + 1) % JOB_QUEUE_SIZE;
for (uint32_t i = 0; i < chunk.iteration_count; ++i) {
chunk.fn(chunk.param, chunk.base_iteration + i);
@ -44,22 +44,22 @@ static void ExecOneJobIfAvailable(vy_worker_data *wd) {
}
static void WorkerEntry(void *param) {
vy_worker_data *wd = param;
rt_worker_data *wd = param;
while (_keep_running) {
vyLockConditionVar(wd->job_queue.lock);
rtLockConditionVar(wd->job_queue.lock);
while (wd->job_queue.head == wd->job_queue.tail && _keep_running) {
vyWaitOnConditionVar(wd->job_queue.lock);
rtWaitOnConditionVar(wd->job_queue.lock);
}
ExecOneJobIfAvailable(wd);
vyUnlockConditionVar(wd->job_queue.lock, false);
rtUnlockConditionVar(wd->job_queue.lock, false);
}
}
void vyInitJobSystem(unsigned int worker_count) {
void rtInitJobSystem(unsigned int worker_count) {
if (worker_count > MAX_WORKERS)
worker_count = MAX_WORKERS;
for (unsigned int i = 0; i < worker_count; ++i) {
_worker_data[i].thread = vySpawnThread(WorkerEntry, &_worker_data[i], "JobWorker");
_worker_data[i].thread = rtSpawnThread(WorkerEntry, &_worker_data[i], "JobWorker");
}
}

View File

@ -1,5 +1,5 @@
#ifndef VY_JOBS_H
#define VY_JOBS_H
#ifndef RT_JOBS_H
#define RT_JOBS_H
/* Work stealing job scheduler */
@ -7,14 +7,14 @@
#include <stdint.h>
typedef void vy_job_fn(void *param, uint32_t iteration);
typedef void rt_job_fn(void *param, uint32_t iteration);
typedef struct {
uint32_t iterations;
vy_job_fn *fn;
rt_job_fn *fn;
void *param;
} vy_job_decl;
} rt_job_decl;
VY_DLLEXPORT void vyDispatchJob(const vy_job_decl *decl);
RT_DLLEXPORT void rtDispatchJob(const rt_job_decl *decl);
#endif

View File

@ -1,20 +1,20 @@
#include <stdio.h>
#include "file_tab.h"
vy_result LoadPackageNames(void) {
rt_result LoadPackageNames(void) {
FILE *f = fopen("data/packages.txt", "r");
if (!f) {
return VY_UNKNOWN_ERROR;
return RT_UNKNOWN_ERROR;
}
while (!feof(f)) {
char line[256];
fscanf(f, "%255s\n", line);
line[255] = '\0';
vyAddFile(line);
rtAddFile(line);
}
fclose(f);
return VY_SUCCESS;
return RT_SUCCESS;
}

View File

@ -1,7 +1,7 @@
#ifndef VY_PACKAGES_H
#define VY_PACKAGES_H
#ifndef RT_PACKAGES_H
#define RT_PACKAGES_H
#ifdef VY_DEFINE_PACKAGE_FILE_STRUCTURES
#ifdef RT_DEFINE_PACKAGE_FILE_STRUCTURES
#include <stdint.h>
#include "xxhash/xxhash.h"
@ -10,7 +10,7 @@
typedef struct {
XXH64_canonical_t checksum;
uint32_t decompressed_size;
} vy_package_asset_header;
} rt_package_asset_header;
#pragma pack(pop)
#endif

View File

@ -1,5 +1,5 @@
#ifndef VY_GFX_BACKEND_H
#define VY_GFX_BACKEND_H
#ifndef RT_GFX_BACKEND_H
#define RT_GFX_BACKEND_H
/* Backend functions and types. */
@ -12,52 +12,52 @@
#ifdef _WIN32
struct HINSTANCE__;
struct HWND__;
#elif defined(VY_USE_XLIB)
#elif defined(RT_USE_XLIB)
struct _XDisplay;
#endif
struct vy_renderer_init_info_s {
struct rt_renderer_init_info_s {
#ifdef _WIN32
struct HINSTANCE__ *hInstance;
struct HWND__ *hWnd;
#elif defined(VY_USE_XLIB)
#elif defined(RT_USE_XLIB)
struct _XDisplay *display;
unsigned long window;
#endif
};
typedef struct {
vy_uid vertex_shader;
vy_uid fragment_shader;
vy_uid compute_shader;
rt_uid vertex_shader;
rt_uid fragment_shader;
rt_uid compute_shader;
vy_relptr texture_bindings;
vy_relptr uniform_bindings;
vy_relptr storage_bindings;
rt_relptr texture_bindings;
rt_relptr uniform_bindings;
rt_relptr storage_bindings;
uint16_t texture_binding_count;
uint16_t uniform_binding_count;
uint16_t storage_binding_count;
} vy_pipeline_info;
} rt_pipeline_info;
typedef void vy_register_renderer_cvars_fn(void);
typedef vy_result vy_init_renderer_fn(const vy_renderer_init_info *info);
typedef void vy_shutdown_renderer_fn(void);
typedef vy_pipeline_handle vy_compile_pipeline_fn(const vy_pipeline_info *info);
typedef void vy_destroy_pipeline_fn(vy_pipeline_handle handle);
typedef void rt_register_renderer_cvars_fn(void);
typedef rt_result rt_init_renderer_fn(const rt_renderer_init_info *info);
typedef void rt_shutdown_renderer_fn(void);
typedef rt_pipeline_handle rt_compile_pipeline_fn(const rt_pipeline_info *info);
typedef void rt_destroy_pipeline_fn(rt_pipeline_handle handle);
typedef struct {
vy_register_renderer_cvars_fn *RegisterCVars;
vy_init_renderer_fn *Init;
vy_shutdown_renderer_fn *Shutdown;
vy_compile_pipeline_fn *CompilePipeline;
vy_destroy_pipeline_fn *DestroyPipeline;
} vy_renderer_api;
rt_register_renderer_cvars_fn *RegisterCVars;
rt_init_renderer_fn *Init;
rt_shutdown_renderer_fn *Shutdown;
rt_compile_pipeline_fn *CompilePipeline;
rt_destroy_pipeline_fn *DestroyPipeline;
} rt_renderer_api;
#define VY_RENDERER_API_FN(name) VY_DLLEXPORT vyRen##name
#define RT_RENDERER_API_FN(name) RT_DLLEXPORT rtRen##name
#ifndef VY_DONT_DEFINE_RENDERER_GLOBAL
extern vy_renderer_api g_renderer;
#ifndef RT_DONT_DEFINE_RENDERER_GLOBAL
extern rt_renderer_api g_renderer;
#endif
#endif

View File

@ -1,47 +1,47 @@
#ifndef VY_VOYAGE_H
#define VY_VOYAGE_H
#ifndef RT_VOYAGE_H
#define RT_VOYAGE_H
/* basic types and macros */
#include <stddef.h>
#include <stdint.h>
#if defined(_MSC_VER) && !defined(VY_STATIC_LIB)
#define VY_DLLEXPORT __declspec(dllexport)
#if defined(_MSC_VER) && !defined(RT_STATIC_LIB)
#define RT_DLLEXPORT __declspec(dllexport)
#else
#define VY_DLLEXPORT
#define RT_DLLEXPORT
#endif
#if defined(_MSC_VER)
#define VY_INLINE __forceinline
#define RT_INLINE __forceinline
#elif defined(__GNUC__) || defined(__clang__)
#define VY_INLINE inline __attribute__((always_inline))
#define RT_INLINE inline __attribute__((always_inline))
#endif
#define VY_UNUSED(x) ((void)sizeof((x)))
#define VY_ARRAY_COUNT(x) (sizeof((x)) / sizeof((x)[0]))
#define RT_UNUSED(x) ((void)sizeof((x)))
#define RT_ARRAY_COUNT(x) (sizeof((x)) / sizeof((x)[0]))
#define VY_KB(n) ((n)*1024U)
#define VY_MB(n) ((n)*1024U * 1024U)
#define VY_GB(n) ((n)*1024U * 1024U * 1024U)
#define RT_KB(n) ((n)*1024U)
#define RT_MB(n) ((n)*1024U * 1024U)
#define RT_GB(n) ((n)*1024U * 1024U * 1024U)
typedef unsigned int vy_result;
typedef unsigned int rt_result;
/* Default result codes */
enum {
VY_SUCCESS = 0,
VY_OUT_OF_MEMORY = 1,
RT_SUCCESS = 0,
RT_OUT_OF_MEMORY = 1,
VY_CUSTOM_ERROR_START,
RT_CUSTOM_ERROR_START,
VY_UNKNOWN_ERROR = (vy_result)-1,
RT_UNKNOWN_ERROR = (rt_result)-1,
};
typedef struct {
const char *start;
unsigned int length;
} vy_text_span;
} rt_text_span;
/* Returns results like strcmp():
* - If the first differing character is smaller in span than in cmp: < 0
@ -50,33 +50,33 @@ typedef struct {
* - If span.length is smaller than strlen(cmp): -1
* - If span.length is greater than strlen(cmp): 1
*/
VY_DLLEXPORT int vyCompareSpanToString(vy_text_span span, const char *cmp);
RT_DLLEXPORT int rtCompareSpanToString(rt_text_span span, const char *cmp);
VY_DLLEXPORT void vyReportError(const char *subsystem, const char *fmt, ...);
RT_DLLEXPORT void rtReportError(const char *subsystem, const char *fmt, ...);
VY_DLLEXPORT void vyLog(const char *subsystem, const char *fmt, ...);
RT_DLLEXPORT void rtLog(const char *subsystem, const char *fmt, ...);
enum {
VY_INVALID_UNICODE = VY_CUSTOM_ERROR_START,
VY_INSUFFICIENT_BUFFER,
RT_INVALID_UNICODE = RT_CUSTOM_ERROR_START,
RT_INSUFFICIENT_BUFFER,
};
/* Returns VY_SUCCESS if the string was successfully converted,
* VY_INVALID_UNICODE if invalid unicode characters were encountered or
* VY_INSUFFICIENT_BUFFER if the provided output buffer is too small */
VY_DLLEXPORT vy_result vyUTF8ToWStr(const char *utf8, wchar_t *wstr, size_t len);
/* Returns RT_SUCCESS if the string was successfully converted,
* RT_INVALID_UNICODE if invalid unicode characters were encountered or
* RT_INSUFFICIENT_BUFFER if the provided output buffer is too small */
RT_DLLEXPORT rt_result rtUTF8ToWStr(const char *utf8, wchar_t *wstr, size_t len);
/* Returns VY_SUCCESS if the string was successfully converted,
* VY_INVALID_UNICODE if invalid unicode characters were encountered or
* VY_INSUFFICIENT_BUFFER if the provided output buffer is too small */
VY_DLLEXPORT vy_result vyWStrToUTF8(const wchar_t *wstr, char *utf8, size_t len);
/* Returns RT_SUCCESS if the string was successfully converted,
* RT_INVALID_UNICODE if invalid unicode characters were encountered or
* RT_INSUFFICIENT_BUFFER if the provided output buffer is too small */
RT_DLLEXPORT rt_result rtWStrToUTF8(const wchar_t *wstr, char *utf8, size_t len);
/* Relative pointer */
typedef struct {
int32_t off;
} vy_relptr;
} rt_relptr;
static VY_INLINE void *vyResolveRelptr(vy_relptr *ptr) {
static RT_INLINE void *rtResolveRelptr(rt_relptr *ptr) {
if (ptr->off != 0) {
char *p = (char *)ptr;
return (void *)(p + (ptrdiff_t)ptr->off);
@ -85,7 +85,7 @@ static VY_INLINE void *vyResolveRelptr(vy_relptr *ptr) {
}
}
static VY_INLINE void vySetRelptr(vy_relptr *ptr, void *target) {
static RT_INLINE void rtSetRelptr(rt_relptr *ptr, void *target) {
if (target) {
char *p = (char *)ptr, *t = (char *)target;
ptrdiff_t d = t - p;
@ -98,7 +98,7 @@ static VY_INLINE void vySetRelptr(vy_relptr *ptr, void *target) {
/* Bitfiddling functions */
/* Portable solution, On x64 using clzl is probably faster. */
static VY_INLINE uint32_t vyNextPowerOfTwo32(uint32_t v) {
static RT_INLINE uint32_t rtNextPowerOfTwo32(uint32_t v) {
v--;
v |= v >> 1;
v |= v >> 2;
@ -112,8 +112,8 @@ static VY_INLINE uint32_t vyNextPowerOfTwo32(uint32_t v) {
/* Runtime init. Initializes basic systems.
* You need to call this, even if you build a CLI only app. */
VY_DLLEXPORT vy_result vyInitRuntime(void);
RT_DLLEXPORT rt_result rtInitRuntime(void);
VY_DLLEXPORT void vyShutdownRuntime(void);
RT_DLLEXPORT void rtShutdownRuntime(void);
#endif

View File

@ -7,7 +7,7 @@
#include <Windows.h>
#endif
VY_DLLEXPORT int vyCompareSpanToString(vy_text_span span, const char *cmp) {
RT_DLLEXPORT int rtCompareSpanToString(rt_text_span span, const char *cmp) {
size_t cmp_len = strlen(cmp);
if (cmp_len != (size_t)span.length)
return (span.length < cmp_len) ? -1 : 1;
@ -18,40 +18,40 @@ VY_DLLEXPORT int vyCompareSpanToString(vy_text_span span, const char *cmp) {
return 0;
}
VY_DLLEXPORT vy_result vyUTF8ToWStr(const char *utf8, wchar_t *wstr, size_t len) {
RT_DLLEXPORT rt_result rtUTF8ToWStr(const char *utf8, wchar_t *wstr, size_t len) {
#ifdef _WIN32
int res = MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, utf8, -1, wstr, (int)len);
if (res > 0) {
return VY_SUCCESS;
return RT_SUCCESS;
} else {
DWORD err = GetLastError();
if (err == ERROR_INSUFFICIENT_BUFFER)
return VY_INSUFFICIENT_BUFFER;
return RT_INSUFFICIENT_BUFFER;
else if (err == ERROR_NO_UNICODE_TRANSLATION)
return VY_INVALID_UNICODE;
return RT_INVALID_UNICODE;
else {
vyReportError("CORE", "Unexpected error in vyUTF8ToWStr(): %u", err);
return VY_UNKNOWN_ERROR;
rtReportError("CORE", "Unexpected error in rtUTF8ToWStr(): %u", err);
return RT_UNKNOWN_ERROR;
}
}
#endif
}
VY_DLLEXPORT vy_result vyWStrToUTF8(const wchar_t *wstr, char *utf8, size_t len) {
RT_DLLEXPORT rt_result rtWStrToUTF8(const wchar_t *wstr, char *utf8, size_t len) {
#ifdef _WIN32
int res = WideCharToMultiByte(CP_UTF8, WC_COMPOSITECHECK, wstr, -1, utf8, (int)len, NULL, NULL);
if (res > 0) {
return VY_SUCCESS;
return RT_SUCCESS;
} else {
DWORD err = GetLastError();
if (err == ERROR_INSUFFICIENT_BUFFER)
return VY_INSUFFICIENT_BUFFER;
return RT_INSUFFICIENT_BUFFER;
else if (err == ERROR_NO_UNICODE_TRANSLATION)
return VY_INVALID_UNICODE;
return RT_INVALID_UNICODE;
else {
vyReportError("CORE", "Unexpected error in vyWStrToUTF8(): %u", err);
return VY_UNKNOWN_ERROR;
rtReportError("CORE", "Unexpected error in rtWStrToUTF8(): %u", err);
return RT_UNKNOWN_ERROR;
}
}
#endif

View File

@ -1,5 +1,5 @@
#ifndef VY_THREADING_H
#define VY_THREADING_H
#ifndef RT_THREADING_H
#define RT_THREADING_H
/* platform independent threading */
@ -9,70 +9,70 @@
/* Mutexes */
typedef struct vy_mutex_s vy_mutex;
typedef struct rt_mutex_s rt_mutex;
VY_DLLEXPORT vy_mutex *vyCreateMutex(void);
RT_DLLEXPORT rt_mutex *rtCreateMutex(void);
VY_DLLEXPORT void vyDestroyMutex(vy_mutex *mutex);
RT_DLLEXPORT void rtDestroyMutex(rt_mutex *mutex);
VY_DLLEXPORT bool vyLockMutex(vy_mutex *mutex);
RT_DLLEXPORT bool rtLockMutex(rt_mutex *mutex);
VY_DLLEXPORT bool vyUnlockMutex(vy_mutex *mutex);
RT_DLLEXPORT bool rtUnlockMutex(rt_mutex *mutex);
/* Condition variables */
typedef struct vy_condition_var_s vy_condition_var;
typedef struct rt_condition_var_s rt_condition_var;
VY_DLLEXPORT vy_condition_var *vyCreateConditionVar(void);
RT_DLLEXPORT rt_condition_var *rtCreateConditionVar(void);
VY_DLLEXPORT void vyDestroyConditionVar(vy_condition_var *var);
RT_DLLEXPORT void rtDestroyConditionVar(rt_condition_var *var);
VY_DLLEXPORT void vyLockConditionVar(vy_condition_var *var);
RT_DLLEXPORT void rtLockConditionVar(rt_condition_var *var);
VY_DLLEXPORT void vyUnlockConditionVar(vy_condition_var *var, bool signal);
RT_DLLEXPORT void rtUnlockConditionVar(rt_condition_var *var, bool signal);
/* The condition variable must be locked by the thread! */
VY_DLLEXPORT void vyWaitOnConditionVar(vy_condition_var *var);
RT_DLLEXPORT void rtWaitOnConditionVar(rt_condition_var *var);
/* Read-Write Lock */
typedef struct {
volatile int reader_count;
vy_condition_var *cond;
} vy_rwlock;
rt_condition_var *cond;
} rt_rwlock;
typedef struct {
bool ok;
vy_rwlock lock;
} vy_create_rwlock_result;
rt_rwlock lock;
} rt_create_rwlock_result;
VY_DLLEXPORT vy_create_rwlock_result vyCreateRWLock(void);
RT_DLLEXPORT rt_create_rwlock_result rtCreateRWLock(void);
VY_DLLEXPORT void vyDestroyRWLock(vy_rwlock *lock);
RT_DLLEXPORT void rtDestroyRWLock(rt_rwlock *lock);
VY_DLLEXPORT void vyLockRead(vy_rwlock *lock);
RT_DLLEXPORT void rtLockRead(rt_rwlock *lock);
VY_DLLEXPORT void vyUnlockRead(vy_rwlock *lock);
RT_DLLEXPORT void rtUnlockRead(rt_rwlock *lock);
VY_DLLEXPORT void vyLockWrite(vy_rwlock *lock);
RT_DLLEXPORT void rtLockWrite(rt_rwlock *lock);
VY_DLLEXPORT void vyUnlockWrite(vy_rwlock *lock);
RT_DLLEXPORT void rtUnlockWrite(rt_rwlock *lock);
/* Threads */
typedef struct vy_thread_s vy_thread;
typedef struct rt_thread_s rt_thread;
typedef void vy_thread_entry_fn(void *param);
typedef void rt_thread_entry_fn(void *param);
VY_DLLEXPORT vy_thread *vySpawnThread(vy_thread_entry_fn *entry, void *param, const char *name);
RT_DLLEXPORT rt_thread *rtSpawnThread(rt_thread_entry_fn *entry, void *param, const char *name);
VY_DLLEXPORT void vyJoinThread(vy_thread *thread);
RT_DLLEXPORT void rtJoinThread(rt_thread *thread);
VY_DLLEXPORT unsigned int vyGetCPUCoreCount(void);
RT_DLLEXPORT unsigned int rtGetCPUCoreCount(void);
typedef uint32_t vy_thread_id;
typedef uint32_t rt_thread_id;
VY_DLLEXPORT vy_thread_id vyGetCurrentThreadId(void);
RT_DLLEXPORT rt_thread_id rtGetCurrentThreadId(void);
VY_DLLEXPORT bool vyIsMainThread(void);
RT_DLLEXPORT bool rtIsMainThread(void);
#endif

View File

@ -4,46 +4,46 @@
#ifdef __linux__
#include <pthread.h>
struct vy_condition_var_s {
struct rt_condition_var_s {
pthread_mutex_t mutex;
pthread_cond_t cond;
ptrdiff_t next_reusable;
};
#define MAX_CONDS 1024
vy_condition_var _conds[MAX_CONDS];
rt_condition_var _conds[MAX_CONDS];
static ptrdiff_t _first_reusable = MAX_CONDS;
static ptrdiff_t _next = 0;
static pthread_mutex_t _guard = PTHREAD_MUTEX_INITIALIZER;
VY_DLLEXPORT vy_condition_var *vyCreateConditionVar(void) {
RT_DLLEXPORT rt_condition_var *rtCreateConditionVar(void) {
pthread_mutex_lock(&_guard);
if (_first_reusable < MAX_CONDS) {
vy_condition_var *cond = &_conds[_first_reusable];
rt_condition_var *cond = &_conds[_first_reusable];
_first_reusable = cond->next_reusable;
pthread_mutex_unlock(&_guard);
return cond;
} else if (_next < MAX_CONDS) {
vy_condition_var *cond = &_conds[_next];
rt_condition_var *cond = &_conds[_next];
if (pthread_mutex_init(&cond->mutex, NULL) != 0) {
vyLog("core", "Condition variable creation failed");
rtLog("core", "Condition variable creation failed");
pthread_mutex_unlock(&_guard);
return NULL;
}
if (pthread_cond_init(&cond->cond, NULL) != 0) {
vyLog("core", "Condition variable creation failed");
rtLog("core", "Condition variable creation failed");
}
cond->next_reusable = MAX_CONDS;
++_next;
pthread_mutex_unlock(&_guard);
return cond;
}
vyReportError("core", "Ran out of condition variable objects");
rtReportError("core", "Ran out of condition variable objects");
pthread_mutex_unlock(&_guard);
return NULL;
}
VY_DLLEXPORT void vyDestroyConditionVar(vy_condition_var *var) {
RT_DLLEXPORT void rtDestroyConditionVar(rt_condition_var *var) {
ptrdiff_t index = var - &_conds[0];
pthread_mutex_lock(&_guard);
var->next_reusable = _first_reusable;
@ -51,17 +51,17 @@ VY_DLLEXPORT void vyDestroyConditionVar(vy_condition_var *var) {
pthread_mutex_unlock(&_guard);
}
VY_DLLEXPORT void vyLockConditionVar(vy_condition_var *var) {
RT_DLLEXPORT void rtLockConditionVar(rt_condition_var *var) {
pthread_mutex_lock(&var->mutex);
}
VY_DLLEXPORT void vyUnlockConditionVar(vy_condition_var *var, bool signal) {
RT_DLLEXPORT void rtUnlockConditionVar(rt_condition_var *var, bool signal) {
if (signal)
pthread_cond_signal(&var->cond);
pthread_mutex_unlock(&var->mutex);
}
VY_DLLEXPORT void vyWaitOnConditionVar(vy_condition_var *var) {
RT_DLLEXPORT void rtWaitOnConditionVar(rt_condition_var *var) {
pthread_cond_wait(&var->cond, &var->mutex);
}
@ -69,47 +69,47 @@ VY_DLLEXPORT void vyWaitOnConditionVar(vy_condition_var *var) {
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
struct vy_condition_var_s {
struct rt_condition_var_s {
CRITICAL_SECTION critical_section;
CONDITION_VARIABLE cond;
ptrdiff_t next_reusable;
};
#define MAX_CONDS 1024
vy_condition_var _conds[MAX_CONDS];
rt_condition_var _conds[MAX_CONDS];
static ptrdiff_t _first_reusable = MAX_CONDS;
static ptrdiff_t _next = 0;
static HANDLE _guard;
static INIT_ONCE _guard_init = INIT_ONCE_STATIC_INIT;
static BOOL CALLBACK InitGuardFn(PINIT_ONCE initOnce, PVOID parameter, PVOID *context) {
VY_UNUSED(initOnce);
VY_UNUSED(parameter);
VY_UNUSED(context);
RT_UNUSED(initOnce);
RT_UNUSED(parameter);
RT_UNUSED(context);
_guard = CreateMutexW(NULL, FALSE, NULL);
return _guard != NULL;
}
VY_DLLEXPORT vy_condition_var *vyCreateConditionVar(void) {
RT_DLLEXPORT rt_condition_var *rtCreateConditionVar(void) {
if (!InitOnceExecuteOnce(&_guard_init, InitGuardFn, NULL, NULL)) {
vyReportError("core", "Failed to initialize the guard mutex.");
rtReportError("core", "Failed to initialize the guard mutex.");
return NULL;
}
if (WaitForSingleObjectEx(_guard, INFINITE, TRUE) != WAIT_OBJECT_0) {
vyLog("core", "Failed to lock the guard variable: %u", GetLastError());
rtLog("core", "Failed to lock the guard variable: %u", GetLastError());
return NULL;
}
if (_first_reusable < MAX_CONDS) {
vy_condition_var *cond = &_conds[_first_reusable];
rt_condition_var *cond = &_conds[_first_reusable];
_first_reusable = cond->next_reusable;
ReleaseMutex(_guard);
return cond;
} else if (_next < MAX_CONDS) {
vy_condition_var *cond = &_conds[_next];
rt_condition_var *cond = &_conds[_next];
if (!InitializeCriticalSectionAndSpinCount(&cond->critical_section, 4000)) {
vyLog("core", "Condition variable creation failed");
rtLog("core", "Condition variable creation failed");
ReleaseMutex(_guard);
return NULL;
}
@ -119,15 +119,15 @@ VY_DLLEXPORT vy_condition_var *vyCreateConditionVar(void) {
ReleaseMutex(_guard);
return cond;
}
vyReportError("core", "Ran out of condition variable objects");
rtReportError("core", "Ran out of condition variable objects");
ReleaseMutex(_guard);
return NULL;
}
VY_DLLEXPORT void vyDestroyConditionVar(vy_condition_var *var) {
RT_DLLEXPORT void rtDestroyConditionVar(rt_condition_var *var) {
ptrdiff_t index = var - &_conds[0];
if (WaitForSingleObjectEx(_guard, INFINITE, TRUE) != WAIT_OBJECT_0) {
vyLog("core", "Failed to lock the guard variable: %u", GetLastError());
rtLog("core", "Failed to lock the guard variable: %u", GetLastError());
return;
}
var->next_reusable = _first_reusable;
@ -135,17 +135,17 @@ VY_DLLEXPORT void vyDestroyConditionVar(vy_condition_var *var) {
ReleaseMutex(_guard);
}
VY_DLLEXPORT void vyLockConditionVar(vy_condition_var *var) {
RT_DLLEXPORT void rtLockConditionVar(rt_condition_var *var) {
EnterCriticalSection(&var->critical_section);
}
VY_DLLEXPORT void vyUnlockConditionVar(vy_condition_var *var, bool signal) {
RT_DLLEXPORT void rtUnlockConditionVar(rt_condition_var *var, bool signal) {
LeaveCriticalSection(&var->critical_section);
if (signal)
WakeAllConditionVariable(&var->cond);
}
VY_DLLEXPORT void vyWaitOnConditionVar(vy_condition_var *var) {
RT_DLLEXPORT void rtWaitOnConditionVar(rt_condition_var *var) {
SleepConditionVariableCS(&var->cond, &var->critical_section, INFINITE);
}

View File

@ -5,48 +5,48 @@
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
struct vy_mutex_s {
struct rt_mutex_s {
HANDLE handle;
ptrdiff_t next_reusable;
DWORD owner;
};
#define MAX_MUTEX 1024
static vy_mutex _mutex[MAX_MUTEX];
static rt_mutex _mutex[MAX_MUTEX];
static ptrdiff_t _first_reusable = MAX_MUTEX;
static ptrdiff_t _next = 0;
static HANDLE _guard;
static INIT_ONCE _guard_init = INIT_ONCE_STATIC_INIT;
static BOOL CALLBACK InitGuardFn(PINIT_ONCE initOnce, PVOID parameter, PVOID *context) {
VY_UNUSED(initOnce);
VY_UNUSED(parameter);
VY_UNUSED(context);
RT_UNUSED(initOnce);
RT_UNUSED(parameter);
RT_UNUSED(context);
_guard = CreateMutexW(NULL, FALSE, NULL);
return _guard != NULL;
}
VY_DLLEXPORT vy_mutex *vyCreateMutex(void) {
RT_DLLEXPORT rt_mutex *rtCreateMutex(void) {
if (!InitOnceExecuteOnce(&_guard_init, InitGuardFn, NULL, NULL)) {
vyReportError("core", "Failed to initialize the guard mutex.");
rtReportError("core", "Failed to initialize the guard mutex.");
return NULL;
}
if (WaitForSingleObjectEx(_guard, INFINITE, TRUE) != WAIT_OBJECT_0) {
vyLog("core", "Failed to lock the guard variable: %u", GetLastError());
rtLog("core", "Failed to lock the guard variable: %u", GetLastError());
return NULL;
}
if (_first_reusable < MAX_MUTEX) {
vy_mutex *mtx = &_mutex[_first_reusable];
rt_mutex *mtx = &_mutex[_first_reusable];
_first_reusable = mtx->next_reusable;
mtx->owner = 0;
return mtx;
} else if (_next < MAX_MUTEX) {
vy_mutex *mtx = &_mutex[_next];
rt_mutex *mtx = &_mutex[_next];
mtx->handle = CreateMutexW(NULL, FALSE, NULL);
if (!mtx->handle) {
vyLog("core", "Mutex creation failed: %u", GetLastError());
rtLog("core", "Mutex creation failed: %u", GetLastError());
return NULL;
}
mtx->next_reusable = MAX_MUTEX;
@ -54,17 +54,17 @@ VY_DLLEXPORT vy_mutex *vyCreateMutex(void) {
++_next;
return mtx;
}
vyReportError("core", "Ran out of mutex objects");
rtReportError("core", "Ran out of mutex objects");
return NULL;
}
VY_DLLEXPORT void vyDestroyMutex(vy_mutex *mutex) {
RT_DLLEXPORT void rtDestroyMutex(rt_mutex *mutex) {
ptrdiff_t index = mutex - &_mutex[0];
mutex->next_reusable = _first_reusable;
_first_reusable = index;
}
VY_DLLEXPORT bool vyLockMutex(vy_mutex *mutex) {
RT_DLLEXPORT bool rtLockMutex(rt_mutex *mutex) {
DWORD caller = GetCurrentThreadId();
DWORD result;
do {
@ -72,7 +72,7 @@ VY_DLLEXPORT bool vyLockMutex(vy_mutex *mutex) {
if (result == WAIT_OBJECT_0) {
mutex->owner = caller;
} else if (result != WAIT_IO_COMPLETION) {
vyLog("core",
rtLog("core",
"WaitForSingleObjectEx returned %x (GetLastError(): %u)",
result,
(result == WAIT_FAILED) ? GetLastError() : 0);
@ -81,10 +81,10 @@ VY_DLLEXPORT bool vyLockMutex(vy_mutex *mutex) {
return result == WAIT_OBJECT_0;
}
VY_DLLEXPORT bool vyUnlockMutex(vy_mutex *mutex) {
RT_DLLEXPORT bool rtUnlockMutex(rt_mutex *mutex) {
DWORD caller = GetCurrentThreadId();
if (caller != mutex->owner) {
vyReportError("core", "Tried to unlock a mutex held by another thread.");
rtReportError("core", "Tried to unlock a mutex held by another thread.");
return false;
}
mutex->owner = 0;
@ -97,28 +97,28 @@ VY_DLLEXPORT bool vyUnlockMutex(vy_mutex *mutex) {
#elif defined(__linux__)
#include <pthread.h>
struct vy_mutex_s {
struct rt_mutex_s {
pthread_mutex_t handle;
ptrdiff_t next_reusable;
};
#define MAX_MUTEX 1024
static vy_mutex _mutex[MAX_MUTEX];
static rt_mutex _mutex[MAX_MUTEX];
static ptrdiff_t _first_reusable = MAX_MUTEX;
static ptrdiff_t _next = 0;
static pthread_mutex_t _guard = PTHREAD_MUTEX_INITIALIZER;
VY_DLLEXPORT vy_mutex *vyCreateMutex(void) {
RT_DLLEXPORT rt_mutex *rtCreateMutex(void) {
pthread_mutex_lock(&_guard);
if (_first_reusable < MAX_MUTEX) {
vy_mutex *mtx = &_mutex[_first_reusable];
rt_mutex *mtx = &_mutex[_first_reusable];
_first_reusable = mtx->next_reusable;
pthread_mutex_unlock(&_guard);
return mtx;
} else if (_next < MAX_MUTEX) {
vy_mutex *mtx = &_mutex[_next];
rt_mutex *mtx = &_mutex[_next];
if (pthread_mutex_init(&mtx->handle, NULL) != 0) {
vyLog("core", "Mutex creation failed");
rtLog("core", "Mutex creation failed");
pthread_mutex_unlock(&_guard);
return NULL;
}
@ -127,12 +127,12 @@ VY_DLLEXPORT vy_mutex *vyCreateMutex(void) {
pthread_mutex_unlock(&_guard);
return mtx;
}
vyReportError("core", "Ran out of mutex objects");
rtReportError("core", "Ran out of mutex objects");
pthread_mutex_unlock(&_guard);
return NULL;
}
VY_DLLEXPORT void vyDestroyMutex(vy_mutex *mutex) {
RT_DLLEXPORT void rtDestroyMutex(rt_mutex *mutex) {
ptrdiff_t index = mutex - &_mutex[0];
pthread_mutex_lock(&_guard);
mutex->next_reusable = _first_reusable;
@ -140,11 +140,11 @@ VY_DLLEXPORT void vyDestroyMutex(vy_mutex *mutex) {
pthread_mutex_unlock(&_guard);
}
VY_DLLEXPORT bool vyLockMutex(vy_mutex *mutex) {
RT_DLLEXPORT bool rtLockMutex(rt_mutex *mutex) {
return pthread_mutex_lock(&mutex->handle) == 0;
}
VY_DLLEXPORT bool vyUnlockMutex(vy_mutex *mutex) {
RT_DLLEXPORT bool rtUnlockMutex(rt_mutex *mutex) {
return pthread_mutex_unlock(&mutex->handle) == 0;
}

View File

@ -4,40 +4,40 @@
/* Based on: https://eli.thegreenplace.net/2019/implementing-reader-writer-locks/ */
VY_DLLEXPORT vy_create_rwlock_result vyCreateRWLock(void) {
vy_create_rwlock_result res;
RT_DLLEXPORT rt_create_rwlock_result rtCreateRWLock(void) {
rt_create_rwlock_result res;
res.lock.reader_count = 0;
res.lock.cond = vyCreateConditionVar();
res.lock.cond = rtCreateConditionVar();
res.ok = res.lock.cond != NULL;
return res;
}
VY_DLLEXPORT void vyDestroyRWLock(vy_rwlock *lock) {
vyDestroyConditionVar(lock->cond);
RT_DLLEXPORT void rtDestroyRWLock(rt_rwlock *lock) {
rtDestroyConditionVar(lock->cond);
lock->cond = NULL;
lock->reader_count = 0;
}
VY_DLLEXPORT void vyLockRead(vy_rwlock *lock) {
vyLockConditionVar(lock->cond);
RT_DLLEXPORT void rtLockRead(rt_rwlock *lock) {
rtLockConditionVar(lock->cond);
++lock->reader_count;
vyUnlockConditionVar(lock->cond, false);
rtUnlockConditionVar(lock->cond, false);
}
VY_DLLEXPORT void vyUnlockRead(vy_rwlock *lock) {
vyLockConditionVar(lock->cond);
RT_DLLEXPORT void rtUnlockRead(rt_rwlock *lock) {
rtLockConditionVar(lock->cond);
assert(lock->reader_count > 0);
--lock->reader_count;
bool signal = lock->reader_count == 0;
vyUnlockConditionVar(lock->cond, signal);
rtUnlockConditionVar(lock->cond, signal);
}
VY_DLLEXPORT void vyLockWrite(vy_rwlock *lock) {
vyLockConditionVar(lock->cond);
RT_DLLEXPORT void rtLockWrite(rt_rwlock *lock) {
rtLockConditionVar(lock->cond);
while (lock->reader_count > 0)
vyWaitOnConditionVar(lock->cond);
rtWaitOnConditionVar(lock->cond);
}
VY_DLLEXPORT void vyUnlockWrite(vy_rwlock *lock) {
vyUnlockConditionVar(lock->cond, true);
RT_DLLEXPORT void rtUnlockWrite(rt_rwlock *lock) {
rtUnlockConditionVar(lock->cond, true);
}

View File

@ -6,59 +6,59 @@
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
struct vy_thread_s {
struct rt_thread_s {
HANDLE handle;
ptrdiff_t next_reusable;
vy_thread_entry_fn *entry;
rt_thread_entry_fn *entry;
void *param;
bool needs_join;
};
#define MAX_THREADS 256
static vy_thread _threads[MAX_THREADS];
static rt_thread _threads[MAX_THREADS];
static ptrdiff_t _first_reusable = MAX_THREADS;
static ptrdiff_t _next = 0;
static HANDLE _guard;
static INIT_ONCE _guard_init = INIT_ONCE_STATIC_INIT;
static vy_thread_id _main_thread_id;
static rt_thread_id _main_thread_id;
/* Called by the runtime during setup */
extern void SetMainThreadId(void) {
_main_thread_id = (vy_thread_id)GetCurrentThreadId();
_main_thread_id = (rt_thread_id)GetCurrentThreadId();
}
static BOOL CALLBACK InitGuardFn(PINIT_ONCE initOnce, PVOID parameter, PVOID *context) {
VY_UNUSED(initOnce);
VY_UNUSED(parameter);
VY_UNUSED(context);
RT_UNUSED(initOnce);
RT_UNUSED(parameter);
RT_UNUSED(context);
_guard = CreateMutexW(NULL, FALSE, NULL);
return _guard != NULL;
}
static DWORD WINAPI win32ThreadWrapper(LPVOID arg) {
vy_thread *user_thread = arg;
rt_thread *user_thread = arg;
user_thread->needs_join = false;
user_thread->entry(user_thread->param);
user_thread->needs_join = true;
return 0;
}
VY_DLLEXPORT vy_thread *vySpawnThread(vy_thread_entry_fn *entry, void *param, const char *name) {
RT_DLLEXPORT rt_thread *rtSpawnThread(rt_thread_entry_fn *entry, void *param, const char *name) {
if (!InitOnceExecuteOnce(&_guard_init, InitGuardFn, NULL, NULL)) {
vyReportError("core", "Failed to initialize the guard mutex.");
rtReportError("core", "Failed to initialize the guard mutex.");
return NULL;
}
vy_thread *thrd = NULL;
rt_thread *thrd = NULL;
if (WaitForSingleObject(_guard, INFINITE) != WAIT_OBJECT_0) {
vyLog("core", "Failed to lock the guard variable: %u", GetLastError());
rtLog("core", "Failed to lock the guard variable: %u", GetLastError());
return NULL;
}
if (_first_reusable < MAX_THREADS) {
@ -79,29 +79,29 @@ VY_DLLEXPORT vy_thread *vySpawnThread(vy_thread_entry_fn *entry, void *param, co
thrd->param = param;
thrd->handle = CreateThread(NULL, 0, win32ThreadWrapper, (LPVOID)thrd, 0, NULL);
if (thrd->handle == NULL) {
vyLog("core", "Thread creation failed");
rtLog("core", "Thread creation failed");
thrd = NULL;
}
WCHAR wname[64];
if (thrd && name && vyUTF8ToWStr(name, wname, sizeof(wname)) == VY_SUCCESS)
if (thrd && name && rtUTF8ToWStr(name, wname, sizeof(wname)) == RT_SUCCESS)
SetThreadDescription(thrd->handle, wname);
} else {
vyReportError("core", "Ran out of thread objects");
rtReportError("core", "Ran out of thread objects");
}
ReleaseMutex(_guard);
return thrd;
}
VY_DLLEXPORT void vyJoinThread(vy_thread *thread) {
RT_DLLEXPORT void rtJoinThread(rt_thread *thread) {
WaitForSingleObject(thread->handle, INFINITE);
CloseHandle(thread->handle);
thread->needs_join = false;
ptrdiff_t index = thread - &_threads[0];
if (WaitForSingleObject(_guard, INFINITE) != WAIT_OBJECT_0) {
vyLog("core", "Failed to lock the guard variable: %u", GetLastError());
rtLog("core", "Failed to lock the guard variable: %u", GetLastError());
return;
}
thread->next_reusable = _first_reusable;
@ -109,18 +109,18 @@ VY_DLLEXPORT void vyJoinThread(vy_thread *thread) {
ReleaseMutex(_guard);
}
VY_DLLEXPORT unsigned int vyGetCPUCoreCount(void) {
RT_DLLEXPORT unsigned int rtGetCPUCoreCount(void) {
SYSTEM_INFO info;
GetSystemInfo(&info);
return (unsigned int)info.dwNumberOfProcessors;
}
VY_DLLEXPORT vy_thread_id vyGetCurrentThreadId(void) {
return (vy_thread_id)GetCurrentThreadId();
RT_DLLEXPORT rt_thread_id rtGetCurrentThreadId(void) {
return (rt_thread_id)GetCurrentThreadId();
}
VY_DLLEXPORT bool vyIsMainThread(void) {
return vyGetCurrentThreadId() == _main_thread_id;
RT_DLLEXPORT bool rtIsMainThread(void) {
return rtGetCurrentThreadId() == _main_thread_id;
}
#elif defined(__linux__)
@ -129,33 +129,33 @@ VY_DLLEXPORT bool vyIsMainThread(void) {
#include <pthread.h>
#include <unistd.h>
struct vy_thread_s {
struct rt_thread_s {
pthread_t handle;
ptrdiff_t next_reusable;
vy_thread_entry_fn *entry;
rt_thread_entry_fn *entry;
void *param;
bool needs_join;
};
#define MAX_THREADS 256
static vy_thread _threads[MAX_THREADS];
static rt_thread _threads[MAX_THREADS];
static ptrdiff_t _first_reusable = MAX_THREADS;
static ptrdiff_t _next = 0;
static pthread_mutex_t _guard = PTHREAD_MUTEX_INITIALIZER;
static void *linuxThreadWrapper(void *arg) {
vy_thread *user_thread = arg;
rt_thread *user_thread = arg;
user_thread->needs_join = false;
user_thread->entry(user_thread->param);
user_thread->needs_join = true;
return NULL;
}
VY_DLLEXPORT vy_thread *vySpawnThread(vy_thread_entry_fn *entry, void *param, const char *name) {
vy_thread *thrd = NULL;
RT_DLLEXPORT rt_thread *rtSpawnThread(rt_thread_entry_fn *entry, void *param, const char *name) {
rt_thread *thrd = NULL;
pthread_mutex_lock(&_guard);
if (_first_reusable < MAX_THREADS) {
thrd = &_threads[_first_reusable];
@ -173,19 +173,19 @@ VY_DLLEXPORT vy_thread *vySpawnThread(vy_thread_entry_fn *entry, void *param, co
thrd->entry = entry;
thrd->param = param;
if (pthread_create(&thrd->handle, NULL, linuxThreadWrapper, thrd) != 0) {
vyLog("core", "Thread creation failed");
rtLog("core", "Thread creation failed");
thrd = NULL;
}
if (thrd && name)
pthread_setname_np(thrd->handle, name);
} else {
vyReportError("core", "Ran out of thread objects");
rtReportError("core", "Ran out of thread objects");
}
pthread_mutex_unlock(&_guard);
return thrd;
}
VY_DLLEXPORT void vyJoinThread(vy_thread *thread) {
RT_DLLEXPORT void rtJoinThread(rt_thread *thread) {
pthread_join(thread->handle, NULL);
thread->needs_join = false;
ptrdiff_t index = thread - &_threads[0];
@ -195,17 +195,17 @@ VY_DLLEXPORT void vyJoinThread(vy_thread *thread) {
pthread_mutex_unlock(&_guard);
}
VY_DLLEXPORT unsigned int vyGetCPUCoreCount(void) {
RT_DLLEXPORT unsigned int rtGetCPUCoreCount(void) {
int n = (int)sysconf(_SC_NPROCESSORS_ONLN);
return (n > 0) ? (unsigned int)n : (unsigned int)sysconf(_SC_NPROCESSORS_CONF);
}
VY_DLLEXPORT vy_thread_id vyGetCurrentThreadId(void) {
return (vy_thread_id)GetCurrentThreadId();
RT_DLLEXPORT rt_thread_id rtGetCurrentThreadId(void) {
return (rt_thread_id)GetCurrentThreadId();
}
VY_DLLEXPORT bool vyIsMainThread(void) {
return vyGetCurrentThreadId() == _main_thread_id;
RT_DLLEXPORT bool rtIsMainThread(void) {
return rtGetCurrentThreadId() == _main_thread_id;
}

View File

@ -1,4 +1,4 @@
#define VY_DEFINE_UIDTAB_FILE_STRUCTURES
#define RT_DEFINE_UIDTAB_FILE_STRUCTURES
#include "uidtab.h"
#include "aio.h"
@ -10,25 +10,25 @@
#include <stdbool.h>
typedef struct {
vy_uid *uids;
vy_uid_data *data;
rt_uid *uids;
rt_uid_data *data;
uint32_t slots;
} vy_uidtab;
} rt_uidtab;
static vy_uidtab _tab;
static rt_uidtab _tab;
vy_result LoadUIDTable(void) {
rt_result LoadUIDTable(void) {
/* We use stdio here, because we cannot load any asset in parallel to this.
* This is because the uidtab is what tells us which assets exist.
*/
FILE *f = fopen("data/uidtab.bin", "rb");
if (!f)
return VY_LOAD_FAILED;
return RT_LOAD_FAILED;
vy_uidtab_header header;
rt_uidtab_header header;
if (fread(&header, sizeof(header), 1, f) != 1) {
fclose(f);
return VY_LOAD_FAILED;
return RT_LOAD_FAILED;
}
/* TODO(Kevin): For some reason, the checksum calculation causes
@ -36,29 +36,29 @@ vy_result LoadUIDTable(void) {
XXH3_state_t *checksum = XXH3_createState();
if (!checksum) {
fclose(f);
return VY_UNKNOWN_ERROR;
return RT_UNKNOWN_ERROR;
}
*/
_tab.slots = vyNextPowerOfTwo32(header.num_entries * 2);
void *mem = malloc((sizeof(vy_uid) + sizeof(vy_uid_data)) * _tab.slots);
_tab.slots = rtNextPowerOfTwo32(header.num_entries * 2);
void *mem = malloc((sizeof(rt_uid) + sizeof(rt_uid_data)) * _tab.slots);
if (!mem) {
fclose(f);
_tab.slots = 0;
return VY_OUT_OF_MEMORY;
return RT_OUT_OF_MEMORY;
}
_tab.uids = mem;
_tab.data = (vy_uid_data *)(_tab.uids + _tab.slots);
memset(mem, 0, (sizeof(vy_uid) + sizeof(vy_uid_data)) * _tab.slots);
_tab.data = (rt_uid_data *)(_tab.uids + _tab.slots);
memset(mem, 0, (sizeof(rt_uid) + sizeof(rt_uid_data)) * _tab.slots);
uint32_t mod = _tab.slots - 1;
for (uint32_t i = 0; i < header.num_entries; ++i) {
vy_uidtab_entry entry;
rt_uidtab_entry entry;
if (fread(&entry, sizeof(entry), 1, f) != 1) {
free(mem);
_tab.slots = 0;
fclose(f);
return VY_LOAD_FAILED;
return RT_LOAD_FAILED;
}
//XXH3_64bits_update(checksum, &entry, sizeof(entry));
@ -66,7 +66,7 @@ vy_result LoadUIDTable(void) {
bool inserted = false;
for (uint32_t j = 0; j < _tab.slots; ++j) {
uint32_t at = (entry.uid + j) & mod;
if (_tab.uids[at] == VY_INVALID_UID) {
if (_tab.uids[at] == RT_INVALID_UID) {
_tab.uids[at] = entry.uid;
_tab.data[at].pkg_file = entry.file;
_tab.data[at].size = entry.size;
@ -77,12 +77,12 @@ vy_result LoadUIDTable(void) {
}
}
if (!inserted) {
vyReportError("core",
rtReportError("core",
"Failed to insert an entry into the uid table. This should not happen.");
fclose(f);
free(mem);
_tab.slots = 0;
return VY_UNKNOWN_ERROR;
return RT_UNKNOWN_ERROR;
}
}
@ -94,12 +94,12 @@ vy_result LoadUIDTable(void) {
XXH3_freeState(checksum);
if (checksum_hash != file_hash) {
vyLog("core",
rtLog("core",
"WARNING: uidtab.bin checksum does not match calculated checksum of loaded entries.");
}
*/
return VY_SUCCESS;
return RT_SUCCESS;
}
void ReleaseUIDTable(void) {
@ -107,13 +107,13 @@ void ReleaseUIDTable(void) {
_tab.slots = 0;
}
VY_DLLEXPORT const vy_uid_data *vyGetUIDData(vy_uid uid) {
RT_DLLEXPORT const rt_uid_data *rtGetUIDData(rt_uid uid) {
uint32_t mod = _tab.slots - 1;
for (uint32_t j = 0; j < _tab.slots; ++j) {
uint32_t at = (uid + j) & mod;
if (_tab.uids[at] == uid) {
return &_tab.data[at];
} else if (_tab.uids[at] == VY_INVALID_UID) {
} else if (_tab.uids[at] == RT_INVALID_UID) {
break;
}
}

View File

@ -1,36 +1,36 @@
#ifndef VY_UIDTAB_H
#define VY_UIDTAB_H
#ifndef RT_UIDTAB_H
#define RT_UIDTAB_H
#include "runtime.h"
#include "file_tab.h"
#include "assets.h"
#include "xxhash/xxhash.h"
#ifdef VY_DEFINE_UIDTAB_FILE_STRUCTURES
#ifdef RT_DEFINE_UIDTAB_FILE_STRUCTURES
#pragma pack(push, 1)
typedef struct {
XXH64_canonical_t checksum;
uint32_t num_entries;
} vy_uidtab_header;
} rt_uidtab_header;
#pragma pack(pop)
#pragma pack(push, 1)
typedef struct {
vy_file_id file;
rt_file_id file;
uint64_t offset;
uint64_t size;
vy_uid uid;
} vy_uidtab_entry;
rt_uid uid;
} rt_uidtab_entry;
#pragma pack(pop)
#endif
/* Data associated with an uid */
typedef struct {
vy_file_id pkg_file;
rt_file_id pkg_file;
uint64_t offset;
uint64_t size;
} vy_uid_data;
} rt_uid_data;
VY_DLLEXPORT const vy_uid_data *vyGetUIDData(vy_uid uid);
RT_DLLEXPORT const rt_uid_data *rtGetUIDData(rt_uid uid);
#endif

View File

@ -3,38 +3,38 @@
#include "runtime/runtime.h"
/* Check basic relative pointer behaviour */
static vy_result RelPtrTest(void) {
char buf[sizeof(vy_relptr) + sizeof(unsigned int)];
vy_relptr *ptr = (vy_relptr *)buf;
unsigned int *target = (unsigned int *)&buf[sizeof(vy_relptr)];
static rt_result RelPtrTest(void) {
char buf[sizeof(rt_relptr) + sizeof(unsigned int)];
rt_relptr *ptr = (rt_relptr *)buf;
unsigned int *target = (unsigned int *)&buf[sizeof(rt_relptr)];
*target = 42;
vySetRelptr(ptr, target);
rtSetRelptr(ptr, target);
void *resolved = vyResolveRelptr(ptr);
void *resolved = rtResolveRelptr(ptr);
if ((uintptr_t)resolved != (uintptr_t)target)
return 1;
if (*(unsigned int *)resolved != *target)
return 2;
return VY_SUCCESS;
return RT_SUCCESS;
}
static vy_result NegRelPtrTest(void) {
char buf[sizeof(unsigned int) + sizeof(vy_relptr)];
static rt_result NegRelPtrTest(void) {
char buf[sizeof(unsigned int) + sizeof(rt_relptr)];
unsigned int *target = (unsigned int *)buf;
vy_relptr *ptr = (vy_relptr *)&buf[sizeof(unsigned int)];
rt_relptr *ptr = (rt_relptr *)&buf[sizeof(unsigned int)];
*target = 42;
vySetRelptr(ptr, target);
rtSetRelptr(ptr, target);
void *resolved = vyResolveRelptr(ptr);
void *resolved = rtResolveRelptr(ptr);
if ((uintptr_t)resolved != (uintptr_t)target)
return 1;
if (*(unsigned int *)resolved != *target)
return 2;
return VY_SUCCESS;
return RT_SUCCESS;
}
/* Scaffolding
@ -42,25 +42,25 @@ static vy_result NegRelPtrTest(void) {
* Run all the test cases, output if they passed or failed.
*/
typedef vy_result vy_test_fnc(void);
typedef rt_result rt_test_fnc(void);
typedef struct {
const char *name;
vy_test_fnc *fnc;
rt_test_fnc *fnc;
} vy_test_case;
} rt_test_case;
#define TEST_CASE(fn) { .name = #fn, .fnc = fn, }
static vy_test_case _test_cases[] = {TEST_CASE(RelPtrTest), TEST_CASE(NegRelPtrTest)};
static rt_test_case _test_cases[] = {TEST_CASE(RelPtrTest), TEST_CASE(NegRelPtrTest)};
int main() {
int out = 0;
for (size_t i = 0; i < VY_ARRAY_COUNT(_test_cases); ++i) {
for (size_t i = 0; i < RT_ARRAY_COUNT(_test_cases); ++i) {
printf("[%s] ... ", _test_cases[i].name);
vy_result res = _test_cases[i].fnc();
if (res == VY_SUCCESS) {
rt_result res = _test_cases[i].fnc();
if (res == RT_SUCCESS) {
printf("OK\n");
}
else {

View File

@ -4,7 +4,7 @@
#include "packages.h"
#include "dependency_tracking.h"
#define VY_ASSETC_DONT_DEFINE_OPTIONS_GLOBAL
#define RT_ASSETC_DONT_DEFINE_OPTIONS_GLOBAL
#include "options.h"
#include "runtime/aio.h"
@ -15,24 +15,24 @@
#include <stdlib.h>
#include <string.h>
extern vy_result vyProcessPipelineFile(vy_file_id file,
extern rt_result rtProcessPipelineFile(rt_file_id file,
void *buffer,
size_t size,
uint32_t flags,
vy_processor_output *output);
rt_processor_output *output);
extern vy_result vyProcessShaderFile(vy_file_id file,
extern rt_result rtProcessShaderFile(rt_file_id file,
void *buffer,
size_t size,
uint32_t flags,
vy_processor_output *output);
rt_processor_output *output);
extern void vyDiscoverAssets(void);
extern void rtDiscoverAssets(void);
vy_assetc_options g_assetc_options = {
rt_assetc_options g_assetc_options = {
.root_directory = ".",
.optimization = VY_ASSET_OPTIMIZATION_NONE,
.renderer_backend = VY_RENDERER_BACKEND_CODE_VK,
.optimization = RT_ASSET_OPTIMIZATION_NONE,
.renderer_backend = RT_RENDERER_BACKEND_CODE_VK,
};
static bool ParseCommandLineArgs(int argc, char **argv) {
@ -44,9 +44,9 @@ static bool ParseCommandLineArgs(int argc, char **argv) {
if (strcmp(argv[i], "-r") == 0 || strcmp(argv[i], "--renderer") == 0) {
if (strcmp(val, "vk") == 0) {
g_assetc_options.renderer_backend = VY_RENDERER_BACKEND_CODE_VK;
g_assetc_options.renderer_backend = RT_RENDERER_BACKEND_CODE_VK;
} else {
vyReportError("ASSETC",
rtReportError("ASSETC",
"Invalid render backend %s. Valid options are: vk",
val);
return false;
@ -54,13 +54,13 @@ static bool ParseCommandLineArgs(int argc, char **argv) {
matched = true;
} else if (strcmp(argv[i], "-o") == 0 || strcmp(argv[i], "--optimization") == 0) {
if (strcmp(val, "none") == 0) {
g_assetc_options.optimization = VY_ASSET_OPTIMIZATION_NONE;
g_assetc_options.optimization = RT_ASSET_OPTIMIZATION_NONE;
} else if (strcmp(val, "space") == 0) {
g_assetc_options.optimization = VY_ASSET_OPTIMIZATION_SPACE;
g_assetc_options.optimization = RT_ASSET_OPTIMIZATION_SPACE;
} else if (strcmp(val, "performance") == 0) {
g_assetc_options.optimization = VY_ASSET_OPTIMIZATION_PERFORMANCE;
g_assetc_options.optimization = RT_ASSET_OPTIMIZATION_PERFORMANCE;
} else {
vyReportError("ASSETC",
rtReportError("ASSETC",
"Invalid optimization level %s. Valid options are: none, space, "
"performance",
val);
@ -68,7 +68,7 @@ static bool ParseCommandLineArgs(int argc, char **argv) {
}
matched = true;
} else if (argv[i][0] == '-') {
vyReportError("ASSETC", "Invalid command line argument %s", argv[i]);
rtReportError("ASSETC", "Invalid command line argument %s", argv[i]);
return false;
}
@ -83,7 +83,7 @@ static bool ParseCommandLineArgs(int argc, char **argv) {
g_assetc_options.root_directory = argv[i];
} else {
/* Maybe have secondary directories later? */
vyReportError("ASSETC",
rtReportError("ASSETC",
"More than one root directory passed as command line "
"argument.");
return false;
@ -93,57 +93,57 @@ static bool ParseCommandLineArgs(int argc, char **argv) {
}
int main(int argc, char **argv) {
vyInitRuntime();
rtInitRuntime();
/* Init assetc */
if (!ParseCommandLineArgs(argc, argv)) {
return 1;
}
vyInitPackages();
rtInitPackages();
if (vyLoadAssetMeta() != VY_SUCCESS) {
if (rtLoadAssetMeta() != RT_SUCCESS) {
return 1;
}
if (vyInitDependencyTracking() != VY_SUCCESS) {
if (rtInitDependencyTracking() != RT_SUCCESS) {
return 1;
}
if (vyAddAssetProcessor(".pipeline", vyProcessPipelineFile) != VY_SUCCESS)
if (rtAddAssetProcessor(".pipeline", rtProcessPipelineFile) != RT_SUCCESS)
return 1;
if (vyAddAssetProcessor(".glsl", vyProcessShaderFile) != VY_SUCCESS)
if (rtAddAssetProcessor(".glsl", rtProcessShaderFile) != RT_SUCCESS)
return 1;
if (vyStartProcessing() != VY_SUCCESS) {
if (rtStartProcessing() != RT_SUCCESS) {
return 1;
}
/* Create necessary directories */
vySetWorkingDirectory(g_assetc_options.root_directory);
vyCreateDirectory("assets");
vyCreateDirectory("actemp");
vyCreateDirectory("data");
rtSetWorkingDirectory(g_assetc_options.root_directory);
rtCreateDirectory("assets");
rtCreateDirectory("actemp");
rtCreateDirectory("data");
/* "Mainloop" */
vyDiscoverAssets();
rtDiscoverAssets();
vyWaitUntilProcessingIsFinished();
vyStopProcessing();
rtWaitUntilProcessingIsFinished();
rtStopProcessing();
/* Write result */
vySaveAssetMeta();
if (vySavePackages() != VY_SUCCESS) {
rtSaveAssetMeta();
if (rtSavePackages() != RT_SUCCESS) {
return 1;
}
if (vyWriteUIDTab() != VY_SUCCESS) {
if (rtWriteUIDTab() != RT_SUCCESS) {
return 1;
}
if (vySaveAssetDependencies() != VY_SUCCESS) {
if (rtSaveAssetDependencies() != RT_SUCCESS) {
return 1;
}
vyShutdownRuntime();
rtShutdownRuntime();
return 0;
}

View File

@ -12,113 +12,113 @@
#define MAP_SIZE 2048
typedef struct {
vy_file_id fids[MAP_SIZE];
vy_uid uids[MAP_SIZE];
vy_assetmeta meta[MAP_SIZE];
rt_file_id fids[MAP_SIZE];
rt_uid uids[MAP_SIZE];
rt_assetmeta meta[MAP_SIZE];
unsigned int used_slots;
} vy_uid_map;
} rt_uid_map;
#pragma pack(push, 1)
typedef struct {
XXH64_canonical_t checksum;
uint32_t num_entries;
uint32_t _reserved;
} vy_assetmeta_header;
} rt_assetmeta_header;
#pragma pack(pop)
#pragma pack(push, 1)
typedef struct {
vy_uid uid;
vy_file_id source_file;
vy_assetmeta meta;
} vy_assetmeta_entry;
rt_uid uid;
rt_file_id source_file;
rt_assetmeta meta;
} rt_assetmeta_entry;
#pragma pack(pop)
static vy_uid_map _map;
static vy_mutex *_guard;
static rt_uid_map _map;
static rt_mutex *_guard;
vy_result vyLoadAssetMeta(void) {
_guard = vyCreateMutex();
rt_result rtLoadAssetMeta(void) {
_guard = rtCreateMutex();
/* Load the meta file */
size_t fsz = vyGetFileSize("actemp/meta.bin");
size_t fsz = rtGetFileSize("actemp/meta.bin");
if (fsz == 0) {
vyLog("ASSETC", "Metadata file 'meta.bin' not found. All assets will be processed.");
return VY_SUCCESS;
rtLog("ASSETC", "Metadata file 'meta.bin' not found. All assets will be processed.");
return RT_SUCCESS;
}
void *buffer = vyAllocBuffer(fsz);
void *buffer = rtAllocBuffer(fsz);
if (!buffer) {
vyReportError("ASSETC", "Failed to allocate buffer for holding asset metadata.");
rtReportError("ASSETC", "Failed to allocate buffer for holding asset metadata.");
return 1;
}
vy_load_batch load;
rt_load_batch load;
load.loads[0].dest = buffer;
load.loads[0].file = vyAddFile("actemp/meta.bin");
load.loads[0].file = rtAddFile("actemp/meta.bin");
load.loads[0].num_bytes = fsz;
load.loads[0].offset = 0;
load.num_loads = 1;
vy_aio_handle handle;
if (vySubmitLoadBatch(&load, &handle) != VY_SUCCESS) {
vyReportError("ASSETC", "Failed to submit load of 'meta.bin'.");
vyReleaseBuffer(buffer, fsz);
rt_aio_handle handle;
if (rtSubmitLoadBatch(&load, &handle) != RT_SUCCESS) {
rtReportError("ASSETC", "Failed to submit load of 'meta.bin'.");
rtReleaseBuffer(buffer, fsz);
return 1;
}
if (vyWaitForAIOCompletion(handle) != VY_AIO_STATE_FINISHED) {
vyReportError("ASSETC", "Failed to load 'meta.bin'.");
vyReleaseBuffer(buffer, fsz);
vyReleaseAIO(handle);
if (rtWaitForAIOCompletion(handle) != RT_AIO_STATE_FINISHED) {
rtReportError("ASSETC", "Failed to load 'meta.bin'.");
rtReleaseBuffer(buffer, fsz);
rtReleaseAIO(handle);
return 1;
}
vyReleaseAIO(handle);
rtReleaseAIO(handle);
const vy_assetmeta_header *header = buffer;
const vy_assetmeta_entry *entries = (vy_assetmeta_entry *)(header + 1);
const rt_assetmeta_header *header = buffer;
const rt_assetmeta_entry *entries = (rt_assetmeta_entry *)(header + 1);
if ((sizeof(vy_assetmeta_entry) * header->num_entries + sizeof(*header)) > fsz) {
vyReportError("ASSETC", "Header of 'meta.bin' is corrupted: Mismatched num_entries and filesize.");
vyReleaseBuffer(buffer, fsz);
if ((sizeof(rt_assetmeta_entry) * header->num_entries + sizeof(*header)) > fsz) {
rtReportError("ASSETC", "Header of 'meta.bin' is corrupted: Mismatched num_entries and filesize.");
rtReleaseBuffer(buffer, fsz);
return 1;
}
XXH64_hash_t hash = XXH3_64bits(entries, sizeof(vy_assetmeta_entry) * header->num_entries);
XXH64_hash_t hash = XXH3_64bits(entries, sizeof(rt_assetmeta_entry) * header->num_entries);
XXH64_hash_t header_hash = XXH64_hashFromCanonical(&header->checksum);
if (hash != header_hash) {
vyReportError("ASSETC",
rtReportError("ASSETC",
"Metadata file 'meta.bin' is corrupted: Wrong checksum.");
vyReleaseBuffer(buffer, fsz);
rtReleaseBuffer(buffer, fsz);
return 1;
}
for (uint32_t i = 0; i < header->num_entries; ++i) {
/* Load here to avoid unaligned pointer */
vy_assetmeta meta = entries[i].meta;
vyAddUIDMapping(entries[i].source_file, entries[i].uid, &meta);
rt_assetmeta meta = entries[i].meta;
rtAddUIDMapping(entries[i].source_file, entries[i].uid, &meta);
}
vyReleaseBuffer(buffer, fsz);
rtReleaseBuffer(buffer, fsz);
return 0;
}
vy_result vySaveAssetMeta(void) {
vy_assetmeta_header header = {0};
rt_result rtSaveAssetMeta(void) {
rt_assetmeta_header header = {0};
/* Count number of entries */
for (size_t i = 0; i < MAP_SIZE; ++i) {
if (_map.fids[i] != VY_INVALID_FILE_ID)
if (_map.fids[i] != RT_INVALID_FILE_ID)
header.num_entries += 1;
}
vy_assetmeta_entry *entries = vyAllocBuffer(sizeof(vy_assetmeta_entry) * header.num_entries);
rt_assetmeta_entry *entries = rtAllocBuffer(sizeof(rt_assetmeta_entry) * header.num_entries);
if (!entries)
return VY_UNKNOWN_ERROR;
return RT_UNKNOWN_ERROR;
/* Store entries */
size_t j = 0;
for (size_t i = 0; i < MAP_SIZE; ++i) {
if (_map.fids[i] != VY_INVALID_FILE_ID) {
if (_map.fids[i] != RT_INVALID_FILE_ID) {
entries[j].source_file = _map.fids[i];
entries[j].uid = _map.uids[i];
entries[j].meta = _map.meta[i];
@ -126,52 +126,52 @@ vy_result vySaveAssetMeta(void) {
}
}
XXH64_hash_t hash = XXH3_64bits(entries, sizeof(vy_assetmeta_entry) * header.num_entries);
XXH64_hash_t hash = XXH3_64bits(entries, sizeof(rt_assetmeta_entry) * header.num_entries);
XXH64_canonicalFromHash(&header.checksum, hash);
header._reserved = 0;
FILE *f = fopen("actemp/meta.bin", "wb");
if (!f) {
vyReportError("ASSETC", "Failed to open 'meta.bin'");
vyReleaseBuffer(entries, sizeof(vy_assetmeta_entry) * header.num_entries);
return VY_UNKNOWN_ERROR;
rtReportError("ASSETC", "Failed to open 'meta.bin'");
rtReleaseBuffer(entries, sizeof(rt_assetmeta_entry) * header.num_entries);
return RT_UNKNOWN_ERROR;
}
if (fwrite(&header, sizeof(header), 1, f) != 1) {
vyReportError("ASSETC", "Failed to write 'meta.bin'");
vyReleaseBuffer(entries, sizeof(vy_assetmeta_entry) * header.num_entries);
return VY_UNKNOWN_ERROR;
rtReportError("ASSETC", "Failed to write 'meta.bin'");
rtReleaseBuffer(entries, sizeof(rt_assetmeta_entry) * header.num_entries);
return RT_UNKNOWN_ERROR;
}
if (fwrite(entries, sizeof(vy_assetmeta_entry), header.num_entries, f) != header.num_entries) {
vyReportError("ASSETC", "Failed to write 'meta.bin'");
vyReleaseBuffer(entries, sizeof(vy_assetmeta_entry) * header.num_entries);
return VY_UNKNOWN_ERROR;
if (fwrite(entries, sizeof(rt_assetmeta_entry), header.num_entries, f) != header.num_entries) {
rtReportError("ASSETC", "Failed to write 'meta.bin'");
rtReleaseBuffer(entries, sizeof(rt_assetmeta_entry) * header.num_entries);
return RT_UNKNOWN_ERROR;
}
fclose(f);
return VY_SUCCESS;
return RT_SUCCESS;
}
vy_uid vyLookupUID(vy_file_id fid) {
vyLockMutex(_guard);
rt_uid rtLookupUID(rt_file_id fid) {
rtLockMutex(_guard);
unsigned int i = 0;
vy_uid result = VY_INVALID_UID;
rt_uid result = RT_INVALID_UID;
while (i < MAP_SIZE) {
unsigned int slot = (fid + i) % MAP_SIZE;
if (_map.fids[slot] == fid) {
result = _map.uids[slot];
break;
} else if (_map.fids[slot] == VY_INVALID_FILE_ID) {
} else if (_map.fids[slot] == RT_INVALID_FILE_ID) {
break;
}
++i;
}
vyUnlockMutex(_guard);
rtUnlockMutex(_guard);
return result;
}
bool vyGetAssetMeta(vy_file_id source_file, vy_assetmeta *meta) {
vyLockMutex(_guard);
bool rtGetAssetMeta(rt_file_id source_file, rt_assetmeta *meta) {
rtLockMutex(_guard);
unsigned int i = 0;
bool result = false;
while (i < MAP_SIZE) {
@ -180,25 +180,25 @@ bool vyGetAssetMeta(vy_file_id source_file, vy_assetmeta *meta) {
*meta = _map.meta[slot];
result = true;
break;
} else if (_map.fids[slot] == VY_INVALID_FILE_ID) {
} else if (_map.fids[slot] == RT_INVALID_FILE_ID) {
break;
}
++i;
}
vyUnlockMutex(_guard);
rtUnlockMutex(_guard);
return result;
}
void vyAddUIDMapping(vy_file_id fid, vy_uid uid, const vy_assetmeta *meta) {
vyLockMutex(_guard);
void rtAddUIDMapping(rt_file_id fid, rt_uid uid, const rt_assetmeta *meta) {
rtLockMutex(_guard);
float fill_rate = (float)_map.used_slots / MAP_SIZE;
if (fill_rate >= .5f) {
vyLog("ASSETC", "UID map is above 50% filled.");
rtLog("ASSETC", "UID map is above 50% filled.");
}
unsigned int i = 0;
while (i < MAP_SIZE) {
unsigned int slot = (fid + i) % MAP_SIZE;
if (_map.fids[slot] == VY_INVALID_FILE_ID) {
if (_map.fids[slot] == RT_INVALID_FILE_ID) {
_map.fids[slot] = fid;
_map.uids[slot] = uid;
if (meta) {
@ -216,7 +216,7 @@ void vyAddUIDMapping(vy_file_id fid, vy_uid uid, const vy_assetmeta *meta) {
++i;
}
if (i == MAP_SIZE) {
vyReportError("ASSETC", "Failed to insert entry into UID map.");
rtReportError("ASSETC", "Failed to insert entry into UID map.");
}
vyUnlockMutex(_guard);
rtUnlockMutex(_guard);
}

View File

@ -1,5 +1,5 @@
#ifndef VY_ASSETC_ASSETMETA_H
#define VY_ASSETC_ASSETMETA_H
#ifndef RT_ASSETC_ASSETMETA_H
#define RT_ASSETC_ASSETMETA_H
#include "runtime/file_tab.h"
#include "runtime/assets.h"
@ -11,18 +11,18 @@ typedef struct {
uint64_t last_changed;
uint64_t compiled_ts;
uint32_t processing_flags;
} vy_assetmeta;
} rt_assetmeta;
vy_result vyLoadAssetMeta(void);
rt_result rtLoadAssetMeta(void);
vy_result vySaveAssetMeta(void);
rt_result rtSaveAssetMeta(void);
/* The UID map associates processed files with generated asset uids. */
void vyAddUIDMapping(vy_file_id fid, vy_uid uid, const vy_assetmeta *meta);
void rtAddUIDMapping(rt_file_id fid, rt_uid uid, const rt_assetmeta *meta);
/* Returns true if the asset is found. false otherwise */
bool vyGetAssetMeta(vy_file_id source_file, vy_assetmeta *meta);
bool rtGetAssetMeta(rt_file_id source_file, rt_assetmeta *meta);
vy_uid vyLookupUID(vy_file_id fid);
rt_uid rtLookupUID(rt_file_id fid);
#endif

View File

@ -10,15 +10,15 @@
#include <stdlib.h>
#include <stdio.h>
vy_result vyParseAssetSettings(const char *text,
rt_result rtParseAssetSettings(const char *text,
size_t length,
const char *file_path,
vy_asset_settings *settings) {
rt_asset_settings *settings) {
unsigned int root_list;
vy_parse_state state;
vy_result res = vyParseDescription(text, length, file_path, &root_list, &state);
if (res != VY_SUCCESS) {
vyReportError("ASSETC", "Failed to parse asset settings: %s", file_path);
rt_parse_state state;
rt_result res = rtParseDescription(text, length, file_path, &root_list, &state);
if (res != RT_SUCCESS) {
rtReportError("ASSETC", "Failed to parse asset settings: %s", file_path);
return res;
}
@ -27,66 +27,66 @@ vy_result vyParseAssetSettings(const char *text,
settings->processing_flags = 0;
settings->reprocess_on_dependency_change = false;
const vy_parsed_stmt *package_stmt = vyFindStatement(&state, root_list, "package");
const rt_parsed_stmt *package_stmt = rtFindStatement(&state, root_list, "package");
if (package_stmt) {
if (package_stmt->form != VY_STMT_FORM_VALUE) {
vyReportError("ASSETC",
if (package_stmt->form != RT_STMT_FORM_VALUE) {
rtReportError("ASSETC",
"Expected a package name as the value of 'package' in %s.",
file_path);
res = VY_UNKNOWN_ERROR;
res = RT_UNKNOWN_ERROR;
goto out;
}
settings->package = vyAddPackageFile(package_stmt->value);
settings->package = rtAddPackageFile(package_stmt->value);
}
const vy_parsed_stmt *flags_stmt = vyFindStatement(&state, root_list, "processing_flags");
const rt_parsed_stmt *flags_stmt = rtFindStatement(&state, root_list, "processing_flags");
if (flags_stmt) {
if (flags_stmt->form != VY_STMT_FORM_VALUE) {
vyReportError("ASSETC",
if (flags_stmt->form != RT_STMT_FORM_VALUE) {
rtReportError("ASSETC",
"Expected a hexadecimal number as the value of 'processing_flags' in %s.",
file_path);
res = VY_UNKNOWN_ERROR;
res = RT_UNKNOWN_ERROR;
goto out;
}
sscanf(flags_stmt->value.start, "%x", &settings->processing_flags);
}
const vy_parsed_stmt *reprocess_stmt =
vyFindStatement(&state, root_list, "reprocess_on_dependency_change");
const rt_parsed_stmt *reprocess_stmt =
rtFindStatement(&state, root_list, "reprocess_on_dependency_change");
if (reprocess_stmt) {
if (reprocess_stmt->form != VY_STMT_FORM_VALUE) {
vyReportError("ASSETC",
if (reprocess_stmt->form != RT_STMT_FORM_VALUE) {
rtReportError("ASSETC",
"Expected either 'true' or 'false' as the value of 'reprocess_on_dependency_change' in %s.",
file_path);
res = VY_UNKNOWN_ERROR;
res = RT_UNKNOWN_ERROR;
goto out;
}
if (vyCompareSpanToString(reprocess_stmt->value, "true") == 0)
if (rtCompareSpanToString(reprocess_stmt->value, "true") == 0)
settings->reprocess_on_dependency_change = true;
else if (vyCompareSpanToString(reprocess_stmt->value, "false") == 0)
else if (rtCompareSpanToString(reprocess_stmt->value, "false") == 0)
settings->reprocess_on_dependency_change = false;
else {
vyReportError("ASSETC",
rtReportError("ASSETC",
"Expected either 'true' or 'false' as the value of "
"'reprocess_on_dependency_change' in %s.",
file_path);
res = VY_UNKNOWN_ERROR;
res = RT_UNKNOWN_ERROR;
goto out;
}
}
out:
vyReleaseParseState(&state);
rtReleaseParseState(&state);
return res;
}
vy_result vyLoadAssetSettings(const char *asset_path, vy_asset_settings *settings) {
rt_result rtLoadAssetSettings(const char *asset_path, rt_asset_settings *settings) {
size_t path_len = strlen(asset_path);
char *as_path = malloc(path_len + 3);
if (!as_path) {
return VY_UNKNOWN_ERROR;
return RT_UNKNOWN_ERROR;
}
memcpy(as_path, asset_path, path_len);
@ -98,47 +98,47 @@ vy_result vyLoadAssetSettings(const char *asset_path, vy_asset_settings *setting
}
strcpy(&as_path[path_len - ext_len], ".as");
size_t as_size = vyGetFileSize(as_path);
size_t as_size = rtGetFileSize(as_path);
if (as_size == 0) {
vyReportError("ASSETC", "Failed to retrieve size of setting file %s", as_path);
rtReportError("ASSETC", "Failed to retrieve size of setting file %s", as_path);
free(as_path);
return VY_UNKNOWN_ERROR;
return RT_UNKNOWN_ERROR;
}
void *as_buffer = vyAllocBuffer(as_size);
void *as_buffer = rtAllocBuffer(as_size);
vy_load_batch as_load;
as_load.loads[0].file = vyAddFile(as_path);
rt_load_batch as_load;
as_load.loads[0].file = rtAddFile(as_path);
as_load.loads[0].num_bytes = as_size;
as_load.loads[0].dest = as_buffer;
if (!as_load.loads[0].dest) {
vyReportError("ASSETC", "Failed to allocate buffer for setting file %s", as_path);
rtReportError("ASSETC", "Failed to allocate buffer for setting file %s", as_path);
free(as_path);
return VY_UNKNOWN_ERROR;
return RT_UNKNOWN_ERROR;
}
as_load.loads[0].offset = 0;
as_load.num_loads = 1;
vy_aio_handle as_handle;
if (vySubmitLoadBatch(&as_load, &as_handle) != VY_SUCCESS) {
vyReportError("ASSETC", "Failed to submit load of setting file %s", as_path);
rt_aio_handle as_handle;
if (rtSubmitLoadBatch(&as_load, &as_handle) != RT_SUCCESS) {
rtReportError("ASSETC", "Failed to submit load of setting file %s", as_path);
free(as_path);
return VY_UNKNOWN_ERROR;
return RT_UNKNOWN_ERROR;
}
if (vyWaitForAIOCompletion(as_handle) != VY_AIO_STATE_FINISHED) {
vyReportError("ASSETC", "Failed to load setting file %s", as_path);
if (rtWaitForAIOCompletion(as_handle) != RT_AIO_STATE_FINISHED) {
rtReportError("ASSETC", "Failed to load setting file %s", as_path);
free(as_path);
return VY_UNKNOWN_ERROR;
return RT_UNKNOWN_ERROR;
}
vyReleaseAIO(as_handle);
rtReleaseAIO(as_handle);
if (vyParseAssetSettings(as_buffer, as_size, as_path, settings) != VY_SUCCESS) {
if (rtParseAssetSettings(as_buffer, as_size, as_path, settings) != RT_SUCCESS) {
free(as_path);
return VY_UNKNOWN_ERROR;
return RT_UNKNOWN_ERROR;
}
free(as_path);
return VY_SUCCESS;
return RT_SUCCESS;
}

View File

@ -1,5 +1,5 @@
#ifndef VY_ASSETC_ASSETSETTINGS_H
#define VY_ASSETC_ASSETSETTINGS_H
#ifndef RT_ASSETC_ASSETSETTINGS_H
#define RT_ASSETC_ASSETSETTINGS_H
#include "runtime/runtime.h"
#include <stdbool.h>
@ -8,14 +8,14 @@ typedef struct {
unsigned int package;
uint32_t processing_flags;
bool reprocess_on_dependency_change;
} vy_asset_settings;
} rt_asset_settings;
vy_result vyParseAssetSettings(const char *text,
rt_result rtParseAssetSettings(const char *text,
size_t length,
const char *file_path,
vy_asset_settings *settings);
rt_asset_settings *settings);
vy_result vyLoadAssetSettings(const char *asset_path, vy_asset_settings *settings);
rt_result rtLoadAssetSettings(const char *asset_path, rt_asset_settings *settings);
#endif

View File

@ -1,13 +1,13 @@
#ifndef VY_ASSETC_COMPILED_H
#define VY_ASSETC_COMPILED_H
#ifndef RT_ASSETC_COMPILED_H
#define RT_ASSETC_COMPILED_H
#include "runtime/runtime.h"
#include "runtime/assets.h"
vy_uid vyGetUID(const char *name);
rt_uid rtGetUID(const char *name);
void vyStoreOutput(vy_uid uid, const void *data, size_t size);
void rtStoreOutput(rt_uid uid, const void *data, size_t size);
vy_result vyWriteCompiledFiles(void);
rt_result rtWriteCompiledFiles(void);
#endif

View File

@ -1,6 +1,6 @@
#include "dependency_tracking.h"
#define VY_DEFINE_DEPENDENCY_FILE_STRUCTURES
#define RT_DEFINE_DEPENDENCY_FILE_STRUCTURES
#include "runtime/assets.h"
#include "runtime/threading.h"
#include "runtime/asset_dependencies.h"
@ -24,11 +24,11 @@
/* 64 byte cache line - 8 (next index + count) / 4 (u32) = 14 */
#define BUCKET_ENTRY_COUNT 14
typedef struct vy_dep_list_bucket_s {
typedef struct rt_dep_list_bucket_s {
uint32_t next;
uint32_t count;
vy_uid entries[BUCKET_ENTRY_COUNT];
} vy_dep_list_bucket;
rt_uid entries[BUCKET_ENTRY_COUNT];
} rt_dep_list_bucket;
typedef union {
/* Indices of the first buckets */
@ -37,47 +37,47 @@ typedef union {
uint32_t dependents;
};
uint32_t lists[2];
} vy_dep_list;
} rt_dep_list;
static vy_mutex *_guard;
static rt_mutex *_guard;
static vy_dep_list_bucket *_buckets;
static rt_dep_list_bucket *_buckets;
static uint32_t _bucket_count;
static uint32_t _bucket_capacity;
#define MAP_SIZE 2048
static vy_uid _uids[MAP_SIZE];
static vy_dep_list _lists[MAP_SIZE];
static rt_uid _uids[MAP_SIZE];
static rt_dep_list _lists[MAP_SIZE];
vy_result vyInitDependencyTracking(void) {
_guard = vyCreateMutex();
rt_result rtInitDependencyTracking(void) {
_guard = rtCreateMutex();
if (!_guard)
return VY_UNKNOWN_ERROR;
return RT_UNKNOWN_ERROR;
_buckets = malloc(sizeof(vy_dep_list_bucket) * 256);
_buckets = malloc(sizeof(rt_dep_list_bucket) * 256);
if (!_buckets)
return VY_UNKNOWN_ERROR;
return RT_UNKNOWN_ERROR;
_bucket_capacity = 256;
_bucket_count = 1;
return VY_SUCCESS;
return RT_SUCCESS;
}
static uint32_t AllocNewBucket(void) {
if (_bucket_count == _bucket_capacity) {
void *t = realloc(_buckets, (size_t)_bucket_capacity * 2 * sizeof(vy_dep_list_bucket));
void *t = realloc(_buckets, (size_t)_bucket_capacity * 2 * sizeof(rt_dep_list_bucket));
if (!t)
return 0;
_buckets = t;
_bucket_capacity *= 2;
}
memset(&_buckets[_bucket_count], 0, sizeof(vy_dep_list_bucket));
memset(&_buckets[_bucket_count], 0, sizeof(rt_dep_list_bucket));
return _bucket_count++;
}
static vy_result InsertIntoList(vy_uid list_asset, vy_uid uid, int list_index) {
vyLockMutex(_guard);
static rt_result InsertIntoList(rt_uid list_asset, rt_uid uid, int list_index) {
rtLockMutex(_guard);
bool inserted = false;
for (uint32_t i = 0; i < MAP_SIZE; i++) {
uint32_t at = (list_asset + i) % MAP_SIZE;
@ -88,13 +88,13 @@ static vy_result InsertIntoList(vy_uid list_asset, vy_uid uid, int list_index) {
if (_lists[at].lists[list_index] == 0) {
_lists[at].lists[list_index] = AllocNewBucket();
if (!_lists[at].lists[list_index]) {
vyUnlockMutex(_guard);
return VY_UNKNOWN_ERROR;
rtUnlockMutex(_guard);
return RT_UNKNOWN_ERROR;
}
}
/* Advance to the end of the list */
vy_dep_list_bucket *bucket = &_buckets[_lists[at].lists[list_index]];
rt_dep_list_bucket *bucket = &_buckets[_lists[at].lists[list_index]];
while (bucket->next != END_OF_LIST) {
bucket = &_buckets[bucket->next];
}
@ -103,8 +103,8 @@ static vy_result InsertIntoList(vy_uid list_asset, vy_uid uid, int list_index) {
if (bucket->count == BUCKET_ENTRY_COUNT) {
bucket->next = AllocNewBucket();
if (!bucket->next) {
vyUnlockMutex(_guard);
return VY_UNKNOWN_ERROR;
rtUnlockMutex(_guard);
return RT_UNKNOWN_ERROR;
}
bucket = &_buckets[bucket->next];
}
@ -116,64 +116,64 @@ static vy_result InsertIntoList(vy_uid list_asset, vy_uid uid, int list_index) {
break;
}
}
vyUnlockMutex(_guard);
rtUnlockMutex(_guard);
assert(inserted);
return VY_SUCCESS;
return RT_SUCCESS;
}
vy_result vyAddAssetDependency(vy_uid dependent, vy_uid dependency) {
vy_result res = InsertIntoList(dependent, dependency, 0);
if (res != VY_SUCCESS)
rt_result rtAddAssetDependency(rt_uid dependent, rt_uid dependency) {
rt_result res = InsertIntoList(dependent, dependency, 0);
if (res != RT_SUCCESS)
return res;
res = InsertIntoList(dependency, dependent, 1);
return res;
}
vy_result vySaveAssetDependencies(void) {
assert(vyIsMainThread());
vy_dependency_file_header header = {.num_lists = 0, .data_size = 0};
rt_result rtSaveAssetDependencies(void) {
assert(rtIsMainThread());
rt_dependency_file_header header = {.num_lists = 0, .data_size = 0};
for (size_t i = 0; i < MAP_SIZE; ++i) {
if (_uids[i] != VY_INVALID_UID) {
if (_uids[i] != RT_INVALID_UID) {
if (!_lists[i].dependencies)
continue;
header.num_lists += 1;
/* Determine the list size */
vy_dep_list_bucket *bucket = &_buckets[_lists[i].dependencies];
rt_dep_list_bucket *bucket = &_buckets[_lists[i].dependencies];
uint32_t total_list_size = bucket->count;
while (bucket->next != END_OF_LIST) {
bucket = &_buckets[bucket->next];
total_list_size += bucket->count;
}
header.data_size += total_list_size * sizeof(vy_uid) + sizeof(vy_dependency_file_list_header);
header.data_size += total_list_size * sizeof(rt_uid) + sizeof(rt_dependency_file_list_header);
}
}
FILE *f = fopen("data/deps.bin", "wb");
if (!f) {
vyReportError("ASSETC", "Failed to open 'deps.bin' for writing.");
return VY_UNKNOWN_ERROR;
rtReportError("ASSETC", "Failed to open 'deps.bin' for writing.");
return RT_UNKNOWN_ERROR;
}
if (fwrite(&header, sizeof(header), 1, f) != 1) {
vyReportError("ASSETC", "Failed to write to 'deps.bin'.");
rtReportError("ASSETC", "Failed to write to 'deps.bin'.");
fclose(f);
return VY_UNKNOWN_ERROR;
return RT_UNKNOWN_ERROR;
}
void *buffer = NULL;
size_t buffer_size = 0;
for (size_t i = 0; i < MAP_SIZE; ++i) {
if (_uids[i] != VY_INVALID_UID) {
if (_uids[i] != RT_INVALID_UID) {
if (!_lists[i].dependencies)
continue;
/* Determine the list size */
vy_dep_list_bucket *bucket = &_buckets[_lists[i].dependencies];
rt_dep_list_bucket *bucket = &_buckets[_lists[i].dependencies];
uint32_t total_list_size = bucket->count;
while (bucket->next != END_OF_LIST) {
bucket = &_buckets[bucket->next];
@ -182,21 +182,21 @@ vy_result vySaveAssetDependencies(void) {
/* Allocate */
size_t required_size =
total_list_size * sizeof(vy_uid) + sizeof(vy_dependency_file_list_header);
total_list_size * sizeof(rt_uid) + sizeof(rt_dependency_file_list_header);
if (required_size > buffer_size) {
void *t = realloc(buffer, required_size);
if (!t) {
free(buffer);
fclose(f);
return VY_UNKNOWN_ERROR;
return RT_UNKNOWN_ERROR;
}
buffer = t;
buffer_size = required_size;
}
/* Fill header */
vy_dependency_file_list_header *list_header = buffer;
vy_uid *list = (vy_uid *)(list_header + 1);
rt_dependency_file_list_header *list_header = buffer;
rt_uid *list = (rt_uid *)(list_header + 1);
list_header->uid = _uids[i];
list_header->num_entries = total_list_size;
@ -204,19 +204,19 @@ vy_result vySaveAssetDependencies(void) {
uint32_t at = 0;
bucket = &_buckets[_lists[i].dependencies];
do {
memcpy(&list[at], bucket->entries, sizeof(vy_uid) * bucket->count);
memcpy(&list[at], bucket->entries, sizeof(rt_uid) * bucket->count);
at += bucket->count;
bucket = &_buckets[bucket->next];
} while (bucket != &_buckets[END_OF_LIST]);
XXH64_hash_t hash = XXH3_64bits(list, sizeof(vy_uid) * total_list_size);
XXH64_hash_t hash = XXH3_64bits(list, sizeof(rt_uid) * total_list_size);
XXH64_canonicalFromHash(&list_header->checksum, hash);
if (fwrite(buffer, required_size, 1, f) != 1) {
vyReportError("ASSETC", "Failed to write to 'deps.bin'.");
rtReportError("ASSETC", "Failed to write to 'deps.bin'.");
fclose(f);
free(buffer);
return VY_UNKNOWN_ERROR;
return RT_UNKNOWN_ERROR;
}
}
}
@ -224,5 +224,5 @@ vy_result vySaveAssetDependencies(void) {
fclose(f);
free(buffer);
return VY_SUCCESS;
return RT_SUCCESS;
}

View File

@ -1,14 +1,14 @@
#ifndef VY_ASSETC_DEPENDENCY_TRACKING_H
#define VY_ASSETC_DEPENDENCY_TRACKING_H
#ifndef RT_ASSETC_DEPENDENCY_TRACKING_H
#define RT_ASSETC_DEPENDENCY_TRACKING_H
#include "runtime/runtime.h"
#include "runtime/assets.h"
vy_result vyInitDependencyTracking(void);
rt_result rtInitDependencyTracking(void);
vy_result vyAddAssetDependency(vy_uid dependent, vy_uid dependency);
rt_result rtAddAssetDependency(rt_uid dependent, rt_uid dependency);
vy_result vySaveAssetDependencies(void);
rt_result rtSaveAssetDependencies(void);
#endif

View File

@ -17,7 +17,7 @@ static bool IsWhitespace(char c) {
return c == ' ' || c == '\t' || c == '\n' || c == '\r';
}
static void SkipWhitespace(vy_parse_state *state) {
static void SkipWhitespace(rt_parse_state *state) {
while (state->at < state->length && IsWhitespace(state->text[state->at])) {
if (state->text[state->at] == '\n')
++state->line;
@ -25,8 +25,8 @@ static void SkipWhitespace(vy_parse_state *state) {
}
}
static bool ParseAttribute(vy_parse_state *state, vy_text_span *_name) {
vy_text_span name;
static bool ParseAttribute(rt_parse_state *state, rt_text_span *_name) {
rt_text_span name;
name.start = &state->text[state->at];
name.length = 0;
while (state->at < state->length && !IsWhitespace(state->text[state->at])) {
@ -34,7 +34,7 @@ static bool ParseAttribute(vy_parse_state *state, vy_text_span *_name) {
++state->at;
++name.length;
} else {
vyReportError("GFX",
rtReportError("GFX",
"%s:%d Unexpected character %c",
state->file,
state->line,
@ -46,8 +46,8 @@ static bool ParseAttribute(vy_parse_state *state, vy_text_span *_name) {
return true;
}
static bool ParseValue(vy_parse_state *state, vy_text_span *_value) {
vy_text_span value;
static bool ParseValue(rt_parse_state *state, rt_text_span *_value) {
rt_text_span value;
value.start = &state->text[state->at];
value.length = 0;
while (state->at < state->length && !IsWhitespace(state->text[state->at]) &&
@ -56,7 +56,7 @@ static bool ParseValue(vy_parse_state *state, vy_text_span *_value) {
++state->at;
++value.length;
} else {
vyReportError("GFX",
rtReportError("GFX",
"%s:%d Unexpected character %c",
state->file,
state->line,
@ -73,18 +73,18 @@ static bool ParseValue(vy_parse_state *state, vy_text_span *_value) {
#define BLOCK_END "END"
#define BLOCK_END_LENGTH 3
VY_INLINE static bool IsBlockBegin(vy_parse_state *state) {
RT_INLINE static bool IsBlockBegin(rt_parse_state *state) {
return (state->length - state->at >= BLOCK_BEGIN_LENGTH) &&
(memcmp(&state->text[state->at], BLOCK_BEGIN, BLOCK_BEGIN_LENGTH) == 0);
}
VY_INLINE static bool IsBlockEnd(vy_parse_state *state) {
RT_INLINE static bool IsBlockEnd(rt_parse_state *state) {
return (state->length - state->at >= BLOCK_END_LENGTH) &&
(memcmp(&state->text[state->at], BLOCK_END, BLOCK_END_LENGTH) == 0);
}
static bool ParseBlock(vy_parse_state *state, vy_text_span *p_value) {
vy_text_span value;
static bool ParseBlock(rt_parse_state *state, rt_text_span *p_value) {
rt_text_span value;
value.start = &state->text[state->at];
value.length = 0;
while (state->at < state->length) {
@ -99,10 +99,10 @@ static bool ParseBlock(vy_parse_state *state, vy_text_span *p_value) {
return false;
}
static bool ParseStmtList(vy_parse_state *state, unsigned int *list_index);
static bool ParseStmtList(rt_parse_state *state, unsigned int *list_index);
static bool ParseStmt(vy_parse_state *state, unsigned int *stmt_index) {
vy_parsed_stmt stmt;
static bool ParseStmt(rt_parse_state *state, unsigned int *stmt_index) {
rt_parsed_stmt stmt;
stmt.next = UINT_MAX; /* end of list */
SkipWhitespace(state);
@ -111,7 +111,7 @@ static bool ParseStmt(vy_parse_state *state, unsigned int *stmt_index) {
SkipWhitespace(state);
if (state->at == state->length) {
vyReportError("GFX", "%s:%d Expected either a value or '{'", state->file, state->line);
rtReportError("GFX", "%s:%d Expected either a value or '{'", state->file, state->line);
return false;
}
@ -119,7 +119,7 @@ static bool ParseStmt(vy_parse_state *state, unsigned int *stmt_index) {
/* Consume '{' */
++state->at;
stmt.form = VY_STMT_FORM_LIST;
stmt.form = RT_STMT_FORM_LIST;
if (!ParseStmtList(state, &stmt.list_index))
return false;
@ -130,14 +130,14 @@ static bool ParseStmt(vy_parse_state *state, unsigned int *stmt_index) {
/* Consume BEGIN */
state->at += BLOCK_BEGIN_LENGTH;
stmt.form = VY_STMT_FORM_BLOCK;
stmt.form = RT_STMT_FORM_BLOCK;
if (!ParseBlock(state, &stmt.block))
return false;
/* Consume END */
state->at += BLOCK_END_LENGTH;
} else {
stmt.form = VY_STMT_FORM_VALUE;
stmt.form = RT_STMT_FORM_VALUE;
if (!ParseValue(state, &stmt.value))
return false;
@ -151,9 +151,9 @@ static bool ParseStmt(vy_parse_state *state, unsigned int *stmt_index) {
/* Add statement to array */
if (state->statement_count == state->statement_capacity) {
unsigned int cap = (state->statement_capacity > 0) ? state->statement_capacity * 2 : 64;
vy_parsed_stmt *temp = realloc(state->statements, sizeof(vy_parsed_stmt) * cap);
rt_parsed_stmt *temp = realloc(state->statements, sizeof(rt_parsed_stmt) * cap);
if (!temp) {
vyReportError("GFX", "While parsing %s: Out of memory\n", state->file);
rtReportError("GFX", "While parsing %s: Out of memory\n", state->file);
return false;
}
state->statements = temp;
@ -165,8 +165,8 @@ static bool ParseStmt(vy_parse_state *state, unsigned int *stmt_index) {
return true;
}
static bool ParseStmtList(vy_parse_state *state, unsigned int *list_index) {
vy_parsed_stmt_list list;
static bool ParseStmtList(rt_parse_state *state, unsigned int *list_index) {
rt_parsed_stmt_list list;
list.first = UINT_MAX;
list.count = 0;
@ -190,10 +190,10 @@ static bool ParseStmtList(vy_parse_state *state, unsigned int *list_index) {
if (state->statement_list_count == state->statement_list_capacity) {
unsigned int cap =
(state->statement_list_capacity > 0) ? state->statement_list_capacity * 2 : 64;
vy_parsed_stmt_list *temp =
realloc(state->statement_lists, sizeof(vy_parsed_stmt_list) * cap);
rt_parsed_stmt_list *temp =
realloc(state->statement_lists, sizeof(rt_parsed_stmt_list) * cap);
if (!temp) {
vyReportError("GFX", "While parsing %s: Out of memory\n", state->file);
rtReportError("GFX", "While parsing %s: Out of memory\n", state->file);
return false;
}
state->statement_lists = temp;
@ -204,14 +204,14 @@ static bool ParseStmtList(vy_parse_state *state, unsigned int *list_index) {
return true;
}
const vy_parsed_stmt * vyFindStatement(const vy_parse_state *state, unsigned int list_index, const char *attribute) {
const rt_parsed_stmt * rtFindStatement(const rt_parse_state *state, unsigned int list_index, const char *attribute) {
if (list_index >= state->statement_list_count)
return NULL;
const vy_parsed_stmt_list *list = &state->statement_lists[list_index];
const rt_parsed_stmt_list *list = &state->statement_lists[list_index];
unsigned int stmt_index = list->first;
for (unsigned int i = 0; i < list->count; ++i) {
const vy_parsed_stmt *stmt = &state->statements[stmt_index];
if (vyCompareSpanToString(stmt->attribute, attribute) == 0)
const rt_parsed_stmt *stmt = &state->statements[stmt_index];
if (rtCompareSpanToString(stmt->attribute, attribute) == 0)
return stmt;
stmt_index = stmt->next;
}
@ -219,13 +219,13 @@ const vy_parsed_stmt * vyFindStatement(const vy_parse_state *state, unsigned int
}
vy_result vyParseDescription(const char *text,
rt_result rtParseDescription(const char *text,
size_t length,
const char *file_path,
unsigned int *_root_list,
vy_parse_state *_state) {
rt_parse_state *_state) {
vy_parse_state state = {.text = text,
rt_parse_state state = {.text = text,
.at = 0,
.length = length,
.line = 1,
@ -242,11 +242,11 @@ vy_result vyParseDescription(const char *text,
*_root_list = root_list;
*_state = state;
return VY_SUCCESS;
return RT_SUCCESS;
}
void vyReleaseParseState(vy_parse_state *state) {
void rtReleaseParseState(rt_parse_state *state) {
free(state->statements);
free(state->statement_lists);
}

View File

@ -1,30 +1,30 @@
#ifndef VY_ASSETC_DESCRIPTION_PARSER_H
#define VY_ASSETC_DESCRIPTION_PARSER_H
#ifndef RT_ASSETC_DESCRIPTION_PARSER_H
#define RT_ASSETC_DESCRIPTION_PARSER_H
#include "runtime/runtime.h"
typedef enum {
VY_STMT_FORM_VALUE,
VY_STMT_FORM_LIST,
VY_STMT_FORM_BLOCK,
} vy_stmt_form;
RT_STMT_FORM_VALUE,
RT_STMT_FORM_LIST,
RT_STMT_FORM_BLOCK,
} rt_stmt_form;
typedef struct {
unsigned int first;
unsigned int count;
} vy_parsed_stmt_list;
} rt_parsed_stmt_list;
typedef struct {
vy_stmt_form form;
vy_text_span attribute;
rt_stmt_form form;
rt_text_span attribute;
union {
vy_text_span value;
vy_text_span block;
rt_text_span value;
rt_text_span block;
unsigned int list_index;
};
/* For lists */
unsigned int next;
} vy_parsed_stmt;
} rt_parsed_stmt;
typedef struct {
const char *file;
@ -33,23 +33,23 @@ typedef struct {
size_t length;
int line;
vy_parsed_stmt *statements;
rt_parsed_stmt *statements;
unsigned int statement_count;
unsigned int statement_capacity;
vy_parsed_stmt_list *statement_lists;
rt_parsed_stmt_list *statement_lists;
unsigned int statement_list_count;
unsigned int statement_list_capacity;
} vy_parse_state;
} rt_parse_state;
vy_result vyParseDescription(const char *text,
rt_result rtParseDescription(const char *text,
size_t length,
const char *file_path,
unsigned int *root_list,
vy_parse_state *state);
rt_parse_state *state);
const vy_parsed_stmt *vyFindStatement(const vy_parse_state *state, unsigned int list_index, const char *attribute);
const rt_parsed_stmt *rtFindStatement(const rt_parse_state *state, unsigned int list_index, const char *attribute);
void vyReleaseParseState(vy_parse_state *state);
void rtReleaseParseState(rt_parse_state *state);
#endif

View File

@ -11,32 +11,32 @@
typedef struct {
char path_scratch[1024];
unsigned int path_end;
} vy_discovery_data;
} rt_discovery_data;
static vy_result LoadCompressedAsset(vy_uid uid, void **buffer, size_t size) {
static rt_result LoadCompressedAsset(rt_uid uid, void **buffer, size_t size) {
}
static vy_result DirectoryHandler(const char *name, vyIterateDirElementType type, void *user) {
vy_discovery_data *data = user;
static rt_result DirectoryHandler(const char *name, rtIterateDirElementType type, void *user) {
rt_discovery_data *data = user;
size_t name_len = strlen(name);
if (type == VY_DIR_ELEMENT_TYPE_FILE) {
if (type == RT_DIR_ELEMENT_TYPE_FILE) {
/* Skip files we don't want to process */
if (name_len >= 3) {
if (memcmp(&name[name_len - 3], ".as", 3) == 0)
return VY_SUCCESS;
return RT_SUCCESS;
}
if (name_len >= 4) {
if (memcmp(&name[name_len - 4], ".pkg", 4) == 0)
return VY_SUCCESS;
return RT_SUCCESS;
else if (memcmp(&name[name_len - 4], ".bin", 4) == 0)
return VY_SUCCESS;
return RT_SUCCESS;
}
if (strcmp(name, "packages.txt") == 0)
return VY_SUCCESS;
return RT_SUCCESS;
if (name[0] == '.') {
return VY_SUCCESS;
return RT_SUCCESS;
}
/* Check if we know that file */
@ -49,49 +49,49 @@ static vy_result DirectoryHandler(const char *name, vyIterateDirElementType type
data->path_scratch[name_len] = '\0';
}
vy_file_id fid = vyAddFile(data->path_scratch);
if (vyLookupUID(fid) != VY_INVALID_UID) {
vy_assetmeta meta = {0};
if (!vyGetAssetMeta(fid, &meta) || (meta.last_changed >= meta.compiled_ts)) {
rt_file_id fid = rtAddFile(data->path_scratch);
if (rtLookupUID(fid) != RT_INVALID_UID) {
rt_assetmeta meta = {0};
if (!rtGetAssetMeta(fid, &meta) || (meta.last_changed >= meta.compiled_ts)) {
/* The file (may have) changed */
vy_result res = vyAddFileToProcessingQueue(fid, meta.processing_flags);
if (res != VY_SUCCESS)
rt_result res = rtAddFileToProcessingQueue(fid, meta.processing_flags);
if (res != RT_SUCCESS)
return res;
}
else {
/* The file is unchanged, we just need to add it to the output again. */
vyLog("ASSETC", "File %s is unchanged.", data->path_scratch);
rtLog("ASSETC", "File %s is unchanged.", data->path_scratch);
vy_asset_settings settings = {0};
if (vyLoadAssetSettings(data->path_scratch, &settings) != VY_SUCCESS) {
vyLog("ASSETC", "Failed to load settings for %s", data->path_scratch);
return VY_UNKNOWN_ERROR;
rt_asset_settings settings = {0};
if (rtLoadAssetSettings(data->path_scratch, &settings) != RT_SUCCESS) {
rtLog("ASSETC", "Failed to load settings for %s", data->path_scratch);
return RT_UNKNOWN_ERROR;
}
/* We need to load the processed data and add it to the package */
vy_uid uid = vyLookupUID(fid);
if (uid == VY_INVALID_UID) {
vyLog("ASSETC", "Failed to lookup UID of known asset %s", data->path_scratch);
return VY_UNKNOWN_ERROR;
rt_uid uid = rtLookupUID(fid);
if (uid == RT_INVALID_UID) {
rtLog("ASSETC", "Failed to lookup UID of known asset %s", data->path_scratch);
return RT_UNKNOWN_ERROR;
}
vyAddUnchangedAssetToPackage(settings.package, uid);
rtAddUnchangedAssetToPackage(settings.package, uid);
}
} else {
/* Process it */
vy_asset_settings settings = {0};
if (vyLoadAssetSettings(data->path_scratch, &settings) != VY_SUCCESS) {
vyLog("ASSETC", "Failed to load settings for %s", data->path_scratch);
rt_asset_settings settings = {0};
if (rtLoadAssetSettings(data->path_scratch, &settings) != RT_SUCCESS) {
rtLog("ASSETC", "Failed to load settings for %s", data->path_scratch);
}
vy_result res = vyAddFileToProcessingQueue(fid, settings.processing_flags);
if (res != VY_SUCCESS)
rt_result res = rtAddFileToProcessingQueue(fid, settings.processing_flags);
if (res != RT_SUCCESS)
return res;
}
} else if (type == VY_DIR_ELEMENT_TYPE_DIRECTORY) {
} else if (type == RT_DIR_ELEMENT_TYPE_DIRECTORY) {
if (strcmp(name, ".") == 0)
return VY_SUCCESS;
return RT_SUCCESS;
if (strcmp(name, "..") == 0)
return VY_SUCCESS;
return RT_SUCCESS;
unsigned int path_end_before = data->path_end;
if (data->path_end > 0)
@ -100,20 +100,20 @@ static vy_result DirectoryHandler(const char *name, vyIterateDirElementType type
data->path_scratch[data->path_end + name_len] = '\0';
data->path_end += (unsigned int)name_len;
vy_result res = vyIterateDirectory(data->path_scratch, user, DirectoryHandler);
if (res != VY_SUCCESS)
rt_result res = rtIterateDirectory(data->path_scratch, user, DirectoryHandler);
if (res != RT_SUCCESS)
return res;
data->path_end = path_end_before;
}
return VY_SUCCESS;
return RT_SUCCESS;
}
void vyDiscoverAssets(void) {
void rtDiscoverAssets(void) {
vy_discovery_data data;
rt_discovery_data data;
memcpy(data.path_scratch, "assets", sizeof("assets"));
data.path_end = sizeof("assets") - 1;
vyIterateDirectory("assets", &data, DirectoryHandler);
rtIterateDirectory("assets", &data, DirectoryHandler);
}

View File

@ -1,28 +1,28 @@
#ifndef VY_ASSETC_OPTIONS_H
#define VY_ASSETC_OPTIONS_H
#ifndef RT_ASSETC_OPTIONS_H
#define RT_ASSETC_OPTIONS_H
#include "runtime/assets.h"
typedef enum {
/* No optimization */
VY_ASSET_OPTIMIZATION_NONE,
RT_ASSET_OPTIMIZATION_NONE,
/* Create small assets */
VY_ASSET_OPTIMIZATION_SPACE,
RT_ASSET_OPTIMIZATION_SPACE,
/* Create assets for fast execution */
VY_ASSET_OPTIMIZATION_PERFORMANCE,
} vy_asset_optimization_level;
RT_ASSET_OPTIMIZATION_PERFORMANCE,
} rt_asset_optimization_level;
/* Options parsed from command line arguments */
typedef struct {
const char *root_directory;
vy_renderer_backend_code renderer_backend;
vy_asset_optimization_level optimization;
} vy_assetc_options;
rt_renderer_backend_code renderer_backend;
rt_asset_optimization_level optimization;
} rt_assetc_options;
#ifndef VY_ASSETC_DONT_DEFINE_OPTIONS_GLOBAL
extern vy_assetc_options g_assetc_options;
#ifndef RT_ASSETC_DONT_DEFINE_OPTIONS_GLOBAL
extern rt_assetc_options g_assetc_options;
#endif
#endif

View File

@ -2,7 +2,7 @@
#include "processing.h"
#include "utils.h"
#define VY_DEFINE_PACKAGE_FILE_STRUCTURES
#define RT_DEFINE_PACKAGE_FILE_STRUCTURES
#include "runtime/threading.h"
#include "runtime/assets.h"
#include "runtime/file_tab.h"
@ -19,30 +19,30 @@
#include "lz4/lz4.h"
typedef struct {
vy_uid uid;
rt_uid uid;
size_t disk_size;
} vy_package_entry;
} rt_package_entry;
typedef struct {
char *name;
unsigned int num_entries;
unsigned int entry_capacity;
vy_package_entry *entries;
} vy_package;
rt_package_entry *entries;
} rt_package;
#define MAX_PACKAGES 1024
vy_package _packages[MAX_PACKAGES];
rt_package _packages[MAX_PACKAGES];
unsigned int _package_count = 0;
vy_mutex *_guard;
rt_mutex *_guard;
unsigned int vyAddPackageFile(vy_text_span name) {
vyLockMutex(_guard);
unsigned int rtAddPackageFile(rt_text_span name) {
rtLockMutex(_guard);
for (unsigned int i = 0; i < _package_count; ++i) {
if (vyCompareSpanToString(name, _packages[i].name + 5) == 0) {
vyUnlockMutex(_guard);
if (rtCompareSpanToString(name, _packages[i].name + 5) == 0) {
rtUnlockMutex(_guard);
return i;
}
}
@ -50,11 +50,11 @@ unsigned int vyAddPackageFile(vy_text_span name) {
/* Create a new package */
_packages[_package_count].name = malloc(name.length + 1 + 5);
if (!_packages[_package_count].name) {
vyReportError("ASSETC",
rtReportError("ASSETC",
"Failed to allocate storage for new package %*.s",
name.length,
name.start);
vyUnlockMutex(_guard);
rtUnlockMutex(_guard);
return UINT_MAX;
}
memcpy(_packages[_package_count].name, "data/", 5);
@ -63,42 +63,42 @@ unsigned int vyAddPackageFile(vy_text_span name) {
unsigned int index = _package_count++;
vyUnlockMutex(_guard);
rtUnlockMutex(_guard);
return index;
}
void vyInitPackages(void) {
_guard = vyCreateMutex();
void rtInitPackages(void) {
_guard = rtCreateMutex();
/* Create the default package (0) */
vyAddPackageFile((vy_text_span){.start = "default.pkg", .length = 12});
rtAddPackageFile((rt_text_span){.start = "default.pkg", .length = 12});
}
static void AddAssetToPackageImpl(unsigned int package,
vy_uid uid,
rt_uid uid,
void *buffer,
size_t size,
bool needs_compression) {
vyLockMutex(_guard);
rtLockMutex(_guard);
if (package >= _package_count) {
vyReportError("ASSETC", "Trying to add an asset to a non-existing package.");
vyUnlockMutex(_guard);
rtReportError("ASSETC", "Trying to add an asset to a non-existing package.");
rtUnlockMutex(_guard);
return;
}
vy_package *pkg = &_packages[package];
rt_package *pkg = &_packages[package];
for (unsigned int i = 0; i < pkg->num_entries; ++i) {
if (pkg->entries[i].uid == uid) {
vyUnlockMutex(_guard);
rtUnlockMutex(_guard);
return;
}
}
if (pkg->num_entries == pkg->entry_capacity) {
unsigned int new_cap = (pkg->entry_capacity > 0) ? 2 * pkg->entry_capacity : 256;
vy_package_entry *n = realloc(pkg->entries, new_cap * sizeof(vy_package_entry));
rt_package_entry *n = realloc(pkg->entries, new_cap * sizeof(rt_package_entry));
if (!n) {
vyReportError("ASSETC", "Failed to grow storage for package %u.", package);
rtReportError("ASSETC", "Failed to grow storage for package %u.", package);
return;
}
pkg->entry_capacity = new_cap;
@ -110,7 +110,7 @@ static void AddAssetToPackageImpl(unsigned int package,
if (needs_compression) {
FILE *tmp_f = fopen(tmp_path, "wb");
if (!tmp_f) {
vyUnlockMutex(_guard);
rtUnlockMutex(_guard);
return;
}
@ -118,7 +118,7 @@ static void AddAssetToPackageImpl(unsigned int package,
void *compressed_buffer = malloc(required_size);
if (!compressed_buffer) {
fclose(tmp_f);
vyUnlockMutex(_guard);
rtUnlockMutex(_guard);
return;
}
@ -127,23 +127,23 @@ static void AddAssetToPackageImpl(unsigned int package,
if (compressed_bytes == 0) {
free(compressed_buffer);
fclose(tmp_f);
vyReportError("ASSETC", "Failed to compress asset %x of package %s", uid, pkg->name);
rtReportError("ASSETC", "Failed to compress asset %x of package %s", uid, pkg->name);
return;
}
vy_package_asset_header header;
rt_package_asset_header header;
XXH64_hash_t checksum = XXH3_64bits_withSeed(buffer, (size_t)compressed_bytes, 0);
XXH64_canonicalFromHash(&header.checksum, checksum);
header.decompressed_size = (uint32_t)size;
if (fwrite(&header, sizeof(header), 1, tmp_f) != 1) {
vyReportError("ASSETC", "Failed to write to actemp/%u.bin", uid);
rtReportError("ASSETC", "Failed to write to actemp/%u.bin", uid);
free(compressed_buffer);
fclose(tmp_f);
return;
}
if (fwrite(buffer, compressed_bytes, 1, tmp_f) != 1) {
vyReportError("ASSETC", "Failed to write to actemp/%u.bin", uid);
rtReportError("ASSETC", "Failed to write to actemp/%u.bin", uid);
free(compressed_buffer);
fclose(tmp_f);
return;
@ -151,11 +151,11 @@ static void AddAssetToPackageImpl(unsigned int package,
fclose(tmp_f);
pkg->entries[pkg->num_entries].disk_size =
(size_t)compressed_bytes + sizeof(vy_package_asset_header);
(size_t)compressed_bytes + sizeof(rt_package_asset_header);
} else {
pkg->entries[pkg->num_entries].disk_size = vyGetFileSize(tmp_path);
pkg->entries[pkg->num_entries].disk_size = rtGetFileSize(tmp_path);
if (pkg->entries[pkg->num_entries].disk_size == 0) {
vyReportError("ASSETC", "Failed to determine size of actemp/%u.bin", uid);
rtReportError("ASSETC", "Failed to determine size of actemp/%u.bin", uid);
}
}
@ -163,21 +163,21 @@ static void AddAssetToPackageImpl(unsigned int package,
++pkg->num_entries;
vyUnlockMutex(_guard);
rtUnlockMutex(_guard);
}
void vyAddAssetToPackage(unsigned int package, vy_uid uid, void *buffer, size_t size) {
void rtAddAssetToPackage(unsigned int package, rt_uid uid, void *buffer, size_t size) {
AddAssetToPackageImpl(package, uid, buffer, size, true);
}
void vyAddUnchangedAssetToPackage(unsigned int package, vy_uid uid) {
void rtAddUnchangedAssetToPackage(unsigned int package, rt_uid uid) {
AddAssetToPackageImpl(package, uid, NULL, 0, false);
}
static vy_result SavePackage(vy_package *pkg) {
static rt_result SavePackage(rt_package *pkg) {
if (pkg->num_entries == 0) {
vyLog("ASSETC", "Package %s has no entries.", pkg->name);
return VY_SUCCESS;
rtLog("ASSETC", "Package %s has no entries.", pkg->name);
return RT_SUCCESS;
}
size_t current_buffer_size = 0;
@ -185,12 +185,12 @@ static vy_result SavePackage(vy_package *pkg) {
size_t offset_in_file = 0;
vy_file_id package_fid = vyAddFile(pkg->name);
rt_file_id package_fid = rtAddFile(pkg->name);
FILE *f = fopen(pkg->name, "wb");
if (!f) {
vyReportError("ASSETC", "Failed to open %s for writing.", pkg->name);
return VY_UNKNOWN_ERROR;
rtReportError("ASSETC", "Failed to open %s for writing.", pkg->name);
return RT_UNKNOWN_ERROR;
}
for (unsigned int i = 0; i < pkg->num_entries; ++i) {
@ -198,42 +198,42 @@ static vy_result SavePackage(vy_package *pkg) {
snprintf(tmp_path, 256, "actemp/%u.bin", pkg->entries[i].uid);
FILE *tmp_f = fopen(tmp_path, "rb");
if (!tmp_f) {
vyReportError("ASSETC", "Failed to open %s for reading.", tmp_path);
rtReportError("ASSETC", "Failed to open %s for reading.", tmp_path);
fclose(f);
free(buffer);
return VY_UNKNOWN_ERROR;
return RT_UNKNOWN_ERROR;
}
if (current_buffer_size < pkg->entries[i].disk_size) {
void *tmp = realloc(buffer, pkg->entries[i].disk_size);
if (!tmp) {
vyReportError("ASSETC", "Failed to allocate buffer (%zu bytes) for reading %s.", pkg->entries[i].disk_size, tmp_path);
rtReportError("ASSETC", "Failed to allocate buffer (%zu bytes) for reading %s.", pkg->entries[i].disk_size, tmp_path);
fclose(f);
fclose(tmp_f);
free(buffer);
return VY_UNKNOWN_ERROR;
return RT_UNKNOWN_ERROR;
}
buffer = tmp;
current_buffer_size = pkg->entries[i].disk_size;
}
if (fread(buffer, pkg->entries[i].disk_size, 1, tmp_f) != 1) {
vyReportError("ASSETC", "Failed to read %s.", tmp_path);
rtReportError("ASSETC", "Failed to read %s.", tmp_path);
fclose(f);
fclose(tmp_f);
free(buffer);
return VY_UNKNOWN_ERROR;
return RT_UNKNOWN_ERROR;
}
if (fwrite(buffer, pkg->entries[i].disk_size, 1, f) != 1) {
vyReportError("ASSETC", "Failed to write (%zu bytes) to %s.", pkg->entries[i].disk_size, pkg->name);
rtReportError("ASSETC", "Failed to write (%zu bytes) to %s.", pkg->entries[i].disk_size, pkg->name);
fclose(f);
fclose(tmp_f);
free(buffer);
return VY_UNKNOWN_ERROR;
return RT_UNKNOWN_ERROR;
}
vyAddUIDTabEntry(package_fid,
rtAddUIDTabEntry(package_fid,
pkg->entries[i].uid,
offset_in_file,
pkg->entries[i].disk_size);
@ -245,18 +245,18 @@ static vy_result SavePackage(vy_package *pkg) {
free(buffer);
fclose(f);
return VY_SUCCESS;
return RT_SUCCESS;
}
vy_result vySavePackages(void) {
assert(vyIsMainThread());
rt_result rtSavePackages(void) {
assert(rtIsMainThread());
/* Save a .txt file with one line per package.
* Enables us to re-init the file-tab in future runs. */
FILE *f = fopen("data/packages.txt", "w");
if (!f) {
vyReportError("ASSETC", "Failed to write to 'packages.txt'");
return VY_UNKNOWN_ERROR;
rtReportError("ASSETC", "Failed to write to 'packages.txt'");
return RT_UNKNOWN_ERROR;
}
for (unsigned int i = 0; i < _package_count; ++i) {
if (_packages[i].num_entries == 0)
@ -266,9 +266,9 @@ vy_result vySavePackages(void) {
fclose(f);
for (unsigned int i = 0; i < _package_count; ++i) {
vy_result res = SavePackage(&_packages[i]);
if (res != VY_SUCCESS)
rt_result res = SavePackage(&_packages[i]);
if (res != RT_SUCCESS)
return res;
}
return VY_SUCCESS;
return RT_SUCCESS;
}

View File

@ -1,16 +1,16 @@
#ifndef VY_ASSETC_PACKAGES_H
#define VY_ASSETC_PACKAGES_H
#ifndef RT_ASSETC_PACKAGES_H
#define RT_ASSETC_PACKAGES_H
#include "runtime/runtime.h"
#include "runtime/assets.h"
void vyInitPackages(void);
void rtInitPackages(void);
unsigned int vyAddPackageFile(vy_text_span name);
unsigned int rtAddPackageFile(rt_text_span name);
void vyAddAssetToPackage(unsigned int package, vy_uid uid, void *buffer, size_t size);
void vyAddUnchangedAssetToPackage(unsigned int package, vy_uid uid);
void rtAddAssetToPackage(unsigned int package, rt_uid uid, void *buffer, size_t size);
void rtAddUnchangedAssetToPackage(unsigned int package, rt_uid uid);
vy_result vySavePackages(void);
rt_result rtSavePackages(void);
#endif

View File

@ -22,13 +22,13 @@
#include "dependency_tracking.h"
typedef struct {
vy_attribute_binding *uniform_bindings;
vy_attribute_binding *storage_bindings;
vy_attribute_binding *texture_bindings;
rt_attribute_binding *uniform_bindings;
rt_attribute_binding *storage_bindings;
rt_attribute_binding *texture_bindings;
vy_uid vertex_shader;
vy_uid fragment_shader;
vy_uid compute_shader;
rt_uid vertex_shader;
rt_uid fragment_shader;
rt_uid compute_shader;
/* TODO Fixed function settings */
@ -37,20 +37,20 @@ typedef struct {
uint16_t uniform_binding_count;
uint16_t storage_binding_count;
uint16_t texture_binding_count;
} vy_parsed_pipeline_data;
} rt_parsed_pipeline_data;
static void
DbgPrintShaderFile(const vy_parse_state *state, unsigned int list_index, unsigned int indent) {
DbgPrintShaderFile(const rt_parse_state *state, unsigned int list_index, unsigned int indent) {
assert(list_index < state->statement_list_count);
const vy_parsed_stmt_list *list = &state->statement_lists[list_index];
const rt_parsed_stmt_list *list = &state->statement_lists[list_index];
unsigned int stmt_index = list->first;
for (unsigned int i = 0; i < list->count; ++i) {
const vy_parsed_stmt *stmt = &state->statements[stmt_index];
const rt_parsed_stmt *stmt = &state->statements[stmt_index];
for (unsigned int j = 0; j < indent; ++j)
printf(" ");
printf("%.*s: ", stmt->attribute.length, stmt->attribute.start);
if (stmt->form == VY_STMT_FORM_VALUE) {
if (stmt->form == RT_STMT_FORM_VALUE) {
printf("%.*s\n", stmt->value.length, stmt->value.start);
} else {
printf("{\n");
@ -62,7 +62,7 @@ DbgPrintShaderFile(const vy_parse_state *state, unsigned int list_index, unsigne
assert(stmt_index == UINT_MAX || stmt_index == 0);
}
static bool ParseBindingIndex(vy_text_span span, unsigned int *index) {
static bool ParseBindingIndex(rt_text_span span, unsigned int *index) {
if (span.length == 0)
return false;
int at = (int)span.length - 1;
@ -73,7 +73,7 @@ static bool ParseBindingIndex(vy_text_span span, unsigned int *index) {
unsigned int digit = (unsigned int)(span.start[at] - '0');
n += digit * exp;
} else {
vyReportError("GFX", "Unexpected non-digit character in binding index");
rtReportError("GFX", "Unexpected non-digit character in binding index");
return false;
}
--at;
@ -83,54 +83,54 @@ static bool ParseBindingIndex(vy_text_span span, unsigned int *index) {
return true;
}
static vy_attribute_value ParseBindingValue(vy_text_span span) {
if (vyCompareSpanToString(span, "MATERIAL_ALBEDO") == 0) {
return VY_ATTRIBUTE_VALUE_MATERIAL_ALBEDO;
} else if (vyCompareSpanToString(span, "MATERIAL_NORMAL") == 0) {
return VY_ATTRIBUTE_VALUE_MATERIAL_NORMAL;
static rt_attribute_value ParseBindingValue(rt_text_span span) {
if (rtCompareSpanToString(span, "MATERIAL_ALBEDO") == 0) {
return RT_ATTRIBUTE_VALUE_MATERIAL_ALBEDO;
} else if (rtCompareSpanToString(span, "MATERIAL_NORMAL") == 0) {
return RT_ATTRIBUTE_VALUE_MATERIAL_NORMAL;
}
vyReportError("GFX", "Unsupported binding value %*.s", span.length, span.start);
return VY_ATTRIBUTE_VALUE_UNDEFINED;
rtReportError("GFX", "Unsupported binding value %*.s", span.length, span.start);
return RT_ATTRIBUTE_VALUE_UNDEFINED;
}
static bool ParseBindings(vy_parse_state *state,
static bool ParseBindings(rt_parse_state *state,
unsigned int root_list,
const char *name,
const char *file_path,
vy_attribute_binding **p_bindings,
rt_attribute_binding **p_bindings,
uint16_t *p_binding_count) {
const vy_parsed_stmt *bindings = vyFindStatement(state, root_list, name);
const rt_parsed_stmt *bindings = rtFindStatement(state, root_list, name);
if (bindings) {
if (bindings->form != VY_STMT_FORM_LIST) {
vyReportError("GFX",
if (bindings->form != RT_STMT_FORM_LIST) {
rtReportError("GFX",
"Expected list of bindings as the value of "
"\"%s\" in %s",
name,
file_path);
return false;
}
const vy_parsed_stmt_list *binding_list = &state->statement_lists[bindings->list_index];
vy_attribute_binding *shader_bindings =
vyAllocBuffer(sizeof(vy_attribute_binding) * binding_list->count);
const rt_parsed_stmt_list *binding_list = &state->statement_lists[bindings->list_index];
rt_attribute_binding *shader_bindings =
rtAllocBuffer(sizeof(rt_attribute_binding) * binding_list->count);
if (!bindings) {
vyReportError("GFX", "Out of memory");
rtReportError("GFX", "Out of memory");
return false;
}
unsigned int binding_count = binding_list->count;
unsigned int stmt_index = binding_list->first;
for (unsigned int i = 0; i < binding_list->count; ++i) {
const vy_parsed_stmt *stmt = &state->statements[stmt_index];
const rt_parsed_stmt *stmt = &state->statements[stmt_index];
if (!ParseBindingIndex(stmt->attribute, &shader_bindings[i].index)) {
vyReleaseBuffer(shader_bindings,
sizeof(vy_attribute_binding) * binding_list->count);
rtReleaseBuffer(shader_bindings,
sizeof(rt_attribute_binding) * binding_list->count);
return false;
}
shader_bindings[i].value = ParseBindingValue(stmt->value);
if (shader_bindings[i].value == VY_ATTRIBUTE_VALUE_UNDEFINED) {
vyReleaseBuffer(shader_bindings,
sizeof(vy_attribute_binding) * binding_list->count);
if (shader_bindings[i].value == RT_ATTRIBUTE_VALUE_UNDEFINED) {
rtReleaseBuffer(shader_bindings,
sizeof(rt_attribute_binding) * binding_list->count);
return false;
}
stmt_index = stmt->next;
@ -146,60 +146,60 @@ static bool ParseBindings(vy_parse_state *state,
}
}
static vy_result ParseShader(vy_parse_state *state,
static rt_result ParseShader(rt_parse_state *state,
unsigned int root_list,
const char *name,
const char *file_path,
uint32_t processing_flags,
vy_uid *p_shader_uid) {
const vy_parsed_stmt *stmt = vyFindStatement(state, root_list, name);
rt_uid *p_shader_uid) {
const rt_parsed_stmt *stmt = rtFindStatement(state, root_list, name);
if (stmt) {
if (stmt->form != VY_STMT_FORM_LIST) {
vyReportError("GFX",
if (stmt->form != RT_STMT_FORM_LIST) {
rtReportError("GFX",
"Expected a list as the value of "
"\"%s\" in %s",
name,
file_path);
return VY_PROCESSING_FAILED;
return RT_PROCESSING_FAILED;
}
const vy_parsed_stmt_list *shader_list = &state->statement_lists[stmt->list_index];
const rt_parsed_stmt_list *shader_list = &state->statement_lists[stmt->list_index];
unsigned int stmt_index = shader_list->first;
for (unsigned int i = 0; i < shader_list->count; ++i) {
const vy_parsed_stmt *shader = &state->statements[stmt_index];
if (shader->form != VY_STMT_FORM_VALUE) {
vyReportError("GFX",
const rt_parsed_stmt *shader = &state->statements[stmt_index];
if (shader->form != RT_STMT_FORM_VALUE) {
rtReportError("GFX",
"Expected a list as the value of "
"\"%s.%*s\" in %s",
name,
(int)shader->attribute.length,
shader->attribute.start,
file_path);
return VY_PROCESSING_FAILED;
return RT_PROCESSING_FAILED;
}
vy_renderer_backend_code backend = VY_INVALID_RENDERER_BACKEND_CODE;
if (vyCompareSpanToString(shader->attribute, "vk") == 0) {
backend = VY_RENDERER_BACKEND_CODE_VK;
rt_renderer_backend_code backend = RT_INVALID_RENDERER_BACKEND_CODE;
if (rtCompareSpanToString(shader->attribute, "vk") == 0) {
backend = RT_RENDERER_BACKEND_CODE_VK;
} else {
vyReportError("GFX",
rtReportError("GFX",
"Invalid renderer backend"
"\"%*s\" in %s of file %s",
(int)shader->attribute.length,
shader->attribute.start,
name,
file_path);
return VY_PROCESSING_FAILED;
return RT_PROCESSING_FAILED;
}
if (backend == g_assetc_options.renderer_backend) {
vy_file_id shader_file = vyAddFileFromSpan(shader->value);
vy_uid uid = vyLookupUID(shader_file);
if (uid == VY_INVALID_UID) {
rt_file_id shader_file = rtAddFileFromSpan(shader->value);
rt_uid uid = rtLookupUID(shader_file);
if (uid == RT_INVALID_UID) {
/* Add the shader file to processing and wait until its done
*/
if (vyAddFileToProcessingQueue(shader_file, processing_flags) != VY_SUCCESS)
return VY_PROCESSING_FAILED;
return VY_PROCESSING_TRY_AGAIN;
if (rtAddFileToProcessingQueue(shader_file, processing_flags) != RT_SUCCESS)
return RT_PROCESSING_FAILED;
return RT_PROCESSING_TRY_AGAIN;
}
*p_shader_uid = uid;
@ -208,44 +208,44 @@ static vy_result ParseShader(vy_parse_state *state,
}
stmt_index = shader->next;
}
return VY_SUCCESS;
return RT_SUCCESS;
}
return VY_PROCESSING_FAILED;
return RT_PROCESSING_FAILED;
}
static uint32_t
ParseOptimizationLevel(vy_parse_state *state, unsigned int root_list, const char *file_path) {
ParseOptimizationLevel(rt_parse_state *state, unsigned int root_list, const char *file_path) {
uint32_t optimization_level;
switch (g_assetc_options.optimization) {
case VY_ASSET_OPTIMIZATION_PERFORMANCE:
optimization_level = VY_SHADER_FLAG_OPTIMIZE_SPEED;
case RT_ASSET_OPTIMIZATION_PERFORMANCE:
optimization_level = RT_SHADER_FLAG_OPTIMIZE_SPEED;
break;
case VY_ASSET_OPTIMIZATION_SPACE:
optimization_level = VY_SHADER_FLAG_OPTIMIZE_SIZE;
case RT_ASSET_OPTIMIZATION_SPACE:
optimization_level = RT_SHADER_FLAG_OPTIMIZE_SIZE;
break;
default:
optimization_level = 0;
}
const vy_parsed_stmt *stmt = vyFindStatement(state, root_list, "optimization");
const rt_parsed_stmt *stmt = rtFindStatement(state, root_list, "optimization");
if (stmt) {
if (stmt->form != VY_STMT_FORM_VALUE) {
vyReportError("GFX",
if (stmt->form != RT_STMT_FORM_VALUE) {
rtReportError("GFX",
"Expected a simple statement for"
"\"optimization\" in %s",
file_path);
return optimization_level;
}
if (vyCompareSpanToString(stmt->value, "speed") == 0) {
optimization_level = VY_SHADER_FLAG_OPTIMIZE_SPEED;
} else if (vyCompareSpanToString(stmt->value, "size") == 0) {
optimization_level = VY_SHADER_FLAG_OPTIMIZE_SIZE;
} else if (vyCompareSpanToString(stmt->value, "none") == 0) {
if (rtCompareSpanToString(stmt->value, "speed") == 0) {
optimization_level = RT_SHADER_FLAG_OPTIMIZE_SPEED;
} else if (rtCompareSpanToString(stmt->value, "size") == 0) {
optimization_level = RT_SHADER_FLAG_OPTIMIZE_SIZE;
} else if (rtCompareSpanToString(stmt->value, "none") == 0) {
optimization_level = 0;
} else {
vyReportError("GFX",
rtReportError("GFX",
"Expected one of 'speed', 'size' and 'none' for \"optimization\" in %s",
file_path);
}
@ -254,18 +254,18 @@ ParseOptimizationLevel(vy_parse_state *state, unsigned int root_list, const char
return optimization_level;
}
static vy_result
ParsePipelineFile(vy_file_id fid, const char *text, size_t length, vy_parsed_pipeline_data *pipeline) {
static rt_result
ParsePipelineFile(rt_file_id fid, const char *text, size_t length, rt_parsed_pipeline_data *pipeline) {
/* This is the grammar for pipeline files:
* <stmt-list> ::= <stmt>*
* <stmt> ::= <attribute> ( ( <value> ';' ) | ( '{' <stmt-list> '}' ) )
* <attribute> ::= [:alnum:]*
* <value>:: = [:alnum:]* */
const char *file_path = vyGetFilePath(fid);
vy_parse_state state;
const char *file_path = rtGetFilePath(fid);
rt_parse_state state;
unsigned int root_list;
vy_result result = vyParseDescription(text, length, file_path, &root_list, &state);
if (result != VY_SUCCESS) {
rt_result result = rtParseDescription(text, length, file_path, &root_list, &state);
if (result != RT_SUCCESS) {
goto out;
}
@ -277,27 +277,27 @@ ParsePipelineFile(vy_file_id fid, const char *text, size_t length, vy_parsed_pip
root_list,
"vertex",
file_path,
VY_SHADER_FLAG_VERTEX | optimization,
&pipeline->vertex_shader) == VY_PROCESSING_TRY_AGAIN) {
result = VY_PROCESSING_TRY_AGAIN;
RT_SHADER_FLAG_VERTEX | optimization,
&pipeline->vertex_shader) == RT_PROCESSING_TRY_AGAIN) {
result = RT_PROCESSING_TRY_AGAIN;
goto out;
}
if (ParseShader(&state,
root_list,
"fragment",
file_path,
VY_SHADER_FLAG_FRAGMENT | optimization,
&pipeline->fragment_shader) == VY_PROCESSING_TRY_AGAIN) {
result = VY_PROCESSING_TRY_AGAIN;
RT_SHADER_FLAG_FRAGMENT | optimization,
&pipeline->fragment_shader) == RT_PROCESSING_TRY_AGAIN) {
result = RT_PROCESSING_TRY_AGAIN;
goto out;
}
if (ParseShader(&state,
root_list,
"compute",
file_path,
VY_SHADER_FLAG_COMPUTE | optimization,
&pipeline->compute_shader) == VY_PROCESSING_TRY_AGAIN) {
result = VY_PROCESSING_TRY_AGAIN;
RT_SHADER_FLAG_COMPUTE | optimization,
&pipeline->compute_shader) == RT_PROCESSING_TRY_AGAIN) {
result = RT_PROCESSING_TRY_AGAIN;
goto out;
}
@ -315,7 +315,7 @@ ParsePipelineFile(vy_file_id fid, const char *text, size_t length, vy_parsed_pip
file_path,
&pipeline->texture_bindings,
&pipeline->texture_binding_count)) {
result = VY_AIO_STATE_FAILED;
result = RT_AIO_STATE_FAILED;
goto out;
}
@ -325,7 +325,7 @@ ParsePipelineFile(vy_file_id fid, const char *text, size_t length, vy_parsed_pip
file_path,
&pipeline->uniform_bindings,
&pipeline->uniform_binding_count)) {
result = VY_AIO_STATE_FAILED;
result = RT_AIO_STATE_FAILED;
goto out;
}
@ -335,7 +335,7 @@ ParsePipelineFile(vy_file_id fid, const char *text, size_t length, vy_parsed_pip
file_path,
&pipeline->storage_bindings,
&pipeline->storage_binding_count)) {
result = VY_AIO_STATE_FAILED;
result = RT_AIO_STATE_FAILED;
goto out;
}
@ -345,29 +345,29 @@ out:
return result;
}
vy_result vyProcessPipelineFile(vy_file_id file,
rt_result rtProcessPipelineFile(rt_file_id file,
void *buffer,
size_t size,
uint32_t flags,
vy_processor_output *output) {
VY_UNUSED(flags);
vy_parsed_pipeline_data tmp;
rt_processor_output *output) {
RT_UNUSED(flags);
rt_parsed_pipeline_data tmp;
memset(&tmp, 0, sizeof(tmp));
vy_result result = ParsePipelineFile(file, buffer, size, &tmp);
if (result == VY_SUCCESS) {
rt_result result = ParsePipelineFile(file, buffer, size, &tmp);
if (result == RT_SUCCESS) {
/* parsed_pipeline_data contains arrays of bindings.
* We need to convert these to a flat buffer that can be written to a file */
size_t outbuffer_size =
sizeof(vy_pipeline_info) +
sizeof(vy_attribute_binding) *
sizeof(rt_pipeline_info) +
sizeof(rt_attribute_binding) *
(tmp.storage_binding_count + tmp.texture_binding_count + tmp.uniform_binding_count);
void *out_buffer = vyAllocBuffer(outbuffer_size);
void *out_buffer = rtAllocBuffer(outbuffer_size);
if (!buffer) {
return VY_PROCESSING_FAILED;
return RT_PROCESSING_FAILED;
}
vy_pipeline_info *info = out_buffer;
rt_pipeline_info *info = out_buffer;
info->vertex_shader = tmp.vertex_shader;
info->fragment_shader = tmp.fragment_shader;
info->compute_shader = tmp.compute_shader;
@ -375,49 +375,49 @@ vy_result vyProcessPipelineFile(vy_file_id file,
info->uniform_binding_count = tmp.uniform_binding_count;
info->storage_binding_count = tmp.storage_binding_count;
vy_attribute_binding *texture_bindings = NULL;
rt_attribute_binding *texture_bindings = NULL;
if (tmp.texture_binding_count > 0) {
texture_bindings = (vy_attribute_binding *)(info + 1);
texture_bindings = (rt_attribute_binding *)(info + 1);
memcpy(texture_bindings,
tmp.texture_bindings,
sizeof(vy_attribute_binding) * tmp.texture_binding_count);
sizeof(rt_attribute_binding) * tmp.texture_binding_count);
}
vy_attribute_binding *uniform_bindings = NULL;
rt_attribute_binding *uniform_bindings = NULL;
if (tmp.uniform_binding_count > 0) {
uniform_bindings = texture_bindings + tmp.texture_binding_count;
memcpy(uniform_bindings,
tmp.uniform_bindings,
sizeof(vy_attribute_binding) * tmp.uniform_binding_count);
sizeof(rt_attribute_binding) * tmp.uniform_binding_count);
}
vy_attribute_binding *storage_bindings = NULL;
rt_attribute_binding *storage_bindings = NULL;
if (tmp.storage_binding_count > 0) {
storage_bindings = uniform_bindings + tmp.uniform_binding_count;
memcpy(storage_bindings,
tmp.storage_bindings,
sizeof(vy_attribute_binding) * tmp.storage_binding_count);
sizeof(rt_attribute_binding) * tmp.storage_binding_count);
}
vySetRelptr(&info->texture_bindings, texture_bindings);
vySetRelptr(&info->uniform_bindings, uniform_bindings);
vySetRelptr(&info->storage_bindings, storage_bindings);
rtSetRelptr(&info->texture_bindings, texture_bindings);
rtSetRelptr(&info->uniform_bindings, uniform_bindings);
rtSetRelptr(&info->storage_bindings, storage_bindings);
vyReleaseBuffer(tmp.texture_bindings,
sizeof(vy_attribute_binding) * tmp.texture_binding_count);
vyReleaseBuffer(tmp.storage_bindings,
sizeof(vy_attribute_binding) * tmp.storage_binding_count);
vyReleaseBuffer(tmp.uniform_bindings,
sizeof(vy_attribute_binding) * tmp.uniform_binding_count);
rtReleaseBuffer(tmp.texture_bindings,
sizeof(rt_attribute_binding) * tmp.texture_binding_count);
rtReleaseBuffer(tmp.storage_bindings,
sizeof(rt_attribute_binding) * tmp.storage_binding_count);
rtReleaseBuffer(tmp.uniform_bindings,
sizeof(rt_attribute_binding) * tmp.uniform_binding_count);
output->data = out_buffer;
output->size = outbuffer_size;
output->asset_uid = vyCalculateUID(vyGetFilePath(file));
output->asset_uid = rtCalculateUID(rtGetFilePath(file));
/* Store dependencies to shaders */
if (info->vertex_shader != VY_INVALID_UID)
result = vyAddAssetDependency(output->asset_uid, info->vertex_shader);
if (info->fragment_shader != VY_INVALID_UID)
result = vyAddAssetDependency(output->asset_uid, info->fragment_shader);
if (info->compute_shader != VY_INVALID_UID)
result = vyAddAssetDependency(output->asset_uid, info->compute_shader);
if (info->vertex_shader != RT_INVALID_UID)
result = rtAddAssetDependency(output->asset_uid, info->vertex_shader);
if (info->fragment_shader != RT_INVALID_UID)
result = rtAddAssetDependency(output->asset_uid, info->fragment_shader);
if (info->compute_shader != RT_INVALID_UID)
result = rtAddAssetDependency(output->asset_uid, info->compute_shader);
}
return result;
}

View File

@ -1,46 +1,46 @@
#ifndef VY_ASSETC_PROCESSING_H
#define VY_ASSETC_PROCESSING_H
#ifndef RT_ASSETC_PROCESSING_H
#define RT_ASSETC_PROCESSING_H
#include "runtime/assets.h"
#include "runtime/file_tab.h"
enum {
VY_PROCESSING_FAILED = VY_CUSTOM_ERROR_START,
RT_PROCESSING_FAILED = RT_CUSTOM_ERROR_START,
/* Used if the processing depends on other files beeing processed first. */
VY_PROCESSING_TRY_AGAIN,
RT_PROCESSING_TRY_AGAIN,
};
typedef struct {
vy_file_id output_file;
rt_file_id output_file;
} vy_asset_options;
} rt_asset_options;
typedef struct {
vy_uid asset_uid;
rt_uid asset_uid;
/* Allocated via the vyAllocBuffer API */
/* Allocated via the rtAllocBuffer API */
void *data;
size_t size;
} vy_processor_output;
} rt_processor_output;
typedef vy_result vy_processor_fn(vy_file_id file,
typedef rt_result rt_processor_fn(rt_file_id file,
void *buffer,
size_t size,
uint32_t flags,
vy_processor_output *output);
rt_processor_output *output);
vy_result vyAddAssetProcessor(const char *file_extension, vy_processor_fn fn);
rt_result rtAddAssetProcessor(const char *file_extension, rt_processor_fn fn);
/* Flags are file type specific */
vy_result vyAddFileToProcessingQueue(vy_file_id file, uint32_t flags);
rt_result rtAddFileToProcessingQueue(rt_file_id file, uint32_t flags);
vy_result vyStartProcessing(void);
void vyStopProcessing(void);
rt_result rtStartProcessing(void);
void rtStopProcessing(void);
vy_uid vyCalculateUID(const char *name);
vy_result vyWriteUIDTab(void);
vy_result vyAddUIDTabEntry(vy_file_id package_fid, vy_uid uid, uint64_t offset, uint64_t size);
rt_uid rtCalculateUID(const char *name);
rt_result rtWriteUIDTab(void);
rt_result rtAddUIDTabEntry(rt_file_id package_fid, rt_uid uid, uint64_t offset, uint64_t size);
void vyWaitUntilProcessingIsFinished(void);
void rtWaitUntilProcessingIsFinished(void);
#endif

View File

@ -1,19 +1,19 @@
#ifndef VY_ASSETC_PROCESSING_FLAGS_H
#define VY_ASSETC_PROCESSING_FLAGS_H
#ifndef RT_ASSETC_PROCESSING_FLAGS_H
#define RT_ASSETC_PROCESSING_FLAGS_H
/* Shader processing flags */
enum {
/* Type is encoded in the lower bits */
VY_SHADER_FLAG_VERTEX = 0x01,
VY_SHADER_FLAG_FRAGMENT = 0x02,
VY_SHADER_FLAG_COMPUTE = 0x03,
RT_SHADER_FLAG_VERTEX = 0x01,
RT_SHADER_FLAG_FRAGMENT = 0x02,
RT_SHADER_FLAG_COMPUTE = 0x03,
VY_SHADER_FLAG_TYPE_MASK =
VY_SHADER_FLAG_VERTEX | VY_SHADER_FLAG_FRAGMENT | VY_SHADER_FLAG_COMPUTE,
RT_SHADER_FLAG_TYPE_MASK =
RT_SHADER_FLAG_VERTEX | RT_SHADER_FLAG_FRAGMENT | RT_SHADER_FLAG_COMPUTE,
VY_SHADER_FLAG_OPTIMIZE_SPEED = 0x04,
VY_SHADER_FLAG_OPTIMIZE_SIZE = 0x08,
VY_SHADER_FLAG_OPTIMIZE_MASK = VY_SHADER_FLAG_OPTIMIZE_SPEED | VY_SHADER_FLAG_OPTIMIZE_SIZE,
RT_SHADER_FLAG_OPTIMIZE_SPEED = 0x04,
RT_SHADER_FLAG_OPTIMIZE_SIZE = 0x08,
RT_SHADER_FLAG_OPTIMIZE_MASK = RT_SHADER_FLAG_OPTIMIZE_SPEED | RT_SHADER_FLAG_OPTIMIZE_SIZE,
};

View File

@ -17,26 +17,26 @@
typedef struct {
vy_file_id fid;
rt_file_id fid;
uint32_t flags;
/* How many times has this file been added? */
unsigned int turn;
} vy_file_processing_queue_entry;
} rt_file_processing_queue_entry;
#define QUEUE_LENGTH 1024
typedef struct {
vy_file_processing_queue_entry entries[QUEUE_LENGTH];
rt_file_processing_queue_entry entries[QUEUE_LENGTH];
unsigned int head;
unsigned int tail;
} vy_file_processing_queue;
} rt_file_processing_queue;
static vy_file_processing_queue _queues[2];
static vy_file_processing_queue *_processing_queue;
static vy_file_processing_queue *_retry_queue;
static rt_file_processing_queue _queues[2];
static rt_file_processing_queue *_processing_queue;
static rt_file_processing_queue *_retry_queue;
static vy_mutex *_guard;
static rt_mutex *_guard;
static bool _keep_running;
/* A single file could have a lot of dependencies. */
@ -47,20 +47,20 @@ static bool _keep_running;
#define FORCE_SINGLE_THREAD 1
static unsigned int _num_processing_threads = 0;
static vy_thread *_processing_threads[MAX_PROCESSING_THREADS];
static rt_thread *_processing_threads[MAX_PROCESSING_THREADS];
static unsigned int _processing_thread_count = 0;
static vy_result vyAddFileToProcessingQueueImpl(vy_file_processing_queue *queue,
vy_file_id file,
static rt_result rtAddFileToProcessingQueueImpl(rt_file_processing_queue *queue,
rt_file_id file,
uint32_t flags,
unsigned int turn) {
vy_result result = VY_SUCCESS;
rt_result result = RT_SUCCESS;
vyLog("ASSETC", "Adding %s to processing queue.", vyGetFilePath(file));
rtLog("ASSETC", "Adding %s to processing queue.", rtGetFilePath(file));
vy_file_processing_queue_entry entry = {
rt_file_processing_queue_entry entry = {
.fid = file,
.flags = flags,
.turn = turn,
@ -70,42 +70,42 @@ static vy_result vyAddFileToProcessingQueueImpl(vy_file_processing_queue *queue,
queue->entries[slot] = entry;
queue->head = (queue->head + 1) % QUEUE_LENGTH;
} else {
vyReportError("ASSETC", "The processing queue is full!");
rtReportError("ASSETC", "The processing queue is full!");
result = 1;
}
return result;
}
vy_result vyAddFileToProcessingQueue(vy_file_id file, uint32_t flags) {
rt_result rtAddFileToProcessingQueue(rt_file_id file, uint32_t flags) {
assert(_guard != NULL);
vyLockMutex(_guard);
vy_result res = vyAddFileToProcessingQueueImpl(_processing_queue, file, flags, 1);
vyUnlockMutex(_guard);
rtLockMutex(_guard);
rt_result res = rtAddFileToProcessingQueueImpl(_processing_queue, file, flags, 1);
rtUnlockMutex(_guard);
return res;
}
#define MAX_PROCESSORS 256
static vy_processor_fn *_processor_fns[MAX_PROCESSORS];
static rt_processor_fn *_processor_fns[MAX_PROCESSORS];
static const char *_processor_exts[MAX_PROCESSORS];
static unsigned int _processor_count;
vy_result vyAddAssetProcessor(const char *file_extension, vy_processor_fn fn) {
rt_result rtAddAssetProcessor(const char *file_extension, rt_processor_fn fn) {
/* Should only be called from main thread */
if (_processor_count == MAX_PROCESSORS) {
vyReportError("ASSETC", "Too many asset processor functions!");
rtReportError("ASSETC", "Too many asset processor functions!");
return 1;
}
_processor_fns[_processor_count] = fn;
_processor_exts[_processor_count] = file_extension;
++_processor_count;
return VY_SUCCESS;
return RT_SUCCESS;
}
static void PopAndSwapSubmittedData(unsigned int at,
unsigned int *count,
vy_file_processing_queue_entry *queue_entries,
vy_aio_handle *handles,
rt_file_processing_queue_entry *queue_entries,
rt_aio_handle *handles,
void **buffers,
size_t *sizes) {
if (at < *count - 1) {
@ -117,9 +117,9 @@ static void PopAndSwapSubmittedData(unsigned int at,
*count = *count - 1;
}
static vy_result ProcessLoadedFile(vy_file_processing_queue_entry entry, void *buffer, size_t size) {
static rt_result ProcessLoadedFile(rt_file_processing_queue_entry entry, void *buffer, size_t size) {
/* Search for a matching processor function */
const char *path = vyGetFilePath(entry.fid);
const char *path = rtGetFilePath(entry.fid);
size_t path_len = strlen(path);
for (unsigned int i = 0; i < _processor_count; ++i) {
size_t ext_len = strlen(_processor_exts[i]);
@ -132,97 +132,97 @@ static vy_result ProcessLoadedFile(vy_file_processing_queue_entry entry, void *b
/* Load the corresponding .as file.
* TODO: Using malloc here is probably relatively slow.
*/
vy_result res;
rt_result res;
vy_asset_settings settings;
if ((res = vyLoadAssetSettings(path, &settings)) != VY_SUCCESS) {
rt_asset_settings settings;
if ((res = rtLoadAssetSettings(path, &settings)) != RT_SUCCESS) {
return res;
}
/* Process the asset */
vy_processor_output out;
rt_processor_output out;
res = _processor_fns[i](entry.fid, buffer, size, entry.flags, &out);
if (res == VY_SUCCESS) {
if (res == RT_SUCCESS) {
/* Add the output to the appropriate package file */
vy_assetmeta meta;
meta.compiled_ts = vyGetCurrentTimestamp();
meta.last_changed = vyGetFileModificationTimestamp(entry.fid);
rt_assetmeta meta;
meta.compiled_ts = rtGetCurrentTimestamp();
meta.last_changed = rtGetFileModificationTimestamp(entry.fid);
meta.processing_flags = entry.flags;
vyAddUIDMapping(entry.fid, out.asset_uid, &meta);
rtAddUIDMapping(entry.fid, out.asset_uid, &meta);
vyAddAssetToPackage(settings.package, out.asset_uid, out.data, out.size);
} else if (res == VY_PROCESSING_TRY_AGAIN) {
rtAddAssetToPackage(settings.package, out.asset_uid, out.data, out.size);
} else if (res == RT_PROCESSING_TRY_AGAIN) {
if (entry.turn < MAX_TURNS) {
vyLockMutex(_guard);
vyAddFileToProcessingQueueImpl(_retry_queue, entry.fid, entry.flags, entry.turn + 1);
vyUnlockMutex(_guard);
rtLockMutex(_guard);
rtAddFileToProcessingQueueImpl(_retry_queue, entry.fid, entry.flags, entry.turn + 1);
rtUnlockMutex(_guard);
} else {
vyLog("ASSETC",
rtLog("ASSETC",
"File '%s' took too many turns to process: %u",
path,
entry.turn);
}
} else {
vyLog("ASSETC", "Failed to process file: %s (Result %u)", path, res);
rtLog("ASSETC", "Failed to process file: %s (Result %u)", path, res);
}
return res;
}
}
vyLog("ASSETC", "No asset processor for file: %s", path);
return VY_UNKNOWN_ERROR;
rtLog("ASSETC", "No asset processor for file: %s", path);
return RT_UNKNOWN_ERROR;
}
static void ProcessingThread(void *_param) {
VY_UNUSED(_param);
RT_UNUSED(_param);
vy_file_processing_queue_entry submitted_entries[VY_LOAD_BATCH_MAX_SIZE];
vy_aio_handle submitted_handles[VY_LOAD_BATCH_MAX_SIZE];
void *submitted_buffers[VY_LOAD_BATCH_MAX_SIZE];
size_t submitted_sizes[VY_LOAD_BATCH_MAX_SIZE];
rt_file_processing_queue_entry submitted_entries[RT_LOAD_BATCH_MAX_SIZE];
rt_aio_handle submitted_handles[RT_LOAD_BATCH_MAX_SIZE];
void *submitted_buffers[RT_LOAD_BATCH_MAX_SIZE];
size_t submitted_sizes[RT_LOAD_BATCH_MAX_SIZE];
unsigned int submitted_outstanding = 0;
while (_keep_running) {
vy_load_batch load_batch;
vy_file_processing_queue_entry load_entries[VY_LOAD_BATCH_MAX_SIZE];
void *load_buffers[VY_LOAD_BATCH_MAX_SIZE];
size_t load_sizes[VY_LOAD_BATCH_MAX_SIZE];
rt_load_batch load_batch;
rt_file_processing_queue_entry load_entries[RT_LOAD_BATCH_MAX_SIZE];
void *load_buffers[RT_LOAD_BATCH_MAX_SIZE];
size_t load_sizes[RT_LOAD_BATCH_MAX_SIZE];
load_batch.num_loads = 0;
bool got_entry = false;
do {
got_entry = false;
vy_file_processing_queue_entry entry = {0};
vyLockMutex(_guard);
rt_file_processing_queue_entry entry = {0};
rtLockMutex(_guard);
if (_processing_queue->head != _processing_queue->tail) {
entry = _processing_queue->entries[_processing_queue->tail];
_processing_queue->tail = (_processing_queue->tail + 1) % QUEUE_LENGTH;
got_entry = true;
} else if (load_batch.num_loads == 0) {
/* Switch the queues -> Retry all the entries that returned VY_PROCESSING_TRY_AGAIN */
/* Switch the queues -> Retry all the entries that returned RT_PROCESSING_TRY_AGAIN */
if (_retry_queue->head != _retry_queue->tail) {
vy_file_processing_queue *tmp = _retry_queue;
rt_file_processing_queue *tmp = _retry_queue;
_retry_queue = _processing_queue;
_processing_queue = tmp;
}
}
vyUnlockMutex(_guard);
rtUnlockMutex(_guard);
/* Retry, if we did not get an entry */
if (!got_entry)
continue;
const char *path = vyGetFilePath(entry.fid);
const char *path = rtGetFilePath(entry.fid);
if (!path) {
vyLog("ASSETC", "Invalid file id: %#x", entry.fid);
rtLog("ASSETC", "Invalid file id: %#x", entry.fid);
continue;
}
vyLog("ASSETC", "Processing %s", path);
rtLog("ASSETC", "Processing %s", path);
size_t fsz = vyGetFileSize(path);
void *dest = vyAllocBuffer(fsz);
size_t fsz = rtGetFileSize(path);
void *dest = rtAllocBuffer(fsz);
if (!dest) {
vyLog("ASSETC", "Ran out of memory for loading the file: %s", path);
rtLog("ASSETC", "Ran out of memory for loading the file: %s", path);
continue;
}
memset(dest, 0, fsz);
@ -235,34 +235,34 @@ static void ProcessingThread(void *_param) {
load_batch.loads[load_batch.num_loads].offset = 0;
load_entries[load_batch.num_loads] = entry;
++load_batch.num_loads;
} while (got_entry && load_batch.num_loads < VY_LOAD_BATCH_MAX_SIZE);
} while (got_entry && load_batch.num_loads < RT_LOAD_BATCH_MAX_SIZE);
vy_aio_handle load_handles[VY_LOAD_BATCH_MAX_SIZE];
rt_aio_handle load_handles[RT_LOAD_BATCH_MAX_SIZE];
if (load_batch.num_loads > 0) {
vy_result submit_result = vySubmitLoadBatch(&load_batch, load_handles);
if (submit_result != VY_SUCCESS) {
vyLog("ASSETC", "SubmitLoadBatch failed: %u", submit_result);
rt_result submit_result = rtSubmitLoadBatch(&load_batch, load_handles);
if (submit_result != RT_SUCCESS) {
rtLog("ASSETC", "SubmitLoadBatch failed: %u", submit_result);
continue;
}
}
/* Process the previously submitted loads */
while (submitted_outstanding > 0) {
vyLockMutex(_guard);
rtLockMutex(_guard);
_processing_thread_count += 1;
vyUnlockMutex(_guard);
rtUnlockMutex(_guard);
for (unsigned int i = 0; i < submitted_outstanding; ++i) {
vy_aio_state state = vyGetAIOState(submitted_handles[i]);
rt_aio_state state = rtGetAIOState(submitted_handles[i]);
switch (state) {
case VY_AIO_STATE_PENDING:
case RT_AIO_STATE_PENDING:
continue;
case VY_AIO_STATE_FAILED:
vyLog("ASSETC",
case RT_AIO_STATE_FAILED:
rtLog("ASSETC",
"Loading file %s failed.",
vyGetFilePath(submitted_entries[i].fid));
vyReleaseAIO(submitted_handles[i]);
vyReleaseBuffer(submitted_buffers[i], submitted_sizes[i]);
rtGetFilePath(submitted_entries[i].fid));
rtReleaseAIO(submitted_handles[i]);
rtReleaseBuffer(submitted_buffers[i], submitted_sizes[i]);
PopAndSwapSubmittedData(i,
&submitted_outstanding,
submitted_entries,
@ -271,11 +271,11 @@ static void ProcessingThread(void *_param) {
submitted_sizes);
--i;
break;
case VY_AIO_STATE_INVALID:
vyLog("ASSETC",
case RT_AIO_STATE_INVALID:
rtLog("ASSETC",
"Got invalid AIO handle for file: %s",
vyGetFilePath(submitted_entries[i].fid));
vyReleaseBuffer(submitted_buffers[i], submitted_sizes[i]);
rtGetFilePath(submitted_entries[i].fid));
rtReleaseBuffer(submitted_buffers[i], submitted_sizes[i]);
PopAndSwapSubmittedData(i,
&submitted_outstanding,
submitted_entries,
@ -284,12 +284,12 @@ static void ProcessingThread(void *_param) {
submitted_sizes);
--i;
break;
case VY_AIO_STATE_FINISHED:
case RT_AIO_STATE_FINISHED:
ProcessLoadedFile(submitted_entries[i],
submitted_buffers[i],
submitted_sizes[i]);
vyReleaseAIO(submitted_handles[i]);
vyReleaseBuffer(submitted_buffers[i], submitted_sizes[i]);
rtReleaseAIO(submitted_handles[i]);
rtReleaseBuffer(submitted_buffers[i], submitted_sizes[i]);
PopAndSwapSubmittedData(i,
&submitted_outstanding,
submitted_entries,
@ -300,9 +300,9 @@ static void ProcessingThread(void *_param) {
}
}
vyLockMutex(_guard);
rtLockMutex(_guard);
_processing_thread_count -= 1;
vyUnlockMutex(_guard);
rtUnlockMutex(_guard);
}
/* Start new round */
@ -318,12 +318,12 @@ static void ProcessingThread(void *_param) {
}
}
vy_result vyStartProcessing(void) {
rt_result rtStartProcessing(void) {
if (!_guard)
_guard = vyCreateMutex();
_guard = rtCreateMutex();
#if !FORCE_SINGLE_THREAD
_num_processing_threads = vyGetCPUCoreCount();
_num_processing_threads = rtGetCPUCoreCount();
if (_num_processing_threads > MAX_PROCESSING_THREADS)
_num_processing_threads = MAX_PROCESSING_THREADS;
#else
@ -335,20 +335,20 @@ vy_result vyStartProcessing(void) {
_keep_running = true;
for (unsigned int i = 0; i < _num_processing_threads; ++i) {
_processing_threads[i] = vySpawnThread(ProcessingThread, NULL, "Processor");
_processing_threads[i] = rtSpawnThread(ProcessingThread, NULL, "Processor");
if (!_processing_threads[i]) {
vyReportError("ASSETC", "Failed to spawn processing thread %u!", i);
rtReportError("ASSETC", "Failed to spawn processing thread %u!", i);
_keep_running = false;
return 1;
}
}
return VY_SUCCESS;
return RT_SUCCESS;
}
void vyStopProcessing(void) {
void rtStopProcessing(void) {
_keep_running = false;
for (unsigned int i = 0; i < _num_processing_threads; ++i)
vyJoinThread(_processing_threads[i]);
rtJoinThread(_processing_threads[i]);
}
@ -360,7 +360,7 @@ void vyStopProcessing(void) {
#endif
void vyWaitUntilProcessingIsFinished(void) {
void rtWaitUntilProcessingIsFinished(void) {
unsigned int done_counter = 0;
while (done_counter < 3) {
#ifdef _WIN32
@ -368,11 +368,11 @@ void vyWaitUntilProcessingIsFinished(void) {
#else
sleep(1);
#endif
vyLockMutex(_guard);
rtLockMutex(_guard);
volatile bool done = _processing_queue->head == _processing_queue->tail &&
_retry_queue->head == _retry_queue->tail &&
_processing_thread_count == 0;
vyUnlockMutex(_guard);
rtUnlockMutex(_guard);
if (done)
++done_counter;
else

View File

@ -21,27 +21,27 @@ static shaderc_include_result *ResolveInclude(void *user_data,
static void ReleaseIncludeResult(void *user_data, shaderc_include_result *result) {
}
vy_result vyProcessShaderFile(vy_file_id file,
rt_result rtProcessShaderFile(rt_file_id file,
void *buffer,
size_t size,
uint32_t flags,
vy_processor_output *output) {
rt_processor_output *output) {
/* If we determine that shader compilation takes too long, we can instead
* keep the compiler around */
shaderc_compiler_t compiler = shaderc_compiler_initialize();
if (!compiler) {
vyLog("ASSETC", "Failed to initialize the shaderc compiler.");
return VY_PROCESSING_FAILED;
rtLog("ASSETC", "Failed to initialize the shaderc compiler.");
return RT_PROCESSING_FAILED;
}
const char *path = vyGetFilePath(file);
const char *path = rtGetFilePath(file);
shaderc_compile_options_t options = shaderc_compile_options_initialize();
if (!options) {
vyLog("ASSETC", "Failed to initialize shader compile options.");
rtLog("ASSETC", "Failed to initialize shader compile options.");
shaderc_compiler_release(compiler);
return VY_PROCESSING_FAILED;
return RT_PROCESSING_FAILED;
}
shaderc_compile_options_set_include_callbacks(options,
@ -49,32 +49,32 @@ vy_result vyProcessShaderFile(vy_file_id file,
ReleaseIncludeResult,
NULL);
uint32_t optimize_from_flags = flags & VY_SHADER_FLAG_OPTIMIZE_MASK;
if (optimize_from_flags == VY_SHADER_FLAG_OPTIMIZE_SPEED)
uint32_t optimize_from_flags = flags & RT_SHADER_FLAG_OPTIMIZE_MASK;
if (optimize_from_flags == RT_SHADER_FLAG_OPTIMIZE_SPEED)
shaderc_compile_options_set_optimization_level(options,
shaderc_optimization_level_performance);
else if (optimize_from_flags == VY_SHADER_FLAG_OPTIMIZE_SIZE)
else if (optimize_from_flags == RT_SHADER_FLAG_OPTIMIZE_SIZE)
shaderc_compile_options_set_optimization_level(options, shaderc_optimization_level_size);
else
shaderc_compile_options_set_optimization_level(options, shaderc_optimization_level_zero);
uint32_t type_from_flags = flags & VY_SHADER_FLAG_TYPE_MASK;
uint32_t type_from_flags = flags & RT_SHADER_FLAG_TYPE_MASK;
shaderc_shader_kind shaderc_kind;
switch (type_from_flags) {
case VY_SHADER_FLAG_VERTEX:
case RT_SHADER_FLAG_VERTEX:
shaderc_kind = shaderc_glsl_vertex_shader;
break;
case VY_SHADER_FLAG_FRAGMENT:
case RT_SHADER_FLAG_FRAGMENT:
shaderc_kind = shaderc_glsl_fragment_shader;
break;
case VY_SHADER_FLAG_COMPUTE:
case RT_SHADER_FLAG_COMPUTE:
shaderc_kind = shaderc_glsl_compute_shader;
break;
default:
vyLog("ASSETC", "Invalid shader stage flag %u", type_from_flags);
rtLog("ASSETC", "Invalid shader stage flag %u", type_from_flags);
shaderc_compile_options_release(options);
shaderc_compiler_release(compiler);
return VY_PROCESSING_FAILED;
return RT_PROCESSING_FAILED;
}
shaderc_compilation_result_t result = shaderc_compile_into_spv(compiler,
@ -89,7 +89,7 @@ vy_result vyProcessShaderFile(vy_file_id file,
shaderc_compilation_status status = shaderc_result_get_compilation_status(result);
if (status != shaderc_compilation_status_success || shaderc_result_get_num_errors(result) > 0) {
vyLog("ASSETC",
rtLog("ASSETC",
"Compilation of %s failed: %s",
path,
shaderc_result_get_error_message(result));
@ -97,17 +97,17 @@ vy_result vyProcessShaderFile(vy_file_id file,
shaderc_result_release(result);
shaderc_compile_options_release(options);
shaderc_compiler_release(compiler);
return VY_PROCESSING_FAILED;
return RT_PROCESSING_FAILED;
}
size_t output_size = shaderc_result_get_length(result);
output->data = vyAllocBuffer(output_size);
output->data = rtAllocBuffer(output_size);
if (!output->data) {
shaderc_result_release(result);
shaderc_compile_options_release(options);
shaderc_compiler_release(compiler);
vyLog("ASSETC", "Failed to allocate %zu bytes for shader compilation output.", output_size);
return VY_PROCESSING_FAILED;
rtLog("ASSETC", "Failed to allocate %zu bytes for shader compilation output.", output_size);
return RT_PROCESSING_FAILED;
}
const uint32_t *spv_bytes = (uint32_t *)shaderc_result_get_bytes(result);
memcpy(output->data, spv_bytes, output_size);
@ -117,7 +117,7 @@ vy_result vyProcessShaderFile(vy_file_id file,
shaderc_compile_options_release(options);
shaderc_compiler_release(compiler);
output->asset_uid = vyCalculateUID(path);
output->asset_uid = rtCalculateUID(path);
return VY_SUCCESS;
return RT_SUCCESS;
}

View File

@ -1,7 +1,7 @@
#include "processing.h"
#include "utils.h"
#define VY_DEFINE_UIDTAB_FILE_STRUCTURES
#define RT_DEFINE_UIDTAB_FILE_STRUCTURES
#include "runtime/threading.h"
#include "runtime/uidtab.h"
@ -11,25 +11,25 @@
#include <stdlib.h>
#include <stdio.h>
static vy_uidtab_entry *_entries;
static rt_uidtab_entry *_entries;
static size_t _entry_capacity;
static size_t _entry_count;
vy_uid vyCalculateUID(const char *name) {
assert(sizeof(XXH32_hash_t) == sizeof(vy_uid));
rt_uid rtCalculateUID(const char *name) {
assert(sizeof(XXH32_hash_t) == sizeof(rt_uid));
size_t len = strlen(name);
return (vy_uid)XXH32(name, len, 0);
return (rt_uid)XXH32(name, len, 0);
}
vy_result vyAddUIDTabEntry(vy_file_id package_fid, vy_uid uid, uint64_t offset, uint64_t size) {
assert(vyIsMainThread());
rt_result rtAddUIDTabEntry(rt_file_id package_fid, rt_uid uid, uint64_t offset, uint64_t size) {
assert(rtIsMainThread());
if (_entry_count == _entry_capacity) {
size_t new_cap = (_entry_capacity > 0) ? _entry_capacity * 2 : 256;
void *t = realloc(_entries, sizeof(vy_uidtab_entry) * new_cap);
void *t = realloc(_entries, sizeof(rt_uidtab_entry) * new_cap);
if (!t)
return VY_UNKNOWN_ERROR;
return RT_UNKNOWN_ERROR;
_entry_capacity = new_cap;
_entries = t;
}
@ -38,32 +38,32 @@ vy_result vyAddUIDTabEntry(vy_file_id package_fid, vy_uid uid, uint64_t offset,
_entries[_entry_count].size = size;
_entries[_entry_count].uid = uid;
_entry_count++;
return VY_SUCCESS;
return RT_SUCCESS;
}
vy_result vyWriteUIDTab(void) {
vy_uidtab_header header;
XXH64_hash_t checksum = XXH3_64bits(_entries, sizeof(vy_uidtab_entry) * _entry_count);
rt_result rtWriteUIDTab(void) {
rt_uidtab_header header;
XXH64_hash_t checksum = XXH3_64bits(_entries, sizeof(rt_uidtab_entry) * _entry_count);
XXH64_canonicalFromHash(&header.checksum, checksum);
header.num_entries = (uint32_t)_entry_count;
FILE *f = fopen("data/uidtab.bin", "wb");
if (!f) {
vyReportError("ASSETC", "Failed to open 'uidtab.bin' for writing.");
return VY_UNKNOWN_ERROR;
rtReportError("ASSETC", "Failed to open 'uidtab.bin' for writing.");
return RT_UNKNOWN_ERROR;
}
if (fwrite(&header, sizeof(header), 1, f) != 1) {
vyReportError("ASSETC", "Failed to write header to 'uidtab.bin'");
rtReportError("ASSETC", "Failed to write header to 'uidtab.bin'");
fclose(f);
return VY_UNKNOWN_ERROR;
return RT_UNKNOWN_ERROR;
}
if (fwrite(_entries, sizeof(vy_uidtab_entry), _entry_count, f) != _entry_count) {
vyReportError("ASSETC", "Failed to write entries to 'uidtab.bin'");
if (fwrite(_entries, sizeof(rt_uidtab_entry), _entry_count, f) != _entry_count) {
rtReportError("ASSETC", "Failed to write entries to 'uidtab.bin'");
fclose(f);
return VY_UNKNOWN_ERROR;
return RT_UNKNOWN_ERROR;
}
fclose(f);
return VY_SUCCESS;
return RT_SUCCESS;
}

View File

@ -5,7 +5,7 @@
#include <Windows.h>
#endif
size_t vyGetFileSize(const char *path) {
size_t rtGetFileSize(const char *path) {
#ifdef _WIN32
WCHAR wpath[MAX_PATH];
MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, path, -1, wpath, MAX_PATH);
@ -16,7 +16,7 @@ size_t vyGetFileSize(const char *path) {
#endif
}
void vySetWorkingDirectory(const char *path) {
void rtSetWorkingDirectory(const char *path) {
#ifdef _WIN32
WCHAR wpath[MAX_PATH];
MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, path, -1, wpath, MAX_PATH);
@ -24,7 +24,7 @@ void vySetWorkingDirectory(const char *path) {
#endif
}
uint64_t vyGetCurrentTimestamp(void) {
uint64_t rtGetCurrentTimestamp(void) {
#ifdef _WIN32
FILETIME ft;
GetSystemTimeAsFileTime(&ft);
@ -34,11 +34,11 @@ uint64_t vyGetCurrentTimestamp(void) {
#endif
}
uint64_t vyGetFileModificationTimestamp(vy_file_id fid) {
uint64_t rtGetFileModificationTimestamp(rt_file_id fid) {
#ifdef _WIN32
const char *path = vyGetFilePath(fid);
const char *path = rtGetFilePath(fid);
if (!path) {
vyLog("ASSETC", "Tried to get modification timestamp of unknown file.");
rtLog("ASSETC", "Tried to get modification timestamp of unknown file.");
return 0;
}
WCHAR wpath[MAX_PATH];
@ -52,34 +52,34 @@ uint64_t vyGetFileModificationTimestamp(vy_file_id fid) {
#endif
}
vy_result vyIterateDirectory(const char *path, void *user, vy_iterate_directory_cb_func iterate_cb) {
rt_result rtIterateDirectory(const char *path, void *user, rt_iterate_directory_cb_func iterate_cb) {
#ifdef _WIN32
vy_result res;
rt_result res;
WCHAR wpath[MAX_PATH];
char wildcard_path[MAX_PATH];
strncpy(wildcard_path, path, MAX_PATH);
strncat(wildcard_path, "\\*", MAX_PATH - strlen(path));
res = vyUTF8ToWStr(wildcard_path, wpath, MAX_PATH);
if (res != VY_SUCCESS)
res = rtUTF8ToWStr(wildcard_path, wpath, MAX_PATH);
if (res != RT_SUCCESS)
return res;
WIN32_FIND_DATAW find;
HANDLE h = FindFirstFileW(wpath, &find);
if (h == INVALID_HANDLE_VALUE)
return VY_UNKNOWN_ERROR;
return RT_UNKNOWN_ERROR;
do {
char utf8_file[MAX_PATH];
res = vyWStrToUTF8(find.cFileName, utf8_file, MAX_PATH);
if (res != VY_SUCCESS)
res = rtWStrToUTF8(find.cFileName, utf8_file, MAX_PATH);
if (res != RT_SUCCESS)
break;
vyIterateDirElementType type;
rtIterateDirElementType type;
if (find.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
type = VY_DIR_ELEMENT_TYPE_DIRECTORY;
type = RT_DIR_ELEMENT_TYPE_DIRECTORY;
else
type = VY_DIR_ELEMENT_TYPE_FILE;
type = RT_DIR_ELEMENT_TYPE_FILE;
res = iterate_cb(utf8_file, type, user);
if (res != VY_SUCCESS)
if (res != RT_SUCCESS)
break;
} while (FindNextFileW(h, &find) != 0);
@ -88,14 +88,14 @@ vy_result vyIterateDirectory(const char *path, void *user, vy_iterate_directory_
#endif
}
vy_result vyCreateDirectory(const char *path) {
rt_result rtCreateDirectory(const char *path) {
#ifdef _WIN32
WCHAR wpath[MAX_PATH];
vy_result res = vyUTF8ToWStr(path, wpath, MAX_PATH);
if (res != VY_SUCCESS)
rt_result res = rtUTF8ToWStr(path, wpath, MAX_PATH);
if (res != RT_SUCCESS)
return res;
if (!CreateDirectoryW(wpath, NULL))
res = VY_UNKNOWN_ERROR;
res = RT_UNKNOWN_ERROR;
return res;
#endif
}

View File

@ -1,27 +1,27 @@
#ifndef VY_ASSETC_UTILS_H
#define VY_ASSETC_UTILS_H
#ifndef RT_ASSETC_UTILS_H
#define RT_ASSETC_UTILS_H
#include <stdint.h>
#include "runtime/file_tab.h"
size_t vyGetFileSize(const char *path);
size_t rtGetFileSize(const char *path);
void vySetWorkingDirectory(const char *path);
void rtSetWorkingDirectory(const char *path);
uint64_t vyGetCurrentTimestamp(void);
uint64_t rtGetCurrentTimestamp(void);
uint64_t vyGetFileModificationTimestamp(vy_file_id fid);
uint64_t rtGetFileModificationTimestamp(rt_file_id fid);
typedef enum {
VY_DIR_ELEMENT_TYPE_FILE,
VY_DIR_ELEMENT_TYPE_DIRECTORY,
} vyIterateDirElementType;
RT_DIR_ELEMENT_TYPE_FILE,
RT_DIR_ELEMENT_TYPE_DIRECTORY,
} rtIterateDirElementType;
typedef vy_result vy_iterate_directory_cb_func(const char *name, vyIterateDirElementType type, void *user);
typedef rt_result rt_iterate_directory_cb_func(const char *name, rtIterateDirElementType type, void *user);
vy_result vyIterateDirectory(const char *path, void *user, vy_iterate_directory_cb_func iterate_cb);
rt_result rtIterateDirectory(const char *path, void *user, rt_iterate_directory_cb_func iterate_cb);
vy_result vyCreateDirectory(const char *path);
rt_result rtCreateDirectory(const char *path);
#endif