SDL_SignalCondition( queue->work_signal );
}
+void _task_queue_stop_normal( enum thread_id thread )
+{
+ struct task_queue *queue = _get_thread_task_queue( thread );
+ SDL_LockMutex( queue->lock );
+ queue->count ++;
+ SDL_UnlockMutex( queue->lock );
+ SDL_SignalCondition( queue->work_signal );
+}
+
b8 _task_queue_process( b8 blocking )
{
struct task_queue *queue = _get_thread_task_queue( _get_thread_id() );
SDL_SignalCondition( queue->blocking_signal );
return 1;
}
- else
- return 0;
+ else return 0;
}
ASSERT_CRITICAL( cnd_signal( &queue->work_signal ) == thrd_success );
}
+void _task_queue_stop_normal( enum thread_id thread )
+{
+ struct task_queue *queue = _get_thread_task_queue( thread );
+ ASSERT_CRITICAL( mtx_lock( &queue->lock ) == thrd_success );
+ queue->count ++;
+ ASSERT_CRITICAL( mtx_unlock( &queue->lock ) == thrd_success );
+ ASSERT_CRITICAL( cnd_signal( &queue->work_signal ) == thrd_success );
+}
+
bool _task_queue_process( bool blocking )
{
struct task_queue *queue = _get_thread_task_queue( _get_thread_id() );
queue_pop( &queue->queue );
queue->count --;
ASSERT_CRITICAL( mtx_unlock( &queue->lock ) == thrd_success );
-
ASSERT_CRITICAL( cnd_signal( &queue->blocking_signal ) == thrd_success );
return 1;
}
- else
- return 0;
+ else return 1;
}
struct task *_task_new( enum thread_id thread, u32 buffer_size, u32 async_flags, const c8 *debug_info );
void task_send( struct task *task, void (*fn)( struct task *task ) );
+void _task_queue_stop_normal( enum thread_id thread );
void *task_buffer( struct task *task );
u32 task_buffer_size( struct task *task );
hook
{
event START
- function "_shaders_compile"
+ function "_shader_init"
+}
+ccmd
+{
+ name reload_shaders
+ function _shader_recompile_ccmd
+ description "Recompile shaders (DEVELOPER ONLY!)"
}
-
-
-
function _dsp_init
}
-
add model.c
add metascene.c
add array_file.c
}
-i32 async_thread( void *_ )
+i32 _async_thread( void *_ )
{
_set_thread_id( k_thread_async );
while( _task_queue_process( 1 ) ) {}
mt_random_seed( &_engine.random, 887765 );
EVENT_CALL( START );
- SDL_CreateThread( async_thread, "ASync thread", NULL );
- ASSERT_CRITICAL( async_thread );
+ SDL_Thread *async_thread = SDL_CreateThread( _async_thread, "ASync thread", NULL );
L_new_frame:;
f64 now = (f64)SDL_GetTicksNS() / 1000000000.0;
if( e.type == SDL_EVENT_QUIT )
{
SDL_DestroyWindow( _engine.window_handle );
+ EVENT_CALL( END );
+ _task_queue_stop_normal( k_thread_async );
+ SDL_WaitThread( async_thread, NULL );
SDL_Quit();
_normal_exit();
}
#include "foundation.h"
#include "vg_opengl.h"
#include "vg_shader.h"
+#include "console_system.h"
GLuint compile_opengl_subshader( GLint type, const c8 *sources[], u32 source_count, b8 critical, const c8 *name )
{
#include "generated/shaders.c"
-void _shaders_compile(void)
+static void _shaders_compile( b8 recompile )
{
for( u32 i=0; i<k_shader_count; i ++ )
{
const c8 *sources[32] = { "#version 330 core\n", NULL };
u32 source_count = 1;
sources[ source_count ++ ] = subshader->source_uniforms;
- sources[ source_count ++ ] = subshader->source_static;
+
+ u32 temp_frame = _start_temporary_frame();
+ if( recompile )
+ {
+ for( u32 k=0; k<subshader->source_count; k ++ )
+ {
+ struct stream file;
+ if( stream_open_file( &file, subshader->source_list[k], k_stream_read ) )
+ {
+ u32 length;
+ sources[ source_count ++ ] = stream_read_all( &file, _temporary_stack_allocator(), 4, &length );
+ stream_close( &file );
+ }
+ else
+ {
+ _end_temporary_frame( temp_frame );
+ goto fail_shader;
+ }
+ }
+ }
+ else
+ sources[ source_count ++ ] = subshader->source_static;
ASSERT_CRITICAL( subshader->type != k_subshader_geometry );
sub_programs[j] = compile_opengl_subshader(
(subshader->type == k_subshader_vertex? GL_VERTEX_SHADER: GL_FRAGMENT_SHADER),
- sources, source_count, 1, shader->name );
- glAttachShader( new_program, sub_programs[j] );
- }
+ sources, source_count, recompile==0, shader->name );
+ _end_temporary_frame( temp_frame );
- link_opengl_program( new_program, 1 );
- _shader_programs[i] = new_program;
-
- for( u32 j=0; j<shader->subshader_count; j ++ )
- glDeleteShader( sub_programs[j] );
+ if( sub_programs[j] )
+ glAttachShader( new_program, sub_programs[j] );
+ else
+ goto fail_shader;
+ }
- for( u32 j=0; j<shader->uniform_count; j ++ )
+ if( link_opengl_program( new_program, recompile==0 ) )
{
- u32 index = shader->uniform_start+j;
- _uniform_locations[ index ] = glGetUniformLocation( new_program, _uniform_aliases[ index ] );
+ if( recompile )
+ glDeleteProgram( _shader_programs[i] );
+ _shader_programs[i] = new_program;
+ for( u32 j=0; j<shader->uniform_count; j ++ )
+ {
+ u32 index = shader->uniform_start+j;
+ _uniform_locations[ index ] = glGetUniformLocation( new_program, _uniform_aliases[ index ] );
+ }
+ $log( $ok, {"Shader complete: "}, {shader->name} );
+ goto cleanup;
}
+
+fail_shader:
+ $log( $error, {"Shader failed: "}, {shader->name} );
+ glDeleteProgram( new_program );
+cleanup:
+ for( u32 j=0; j<shader->subshader_count; j ++ )
+ if( sub_programs[j] )
+ glDeleteShader( sub_programs[j] );
}
}
+void _shader_init(void)
+{
+ _shaders_compile(0);
+}
+
void _shader_bind( enum shader_id id )
{
glUseProgram( _shader_programs[ id ] );
}
+
+i32 _shader_recompile_ccmd( struct console_arguments *args )
+{
+ _shaders_compile(1);
+ return 0;
+}
name START
prototype "void"
}
+event
+{
+ name END
+ prototype "void"
+}
add options.c
add logging.c
void *stream_read_all( struct stream *stream, struct stack_allocator *stack, u32 alignment, u32 *length )
{
- stack_allocate( stack, 0, alignment, "Alignment" );
- i32 space = ((i32)stack->capacity - (i32)alignment) - (i32)stack->offset;
- void *buffer = stack_allocate( stack, space, alignment, "Remaining buffer" );
- u32 l = stream_read( stream, buffer, space );
- stack_extend_last( stack, buffer, -(i32)( space - l ) );
+ void *buffer = stack_allocate( stack, 1, alignment, "Stream data" );
+ u32 l = 0;
+ while( stream_read( stream, buffer+l, 1 ) )
+ {
+ stack_extend_last( stack, buffer, 1 );
+ l ++;
+ }
+ ((u8 *)buffer)[l] = 0x00;
*length = l;
return buffer;
}
{
VG_PRE_MAIN;
EVENT_CALL( START );
+ _normal_exit();
}
{
ASSERT_CRITICAL( source_count < ARRAY_COUNT( sources ) );
- /* FIXME: EXPAND PATH TO FULL PATH LIKE SOURCE ADDS */
const c8 *path = keyvalues_value( &_assembly, source_it, NULL );
- $v_string( &C, {" \""}, {path}, {"\",\n"} );
+ u32 context_block = _assembly_kv_file_context( source_it );
+ $v_string( &C, {" \""}, {keyvalues_read_string( &_assembly, context_block, "folder", NULL )},
+ {"/"}, {path}, {"\",\n"} );
+
sources[ source_count ++ ] = source_it;
}