rename the engine to recreational.tech
This commit is contained in:
parent
448d448430
commit
abb367dffc
5
.gitignore
vendored
5
.gitignore
vendored
@ -4,4 +4,7 @@
|
||||
|
||||
# assetc directories
|
||||
/actemp/*
|
||||
/data/*
|
||||
/data/*
|
||||
|
||||
/.cache/*
|
||||
/.vs/*
|
||||
|
16
meson.build
16
meson.build
@ -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,
|
||||
@ -190,4 +190,4 @@ rttest_exe = executable('rttest',
|
||||
link_with : runtime_link_libs,
|
||||
include_directories : incdir,
|
||||
win_subsystem : 'console')
|
||||
test('runtime test', rttest_exe)
|
||||
test('runtime test', rttest_exe)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
@ -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");
|
||||
}
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
@ -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
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
@ -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);
|
||||
}
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
@ -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
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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
|
||||
}
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user