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/file_tab.h',
|
||||
'src/runtime/gfx.h',
|
||||
'src/runtime/handles.h',
|
||||
'src/runtime/jobs.h',
|
||||
'src/runtime/packages.h',
|
||||
'src/runtime/renderer_api.h',
|
||||
@ -113,7 +114,7 @@ if vk_dep.found()
|
||||
|
||||
'src/renderer/vk/init.c',
|
||||
'src/renderer/vk/swapchain.c',
|
||||
'src/renderer/vk/gfx_pipelines.c',
|
||||
'src/renderer/vk/pipelines.c',
|
||||
|
||||
# Contrib Sources
|
||||
'contrib/volk/volk.h',
|
||||
|
@ -1,3 +1,10 @@
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
#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;
|
||||
}
|
||||
|
||||
extern vy_result InitPipelineManagement(void);
|
||||
extern void ShutdownPipelineManagement(void);
|
||||
|
||||
vy_result VY_RENDERER_API_FN(Init)(const vy_renderer_init_info *info) {
|
||||
vyLog("vk", "Init");
|
||||
|
||||
@ -444,6 +447,9 @@ vy_result VY_RENDERER_API_FN(Init)(const vy_renderer_init_info *info) {
|
||||
if (res != VY_SUCCESS)
|
||||
return res;
|
||||
res = CreateDevice();
|
||||
if (res != VY_SUCCESS)
|
||||
return res;
|
||||
res = InitPipelineManagement();
|
||||
if (res != VY_SUCCESS)
|
||||
return res;
|
||||
res = vyCreateSwapchain();
|
||||
@ -457,6 +463,7 @@ void VY_RENDERER_API_FN(Shutdown)(void) {
|
||||
vyLog("vk", "Shutdown");
|
||||
vkDeviceWaitIdle(g_gpu.device);
|
||||
vyDestroySwapchain();
|
||||
ShutdownPipelineManagement();
|
||||
vkDestroyDevice(g_gpu.device, g_gpu.alloc_cb);
|
||||
vkDestroySurfaceKHR(g_gpu.instance, g_gpu.surface, 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);
|
||||
volatile vy_asset_cache_entry *entry = GetEntry(uid);
|
||||
vyLockWrite(&_lock);
|
||||
vy_asset_cache_entry *entry = GetEntry(uid);
|
||||
if (entry) {
|
||||
if (entry->state == CACHE_ENTRY_STATE_LOADED) {
|
||||
++entry->refcount;
|
||||
result.data = entry->buffer;
|
||||
result.size = entry->size;
|
||||
} else if (entry->state == CACHE_ENTRY_STATE_LOADING) {
|
||||
/* Promote to write lock */
|
||||
vyUnlockRead(&_lock);
|
||||
vyLockWrite(&_lock);
|
||||
if (entry->state == CACHE_ENTRY_STATE_LOADING) {
|
||||
assert(entry->load != VY_AIO_INVALID_HANDLE);
|
||||
++entry->refcount;
|
||||
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.size = entry->size;
|
||||
} else {
|
||||
result.result = VY_LOAD_FAILED;
|
||||
}
|
||||
} else {
|
||||
ReleaseEntry((vy_asset_cache_entry *)entry);
|
||||
ReleaseEntry(entry);
|
||||
vyLog("ASSET_CACHE", "Failed to load asset %u", uid);
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
enum {
|
||||
VY_UNKNOWN_ASSET = VY_SUCCESS + 1,
|
||||
VY_UNKNOWN_ASSET = VY_CUSTOM_ERROR_START,
|
||||
VY_BUFFER_ALLOC_FAILED,
|
||||
VY_LOAD_FAILED,
|
||||
VY_ASSET_CACHE_FULL,
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include "runtime.h"
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
|
@ -25,9 +25,12 @@ VY_DLLEXPORT void vyShutdownGFX(void);
|
||||
|
||||
/* Handles backend objects */
|
||||
|
||||
#define VY_GFX_HANDLE_MAX_VERSION 255
|
||||
|
||||
typedef struct {
|
||||
uint32_t index;
|
||||
} vy_gfx_pipeline_handle;
|
||||
uint32_t version : 8;
|
||||
uint32_t index : 24;
|
||||
} vy_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
|
||||
|
@ -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 vy_result VY_RENDERER_API_FN(Init)(const vy_renderer_init_info *);
|
||||
extern void VY_RENDERER_API_FN(Shutdown)(void);
|
||||
extern vy_gfx_pipeline_handle
|
||||
VY_RENDERER_API_FN(CompileComputePipeline)(const vy_compute_pipeline_info *);
|
||||
extern vy_gfx_pipeline_handle
|
||||
VY_RENDERER_API_FN(CompileGraphicsPipeline)(const vy_graphics_pipeline_info *);
|
||||
extern vy_pipeline_handle VY_RENDERER_API_FN(CompilePipeline)(const vy_pipeline_info *);
|
||||
extern void VY_RENDERER_API_FN(DestroyPipeline)(vy_pipeline_handle handle);
|
||||
#endif
|
||||
|
||||
static bool LoadRenderer(void) {
|
||||
@ -50,8 +48,8 @@ static bool LoadRenderer(void) {
|
||||
RETRIEVE_SYMBOL(RegisterCVars, vy_register_renderer_cvars_fn);
|
||||
RETRIEVE_SYMBOL(Init, vy_init_renderer_fn);
|
||||
RETRIEVE_SYMBOL(Shutdown, vy_shutdown_renderer_fn);
|
||||
RETRIEVE_SYMBOL(CompileComputePipeline, vy_compile_compute_pipeline_fn);
|
||||
RETRIEVE_SYMBOL(CompileGraphicsPipeline, vy_compile_graphics_pipeline_fn);
|
||||
RETRIEVE_SYMBOL(CompilePipeline, vy_compile_pipeline_fn);
|
||||
RETRIEVE_SYMBOL(DestroyPipeline, vy_destroy_pipeline_fn);
|
||||
} else {
|
||||
vyReportError("GFX",
|
||||
"Unsupported renderer backend: (%s) %s",
|
||||
@ -64,8 +62,8 @@ static bool LoadRenderer(void) {
|
||||
g_renderer.RegisterCVars = &vyRenRegisterCVars;
|
||||
g_renderer.Init = &vyRenInit;
|
||||
g_renderer.Shutdown = &vyRenShutdown;
|
||||
g_renderer.CompileComputePipeline = &vyRenCompileComputePipeline;
|
||||
g_renderer.CompileGraphicsPipeline = &vyRenCompileGraphicsPipeline;
|
||||
g_renderer.CompilePipeline = &vyRenCompilePipeline;
|
||||
g_renderer.DestroyPipeline = &vyRenDestroyPipeline;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
@ -3,6 +3,9 @@
|
||||
|
||||
/* All handle types should contain a uint32_t index */
|
||||
|
||||
#define VY_INVALID_HANDLE \
|
||||
{ .index = 0 }
|
||||
|
||||
#define VY_IS_HANDLE_VALID(handle) ((handle).index != 0)
|
||||
|
||||
#endif
|
||||
|
@ -26,19 +26,6 @@ struct vy_renderer_init_info_s {
|
||||
#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 {
|
||||
vy_uid vertex_shader;
|
||||
vy_uid fragment_shader;
|
||||
@ -56,16 +43,15 @@ typedef struct {
|
||||
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_gfx_pipeline_handle vy_compile_compute_pipeline_fn(const vy_compute_pipeline_info *info);
|
||||
typedef vy_gfx_pipeline_handle
|
||||
vy_compile_graphics_pipeline_fn(const vy_graphics_pipeline_info *info);
|
||||
typedef vy_pipeline_handle vy_compile_pipeline_fn(const vy_pipeline_info *info);
|
||||
typedef void vy_destroy_pipeline_fn(vy_pipeline_handle handle);
|
||||
|
||||
typedef struct {
|
||||
vy_register_renderer_cvars_fn *RegisterCVars;
|
||||
vy_init_renderer_fn *Init;
|
||||
vy_shutdown_renderer_fn *Shutdown;
|
||||
vy_compile_compute_pipeline_fn *CompileComputePipeline;
|
||||
vy_compile_graphics_pipeline_fn *CompileGraphicsPipeline;
|
||||
vy_compile_pipeline_fn *CompilePipeline;
|
||||
vy_destroy_pipeline_fn *DestroyPipeline;
|
||||
} vy_renderer_api;
|
||||
|
||||
#define VY_RENDERER_API_FN(name) VY_DLLEXPORT vyRen##name
|
||||
|
@ -27,8 +27,16 @@
|
||||
#define VY_GB(n) ((n)*1024U * 1024U * 1024U)
|
||||
|
||||
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 {
|
||||
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, ...);
|
||||
|
||||
enum {
|
||||
VY_INVALID_UNICODE = 1,
|
||||
VY_INSUFFICIENT_BUFFER = 2,
|
||||
VY_INVALID_UNICODE = VY_CUSTOM_ERROR_START,
|
||||
VY_INSUFFICIENT_BUFFER,
|
||||
};
|
||||
|
||||
/* Returns VY_SUCCESS if the string was successfully converted,
|
||||
|
@ -45,7 +45,7 @@ vy_result LoadUIDTable(void) {
|
||||
if (!mem) {
|
||||
fclose(f);
|
||||
_tab.slots = 0;
|
||||
return VY_BUFFER_ALLOC_FAILED;
|
||||
return VY_OUT_OF_MEMORY;
|
||||
}
|
||||
_tab.uids = mem;
|
||||
_tab.data = (vy_uid_data *)(_tab.uids + _tab.slots);
|
||||
|
@ -6,6 +6,8 @@
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
extern int memcmp(const void *s1, const void *s2, size_t n);
|
||||
|
||||
static bool IsAllowedChar(char c) {
|
||||
return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
|
||||
(c == '.') || (c == '_') || (c == '/');
|
||||
@ -66,6 +68,37 @@ static bool ParseValue(vy_parse_state *state, vy_text_span *_value) {
|
||||
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 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 '}' */
|
||||
if (state->at < state->length && state->text[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 {
|
||||
stmt.form = VY_STMT_FORM_VALUE;
|
||||
if (!ParseValue(state, &stmt.value))
|
||||
|
@ -6,6 +6,7 @@
|
||||
typedef enum {
|
||||
VY_STMT_FORM_VALUE,
|
||||
VY_STMT_FORM_LIST,
|
||||
VY_STMT_FORM_BLOCK,
|
||||
} vy_stmt_form;
|
||||
|
||||
typedef struct {
|
||||
@ -18,6 +19,7 @@ typedef struct {
|
||||
vy_text_span attribute;
|
||||
union {
|
||||
vy_text_span value;
|
||||
vy_text_span block;
|
||||
unsigned int list_index;
|
||||
};
|
||||
/* For lists */
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include "runtime/file_tab.h"
|
||||
|
||||
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. */
|
||||
VY_PROCESSING_TRY_AGAIN,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user