started work on pipeline parsing
This commit is contained in:
parent
d5ab965d64
commit
448d448430
1
assets/shader/test.as
Normal file
1
assets/shader/test.as
Normal file
@ -0,0 +1 @@
|
|||||||
|
package pipelines.pkg;
|
7
assets/shader/test.pipeline
Normal file
7
assets/shader/test.pipeline
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
optimization speed;
|
||||||
|
|
||||||
|
vertex BEGIN
|
||||||
|
layout (location = 0) uniform vec3 foo;
|
||||||
|
void main() {
|
||||||
|
}
|
||||||
|
END
|
@ -58,6 +58,7 @@ runtime_lib = library('vyrt',
|
|||||||
'src/runtime/dynamic_libs.h',
|
'src/runtime/dynamic_libs.h',
|
||||||
'src/runtime/file_tab.h',
|
'src/runtime/file_tab.h',
|
||||||
'src/runtime/gfx.h',
|
'src/runtime/gfx.h',
|
||||||
|
'src/runtime/handles.h',
|
||||||
'src/runtime/jobs.h',
|
'src/runtime/jobs.h',
|
||||||
'src/runtime/packages.h',
|
'src/runtime/packages.h',
|
||||||
'src/runtime/renderer_api.h',
|
'src/runtime/renderer_api.h',
|
||||||
@ -113,7 +114,7 @@ if vk_dep.found()
|
|||||||
|
|
||||||
'src/renderer/vk/init.c',
|
'src/renderer/vk/init.c',
|
||||||
'src/renderer/vk/swapchain.c',
|
'src/renderer/vk/swapchain.c',
|
||||||
'src/renderer/vk/gfx_pipelines.c',
|
'src/renderer/vk/pipelines.c',
|
||||||
|
|
||||||
# Contrib Sources
|
# Contrib Sources
|
||||||
'contrib/volk/volk.h',
|
'contrib/volk/volk.h',
|
||||||
|
@ -1,3 +1,10 @@
|
|||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* C standard library*/
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <math.h>
|
@ -1,159 +0,0 @@
|
|||||||
#include "runtime/gfx.h"
|
|
||||||
#include "runtime/runtime.h"
|
|
||||||
|
|
||||||
#include "runtime/renderer_api.h"
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
|
|
||||||
unsigned int prog;
|
|
||||||
} vy_gl_pipeline;
|
|
||||||
|
|
||||||
#define NUM_SLOTS 256
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint32_t generation_in_use[NUM_SLOTS];
|
|
||||||
vy_gl_pipeline pipelines[NUM_SLOTS];
|
|
||||||
} vy_pipeline_storage;
|
|
||||||
|
|
||||||
static vy_pipeline_storage _storage;
|
|
||||||
|
|
||||||
static vy_gfx_pipeline_handle StorePipeline(vy_gl_pipeline pipeline) {
|
|
||||||
/* Search for free slot */
|
|
||||||
uint32_t slot = NUM_SLOTS;
|
|
||||||
for (uint32_t i = 0; i < NUM_SLOTS; ++i) {
|
|
||||||
if ((_storage.generation_in_use[i] & 0x1) == 0) {
|
|
||||||
slot = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (slot == NUM_SLOTS) {
|
|
||||||
vyReportError("GL_GFX", "Ran out of pipeline storage slots");
|
|
||||||
return (vy_gfx_pipeline_handle){0};
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t generation = _storage.generation_in_use[slot] >> 1;
|
|
||||||
generation = (generation + 1) & 0x1;
|
|
||||||
|
|
||||||
_storage.pipelines[slot] = pipeline;
|
|
||||||
_storage.generation_in_use[slot] = (generation << 1) | 0x1;
|
|
||||||
|
|
||||||
vy_gfx_pipeline_handle id;
|
|
||||||
id.index = (generation << 27) | slot;
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ReleasePipelineSlot(vy_gfx_pipeline_handle id) {
|
|
||||||
uint32_t slot = id.index & 0x08ffffff;
|
|
||||||
uint32_t gen = (id.index >> 27) & 0x1f;
|
|
||||||
if (slot >= NUM_SLOTS)
|
|
||||||
return;
|
|
||||||
gen = gen << 1 | 0x1;
|
|
||||||
if (_storage.generation_in_use[slot] == gen)
|
|
||||||
_storage.generation_in_use[slot] &= ~0x1;
|
|
||||||
}
|
|
||||||
|
|
||||||
vy_gfx_pipeline_handle
|
|
||||||
VY_RENDERER_API_FN(CompileComputePipeline)(const vy_compute_pipeline_info *info) {
|
|
||||||
#if 0
|
|
||||||
char info_log[512];
|
|
||||||
|
|
||||||
GLuint prog = glCreateProgram();
|
|
||||||
GLuint shader = glCreateShader(GL_COMPUTE_SHADER);
|
|
||||||
|
|
||||||
GLchar *code = (GLchar *)info->compute_source;
|
|
||||||
GLint code_len = (GLint)info->compute_source_length;
|
|
||||||
glShaderSource(shader, 1, (const GLchar **)&code, &code_len);
|
|
||||||
glCompileShader(shader);
|
|
||||||
|
|
||||||
GLint success;
|
|
||||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
|
|
||||||
if (!success) {
|
|
||||||
glGetShaderInfoLog(shader, 512, NULL, info_log);
|
|
||||||
vyReportError("GL_GFX",
|
|
||||||
"Failed to compile compute shader\n%s",
|
|
||||||
info_log);
|
|
||||||
glDeleteProgram(prog);
|
|
||||||
glDeleteShader(shader);
|
|
||||||
return (vy_gfx_pipeline_handle){0};
|
|
||||||
}
|
|
||||||
glAttachShader(prog, shader);
|
|
||||||
glLinkProgram(prog);
|
|
||||||
glGetProgramiv(prog, GL_LINK_STATUS, &success);
|
|
||||||
if (!success) {
|
|
||||||
glGetProgramInfoLog(prog, 512, NULL, info_log);
|
|
||||||
vyReportError("GL_GFX", "Failed to link compute shader\n%s", info_log);
|
|
||||||
glDeleteShader(shader);
|
|
||||||
glDeleteProgram(prog);
|
|
||||||
return (vy_gfx_pipeline_handle){0};
|
|
||||||
}
|
|
||||||
glDeleteShader(shader);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
vy_gl_pipeline pipeline;
|
|
||||||
pipeline.prog = 0;
|
|
||||||
return StorePipeline(pipeline);
|
|
||||||
}
|
|
||||||
|
|
||||||
vy_gfx_pipeline_handle
|
|
||||||
VY_RENDERER_API_FN(CompileGraphicsPipeline)(const vy_graphics_pipeline_info *info) {
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
char info_log[512];
|
|
||||||
GLuint prog = glCreateProgram();
|
|
||||||
GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER);
|
|
||||||
GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
|
|
||||||
|
|
||||||
GLchar *code = (GLchar *)info->vertex_source;
|
|
||||||
GLint code_len = (GLint)info->vertex_source_length;
|
|
||||||
glShaderSource(vertex_shader, 1, (const GLchar **)&code, &code_len);
|
|
||||||
glCompileShader(vertex_shader);
|
|
||||||
|
|
||||||
GLint success;
|
|
||||||
glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &success);
|
|
||||||
if (!success) {
|
|
||||||
glGetShaderInfoLog(vertex_shader, 512, NULL, info_log);
|
|
||||||
vyReportError("GL_GFX",
|
|
||||||
"Failed to compile vertex shader\n%s",
|
|
||||||
info_log);
|
|
||||||
glDeleteShader(vertex_shader);
|
|
||||||
glDeleteShader(fragment_shader);
|
|
||||||
glDeleteProgram(prog);
|
|
||||||
return (vy_gfx_pipeline_handle){0};
|
|
||||||
}
|
|
||||||
glAttachShader(prog, vertex_shader);
|
|
||||||
|
|
||||||
code = (GLchar *)info->fragment_source;
|
|
||||||
code_len = (GLint)info->fragment_source_length;
|
|
||||||
glShaderSource(fragment_shader, 1, (const GLchar **)&code, &code_len);
|
|
||||||
glCompileShader(fragment_shader);
|
|
||||||
|
|
||||||
glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &success);
|
|
||||||
if (!success) {
|
|
||||||
glGetShaderInfoLog(fragment_shader, 512, NULL, info_log);
|
|
||||||
vyReportError("GFX", "Failed to compile fragment shader\n%s", info_log);
|
|
||||||
glDeleteShader(fragment_shader);
|
|
||||||
glDeleteShader(fragment_shader);
|
|
||||||
glDeleteProgram(prog);
|
|
||||||
return (vy_gfx_pipeline_handle){0};
|
|
||||||
}
|
|
||||||
glAttachShader(prog, fragment_shader);
|
|
||||||
|
|
||||||
glLinkProgram(prog);
|
|
||||||
glGetProgramiv(prog, GL_LINK_STATUS, &success);
|
|
||||||
if (!success) {
|
|
||||||
glGetProgramInfoLog(prog, 512, NULL, info_log);
|
|
||||||
vyReportError("GFX", "Failed to link graphics shader\n%s", info_log);
|
|
||||||
glDeleteShader(vertex_shader);
|
|
||||||
glDeleteShader(fragment_shader);
|
|
||||||
glDeleteProgram(prog);
|
|
||||||
return (vy_gfx_pipeline_handle){0};
|
|
||||||
}
|
|
||||||
|
|
||||||
glDeleteShader(vertex_shader);
|
|
||||||
glDeleteShader(fragment_shader);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
vy_gl_pipeline pipeline;
|
|
||||||
pipeline.prog = 0;
|
|
||||||
return StorePipeline(pipeline);
|
|
||||||
}
|
|
@ -420,6 +420,9 @@ static vy_result CreateDevice(void) {
|
|||||||
return VY_SUCCESS;
|
return VY_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern vy_result InitPipelineManagement(void);
|
||||||
|
extern void ShutdownPipelineManagement(void);
|
||||||
|
|
||||||
vy_result VY_RENDERER_API_FN(Init)(const vy_renderer_init_info *info) {
|
vy_result VY_RENDERER_API_FN(Init)(const vy_renderer_init_info *info) {
|
||||||
vyLog("vk", "Init");
|
vyLog("vk", "Init");
|
||||||
|
|
||||||
@ -444,6 +447,9 @@ vy_result VY_RENDERER_API_FN(Init)(const vy_renderer_init_info *info) {
|
|||||||
if (res != VY_SUCCESS)
|
if (res != VY_SUCCESS)
|
||||||
return res;
|
return res;
|
||||||
res = CreateDevice();
|
res = CreateDevice();
|
||||||
|
if (res != VY_SUCCESS)
|
||||||
|
return res;
|
||||||
|
res = InitPipelineManagement();
|
||||||
if (res != VY_SUCCESS)
|
if (res != VY_SUCCESS)
|
||||||
return res;
|
return res;
|
||||||
res = vyCreateSwapchain();
|
res = vyCreateSwapchain();
|
||||||
@ -457,6 +463,7 @@ void VY_RENDERER_API_FN(Shutdown)(void) {
|
|||||||
vyLog("vk", "Shutdown");
|
vyLog("vk", "Shutdown");
|
||||||
vkDeviceWaitIdle(g_gpu.device);
|
vkDeviceWaitIdle(g_gpu.device);
|
||||||
vyDestroySwapchain();
|
vyDestroySwapchain();
|
||||||
|
ShutdownPipelineManagement();
|
||||||
vkDestroyDevice(g_gpu.device, g_gpu.alloc_cb);
|
vkDestroyDevice(g_gpu.device, g_gpu.alloc_cb);
|
||||||
vkDestroySurfaceKHR(g_gpu.instance, g_gpu.surface, g_gpu.alloc_cb);
|
vkDestroySurfaceKHR(g_gpu.instance, g_gpu.surface, g_gpu.alloc_cb);
|
||||||
vkDestroyInstance(g_gpu.instance, g_gpu.alloc_cb);
|
vkDestroyInstance(g_gpu.instance, g_gpu.alloc_cb);
|
||||||
|
103
src/renderer/vk/pipelines.c
Normal file
103
src/renderer/vk/pipelines.c
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
#include "runtime/renderer_api.h"
|
||||||
|
#include "runtime/config.h"
|
||||||
|
#include "runtime/handles.h"
|
||||||
|
#include "runtime/threading.h"
|
||||||
|
|
||||||
|
#include "gpu.h"
|
||||||
|
#include "pipelines.h"
|
||||||
|
|
||||||
|
#include <volk/volk.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
VY_CVAR_I(r_VkMaxPipelineCount, "Maximum number of pipeline objects. Default: 1024", 1024);
|
||||||
|
|
||||||
|
typedef struct vy_pipeline_s {
|
||||||
|
uint32_t version;
|
||||||
|
vy_pipeline pipeline;
|
||||||
|
struct vy_pipeline_s *next_free;
|
||||||
|
} vy_pipeline_slot;
|
||||||
|
|
||||||
|
static vy_pipeline_slot *_pipelines;
|
||||||
|
static vy_pipeline_slot *_first_free;
|
||||||
|
static vy_rwlock _lock;
|
||||||
|
|
||||||
|
vy_result InitPipelineManagement(void) {
|
||||||
|
vy_create_rwlock_result lock_res = vyCreateRWLock();
|
||||||
|
if (!lock_res.ok)
|
||||||
|
return VY_UNKNOWN_ERROR;
|
||||||
|
_lock = lock_res.lock;
|
||||||
|
|
||||||
|
_pipelines = calloc(r_VkMaxPipelineCount.i, sizeof(vy_pipeline_slot));
|
||||||
|
if (!_pipelines) {
|
||||||
|
vyDestroyRWLock(&_lock);
|
||||||
|
return VY_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DestroyPipeline(vy_pipeline_slot *slot) {
|
||||||
|
if (slot->pipeline.pipeline) {
|
||||||
|
vkDestroyPipeline(g_gpu.device, slot->pipeline.pipeline, g_gpu.alloc_cb);
|
||||||
|
}
|
||||||
|
slot->next_free = _first_free;
|
||||||
|
_first_free = slot;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShutdownPipelineManagement(void) {
|
||||||
|
for (int i = 1; i < r_VkMaxPipelineCount.i; ++i) {
|
||||||
|
DestroyPipeline(&_pipelines[i]);
|
||||||
|
}
|
||||||
|
free(_pipelines);
|
||||||
|
vyDestroyRWLock(&_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);
|
||||||
|
if (!_first_free) {
|
||||||
|
vyLog("VK", "No free pipeline slots!");
|
||||||
|
vyUnlockWrite(&_lock);
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
vy_pipeline_slot *slot = _first_free;
|
||||||
|
_first_free = slot->next_free;
|
||||||
|
slot->version = (slot->version + 1) & VY_GFX_HANDLE_MAX_VERSION;
|
||||||
|
vyUnlockWrite(&_lock);
|
||||||
|
|
||||||
|
/* No other thread that calls compile gets the same slot.
|
||||||
|
* Another thread accessing the slot via GetPipeline would get a version mismatch.
|
||||||
|
* The same holds for DestroyPipeline
|
||||||
|
*/
|
||||||
|
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VY_RENDERER_API_FN(DestroyPipeline)(vy_pipeline_handle handle) {
|
||||||
|
if (handle.index >= (uint32_t)r_VkMaxPipelineCount.i)
|
||||||
|
return;
|
||||||
|
vyLockWrite(&_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);
|
||||||
|
}
|
||||||
|
|
||||||
|
const vy_pipeline *vyGetPipeline(vy_pipeline_handle handle) {
|
||||||
|
if (handle.index >= (uint32_t)r_VkMaxPipelineCount.i)
|
||||||
|
return NULL;
|
||||||
|
vyLockRead(&_lock);
|
||||||
|
vy_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);
|
||||||
|
return res;
|
||||||
|
}
|
15
src/renderer/vk/pipelines.h
Normal file
15
src/renderer/vk/pipelines.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#ifndef VY_VK_PIPELINES_H
|
||||||
|
#define VY_VK_PIPELINES_H
|
||||||
|
|
||||||
|
#include <volk/volk.h>
|
||||||
|
|
||||||
|
#include "runtime/gfx.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
VkPipeline pipeline;
|
||||||
|
} vy_pipeline;
|
||||||
|
|
||||||
|
/* A pipeline is immutable after creation. */
|
||||||
|
const vy_pipeline *vyGetPipeline(vy_pipeline_handle handle);
|
||||||
|
|
||||||
|
#endif
|
@ -318,40 +318,62 @@ VY_DLLEXPORT vy_get_asset_result vyGetAsset(vy_uid uid) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vyLockRead(&_lock);
|
vyLockWrite(&_lock);
|
||||||
volatile vy_asset_cache_entry *entry = GetEntry(uid);
|
vy_asset_cache_entry *entry = GetEntry(uid);
|
||||||
if (entry) {
|
if (entry) {
|
||||||
if (entry->state == CACHE_ENTRY_STATE_LOADED) {
|
if (entry->state == CACHE_ENTRY_STATE_LOADED) {
|
||||||
++entry->refcount;
|
++entry->refcount;
|
||||||
result.data = entry->buffer;
|
result.data = entry->buffer;
|
||||||
result.size = entry->size;
|
result.size = entry->size;
|
||||||
} else if (entry->state == CACHE_ENTRY_STATE_LOADING) {
|
} else if (entry->state == CACHE_ENTRY_STATE_LOADING) {
|
||||||
/* Promote to write lock */
|
|
||||||
vyUnlockRead(&_lock);
|
|
||||||
vyLockWrite(&_lock);
|
|
||||||
if (entry->state == CACHE_ENTRY_STATE_LOADING) {
|
if (entry->state == CACHE_ENTRY_STATE_LOADING) {
|
||||||
assert(entry->load != VY_AIO_INVALID_HANDLE);
|
assert(entry->load != VY_AIO_INVALID_HANDLE);
|
||||||
++entry->refcount;
|
++entry->refcount;
|
||||||
if (vyWaitForAIOCompletion(entry->load) == VY_AIO_STATE_FINISHED) {
|
if (vyWaitForAIOCompletion(entry->load) == VY_AIO_STATE_FINISHED) {
|
||||||
if (DecompressEntry(uid, (vy_asset_cache_entry *)entry)) {
|
if (DecompressEntry(uid, entry)) {
|
||||||
result.data = entry->buffer;
|
result.data = entry->buffer;
|
||||||
result.size = entry->size;
|
result.size = entry->size;
|
||||||
} else {
|
} else {
|
||||||
result.result = VY_LOAD_FAILED;
|
result.result = VY_LOAD_FAILED;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ReleaseEntry((vy_asset_cache_entry *)entry);
|
ReleaseEntry(entry);
|
||||||
vyLog("ASSET_CACHE", "Failed to load asset %u", uid);
|
vyLog("ASSET_CACHE", "Failed to load asset %u", uid);
|
||||||
result.result = VY_LOAD_FAILED;
|
result.result = VY_LOAD_FAILED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vyUnlockWrite(&_lock);
|
|
||||||
|
|
||||||
/* To match the unlock below */
|
|
||||||
vyLockRead(&_lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Remove from the reclaim list */
|
||||||
|
if (_first_reclaim == entry)
|
||||||
|
_first_reclaim = entry->next_reclaim;
|
||||||
|
if (_last_reclaim == entry)
|
||||||
|
_last_reclaim = entry->prev_reclaim;
|
||||||
|
if (entry->next_reclaim)
|
||||||
|
entry->next_reclaim->prev_reclaim = entry->prev_reclaim;
|
||||||
|
if (entry->prev_reclaim)
|
||||||
|
entry->prev_reclaim->next_reclaim = entry->next_reclaim;
|
||||||
}
|
}
|
||||||
vyUnlockRead(&_lock);
|
vyUnlockWrite(&_lock);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
VY_DLLEXPORT void vyReleaseAsset(vy_uid uid) {
|
||||||
|
vyLockWrite(&_lock);
|
||||||
|
vy_asset_cache_entry *entry = GetEntry(uid);
|
||||||
|
if (entry && entry->refcount > 0) {
|
||||||
|
--entry->refcount;
|
||||||
|
if (entry->refcount == 0) {
|
||||||
|
/* add to the reclaim list */
|
||||||
|
if (_last_reclaim)
|
||||||
|
_last_reclaim->next_reclaim = entry;
|
||||||
|
if (!_first_reclaim)
|
||||||
|
_first_reclaim = entry;
|
||||||
|
entry->prev_reclaim = _last_reclaim;
|
||||||
|
entry->next_reclaim = NULL;
|
||||||
|
_last_reclaim = entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vyUnlockWrite(&_lock);
|
||||||
}
|
}
|
@ -20,7 +20,7 @@ enum {
|
|||||||
typedef uint8_t vy_renderer_backend_code;
|
typedef uint8_t vy_renderer_backend_code;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
VY_UNKNOWN_ASSET = VY_SUCCESS + 1,
|
VY_UNKNOWN_ASSET = VY_CUSTOM_ERROR_START,
|
||||||
VY_BUFFER_ALLOC_FAILED,
|
VY_BUFFER_ALLOC_FAILED,
|
||||||
VY_LOAD_FAILED,
|
VY_LOAD_FAILED,
|
||||||
VY_ASSET_CACHE_FULL,
|
VY_ASSET_CACHE_FULL,
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
#include "runtime.h"
|
#include "runtime.h"
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
VY_BUFFER_MGR_OUT_OF_MEMORY = VY_SUCCESS + 1,
|
VY_BUFFER_MGR_OUT_OF_MEMORY = VY_CUSTOM_ERROR_START,
|
||||||
VY_BUFFER_MGR_MUTEX_CREATION_FAILED,
|
VY_BUFFER_MGR_MUTEX_CREATION_FAILED,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -25,9 +25,12 @@ VY_DLLEXPORT void vyShutdownGFX(void);
|
|||||||
|
|
||||||
/* Handles backend objects */
|
/* Handles backend objects */
|
||||||
|
|
||||||
|
#define VY_GFX_HANDLE_MAX_VERSION 255
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t index;
|
uint32_t version : 8;
|
||||||
} vy_gfx_pipeline_handle;
|
uint32_t index : 24;
|
||||||
|
} vy_pipeline_handle;
|
||||||
|
|
||||||
/* Attributes are used to bind buffers (or textures) to symbolic values.
|
/* Attributes are used to bind buffers (or textures) to symbolic values.
|
||||||
* For example, an attribute might be bound to "CELL_GRID", which would be
|
* For example, an attribute might be bound to "CELL_GRID", which would be
|
||||||
|
@ -23,10 +23,8 @@ VY_CVAR_S(rt_Renderer, "Select the render backend. Available options: [vk], Defa
|
|||||||
extern void VY_RENDERER_API_FN(RegisterCVars)(void);
|
extern void VY_RENDERER_API_FN(RegisterCVars)(void);
|
||||||
extern vy_result VY_RENDERER_API_FN(Init)(const vy_renderer_init_info *);
|
extern vy_result VY_RENDERER_API_FN(Init)(const vy_renderer_init_info *);
|
||||||
extern void VY_RENDERER_API_FN(Shutdown)(void);
|
extern void VY_RENDERER_API_FN(Shutdown)(void);
|
||||||
extern vy_gfx_pipeline_handle
|
extern vy_pipeline_handle VY_RENDERER_API_FN(CompilePipeline)(const vy_pipeline_info *);
|
||||||
VY_RENDERER_API_FN(CompileComputePipeline)(const vy_compute_pipeline_info *);
|
extern void VY_RENDERER_API_FN(DestroyPipeline)(vy_pipeline_handle handle);
|
||||||
extern vy_gfx_pipeline_handle
|
|
||||||
VY_RENDERER_API_FN(CompileGraphicsPipeline)(const vy_graphics_pipeline_info *);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static bool LoadRenderer(void) {
|
static bool LoadRenderer(void) {
|
||||||
@ -50,8 +48,8 @@ static bool LoadRenderer(void) {
|
|||||||
RETRIEVE_SYMBOL(RegisterCVars, vy_register_renderer_cvars_fn);
|
RETRIEVE_SYMBOL(RegisterCVars, vy_register_renderer_cvars_fn);
|
||||||
RETRIEVE_SYMBOL(Init, vy_init_renderer_fn);
|
RETRIEVE_SYMBOL(Init, vy_init_renderer_fn);
|
||||||
RETRIEVE_SYMBOL(Shutdown, vy_shutdown_renderer_fn);
|
RETRIEVE_SYMBOL(Shutdown, vy_shutdown_renderer_fn);
|
||||||
RETRIEVE_SYMBOL(CompileComputePipeline, vy_compile_compute_pipeline_fn);
|
RETRIEVE_SYMBOL(CompilePipeline, vy_compile_pipeline_fn);
|
||||||
RETRIEVE_SYMBOL(CompileGraphicsPipeline, vy_compile_graphics_pipeline_fn);
|
RETRIEVE_SYMBOL(DestroyPipeline, vy_destroy_pipeline_fn);
|
||||||
} else {
|
} else {
|
||||||
vyReportError("GFX",
|
vyReportError("GFX",
|
||||||
"Unsupported renderer backend: (%s) %s",
|
"Unsupported renderer backend: (%s) %s",
|
||||||
@ -64,8 +62,8 @@ static bool LoadRenderer(void) {
|
|||||||
g_renderer.RegisterCVars = &vyRenRegisterCVars;
|
g_renderer.RegisterCVars = &vyRenRegisterCVars;
|
||||||
g_renderer.Init = &vyRenInit;
|
g_renderer.Init = &vyRenInit;
|
||||||
g_renderer.Shutdown = &vyRenShutdown;
|
g_renderer.Shutdown = &vyRenShutdown;
|
||||||
g_renderer.CompileComputePipeline = &vyRenCompileComputePipeline;
|
g_renderer.CompilePipeline = &vyRenCompilePipeline;
|
||||||
g_renderer.CompileGraphicsPipeline = &vyRenCompileGraphicsPipeline;
|
g_renderer.DestroyPipeline = &vyRenDestroyPipeline;
|
||||||
#endif
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,9 @@
|
|||||||
|
|
||||||
/* All handle types should contain a uint32_t index */
|
/* All handle types should contain a uint32_t index */
|
||||||
|
|
||||||
|
#define VY_INVALID_HANDLE \
|
||||||
|
{ .index = 0 }
|
||||||
|
|
||||||
#define VY_IS_HANDLE_VALID(handle) ((handle).index != 0)
|
#define VY_IS_HANDLE_VALID(handle) ((handle).index != 0)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -26,19 +26,6 @@ struct vy_renderer_init_info_s {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
const char *compute_source;
|
|
||||||
size_t compute_source_length;
|
|
||||||
} vy_compute_pipeline_info;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
const char *vertex_source;
|
|
||||||
size_t vertex_source_length;
|
|
||||||
|
|
||||||
const char *fragment_source;
|
|
||||||
size_t fragment_source_length;
|
|
||||||
} vy_graphics_pipeline_info;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
vy_uid vertex_shader;
|
vy_uid vertex_shader;
|
||||||
vy_uid fragment_shader;
|
vy_uid fragment_shader;
|
||||||
@ -56,16 +43,15 @@ typedef struct {
|
|||||||
typedef void vy_register_renderer_cvars_fn(void);
|
typedef void vy_register_renderer_cvars_fn(void);
|
||||||
typedef vy_result vy_init_renderer_fn(const vy_renderer_init_info *info);
|
typedef vy_result vy_init_renderer_fn(const vy_renderer_init_info *info);
|
||||||
typedef void vy_shutdown_renderer_fn(void);
|
typedef void vy_shutdown_renderer_fn(void);
|
||||||
typedef vy_gfx_pipeline_handle vy_compile_compute_pipeline_fn(const vy_compute_pipeline_info *info);
|
typedef vy_pipeline_handle vy_compile_pipeline_fn(const vy_pipeline_info *info);
|
||||||
typedef vy_gfx_pipeline_handle
|
typedef void vy_destroy_pipeline_fn(vy_pipeline_handle handle);
|
||||||
vy_compile_graphics_pipeline_fn(const vy_graphics_pipeline_info *info);
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
vy_register_renderer_cvars_fn *RegisterCVars;
|
vy_register_renderer_cvars_fn *RegisterCVars;
|
||||||
vy_init_renderer_fn *Init;
|
vy_init_renderer_fn *Init;
|
||||||
vy_shutdown_renderer_fn *Shutdown;
|
vy_shutdown_renderer_fn *Shutdown;
|
||||||
vy_compile_compute_pipeline_fn *CompileComputePipeline;
|
vy_compile_pipeline_fn *CompilePipeline;
|
||||||
vy_compile_graphics_pipeline_fn *CompileGraphicsPipeline;
|
vy_destroy_pipeline_fn *DestroyPipeline;
|
||||||
} vy_renderer_api;
|
} vy_renderer_api;
|
||||||
|
|
||||||
#define VY_RENDERER_API_FN(name) VY_DLLEXPORT vyRen##name
|
#define VY_RENDERER_API_FN(name) VY_DLLEXPORT vyRen##name
|
||||||
|
@ -27,8 +27,16 @@
|
|||||||
#define VY_GB(n) ((n)*1024U * 1024U * 1024U)
|
#define VY_GB(n) ((n)*1024U * 1024U * 1024U)
|
||||||
|
|
||||||
typedef unsigned int vy_result;
|
typedef unsigned int vy_result;
|
||||||
#define VY_SUCCESS 0
|
|
||||||
#define VY_UNKNOWN_ERROR (vy_result)-1
|
/* Default result codes */
|
||||||
|
enum {
|
||||||
|
VY_SUCCESS = 0,
|
||||||
|
VY_OUT_OF_MEMORY = 1,
|
||||||
|
|
||||||
|
VY_CUSTOM_ERROR_START,
|
||||||
|
|
||||||
|
VY_UNKNOWN_ERROR = (vy_result)-1,
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const char *start;
|
const char *start;
|
||||||
@ -49,8 +57,8 @@ VY_DLLEXPORT void vyReportError(const char *subsystem, const char *fmt, ...);
|
|||||||
VY_DLLEXPORT void vyLog(const char *subsystem, const char *fmt, ...);
|
VY_DLLEXPORT void vyLog(const char *subsystem, const char *fmt, ...);
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
VY_INVALID_UNICODE = 1,
|
VY_INVALID_UNICODE = VY_CUSTOM_ERROR_START,
|
||||||
VY_INSUFFICIENT_BUFFER = 2,
|
VY_INSUFFICIENT_BUFFER,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Returns VY_SUCCESS if the string was successfully converted,
|
/* Returns VY_SUCCESS if the string was successfully converted,
|
||||||
|
@ -45,7 +45,7 @@ vy_result LoadUIDTable(void) {
|
|||||||
if (!mem) {
|
if (!mem) {
|
||||||
fclose(f);
|
fclose(f);
|
||||||
_tab.slots = 0;
|
_tab.slots = 0;
|
||||||
return VY_BUFFER_ALLOC_FAILED;
|
return VY_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
_tab.uids = mem;
|
_tab.uids = mem;
|
||||||
_tab.data = (vy_uid_data *)(_tab.uids + _tab.slots);
|
_tab.data = (vy_uid_data *)(_tab.uids + _tab.slots);
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
extern int memcmp(const void *s1, const void *s2, size_t n);
|
||||||
|
|
||||||
static bool IsAllowedChar(char c) {
|
static bool IsAllowedChar(char c) {
|
||||||
return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
|
return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
|
||||||
(c == '.') || (c == '_') || (c == '/');
|
(c == '.') || (c == '_') || (c == '/');
|
||||||
@ -66,6 +68,37 @@ static bool ParseValue(vy_parse_state *state, vy_text_span *_value) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define BLOCK_BEGIN "BEGIN"
|
||||||
|
#define BLOCK_BEGIN_LENGTH 5
|
||||||
|
#define BLOCK_END "END"
|
||||||
|
#define BLOCK_END_LENGTH 3
|
||||||
|
|
||||||
|
VY_INLINE static bool IsBlockBegin(vy_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) {
|
||||||
|
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;
|
||||||
|
value.start = &state->text[state->at];
|
||||||
|
value.length = 0;
|
||||||
|
while (state->at < state->length) {
|
||||||
|
if (state->text[state->at] == BLOCK_END[0] && IsBlockEnd(state)) {
|
||||||
|
*p_value = value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
++value.length;
|
||||||
|
++state->at;
|
||||||
|
}
|
||||||
|
/* did not find END */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static bool ParseStmtList(vy_parse_state *state, unsigned int *list_index);
|
static bool ParseStmtList(vy_parse_state *state, unsigned int *list_index);
|
||||||
|
|
||||||
static bool ParseStmt(vy_parse_state *state, unsigned int *stmt_index) {
|
static bool ParseStmt(vy_parse_state *state, unsigned int *stmt_index) {
|
||||||
@ -93,6 +126,16 @@ static bool ParseStmt(vy_parse_state *state, unsigned int *stmt_index) {
|
|||||||
/* Consume '}' */
|
/* Consume '}' */
|
||||||
if (state->at < state->length && state->text[state->at] == '}')
|
if (state->at < state->length && state->text[state->at] == '}')
|
||||||
++state->at;
|
++state->at;
|
||||||
|
} else if (IsBlockBegin(state)) {
|
||||||
|
/* Consume BEGIN */
|
||||||
|
state->at += BLOCK_BEGIN_LENGTH;
|
||||||
|
|
||||||
|
stmt.form = VY_STMT_FORM_BLOCK;
|
||||||
|
if (!ParseBlock(state, &stmt.block))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* Consume END */
|
||||||
|
state->at += BLOCK_END_LENGTH;
|
||||||
} else {
|
} else {
|
||||||
stmt.form = VY_STMT_FORM_VALUE;
|
stmt.form = VY_STMT_FORM_VALUE;
|
||||||
if (!ParseValue(state, &stmt.value))
|
if (!ParseValue(state, &stmt.value))
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
VY_STMT_FORM_VALUE,
|
VY_STMT_FORM_VALUE,
|
||||||
VY_STMT_FORM_LIST,
|
VY_STMT_FORM_LIST,
|
||||||
|
VY_STMT_FORM_BLOCK,
|
||||||
} vy_stmt_form;
|
} vy_stmt_form;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -18,6 +19,7 @@ typedef struct {
|
|||||||
vy_text_span attribute;
|
vy_text_span attribute;
|
||||||
union {
|
union {
|
||||||
vy_text_span value;
|
vy_text_span value;
|
||||||
|
vy_text_span block;
|
||||||
unsigned int list_index;
|
unsigned int list_index;
|
||||||
};
|
};
|
||||||
/* For lists */
|
/* For lists */
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
#include "runtime/file_tab.h"
|
#include "runtime/file_tab.h"
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
VY_PROCESSING_FAILED = VY_SUCCESS + 1,
|
VY_PROCESSING_FAILED = VY_CUSTOM_ERROR_START,
|
||||||
/* Used if the processing depends on other files beeing processed first. */
|
/* Used if the processing depends on other files beeing processed first. */
|
||||||
VY_PROCESSING_TRY_AGAIN,
|
VY_PROCESSING_TRY_AGAIN,
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user