From c35c191ec51c86c4153ccf86aab54b9d7c6f0b91 Mon Sep 17 00:00:00 2001 From: hgn Date: Sat, 4 Oct 2025 22:21:38 +0000 Subject: [PATCH] hooks and shaders into metacompiler tool --- foundation.kv | 44 ++- include/common_api.h | 7 + include/engine_interface.h | 8 - shaders/blit_tex.fs | 34 --- source/engine/main.c | 11 +- source/engine/shader.c | 27 ++ source/foundation/logging.c | 6 +- source/foundation/stream.c | 25 +- source/foundation/string.c | 2 +- source/tools/metacompiler.c | 533 +++++++++++++++++++++++++++++------- 10 files changed, 544 insertions(+), 153 deletions(-) diff --git a/foundation.kv b/foundation.kv index f375ddc..fb1c376 100644 --- a/foundation.kv +++ b/foundation.kv @@ -217,8 +217,24 @@ add source/foundation/async.c shader { name blit - fragment shaders/blit.vs - vertex shaders/blit.fs + + subshader + { + type vertex + add shaders/blit.vs + + uniform + { + type sampler2D + alias uTexMain + } + } + + subshader + { + type fragment + add shaders/blit_tex.fs + } } cvar @@ -232,17 +248,27 @@ add source/foundation/async.c event { - name TEST_HOOK + name ENGINE_INIT + prototype "void" } - event { - name WORLD_RENDER + name ENGINE_FIXED_UPDATE + prototype "void" } - - hook + event + { + name ENGINE_UPDATE + prototype "void" + } + event + { + name ENGINE_RENDER + prototype "void" + } + event { - event TEST_HOOK - function _run_on_hook + name ENGINE_UI + prototype "void" } } diff --git a/include/common_api.h b/include/common_api.h index a38dca2..2c3c7b7 100644 --- a/include/common_api.h +++ b/include/common_api.h @@ -169,6 +169,7 @@ enum stream_flag k_stream_procedural = 0x20, k_stream_stack = 0x40, k_stream_posix = 0x80, + k_stream_auto = 0x100, /* modes */ k_stream_write = 0x1, @@ -193,6 +194,7 @@ struct stream }; }; +void stream_open_auto( struct stream *stream, u32 flags ); void stream_open_stack( struct stream *stream, struct stack_allocator *stack, u32 flags ); void stream_open_buffer_write( struct stream *stream, void *buffer, u32 buffer_length, u32 flags ); void stream_open_buffer_read( struct stream *stream, const void *buffer, u32 buffer_length, u32 flags ); @@ -362,3 +364,8 @@ const c8 *directory_entry_name( struct directory *directory ); bool directory_next_entry( struct directory *directory ); enum directory_entry_type directory_entry_type( struct directory *directory ); void directory_close( struct directory *directory ); + +#define EVENT_CALL( NAME, ... ) \ + for( u32 ev_iter=0; _event_##NAME##_subscribers[ ev_iter ]; ev_iter ++ ) \ + _event_##NAME##_subscribers[ ev_iter ]( __VA_ARGS__ ); + diff --git a/include/engine_interface.h b/include/engine_interface.h index c0dd5bc..be2c03e 100644 --- a/include/engine_interface.h +++ b/include/engine_interface.h @@ -17,14 +17,6 @@ struct _engine } extern _engine; -IMPL void _engine_init(void); -IMPL void _engine_fixed_update(void); -IMPL void _engine_update(void); -IMPL void _engine_render(void); -IMPL void _engine_ui(void); - -API void _engine_something(void); - enum input_type { k_input_type_action, diff --git a/shaders/blit_tex.fs b/shaders/blit_tex.fs index 634e84f..0d39a1b 100644 --- a/shaders/blit_tex.fs +++ b/shaders/blit_tex.fs @@ -1,41 +1,7 @@ out vec4 FragColor; -uniform sampler2D uTexMain; - in vec2 aUv; -float kPi = 3.14159265358979; - -vec2 fisheye_distort(vec2 xy) -{ - float aperture = 1350.0; - float apertureHalf = 0.5 * aperture * (kPi / 180.0); - float maxFactor = sin(apertureHalf); - - vec2 uv; - float d = length(xy); - if(d < (2.0-maxFactor)) - { - d = length(xy * maxFactor); - float z = sqrt(1.0 - d * d); - float r = atan(d, z) / kPi; - float phi = atan(xy.y, xy.x); - - uv.x = r * cos(phi) + 0.5; - uv.y = r * sin(phi) + 0.5; - } - else - { - uv = 0.5*xy + 0.5; - } - - return uv; -} - - void main() { - vec2 vwarp = 2.0*aUv - 1.0; - vwarp = fisheye_distort( vwarp ); - FragColor = texture( uTexMain, aUv ); } diff --git a/source/engine/main.c b/source/engine/main.c index e7da0d3..8f4d938 100644 --- a/source/engine/main.c +++ b/source/engine/main.c @@ -7,6 +7,7 @@ // TODO: temp #include "console_core.h" +#include "generated/hooks.h" struct _engine _engine; @@ -53,7 +54,7 @@ i32 main( i32 argc, const c8 *argv[] ) //if( vg_long_opt( "no-steam", "Disable Steam integration (Good idea for pirating)" ) ) // _steam_api.disabled = 1; - _engine_init(); + EVENT_CALL( ENGINE_INIT ); _options_check_end(); ASSERT_CRITICAL( glfwInit() ); @@ -128,7 +129,7 @@ L_new_frame:; fixed_accumulator -= 1.0/60.0; fixed_time += _engine.time_delta; _engine.time = fixed_time; - _engine_fixed_update(); + EVENT_CALL( ENGINE_FIXED_UPDATE ); } else break; } @@ -137,12 +138,12 @@ L_new_frame:; _engine.time_fixed_extrapolate = fixed_accumulator / (1.0/60.0); /* normal update */ - _engine_update(); + EVENT_CALL( ENGINE_UPDATE ); glfwGetFramebufferSize( _engine.window_handle, &_engine.w, &_engine.h ); - _engine_render(); + EVENT_CALL( ENGINE_RENDER ); _engine_ui_pre_render(); - _engine_ui(); + EVENT_CALL( ENGINE_UI ); if( _engine_backend.console_open ) _engine_console_ui(); _engine_ui_post_render(); diff --git a/source/engine/shader.c b/source/engine/shader.c index d778c43..2d2b3b2 100644 --- a/source/engine/shader.c +++ b/source/engine/shader.c @@ -1,4 +1,7 @@ #include "opengl.h" +#include "generated/shaders.h" + +GLuint _uniform_locations[ k_shader_uniform_count ]; GLuint compile_opengl_subshader( GLint type, const c8 *src, bool critical, const c8 *debug_path ) { @@ -66,3 +69,27 @@ GLuint compile_opengl_shader( const c8 *vs, const c8 *fs ) glDeleteShader( frag ); return program; } + +struct shader +{ + const c8 *name; + u32 subshader_count, uniform_start, uniform_count; + + struct subshader + { + enum subshader_type + { + k_subshader_vertex, + k_subshader_fragment, + k_subshader_geometry + } + type; + u32 source_count; + const c8 **source_list; + const c8 *source_static; + const c8 *source_uniforms; + } + *subshaders; +}; + +#include "generated/shaders.c" diff --git a/source/foundation/logging.c b/source/foundation/logging.c index b3eee60..a90917d 100644 --- a/source/foundation/logging.c +++ b/source/foundation/logging.c @@ -36,6 +36,8 @@ void _log_add_listener( void (*fn)(const c8 *line, u32 length, u32 type), u32 fi static u32 _log_stream_passthrough( struct stream *stream, const void *buffer, u32 length ) { + // TODO: Allow colour codes into the line buffer, but those dont count towards line length. + // the AFTERWARDS, filter out the codes and send those to the listeners. for( u32 i=0; ioffset-line_start) < 20 ) string_append_c8( output, ' ' ); + while( (output->offset-line_start) < 30 ) string_append_c8( output, ' ' ); if( type == $error ) string_append( output, KRED "ERR|", 0 ); else if( type == $warning ) string_append( output, KYEL "WRN|", 0 ); else if( type == $ok ) string_append( output, KGRN "OK |", 0 ); diff --git a/source/foundation/stream.c b/source/foundation/stream.c index 1569695..b4c8d8a 100644 --- a/source/foundation/stream.c +++ b/source/foundation/stream.c @@ -17,6 +17,20 @@ void stream_open_stack( struct stream *stream, struct stack_allocator *stack, u3 } } +void stream_open_auto( struct stream *stream, u32 flags ) +{ + stream->flags = flags | k_stream_write | k_stream_auto; + stream->buffer_length = 256; + stream->buffer_write = _heap_allocate( 256 ); + stream->offset = 0; + + if( flags & k_stream_null_terminate ) + { + stream->buffer_length --; + ((u8 *)stream->buffer_write)[0] = 0; + } +} + static void stream_open_buffer_all( struct stream *stream, u32 buffer_length, u32 flags ) { stream->flags = flags | k_stream_buffer; @@ -57,7 +71,7 @@ bool stream_open_file( struct stream *stream, const c8 *path, u32 flags ) return 1; else { - $log( $error, {"Failure to open file stream "}, $errno() ); + $log( $error, {"Failure to open file stream '"}, {path}, {"' "}, $errno() ); return 0; } } @@ -142,6 +156,15 @@ u32 stream_write( struct stream *stream, const void *buffer, u32 length ) write_length = length; } + while( (stream->flags & k_stream_auto) && (write_length < length) ) + { + u32 new_size = stream->buffer_length + 2048; + u32 alloc_size = (stream->flags & k_stream_null_terminate)? new_size+1: new_size; + stream->buffer_write = _heap_reallocate( stream->buffer_write, alloc_size ); + stream->buffer_length = new_size; + write_length = stream_usable_length( stream, length ); + } + if( stream->flags & k_stream_posix ) { u64 l = fwrite( buffer, 1, write_length, stream->posix_stream ); diff --git a/source/foundation/string.c b/source/foundation/string.c index 256d601..9a9a063 100644 --- a/source/foundation/string.c +++ b/source/foundation/string.c @@ -3,7 +3,7 @@ const c8 *string_get( struct stream *string ) { - ASSERT_CRITICAL( string->flags & (k_stream_stack|k_stream_buffer) ); + ASSERT_CRITICAL( string->flags & (k_stream_stack|k_stream_buffer|k_stream_auto) ); ASSERT_CRITICAL( string->flags & k_stream_null_terminate ); return (const c8 *)string->buffer_write; } diff --git a/source/tools/metacompiler.c b/source/tools/metacompiler.c index f86c734..680c680 100644 --- a/source/tools/metacompiler.c +++ b/source/tools/metacompiler.c @@ -23,6 +23,22 @@ struct } static _threads; +struct hook_event +{ + struct stream alias, returns, proto; + struct stretchy_allocator users; +}; +struct hook_user +{ + struct stream function_name; +}; +struct +{ + bool using; + struct stretchy_allocator events; +} +static _hooks; + struct { bool using; @@ -31,6 +47,35 @@ struct } static _console; +enum subshader_type +{ + k_subshader_vertex, + k_subshader_fragment, + k_subshader_geometry +}; +struct shader +{ + struct stream name; + struct subshader + { + enum subshader_type type; + struct stream debug_source_list, static_source, uniform_source; + u32 debug_source_count; + } + subshaders[3]; + u32 subshader_count; + + u32 uniform_start, uniform_count; +}; +struct +{ + bool using; + struct stream shader_enum, uniform_enum, uniform_aliases, uniform_func_protos, uniform_funcs; + u32 uniform_count; + struct stretchy_allocator shaders; +} +static _shaders; + struct block_context { enum target_type @@ -41,7 +86,9 @@ struct block_context k_target_shader, k_target_cvar, k_target_ccmd, - k_target_thread + k_target_thread, + k_target_hook, + k_target_subshader } target; u32 feature_count; @@ -54,92 +101,254 @@ void _parse_kv_block( struct keyvalues *kvs, u32 block, struct block_context con const c8 *block_key = keyvalues_key( kvs, block, NULL ); if( block_key != NULL ) { - ASSERT_CRITICAL( context.target == k_target_main ); - if( compare_buffers( block_key, 0, "input_layer", 0 )) + if( context.target == k_target_shader ) + { + if( compare_buffers( block_key, 0, "subshader", 0 )) + { + context.target = k_target_subshader; + + struct shader *shader = stretchy_get( &_shaders.shaders, stretchy_count( &_shaders.shaders ) -1 ); + struct subshader *subshader = &shader->subshaders[ shader->subshader_count ++ ]; + + const c8 *type = keyvalues_read_string( kvs, block, "type", NULL ); + ASSERT_CRITICAL( type ); + + if( compare_buffers( type, 0, "vertex", 0 ) ) + subshader->type = k_subshader_vertex; + else if( compare_buffers( type, 0, "fragment", 0 ) ) + subshader->type = k_subshader_fragment; + else if( compare_buffers( type, 0, "geometry", 0 ) ) + subshader->type = k_subshader_geometry; + else + { + $log( $warning, {"Invalid subshader type '"}, {type}, {"'"} ); + return; + } + + subshader->debug_source_count = 0; + stream_open_auto( &subshader->debug_source_list, k_stream_null_terminate ); + stream_open_auto( &subshader->static_source, k_stream_null_terminate ); + stream_open_auto( &subshader->uniform_source, k_stream_null_terminate ); + } + else + { + $log( $warning, {"We don't have a compiler:shader definition for block '"}, {block_key}, {"'"} ); + return; + } + } + else if( context.target == k_target_subshader ) { - _input.using = 1; - context.target = k_target_input_layer; - const c8 *layer_name = keyvalues_read_string( kvs, block, "name", NULL ); - ASSERT_CRITICAL( layer_name ); + struct shader *shader = stretchy_get( &_shaders.shaders, stretchy_count( &_shaders.shaders ) -1 ); + struct subshader *subshader = &shader->subshaders[ shader->subshader_count -1 ]; - $v_string( &_input.layer_enums, {" k_input_layer_"}, {layer_name}, {",\n"} ); + if( compare_buffers( block_key, 0, "uniform", 0 )) + { + const c8 *alias = keyvalues_read_string( kvs, block, "alias", NULL ); + const c8 *type = keyvalues_read_string( kvs, block, "type", NULL ); + ASSERT_CRITICAL( type && alias ); + + struct glsl_trans + { + const c8 *type, *args, *call, *end; + } + type_list[] = + { + { "int", "i32 b", "glUniform1i", "b" }, + { "vec2", "v2f v", "glUniform2fv", "1,v" }, + { "vec3", "v3f v", "glUniform3fv", "1,v" }, + { "vec4", "v4f v", "glUniform4fv", "1,v" }, + { "bool", "i32 b", "glUniform1i", "b" }, + { "mat2", "m2x2f m", "glUniformMatrix2fv", "1,GL_FALSE,(f32*)m" }, + { "mat3", "m3x3f m", "glUniformMatrix3fv", "1,GL_FALSE,(f32*)m" }, + { "mat4", "m4x4f m", "glUniformMatrix4fv", "1,GL_FALSE,(f32*)m" }, + { "float", "f32 f", "glUniform1f", "f" }, + { "mat4x3", "m4x3f m", "glUniformMatrix4x3fv", "1,GL_FALSE,(f32*)m" }, + { "sampler2D", "i32 i", "glUniform1i", "i" }, + { "usampler3D", "i32 i", "glUniform1i", "i" }, + { "samplerCube", "i32 i", "glUniform1i", "i" }, + { "samplerBuffer","i32 i", "glUniform1i", "i" }, + }, + *trans = NULL; + + for( u32 i=0; iname)}, {"_"}, {alias}, {",\n"} ); + $v_string( &_shaders.uniform_aliases, {" [k_shader_"}, {string_get(&shader->name)}, {"_"}, {alias}, {"] = \""}, + {alias},{"\",\n"} ); + $v_string( &subshader->uniform_source, {"uniform "}, {type}, {" "}, {alias}, {"\\n"} ); + + $v_string( &_shaders.uniform_func_protos, {"void _shader"}, {string_get(&shader->name)}, {"_"}, {alias}, {"( "},{trans->args},{" );\n"} ); + $v_string( &_shaders.uniform_funcs, {"void _shader"}, {string_get(&shader->name)}, {"_"}, {alias}, {"( "},{trans->args},{" )"}, + {"{ "},{trans->call},{"( _uniform_locations["}, + {"k_shader_"}, {string_get(&shader->name)}, {"_"}, {alias}, + {"], "},{trans->end},{" ); }\n"}); + + shader->uniform_count ++; + _shaders.uniform_count ++; + } + else + { + $log( $warning, {"We don't have a compiler:subshader definition for block '"}, {block_key}, {"'"} ); + return; + } } - else if( compare_buffers( block_key, 0, "input", 0 )) + else { - _input.using = 1; - context.target = k_target_input; + ASSERT_CRITICAL( context.target == k_target_main ); + if( compare_buffers( block_key, 0, "input_layer", 0 )) + { + _input.using = 1; + context.target = k_target_input_layer; + const c8 *layer_name = keyvalues_read_string( kvs, block, "name", NULL ); + ASSERT_CRITICAL( layer_name ); + + $v_string( &_input.layer_enums, {" k_input_layer_"}, {layer_name}, {",\n"} ); + } + else if( compare_buffers( block_key, 0, "input", 0 )) + { + _input.using = 1; + context.target = k_target_input; - const c8 *name = keyvalues_read_string( kvs, block, "name", NULL ); - ASSERT_CRITICAL( name ); + const c8 *name = keyvalues_read_string( kvs, block, "name", NULL ); + ASSERT_CRITICAL( name ); - const c8 *type = keyvalues_read_string( kvs, block, "type", NULL ); - ASSERT_CRITICAL( type ); + const c8 *type = keyvalues_read_string( kvs, block, "type", NULL ); + ASSERT_CRITICAL( type ); - const c8 *layer_mask = keyvalues_read_string( kvs, block, "layer_mask", NULL ); - - $v_string( &_input.input_enums, {" k_input_"},{type},{"_"}, {name}, {",\n"} ); - $v_string( &_input.input_structures, {" [k_input_"},{type},{"_"},{name},{"]=\n {\n"} ); - $v_string( &_input.input_structures, {" .name = \""},{name},{"\",\n"} ); - $v_string( &_input.input_structures, {" .type = k_input_type_"},{type},{",\n"} ); + const c8 *layer_mask = keyvalues_read_string( kvs, block, "layer_mask", NULL ); + + $v_string( &_input.input_enums, {" k_input_"},{type},{"_"}, {name}, {",\n"} ); + $v_string( &_input.input_structures, {" [k_input_"},{type},{"_"},{name},{"]=\n {\n"} ); + $v_string( &_input.input_structures, {" .name = \""},{name},{"\",\n"} ); + $v_string( &_input.input_structures, {" .type = k_input_type_"},{type},{",\n"} ); - if( layer_mask ) - $v_string( &_input.input_structures, {" .layer_mask = 1<subshader_count = 0; + shader->uniform_start = _shaders.uniform_count; + shader->uniform_count = 0; + + stream_open_auto( &shader->name, k_stream_null_terminate ); + $v_string( &shader->name, {keyvalues_read_string( kvs, block, "name", NULL )} ); + $v_string( &_shaders.shader_enum, {" k_shader_"}, {string_get(&shader->name)}, {",\n"} ); + } + else if( compare_buffers( block_key, 0, "thread", 0 )) + { + _threads.using = 1; + context.target = k_target_thread; + const c8 *name = keyvalues_read_string( kvs, block, "name", NULL ); + ASSERT_CRITICAL( name ); - $v_string( &_threads.enums, {" k_thread_"},{name}, {",\n"} ); - $v_string( &_threads.structures, {" [k_thread_"},{name},{"]=\n {\n"} ); - $v_string( &_threads.structures, {" .name = \""}, {name}, {"\",\n"} ); + $v_string( &_threads.enums, {" k_thread_"},{name}, {",\n"} ); + $v_string( &_threads.structures, {" [k_thread_"},{name},{"]=\n {\n"} ); + $v_string( &_threads.structures, {" .name = \""}, {name}, {"\",\n"} ); - u32 queue_size_m = 0; - if( keyvalues_read_u32s( kvs, block, "queue_size_m", NULL, &queue_size_m, 1 ) ) - $v_string( &_threads.structures, {" .queue_size_m = "}, $unsigned(queue_size_m), {",\n"} ); + u32 queue_size_m = 0; + if( keyvalues_read_u32s( kvs, block, "queue_size_m", NULL, &queue_size_m, 1 ) ) + $v_string( &_threads.structures, {" .queue_size_m = "}, $unsigned(queue_size_m), {",\n"} ); - $v_string( &_threads.structures, {" },\n"} ); - } - else - { - $log( $warning, {"We don't have a compiler definition for block '"}, {block_key}, {"'"} ); - return; + $v_string( &_threads.structures, {" },\n"} ); + } + else if( compare_buffers( block_key, 0, "event", 0 )) + { + _hooks.using = 1; + context.target = k_target_hook; + const c8 *name = keyvalues_read_string( kvs, block, "name", NULL ); + const c8 *prototype = keyvalues_read_string( kvs, block, "prototype", NULL ); + const c8 *returns = keyvalues_read_string( kvs, block, "returns", "void" ); + ASSERT_CRITICAL( name && prototype && returns ); + + struct hook_event *event = stretchy_append( &_hooks.events ); + + stream_open_auto( &event->alias, k_stream_null_terminate ); + $v_string( &event->alias, {name} ); + stream_open_auto( &event->returns, k_stream_null_terminate ); + $v_string( &event->returns, {returns} ); + stream_open_auto( &event->proto, k_stream_null_terminate ); + $v_string( &event->proto, {prototype} ); + + stretchy_init( &event->users, sizeof( struct hook_user ) ); + } + else if( compare_buffers( block_key, 0, "hook", 0 )) + { + _hooks.using = 1; + const c8 *event_alias = keyvalues_read_string( kvs, block, "event", NULL ); + const c8 *function = keyvalues_read_string( kvs, block, "function", NULL ); + + ASSERT_CRITICAL( event_alias && function ); + + bool found = 0; + + for( u32 i=0; ialias ), 0, event_alias, 0 ) ) + { + struct hook_user *user = stretchy_append( &event->users ); + stream_open_auto( &user->function_name, k_stream_null_terminate ); + $v_string( &user->function_name, {function} ); + found = 1; + break; + } + } + + if( !found ) + { + $log( $fatal, {"We don't have an event registered called '"}, {event_alias}, {"'"} ); + _fatal_exit(); + } + } + else + { + $log( $warning, {"We don't have a compiler definition for block '"}, {block_key}, {"'"} ); + return; + } } } @@ -207,6 +416,39 @@ void _parse_kv_block( struct keyvalues *kvs, u32 block, struct block_context con if( compare_buffers( key, 0, "define", 0 ) ) $v_string( &_metacompiler.include_path_list, {" -D"}, {value}, {" \\\n"} ); } + else if( context.target == k_target_subshader ) + { + struct shader *shader = stretchy_get( &_shaders.shaders, stretchy_count( &_shaders.shaders ) -1 ); + struct subshader *subshader = &shader->subshaders[ shader->subshader_count -1 ]; + + if( compare_buffers( key, 0, "add", 0 ) ) + { + u32 temp_frame = _start_temporary_frame(); + { + struct stream path_string; + stream_open_stack( &path_string, _temporary_stack_allocator(), k_stream_null_terminate ); + $v_string( &path_string, {context.folder}, {"/"}, {value} ); + + struct stream source; + ASSERT_CRITICAL( stream_open_file( &source, string_get( &path_string ), k_stream_read ) ); + + u32 block_size = BYTES_KB(128); + c8 *temp = _temporary_allocate( block_size, 4 ); + while(1) + { + u32 l = stream_read( &source, temp, block_size ); + $v_string( &subshader->static_source, {temp, .length = l} ); + if( l != block_size ) + break; + } + + stream_close( &source ); + $v_string( &subshader->debug_source_list, {" \""}, {string_get(&path_string)}, {"\",\n"} ); + subshader->debug_source_count ++; + } + _end_temporary_frame( temp_frame ); + } + } kv = keyvalues_get_next( kvs, kv ); } @@ -355,24 +597,27 @@ i32 _terminal_main(void) { buffer_copy( "project", 0, _metacompiler.project_name, sizeof(_metacompiler.project_name) ); - u32 size = BYTES_MB(8), - options = k_stream_null_terminate|k_stream_overflow_error; - stream_open_buffer_write( &_metacompiler.source_list, _heap_allocate(size), size, options ); - stream_open_buffer_write( &_metacompiler.include_path_list, _heap_allocate(size), size, options ); - stream_open_buffer_write( &_metacompiler.define_list, _heap_allocate(size), size, options ); - stream_open_buffer_write( &_metacompiler.configuration, _heap_allocate(size), size, options ); - - stream_open_buffer_write( &_input.layer_enums, _heap_allocate(size), size, options ); - stream_open_buffer_write( &_input.input_enums, _heap_allocate(size), size, options ); - stream_open_buffer_write( &_input.input_structures, _heap_allocate(size), size, options ); - - stream_open_buffer_write( &_console.cvar_header, _heap_allocate(size), size, options ); - stream_open_buffer_write( &_console.cvar_definitions, _heap_allocate(size), size, options ); - stream_open_buffer_write( &_console.command_definitions, _heap_allocate(size), size, options ); - stream_open_buffer_write( &_console.command_prototypes, _heap_allocate(size), size, options ); - - stream_open_buffer_write( &_threads.enums, _heap_allocate(size), size, options ); - stream_open_buffer_write( &_threads.structures, _heap_allocate(size), size, options ); + u32 options = k_stream_null_terminate; + stream_open_auto( &_metacompiler.source_list, options ); + stream_open_auto( &_metacompiler.include_path_list, options ); + stream_open_auto( &_metacompiler.define_list, options ); + stream_open_auto( &_metacompiler.configuration, options ); + stream_open_auto( &_input.layer_enums, options ); + stream_open_auto( &_input.input_enums, options ); + stream_open_auto( &_input.input_structures, options ); + stream_open_auto( &_console.cvar_header, options ); + stream_open_auto( &_console.cvar_definitions, options ); + stream_open_auto( &_console.command_definitions, options ); + stream_open_auto( &_console.command_prototypes, options ); + stream_open_auto( &_threads.enums, options ); + stream_open_auto( &_threads.structures, options ); + stream_open_auto( &_shaders.shader_enum, options ); + stream_open_auto( &_shaders.uniform_enum, options ); + stream_open_auto( &_shaders.uniform_aliases, options ); + stream_open_auto( &_shaders.uniform_funcs, options ); + stream_open_auto( &_shaders.uniform_func_protos, options ); + stretchy_init( &_hooks.events, sizeof( struct hook_event ) ); + stretchy_init( &_shaders.shaders, sizeof( struct shader ) ); if( platform == k_platform_linux ) _metacompiler.enabled_features[0] = "linux"; if( platform == k_platform_windows ) _metacompiler.enabled_features[0] = "windows"; @@ -382,7 +627,8 @@ i32 _terminal_main(void) _append_kv_list( target_file_path, context ); system_call( "mkdir -p generated" ); - + + $log( $info, {"Generating input header"} ); if( _input.using ) { struct stream input_header, input_source; @@ -397,6 +643,7 @@ i32 _terminal_main(void) stream_close( &input_source ); } + $log( $info, {"Generating threads header"} ); if( _threads.using ) { struct stream thread_header, thread_source; @@ -412,6 +659,7 @@ i32 _terminal_main(void) stream_close( &thread_source ); } + $log( $info, {"Generating console header"} ); if( _console.using ) { struct stream console_header, console_source; @@ -427,6 +675,105 @@ i32 _terminal_main(void) stream_close( &console_source ); } + $log( $info, {"Generating hooks header"} ); + if( _hooks.using ) + { + struct stream header, source; + ASSERT_CRITICAL( stream_open_file( &header, "generated/hooks.h", k_stream_write ) ); + ASSERT_CRITICAL( stream_open_file( &source, "generated/hooks.c", k_stream_write ) ); + + for( u32 i=0; ireturns ), + *alias = string_get( &event->alias ), + *prototype = string_get( &event->proto ); + + $v_string( &header, {"extern "}, {returns}, {" (*_event_"}, {alias}, {"_subscribers[])( "}, {prototype}, {" );\n"} ); + + for( u32 j=0; jusers ); j ++ ) + { + struct hook_user *user = stretchy_get( &event->users, j ); + $v_string( &source, {returns}, {" "}, {string_get(&user->function_name)}, {"( "}, {prototype}, {" );\n"} ); + } + $v_string( &source, {"\n"} ); + + $v_string( &source, {returns}, {" (*_event_"}, {alias}, {"_subscribers[])( "}, {prototype}, {" ) = \n{\n"} ); + for( u32 j=0; jusers ); j ++ ) + { + struct hook_user *user = stretchy_get( &event->users, j ); + $v_string( &source, {" "}, {string_get(&user->function_name)}, {",\n"} ); + } + $v_string( &source, {" NULL\n};\n\n"} ); + } + + stream_close( &source ); + stream_close( &header ); + + $v_string( &_metacompiler.source_list, {" generated/hooks.c \\\n"} ); + } + + $log( $info, {"Generating shader header"} ); + if( _shaders.using ) + { + struct stream header, source; + ASSERT_CRITICAL( stream_open_file( &header, "generated/shaders.h", k_stream_write ) ); + ASSERT_CRITICAL( stream_open_file( &source, "generated/shaders.c", k_stream_write ) ); + + $v_string( &header, {"enum shader_id\n{\n"}, {string_get( &_shaders.shader_enum )}, {" k_shader_count\n};\n"} ); + $v_string( &header, {"enum shader_uniform_id\n{\n"}, {string_get( &_shaders.uniform_enum )}, {" k_shader_uniform_count\n};\n"} ); + $v_string( &header, {string_get( &_shaders.uniform_func_protos )} ); + + $v_string( &source, {"const c8 *_uniform_aliases[] = \n{\n"}, {string_get( &_shaders.uniform_aliases )}, {"};\n"} ); + + $v_string( &source, {"struct shader _shader_definitions[] = {\n"} ); + for( u32 i=0; iname )}, {"] = \n {\n"} ); + $v_string( &source, {" .name = \""}, {string_get( &shader->name )}, {"\",\n"} ); + $v_string( &source, {" .subshader_count = "}, $unsigned( shader->subshader_count ), {",\n"} ); + $v_string( &source, {" .uniform_start = "}, $unsigned( shader->uniform_start ), {",\n"} ); + $v_string( &source, {" .uniform_count = "}, $unsigned( shader->uniform_count ), {",\n"} ); + $v_string( &source, {" .subshaders = (struct subshader[])\n {\n"} ); + + for( u32 j=0; jsubshader_count; j ++ ) + { + struct subshader *subshader = &shader->subshaders[ j ]; + $v_string( &source, {" {\n"} ); + $v_string( &source, {" .type = "}, + { (const c8 *[]){ [k_subshader_vertex] = "k_subshader_vertex", + [k_subshader_fragment] = "k_subshader_fragment", + [k_subshader_geometry] = "k_subshader_geometry" }[ subshader->type ] }, {",\n"} ); + $v_string( &source, {" .source_count = "}, $unsigned( subshader->debug_source_count ), {",\n"} ); + $v_string( &source, {" .source_list = (const c8 *[])\n"} ); + $v_string( &source, {" {\n"} ); + $v_string( &source, {string_get( &subshader->debug_source_list )} ); + $v_string( &source, {" },\n"} ); + $v_string( &source, {" .source_static = \""} ); + + for( u32 k=0; kstatic_source.offset; k ++ ) + { + c8 c = subshader->static_source.buffer_read[ k ]; + if( c == '\n' ) $v_string( &source, {"\\n"} ); + else string_append_c8( &source, c ); + } + $v_string( &source, {"\",\n"} ); + $v_string( &source, {" .source_uniforms = \""}, {string_get( &subshader->uniform_source )}, {"\",\n"} ); + $v_string( &source, {" },\n"} ); + } + + $v_string( &source, {" },\n"} ); + $v_string( &source, {" },\n"} ); + } + $v_string( &source, {"};\n"} ); + $v_string( &source, {string_get( &_shaders.uniform_funcs )} ); + + stream_close( &source ); + stream_close( &header ); + } + /* main */ u32 temp_frame = _start_temporary_frame(); { -- 2.25.1