From: hgn Date: Fri, 6 Sep 2024 02:02:08 +0000 (+0100) Subject: adjust fatal errors X-Git-Url: https://harrygodden.com/git/?a=commitdiff_plain;h=f45e6edd22f03528d9f0351761460ddc00b7908a;p=vg.git adjust fatal errors --- diff --git a/vg_async.c b/vg_async.c index 7916282..9a3da53 100644 --- a/vg_async.c +++ b/vg_async.c @@ -18,16 +18,19 @@ vg_async_item *vg_async_alloc( u32 size ) remaining = vg_linear_remaining( vg_async.buffer ), capacity = vg_linear_get_capacity( vg_async.buffer ); - if( total_allocation > capacity ){ + if( total_allocation > capacity ) + { SDL_AtomicUnlock( &vg_async.sl_index ); - vg_error( "Requested: %umb. Buffer size: %umb\n", + vg_fatal_condition(); + vg_info( "async alloc invalid size\n" ); + vg_info( "Requested: %umb. Buffer size: %umb\n", (total_allocation/1024)/1024, (capacity/1024)/1024 ); - - vg_fatal_error( "async alloc invalid size\n" ); + vg_fatal_exit(); } - if( total_allocation > remaining ){ + if( total_allocation > remaining ) + { SDL_AtomicUnlock( &vg_async.sl_index ); SDL_SemWait( vg_async.sem_wait_for_flush ); SDL_AtomicLock( &vg_async.sl_index ); @@ -65,14 +68,14 @@ vg_async_item *vg_async_alloc( u32 size ) */ void vg_async_stall(void) { - vg_assert_thread(k_thread_purpose_loader); + VG_ASSERT( vg_thread_purpose() == k_thread_purpose_loader ); SDL_SemWait( vg_async.sem_wait_for_flush ); } void vg_async_dispatch( vg_async_item *item, void (*runner)( void *payload, u32 size ) ) { - vg_assert_thread(k_thread_purpose_loader); + VG_ASSERT( vg_thread_purpose() == k_thread_purpose_loader ); if( SDL_SemValue(vg_async.sem_wait_for_flush) ) SDL_SemWait(vg_async.sem_wait_for_flush); @@ -84,7 +87,7 @@ void vg_async_dispatch( vg_async_item *item, void vg_async_call( void (*runner)( void *payload, u32 size ), void *payload, u32 size ) { - vg_assert_thread(k_thread_purpose_loader); + VG_ASSERT( vg_thread_purpose() == k_thread_purpose_loader ); vg_async_item *call = vg_async_alloc(0); call->payload = payload; call->size = size; diff --git a/vg_audio.c b/vg_audio.c index 99b4382..e7bc7e5 100644 --- a/vg_audio.c +++ b/vg_audio.c @@ -631,22 +631,22 @@ static void audio_channel_mix( audio_channel *ch, float *buffer ) if( !vg_validf( framevol_l ) || !vg_validf( framevol_r ) || - !vg_validf( frame_samplerate ) ){ - vg_fatal_error( "Invalid sampling conditions.\n" - "This crash is to protect your ears.\n" - " channel: %p (%s)\n" - " sample_rate: %f\n" - " volume: L%f R%f\n" - " listener: %.2f %.2f %.2f [%.2f %.2f %.2f]\n", - ch, ch->name, frame_samplerate, - framevol_l, framevol_r, - vg_audio.internal_listener_pos[0], - vg_audio.internal_listener_pos[1], - vg_audio.internal_listener_pos[2], - vg_audio.internal_listener_ears[0], - vg_audio.internal_listener_ears[1], - vg_audio.internal_listener_ears[2] - ); + !vg_validf( frame_samplerate ) ) + { + vg_fatal_condition(); + vg_info( "Invalid sampling conditions.\n" + "This crash is to protect your ears.\n" ); + vg_info( " channel: %p (%s)\n", ch, ch->name ); + vg_info( " sample_rate: %f\n", frame_samplerate ); + vg_info( " volume: L%f R%f\n", framevol_l, framevol_r ); + vg_info( " listener: %.2f %.2f %.2f [%.2f %.2f %.2f]\n", + vg_audio.internal_listener_pos[0], + vg_audio.internal_listener_pos[1], + vg_audio.internal_listener_pos[2], + vg_audio.internal_listener_ears[0], + vg_audio.internal_listener_ears[1], + vg_audio.internal_listener_ears[2] ); + vg_fatal_exit(); } } @@ -983,9 +983,11 @@ void audio_clip_load( audio_clip *clip, void *lin_alloc ) * NULL when we get the clip */ - if( format == k_audio_format_vorbis ){ - if( !clip->path ){ - vg_fatal_error( "No path specified, embeded vorbis unsupported" ); + if( format == k_audio_format_vorbis ) + { + if( !clip->path ) + { + vg_error( "No path specified, embeded vorbis unsupported\n" ); } audio_lock(); @@ -993,17 +995,22 @@ void audio_clip_load( audio_clip *clip, void *lin_alloc ) audio_unlock(); if( !clip->data ) - vg_fatal_error( "Audio failed to load" ); + { + vg_error( "Audio failed to load\n" ); + } float mb = (float)(clip->size) / (1024.0f*1024.0f); vg_info( "Loaded audio clip '%s' (%.1fmb)\n", clip->path, mb ); } - else if( format == k_audio_format_stereo ){ - vg_fatal_error( "Unsupported format (Stereo uncompressed)" ); + else if( format == k_audio_format_stereo ) + { + vg_error( "Unsupported format (Stereo uncompressed)\n" ); } - else if( format == k_audio_format_bird ){ - if( !clip->data ){ - vg_fatal_error( "No data, external birdsynth unsupported" ); + else if( format == k_audio_format_bird ) + { + if( !clip->data ) + { + vg_error( "No data, external birdsynth unsupported\n" ); } u32 total_size = clip->size + sizeof(struct synth_bird); @@ -1011,7 +1018,9 @@ void audio_clip_load( audio_clip *clip, void *lin_alloc ) total_size = vg_align8( total_size ); if( total_size > AUDIO_DECODE_SIZE ) - vg_fatal_error( "Bird coding too long\n" ); + { + vg_error( "Bird coding too long, and exceeds maximum decode size\n" ); + } struct synth_bird *bird = vg_linear_alloc( lin_alloc, total_size ); memcpy( &bird->settings, clip->data, clip->size ); @@ -1021,9 +1030,11 @@ void audio_clip_load( audio_clip *clip, void *lin_alloc ) vg_info( "Loaded bird synthesis pattern (%u bytes)\n", total_size ); } - else{ - if( !clip->path ){ - vg_fatal_error( "No path specified, embeded mono unsupported" ); + else + { + if( !clip->path ) + { + vg_error( "No path specified, embeded mono unsupported\n" ); } vg_linear_clear( vg_mem.scratch ); @@ -1040,10 +1051,13 @@ void audio_clip_load( audio_clip *clip, void *lin_alloc ) stb_vorbis *decoder = stb_vorbis_open_memory( filedata, fsize, &err, &alloc ); - if( !decoder ){ - vg_error( "stb_vorbis_open_memory failed on '%s' (%d)\n", + if( !decoder ) + { + vg_fatal_condition(); + vg_info( "Vorbis decode error\n" ); + vg_info( "stb_vorbis_open_memory failed on '%s' (%d)\n", clip->path, err ); - vg_fatal_error( "Vorbis decode error" ); + vg_fatal_exit(); } /* only mono is supported in uncompressed */ @@ -1059,13 +1073,9 @@ void audio_clip_load( audio_clip *clip, void *lin_alloc ) decoder, clip->data, length_samples ); if( read_samples != length_samples ) - vg_fatal_error( "Decode error" ); - -#if 0 - float mb = (float)(data_size) / (1024.0f*1024.0f); - vg_info( "Loaded audio clip '%s' (%.1fmb) %u samples\n", clip->path, mb, - length_samples ); -#endif + { + vg_error( "Decode error, read_samples did not match length_samples\n" ); + } } } @@ -1081,6 +1091,7 @@ static void audio_require_clip_loaded( audio_clip *clip ) return; audio_unlock(); + vg_fatal_error( "Must load audio clip before playing! \n" ); } diff --git a/vg_audio_dsp.c b/vg_audio_dsp.c index 3714e32..e362b3e 100644 --- a/vg_audio_dsp.c +++ b/vg_audio_dsp.c @@ -9,7 +9,10 @@ float *dsp_allocate( u32 samples ) samples = vg_align4( samples ); if( vg_dsp.allocations + samples > (1024*1024)/4 ) - vg_fatal_error( "too much dsp" ); + { + vg_fatal_error( "Ran out of memory in the DSP buffer\n" + " Request was %u samples\n", samples ); + } float *buf = &vg_dsp.buffer[ vg_dsp.allocations ]; vg_dsp.allocations += samples; diff --git a/vg_build.h b/vg_build.h index 5fce6f0..9a1d861 100644 --- a/vg_build.h +++ b/vg_build.h @@ -224,14 +224,26 @@ vg_compiler_run( struct vg_project *project, { /* check for problems in configuration */ if( env->libc != k_libc_version_native ) + { if( env->compiler != k_compiler_zigcc ) - vg_fatal_error( + { + vg_fatal_condition(); + vg_info( "Cannot specify libc version using the '%s' compiler.\n", compiler_names[ env->compiler ] ); + vg_fatal_exit(); + } + } if( env->compiler == k_compiler_clang ) + { if( env->platform != k_platform_linux ) - vg_fatal_error( "Cannot compile for '%s' using the '%s' compiler;" ); + { + vg_fatal_condition(); + vg_info( "Cannot compile for '%s' using the '%s' compiler;" ); + vg_fatal_exit(); + } + } vg_str cmd = {0}; vg_strcat( &cmd, "ccache " ); @@ -509,7 +521,12 @@ vg_make_app( struct vg_project *proj, appname, k_obj_type_exe ); } else - vg_fatal_error( "Programming error" ); + { + vg_fatal_condition(); + vg_info( "No compile procedure set for platform '%s'\n", + platform_names[env->platform] ); + vg_fatal_exit(); + } return (struct compile_result){}; } diff --git a/vg_build_utils_shader.h b/vg_build_utils_shader.h index 0bbb816..235c67c 100644 --- a/vg_build_utils_shader.h +++ b/vg_build_utils_shader.h @@ -187,11 +187,7 @@ int vg_build_shader( char *src_vert, /* path/to/vert.vs */ FILE *header = fopen( path_header, "w" ); if( !header ) - { - fprintf(stderr, "Could not open '%s'\n", path_header ); - vg_fatal_error( "IO error" ); - return 0; - } + vg_fatal_error( "Could not open '%s'\n", path_header ); fprintf( header, "#pragma once\n" ); fprintf( header, "#include \"vg/vg_engine.h\"\n" ); @@ -206,7 +202,6 @@ int vg_build_shader( char *src_vert, /* path/to/vert.vs */ { fclose( header ); vg_fatal_error( "Failed to assemble vertex source code" ); - return 0; } vg_strcatf( c_body, "\n .fs = \n" ); @@ -214,7 +209,6 @@ int vg_build_shader( char *src_vert, /* path/to/vert.vs */ { fclose( header ); vg_fatal_error( "Failed to assemble fragment source code" ); - return 0; } vg_strcatf( c_body, "\n};\n\n" ); @@ -254,7 +248,7 @@ int vg_build_shader( char *src_vert, /* path/to/vert.vs */ if( uf->array ) continue; - for( int j=0; jdepth+1 >= vg_list_size(it->stack) ){ + if( it->depth+1 >= VG_ARRAY_LEN(it->stack) ){ vg_error( "Maximum stack reached!\n" ); return 0; } diff --git a/vg_console.c b/vg_console.c index 0f7387d..00d8e5f 100644 --- a/vg_console.c +++ b/vg_console.c @@ -10,11 +10,8 @@ struct vg_console vg_console; void vg_console_reg_var( const char *alias, void *ptr, enum vg_var_dtype type, u32 flags ) { - if( vg_thread_purpose() == k_thread_purpose_main ) - vg_fatal_error( "FIXME: Cannot register VAR from main thread" ); - - if( vg_console.var_count > vg_list_size(vg_console.vars) ) - vg_fatal_error( "Too many vars registered" ); + VG_ASSERT( vg_thread_purpose() != k_thread_purpose_main ); + VG_ASSERT( vg_console.var_count < VG_ARRAY_LEN(vg_console.vars) ); vg_var *var = &vg_console.vars[ vg_console.var_count ++ ]; var->name = alias; @@ -29,11 +26,8 @@ void vg_console_reg_cmd( const char *alias, int (*function)(int argc, const char *argv[]), void (*poll_suggest)(int argc, const char *argv[]) ) { - if( vg_thread_purpose() == k_thread_purpose_main ) - vg_fatal_error( "FIXME: Cannot register CMD from main thread" ); - - if( vg_console.function_count > vg_list_size(vg_console.functions) ) - vg_fatal_error( "Too many functions registered" ); + VG_ASSERT( vg_thread_purpose() != k_thread_purpose_main ); + VG_ASSERT( vg_console.function_count < VG_ARRAY_LEN(vg_console.functions) ); vg_cmd *cmd = &vg_console.functions[ vg_console.function_count ++ ]; @@ -345,10 +339,10 @@ void console_suggest_score_text( const char *str, const char *input, best_pos = j; /* insert if good score */ - if( best_pos < vg_list_size( vg_console.suggestions ) ) + if( best_pos < VG_ARRAY_LEN( vg_console.suggestions ) ) { int start = VG_MIN( vg_console.suggestion_count, - vg_list_size( vg_console.suggestions )-1 ); + VG_ARRAY_LEN( vg_console.suggestions )-1 ); for( int j=start; j>best_pos; j -- ) vg_console.suggestions[j] = vg_console.suggestions[j-1]; @@ -357,7 +351,7 @@ void console_suggest_score_text( const char *str, const char *input, vg_console.suggestions[ best_pos ].lev_score = score; if( vg_console.suggestion_count < - vg_list_size( vg_console.suggestions ) ) + VG_ARRAY_LEN( vg_console.suggestions ) ) vg_console.suggestion_count ++; } } @@ -452,7 +446,7 @@ static void _console_fetch_suggestion( ui_context *ctx ) { strncpy( target, vg_console.suggestions[ vg_console.suggestion_select ].str, - vg_list_size( vg_console.input )-1 ); + VG_ARRAY_LEN( vg_console.input )-1 ); _ui_textbox_move_cursor( ctx, &ctx->textbox.cursor_user, @@ -515,7 +509,7 @@ static void console_history_get( char* buf, int entry_num ) int offset = VG_MIN( entry_num, vg_console.history_count -1 ), pick = (vg_console.history_last - offset) % - vg_list_size( vg_console.history ); + VG_ARRAY_LEN( vg_console.history ); strcpy( buf, vg_console.history[ pick ] ); } @@ -532,7 +526,7 @@ static void _vg_console_on_up( ui_context *ctx, char *buf, u32 len ) vg_console.history_pos+1, VG_MIN ( - vg_list_size( vg_console.history ), + VG_ARRAY_LEN( vg_console.history ), vg_console.history_count - 1 ) ) @@ -542,7 +536,7 @@ static void _vg_console_on_up( ui_context *ctx, char *buf, u32 len ) _ui_textbox_move_cursor( ctx, &ctx->textbox.cursor_user, &ctx->textbox.cursor_pos, - vg_list_size(vg_console.input)-1, 1 ); + VG_ARRAY_LEN(vg_console.input)-1, 1 ); } } @@ -556,7 +550,7 @@ static void _vg_console_on_down( ui_context *ctx, char *buf, u32 len ) _ui_textbox_move_cursor( ctx, &ctx->textbox.cursor_user, &ctx->textbox.cursor_pos, - vg_list_size(vg_console.input)-1, 1 ); + VG_ARRAY_LEN(vg_console.input)-1, 1 ); } } @@ -573,9 +567,9 @@ static void _vg_console_on_enter( ui_context *ctx, char *buf, u32 len ) vg_console.history[ vg_console.history_last ]) ) { vg_console.history_last = ( vg_console.history_last + 1) % - vg_list_size(vg_console.history ); + VG_ARRAY_LEN(vg_console.history ); vg_console.history_count = - VG_MIN( vg_list_size( vg_console.history ), + VG_MIN( VG_ARRAY_LEN( vg_console.history ), vg_console.history_count + 1 ); strcpy( vg_console.history[ vg_console.history_last ], vg_console.input ); @@ -673,7 +667,7 @@ void vg_console_draw( ui_context *ctx ) { ptr --; - if( ptr < 0 ) ptr = vg_list_size( vg_log.log )-1; + if( ptr < 0 ) ptr = VG_ARRAY_LEN( vg_log.log )-1; ui_text( ctx, rect_line, vg_log.log[ptr], 1, k_ui_align_left, 0 ); rect_line[1] -= fh; @@ -691,7 +685,7 @@ void vg_console_draw( ui_context *ctx ) .enter = _vg_console_on_enter, }; ui_textbox( ctx, rect_input, NULL, - vg_console.input, vg_list_size(vg_console.input), 1, + vg_console.input, VG_ARRAY_LEN(vg_console.input), 1, UI_TEXTBOX_AUTOFOCUS, &callbacks ); /* diff --git a/vg_engine.c b/vg_engine.c index ddcda8f..2470b49 100644 --- a/vg_engine.c +++ b/vg_engine.c @@ -12,42 +12,34 @@ struct vg_engine vg = #include "vg/vg_ui/imgui_impl_opengl.c" #include "vg/vg_default_font.gc" -#define TEMP_STATUS_LOCK SDL_AtomicLock -#define TEMP_STATUS_UNLOCK SDL_AtomicUnlock -#define TEMP_SEM_POST(X) SDL_SemPost( X ) -#define TEMP_SEM_WAIT(X) SDL_SemWait( X ) -#define TEMP_SEM_GET(X) SDL_SemValue( X ) - enum engine_status _vg_engine_status(void) { - TEMP_STATUS_LOCK( &vg.sl_status ); + SDL_AtomicLock( &vg.sl_status ); enum engine_status status = vg.engine_status; - TEMP_STATUS_UNLOCK( &vg.sl_status ); + SDL_AtomicUnlock( &vg.sl_status ); return status; } enum vg_thread_purpose vg_thread_purpose(void) { - TEMP_STATUS_LOCK( &vg.sl_status ); - if( vg.thread_id_main == SDL_GetThreadID(NULL) ) + SDL_AtomicLock( &vg.sl_status ); + + SDL_threadID id = SDL_GetThreadID(NULL); + if( vg.thread_id_main == id ) { - TEMP_STATUS_UNLOCK( &vg.sl_status ); + SDL_AtomicUnlock( &vg.sl_status ); return k_thread_purpose_main; } - else + else if( vg.thread_id_loader == id ) { - TEMP_STATUS_UNLOCK( &vg.sl_status ); + SDL_AtomicUnlock( &vg.sl_status ); return k_thread_purpose_loader; } -} - -static void vg_assert_thread( enum vg_thread_purpose required ) -{ - enum vg_thread_purpose purpose = vg_thread_purpose(); - - if( purpose != required ){ - vg_fatal_error( "thread_purpose must be %u not %u\n", required, purpose ); + else + { + SDL_AtomicUnlock( &vg.sl_status ); + return k_thread_purpose_nothing; } } @@ -77,20 +69,6 @@ static struct vg_profile vg_prof_update = {.name="update()"}, vg_prof_render = {.name="render()"}, vg_prof_swap = {.name="swap"}; -void vg_checkgl( const char *src_info ) -{ - int fail = 0; - - GLenum err; - while( (err = glGetError()) != GL_NO_ERROR ){ - vg_error( "(%s) OpenGL Error: #%d\n", src_info, err ); - fail = 1; - } - - if( fail ) - vg_fatal_error( "OpenGL Error" ); -} - static void async_vg_bake_shaders( void *payload, u32 size ) { vg_shaders_compile(); @@ -106,11 +84,11 @@ void async_internal_complete( void *payload, u32 size ) { vg_success( "Internal async setup complete\n" ); - TEMP_STATUS_LOCK( &vg.sl_status ); + SDL_AtomicLock( &vg.sl_status ); if( vg.engine_status == k_engine_status_crashed ) { - TEMP_STATUS_UNLOCK( &vg.sl_status ); + SDL_AtomicUnlock( &vg.sl_status ); return; } else @@ -118,9 +96,7 @@ void async_internal_complete( void *payload, u32 size ) vg.engine_status = k_engine_status_running; } - TEMP_STATUS_UNLOCK( &vg.sl_status ); - - vg.client_has_control = 1; + SDL_AtomicUnlock( &vg.sl_status ); } #ifdef VG_CUSTOM_SHADERS @@ -455,13 +431,8 @@ static int vg_framefilter( double dt ){ return 0; } -static int _vg_crashscreen(void) +static void _vg_crashscreen(void) { -#if 0 - if( vg_getkey( SDLK_ESCAPE ) ) - return 1; -#endif - glBindFramebuffer( GL_FRAMEBUFFER, 0 ); glEnable(GL_BLEND); glDisable(GL_DEPTH_TEST); @@ -472,11 +443,22 @@ static int _vg_crashscreen(void) glClear( GL_COLOR_BUFFER_BIT ); glViewport( 0,0, vg.window_x, vg.window_y ); -#if 0 - _vg_render_log(); -#endif + ui_prerender( &vg_ui.ctx ); + vg_ui_set_screen( vg.window_x, vg.window_y ); + ui_update_mouse( &vg_ui.ctx, + (ui_px[2]){ vg.mouse_pos[0], vg.mouse_pos[1] }, vg.mouse_state ); - return 0; + vg_framebuffer_ui( &vg_ui.ctx ); + + vg_console.enabled = 1; + ui_ignore_input_frames( &vg_ui.ctx, 10 ); + vg_gui( &vg_ui.ctx ); + ui_ignore_input_frames( &vg_ui.ctx, 0 ); + ui_capture_mouse( &vg_ui.ctx, 1 ); + vg_console_draw( &vg_ui.ctx ); + + ui_postrender( &vg_ui.ctx, vg.time_frame_delta ); + vg_ui_post_update(); } static void _vg_gameloop(void) @@ -521,8 +503,7 @@ static void _vg_gameloop(void) if( status == k_engine_status_crashed ) { - if( _vg_crashscreen() ) - break; + _vg_crashscreen(); } else { @@ -726,16 +707,16 @@ static void _vg_terminate(void) /* Shutdown */ vg_console_write_persistent(); - TEMP_STATUS_LOCK( &vg.sl_status ); + SDL_AtomicLock( &vg.sl_status ); vg.engine_status = k_engine_status_none; - TEMP_STATUS_UNLOCK( &vg.sl_status ); + SDL_AtomicUnlock( &vg.sl_status ); - vg_loader_free(); - - vg_success( "If you see this it means everything went.. \"well\".....\n" ); + vg_loader_atexit(); SDL_GL_DeleteContext( vg.gl_context ); SDL_Quit(); + + vg_success( "The program has terminated 'correctly'\n" ); exit(0); } @@ -778,28 +759,45 @@ void vg_enter( int argc, char *argv[], const char *window_name ) /* Opengl-required systems */ vg_ui_init(); - vg_loader_init(); vg.engine_status = k_engine_status_load_internal; + vg_loader_step( vg_loader_init, vg_loader_free ); _vg_opengl_sync_init(); - vg_loader_start( _vg_load_full, NULL ); + vg_loader_start( _vg_load_full, NULL ); _vg_gameloop(); _vg_terminate(); } -void vg_fatal_error( const char *fmt, ... ) +#ifndef _WIN32 + #include +#endif + +void vg_fatal_exit(void) { - va_list args; - va_start( args, fmt ); - _vg_logx_va( stderr, NULL, "fatal", KRED, fmt, args ); - va_end( args ); + /* append backtrace */ +#if !defined(_WIN32) + void *array[20]; + char **strings; + int size, i; + + size = backtrace( array, 20 ); + strings = backtrace_symbols( array, size ); + + if( strings != NULL ) + { + vg_info( "\n\n---------------- gnu backtrace -------------\n" ); - vg_print_backtrace(); + for( int i=0; i @@ -125,13 +126,6 @@ struct vg_engine SDL_GLContext gl_context; SDL_sem *sem_loader; /* allows only one loader at a time */ - bool client_has_control; /* [T0] If 0: VG will display a loader screen - If 1: The game is responsible for - drawing everything. - This can be set back to 0 after vg_load is - complete to blinder the client - Not recommended! */ - SDL_threadID thread_id_main, thread_id_loader; diff --git a/vg_framebuffer.c b/vg_framebuffer.c index 8a70b61..253c3a5 100644 --- a/vg_framebuffer.c +++ b/vg_framebuffer.c @@ -74,8 +74,10 @@ void vg_framebuffer_bind_texture( vg_framebuffer *fb, int attachment, int slot ) if( (at->purpose != k_framebuffer_attachment_type_texture) && (at->purpose != k_framebuffer_attachment_type_texture_depth) ) { - vg_fatal_error( "illegal operation: bind non-texture framebuffer" - " attachment to texture slot" ); + vg_fatal_condition(); + vg_info( "illegal operation: bind non-texture framebuffer" + " attachment to texture slot" ); + vg_fatal_exit(); } glActiveTexture( GL_TEXTURE0 + slot ); @@ -99,7 +101,7 @@ static const char *render_fb_attachment_str( GLenum e ) FB_FORMAT_STR(GL_DEPTH_STENCIL_ATTACHMENT) }; - for( int i=0; iattachments = vg_linear_alloc( alloc, @@ -311,17 +317,17 @@ static void async_framebuffer_create( void *payload, u32 size ) } else { + vg_fatal_condition(); if( result == GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT ) - vg_error( " status: Incomplete attachment" ); + vg_info( " status: Incomplete attachment" ); else if( result == GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT ) - vg_error( " status: Missing attachment" ); + vg_info( " status: Missing attachment" ); else if( result == GL_FRAMEBUFFER_UNSUPPORTED ) - vg_error( " status: Unsupported framebuffer format" ); + vg_info( " status: Unsupported framebuffer format" ); else - vg_error( " status: Generic Error" ); - + vg_info( " status: Generic Error" ); vg_info( "}\n" ); - vg_fatal_error( "Incomplete framebuffer (see logs)" ); + vg_fatal_exit(); } } diff --git a/vg_input.c b/vg_input.c index d4e51bc..ee0df5f 100644 --- a/vg_input.c +++ b/vg_input.c @@ -394,7 +394,7 @@ next_code:; else if( op == vg_gui_visible ) pc ++; else - vg_fatal_error( "unknown op\n" ); + vg_fatal_error( "unknown op (%u)\n", op ); goto next_code; } @@ -406,10 +406,10 @@ const char *controller_button_str( SDL_GameControllerButton button ) { static const char *controller_glyphs[ SDL_CONTROLLER_BUTTON_MAX ][2] = { /* xbox/generic playstation */ - [ SDL_CONTROLLER_BUTTON_A ] = { KGRN "\x06\x02\x85",KBLU "\x06\x02\x82" }, - [ SDL_CONTROLLER_BUTTON_B ] = { KRED "\x06\x02\x86",KRED "\x06\x02\x81" }, - [ SDL_CONTROLLER_BUTTON_X ] = { KBLU "\x06\x02\x83",KMAG "\x06\x02\x7f" }, - [ SDL_CONTROLLER_BUTTON_Y ] = { KYEL "\x06\x02\x84",KGRN "\x06\x02\x80" }, + [ SDL_CONTROLLER_BUTTON_A ] = { KGRN "\x06\x02\x85",KBLU "\x06\x02\x82" }, + [ SDL_CONTROLLER_BUTTON_B ] = { KRED "\x06\x02\x86",KRED "\x06\x02\x81" }, + [ SDL_CONTROLLER_BUTTON_X ] = { KBLU "\x06\x02\x83",KMAG "\x06\x02\x7f" }, + [ SDL_CONTROLLER_BUTTON_Y ] = { KYEL "\x06\x02\x84",KGRN "\x06\x02\x80" }, [ SDL_CONTROLLER_BUTTON_LEFTSTICK ] = { "\x87","\x87" }, [ SDL_CONTROLLER_BUTTON_RIGHTSTICK ] = { "\x8b","\x8b" }, [ SDL_CONTROLLER_BUTTON_LEFTSHOULDER ] = { "\x91","\x91" }, diff --git a/vg_io.c b/vg_io.c index 76e8ca3..b100992 100644 --- a/vg_io.c +++ b/vg_io.c @@ -108,17 +108,16 @@ void vg_dir_close( vg_dir *dir ) dir->index = 0; } -void vg_file_print_invalid( FILE *fp ) +void vg_file_error_info( FILE *fp ) { - if( feof( fp )) { + if( feof( fp )) + { vg_error( "mdl_open: header too short\n" ); } - else{ - if( ferror( fp )) - vg_error( "mdl_open: %s\n", strerror(errno) ); - else - vg_error( "mdl_open: unkown failure\n" ); - + else + { + if( ferror( fp )) vg_info( "fopen: %s\n", strerror(errno) ); + else vg_info( "fopen: unkown failure\n" ); } } @@ -128,13 +127,15 @@ void vg_file_print_invalid( FILE *fp ) void *vg_file_read( void *lin_alloc, const char *path, u32 *size ) { FILE *f = fopen( path, "rb" ); - if( f ){ + if( f ) + { void *buffer = lin_alloc? vg_linear_alloc( lin_alloc, 0 ): NULL; u64 current = 0; /* read in chunks */ - for( u32 i=0; 1; i++ ){ + for( u32 i=0; 1; i++ ) + { if( lin_alloc ) buffer = vg_linear_extend( lin_alloc,buffer,VG_FILE_IO_CHUNK_SIZE ); else @@ -143,18 +144,27 @@ void *vg_file_read( void *lin_alloc, const char *path, u32 *size ) u64 l = fread( buffer + current, 1, VG_FILE_IO_CHUNK_SIZE, f ); current += l; - if( l != VG_FILE_IO_CHUNK_SIZE ){ - if( feof( f ) ){ + if( l != VG_FILE_IO_CHUNK_SIZE ) + { + if( feof( f ) ) + { break; } - else{ - if( ferror( f ) ){ + else + { + if( ferror( f ) ) + { fclose(f); - vg_fatal_error( "read error" ); + vg_fatal_condition(); + vg_info( "Read error\n" ); + vg_fatal_exit(); } - else{ + else + { fclose(f); - vg_fatal_error( "unknown error codition" ); + vg_fatal_condition(); + vg_info( "Unknown error condition\n" ); + vg_fatal_exit(); } } } diff --git a/vg_io.h b/vg_io.h index fefb6bf..0991f0e 100644 --- a/vg_io.h +++ b/vg_io.h @@ -35,7 +35,6 @@ int vg_dirskip( vg_dir *dir ); int vg_dir_next_entry( vg_dir *dir ); enum vg_entry_type vg_dir_entry_type( vg_dir *dir ); void vg_dir_close( vg_dir *dir ); -void vg_file_print_invalid( FILE *fp ); /* * File I/O @@ -50,3 +49,4 @@ char *vg_file_read_text( void *lin_alloc, const char *path, u32 *sz ); int vg_asset_write( const char *path, void *data, i64 size ); int vg_file_copy( const char *src, const char *dst, void *lin_alloc ); const char *vg_path_filename( const char *path ); +void vg_file_error_info( FILE *fp ); diff --git a/vg_lines.c b/vg_lines.c index 6315482..94f8b68 100644 --- a/vg_lines.c +++ b/vg_lines.c @@ -57,7 +57,6 @@ static void async_vg_lines_init( void *payload, u32 payload_size ) glBufferData( GL_ARRAY_BUFFER, VG_LINES_BUFFER_SIZE, NULL, GL_DYNAMIC_DRAW ); glBindVertexArray( vg_lines.vao ); - VG_CHECK_GL_ERR(); /* Pointers */ glVertexAttribPointer( @@ -79,8 +78,6 @@ static void async_vg_lines_init( void *payload, u32 payload_size ) (void*)(offsetof( struct vg_lines_vert, colour )) ); glEnableVertexAttribArray( 1 ); - - VG_CHECK_GL_ERR(); } void vg_lines_init(void) @@ -187,7 +184,7 @@ void vg_line_boxf( boxf box, u32 colour ) {4,5},{5,7},{7,6},{6,4}, {4,0},{5,1},{6,2},{7,3}}; - vg_line_mesh( verts, indices, vg_list_size(indices), colour ); + vg_line_mesh( verts, indices, VG_ARRAY_LEN(indices), colour ); } void vg_line_boxf_transformed( m4x3f m, boxf box, u32 colour ) @@ -205,7 +202,7 @@ void vg_line_boxf_transformed( m4x3f m, boxf box, u32 colour ) {4,5},{5,7},{7,6},{6,4}, {4,0},{5,1},{6,2},{7,3}}; - vg_line_mesh( verts, indices, vg_list_size(indices), colour ); + vg_line_mesh( verts, indices, VG_ARRAY_LEN(indices), colour ); } void vg_line_cross(v3f pos,u32 colour, float scale) diff --git a/vg_loader.c b/vg_loader.c index 4859f75..f16d2c4 100644 --- a/vg_loader.c +++ b/vg_loader.c @@ -78,18 +78,18 @@ void vg_loader_init(void) glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE, sizeof(float)*2, (void*)0 ); glEnableVertexAttribArray( 0 ); - VG_CHECK_GL_ERR(); - - if( !vg_shader_compile( &_shader_loader ) ) - vg_fatal_error( "failed to compile shader" ); + vg_compile_shader( &_shader_loader ); } -static void vg_loader_free(void) +void vg_loader_free(void) { - vg_info( "vg_loader_free\n" ); glDeleteVertexArrays( 1, &vg_loader.vao ); glDeleteBuffers( 1, &vg_loader.vbo ); +} +void vg_loader_atexit(void) +{ + vg_info( "Shutdown steps\n" ); for( int i=0; i -#endif - struct vg_log vg_log; static void _vg_log_append_line( const char *str ) { - if( vg_log.log_line_count < vg_list_size( vg_log.log ) ) + if( vg_log.log_line_count < VG_ARRAY_LEN( vg_log.log ) ) vg_log.log_line_count ++; char *dest = vg_log.log[ vg_log.log_line_current ++ ]; - vg_strncpy( str, dest, vg_list_size(vg_log.log[0]), k_strncpy_allow_cutoff ); + vg_strncpy( str, dest, VG_ARRAY_LEN(vg_log.log[0]), k_strncpy_allow_cutoff ); - if( vg_log.log_line_current >= vg_list_size( vg_log.log ) ) + if( vg_log.log_line_current >= VG_ARRAY_LEN( vg_log.log ) ) vg_log.log_line_current = 0; } @@ -40,12 +36,12 @@ void _vg_logx_va( FILE *file, char buffer[4096]; - vsnprintf( buffer, vg_list_size(buffer), fmt, args ); + vsnprintf( buffer, VG_ARRAY_LEN(buffer), fmt, args ); const char *line = buffer; char logline[96]; - for( u32 i=0; icur + size) > alloc->size ) - { vg_fatal_error( "linear allocator overflow (%u + %u > %u)\n", - alloc->cur, size, alloc->size ); - } + alloc->cur, size, alloc->size ); if( alloc->flags & VG_MEMORY_SYSTEM ) { if( (alloc->allocation_count + 1) > VG_MAX_ALLOCATIONS ) { - vg_error( "Alloc (%p) allocation count is at the limit of" - " %u allocations.\n", alloc, VG_MAX_ALLOCATIONS ); - vg_fatal_error( "Max linear allocations reached" ); + vg_fatal_condition(); + vg_info( "Linear allocators marked as 'SYSTEMS', have a hard limit of " + "%u allocations.\n\n" + "The limit was exceeded by the following request:\n", + VG_MAX_ALLOCATIONS ); + vg_info( " Name: %s\n", constr_name ); + vg_info( " Size: %u bytes\n", size ); + vg_fatal_exit(); } } void *data; - if( vg_mem.use_libc_malloc && (alloc->flags & VG_MEMORY_SYSTEM) ){ + if( vg_mem.use_libc_malloc && (alloc->flags & VG_MEMORY_SYSTEM) ) + { data = malloc( size ); vg_allocation_meta *meta = &alloc->alloc_table[ alloc->allocation_count ]; @@ -69,24 +73,21 @@ void *_vg_linear_alloc( void *buffer, u32 size, const char *constr_name ) meta->size = size; meta->name = constr_name; } - else{ + else data = buffer + alloc->cur; - } u8 *bytes = data; - for( u32 i=0; iallocation_count ++; alloc->last_alloc = data; alloc->last_alloc_size = size; alloc->cur += size; - if( ((u64)data) % 8 ){ - vg_fatal_error( "unaligned" ); - } - + if( ((u64)data) % 8 ) + vg_fatal_error( "Resultant allocation was unaligned, most likely memory " + "corruption or programmer error\n" ); return data; } @@ -100,28 +101,29 @@ void *vg_linear_resize( void *buffer, void *data, u32 newsize ) newsize = vg_align8( newsize ); if( alloc->last_alloc != data ) - vg_fatal_error( "This block has been fixed!" ); + vg_fatal_error( "Tried to resize allocation in linear allocator which " + "has allocated other things after this block.\n" ); if( (alloc->cur - alloc->last_alloc_size + newsize) > alloc->size ) - vg_fatal_error( "Cannot resize, overflow" ); + vg_fatal_error( "Tried to resize allocation to new size which would " + "overflow the allocator\n" ); alloc->cur -= alloc->last_alloc_size; alloc->cur += newsize; alloc->last_alloc_size = newsize; - if( vg_mem.use_libc_malloc && (alloc->flags & VG_MEMORY_SYSTEM) ){ + if( vg_mem.use_libc_malloc && (alloc->flags & VG_MEMORY_SYSTEM) ) + { data = realloc( data, newsize ); if( !data ) - vg_fatal_error( "realloc failed" ); + vg_fatal_error( "We are libc mode, and realloc failed" ); alloc->alloc_table[ alloc->allocation_count-1 ].data = data; alloc->alloc_table[ alloc->allocation_count-1 ].size = newsize; alloc->last_alloc = data; return data; } - else{ - return data; - } + else return data; } /* its possible to delete just the last item */ @@ -129,12 +131,12 @@ void vg_linear_del( void *buffer, void *data ) { vg_linear_allocator *alloc = vg_linear_header( buffer ); - if( alloc->last_alloc != data ){ - vg_fatal_error( "This block has been fixed! Last alloc: %p, this: %p\n", - alloc->last_alloc, data ); - } + if( alloc->last_alloc != data ) + vg_fatal_error( "This block has been fixed and cannot be deleted.\n" + "Last alloc: %p, this: %p\n", alloc->last_alloc, data ); - if( vg_mem.use_libc_malloc && (alloc->flags & VG_MEMORY_SYSTEM) ){ + if( vg_mem.use_libc_malloc && (alloc->flags & VG_MEMORY_SYSTEM) ) + { vg_allocation_meta *meta = &alloc->alloc_table[alloc->allocation_count-1]; if( meta->type == k_allocation_type_linear ) vg_fatal_error( "Cannot free a linear allocator in this conext" ); @@ -229,25 +231,27 @@ void vg_linear_clear( void *buffer ) void *_vg_create_linear_allocator( void *lin_alloc, u32 size, u16 flags, const char *constr_name) { - if( sizeof( vg_linear_allocator ) != 32 ) - vg_fatal_error( "Programming error" ); + VG_ASSERT( sizeof( vg_linear_allocator ) == 32 ); vg_linear_allocator *header; u32 block_size = size + sizeof(vg_linear_allocator); /* Creating it inside an existing one */ - if( lin_alloc ){ + if( lin_alloc ) + { vg_linear_allocator *alloc = vg_linear_header( lin_alloc ); if( alloc->cur + block_size > alloc->size ) - vg_fatal_error( "Out of memory" ); + vg_fatal_error( "Out of memory (%u + %u > %u)\n", + alloc->cur, block_size, alloc->size ); if( alloc->allocation_count + 1 > VG_MAX_ALLOCATIONS ) - vg_fatal_error( "Max allocations in linear allocator" ); + vg_fatal_error( "Exceeded max allocations in linear allocator (%u)\n", + VG_MAX_ALLOCATIONS ); if( (flags && VG_MEMORY_SYSTEM) && (alloc->flags & VG_MEMORY_REALTIME) ) - vg_fatal_error( "Cannot declare realtime allocator inside systems" - " allocator" ); + vg_fatal_error( "Cannot declare realtime allocator inside systems " + "allocator"); if( vg_mem.use_libc_malloc ){ vg_allocation_meta *meta = @@ -263,9 +267,7 @@ void *_vg_create_linear_allocator( void *lin_alloc, u32 size, meta->size = size; meta->name = constr_name; } - else{ - header = lin_alloc + alloc->cur; - } + else header = lin_alloc + alloc->cur; alloc->cur += block_size; alloc->last_alloc = header; @@ -286,12 +288,12 @@ void *_vg_create_linear_allocator( void *lin_alloc, u32 size, header->size = size; header->flags = flags; - if( vg_mem.use_libc_malloc && (flags & VG_MEMORY_SYSTEM) ){ + if( vg_mem.use_libc_malloc && (flags & VG_MEMORY_SYSTEM) ) + { u32 table_size = sizeof(vg_allocation_meta)*VG_MAX_ALLOCATIONS; header->alloc_table = malloc( table_size ); } - else - header->alloc_table = NULL; + else header->alloc_table = NULL; return header+1; } diff --git a/vg_mem.h b/vg_mem.h index 94042a9..6fde883 100644 --- a/vg_mem.h +++ b/vg_mem.h @@ -1,6 +1,6 @@ #pragma once -#define VG_MAX_ALLOCATIONS 256 +#define VG_MAX_ALLOCATIONS 128 typedef struct vg_linear_allocator vg_linear_allocator; typedef struct vg_allocation_meta vg_allocation_meta; diff --git a/vg_mem_pool.c b/vg_mem_pool.c index 1fe3302..0a830a2 100644 --- a/vg_mem_pool.c +++ b/vg_mem_pool.c @@ -69,12 +69,11 @@ void vg_pool_watch( vg_pool *pool, u16 id ) { vg_pool_node *node = vg_pool_nodeptr( pool, id ); - if( !node->ref_count ){ + if( !node->ref_count ) vg_pool_unlink( pool, id ); - } if( node->ref_count == 0xffff ) - vg_fatal_error( "pool watch missmatch (limit is 128)\n" ); + vg_fatal_error( "Pool watch missmatch (limit is 128)\n" ); node->ref_count ++; } @@ -88,7 +87,8 @@ void vg_pool_unwatch( vg_pool *pool, u16 id ) vg_fatal_error( "pool unwatch missmatch (no watchers)\n" ); node->ref_count --; - if( !node->ref_count ){ + if( !node->ref_count ) + { vg_pool_node *head = vg_pool_nodeptr( pool, pool->head ), *tail = vg_pool_nodeptr( pool, pool->tail ); diff --git a/vg_msg.c b/vg_msg.c index 16ce1d8..facd66b 100644 --- a/vg_msg.c +++ b/vg_msg.c @@ -119,7 +119,7 @@ u32 vg_msg_cmd_bytecount( u8 code ) u8 vg_msg_count_bits( u32 count ) { - if( count > 16 ) vg_fatal_error( "Too large\n" ); + VG_ASSERT( count <= 16 ); return ((count-1)<<2); } diff --git a/vg_opengl.c b/vg_opengl.c new file mode 100644 index 0000000..8e4e55a --- /dev/null +++ b/vg_opengl.c @@ -0,0 +1,38 @@ +#include "vg/vg_opengl.h" + +static const char *gl_error_names[] = +{ + "GL_INVALID_ENUM", + "GL_INVALID_VALUE", + "GL_INVALID_OPERATION", + "GL_STACK_OVERFLOW", + "GL_STACK_UNDERFLOW", + "GL_OUT_OF_MEMORY", + "GL_INVALID_FRAMEBUFFER_OPERATION" +}; + +void vg_opengl_log_errors(void) +{ + u32 err_count = 0; + GLenum err; + while( (err = glGetError()) != GL_NO_ERROR ) + { + if( !err_count ) + vg_info( "OpenGL error buffer:\n" ); + + u32 err_i = err - 0x0500; + if( err_i < VG_ARRAY_LEN(gl_error_names) ) + { + vg_info( " %u %s\n", err, gl_error_names[ err_i ] ); + } + else + { + vg_info( "%u (unknown code)\n", err ); + } + + err_count ++; + } + + if( !err_count ) + vg_info( "OpenGL error buffer is empty.\n" ); +} diff --git a/vg_opengl.h b/vg_opengl.h index 3656719..a59c1f0 100644 --- a/vg_opengl.h +++ b/vg_opengl.h @@ -1 +1,3 @@ #include "dep/glad/glad.h" + +void vg_opengl_log_errors(void); diff --git a/vg_platform.h b/vg_platform.h index b846b06..e9bf50b 100644 --- a/vg_platform.h +++ b/vg_platform.h @@ -28,15 +28,16 @@ typedef v3f m4x3f[4]; typedef v4f m4x4f[4]; typedef v3f boxf[2]; -/* anything compiled against VG shall implement this function somewhere. */ +/* anything compiled against VG shall implement vg_fatal_exit() somewhere. */ +void vg_fatal_condition(void); +void vg_fatal_exit(void); void vg_fatal_error( const char *fmt, ... ); #define VG_ASSERT( ITEM, ... ) \ - if( !( ITEM ) ) { \ - vg_fatal_error( "Assertion failed: " VG_LOG_MCSTR(ITEM) "\n" \ - VG_LOG_WHERE ); \ - } + if( !( ITEM ) ) { \ + vg_fatal_error( "Assertion failed: " VG_LOG_MCSTR(ITEM) "\n" VG_LOG_WHERE );\ + } #define VG_MIN( A, B ) ((A)<(B)?(A):(B)) #define VG_MAX( A, B ) ((A)>(B)?(A):(B)) -#define vg_list_size( A ) (sizeof(A)/sizeof(A[0])) +#define VG_ARRAY_LEN( A ) (sizeof(A)/sizeof(A[0])) diff --git a/vg_profiler.c b/vg_profiler.c index 79e0723..4785743 100644 --- a/vg_profiler.c +++ b/vg_profiler.c @@ -52,7 +52,7 @@ void vg_profile_drawn( ui_context *ctx, struct vg_profile **profiles, u32 count, ui_fill( ctx, panel, 0xa0000000 ); - if( count > 8 ) vg_fatal_error( "Too many profiles\n" ); + VG_ASSERT( count <= 8 ); f64 avgs[8]; u32 colours[8]; diff --git a/vg_rigidbody.c b/vg_rigidbody.c index bcfebc5..322f42a 100644 --- a/vg_rigidbody.c +++ b/vg_rigidbody.c @@ -89,11 +89,11 @@ void rb_extrapolate( rigidbody *rb, v3f co, v4f q ) void rb_iter( rigidbody *rb ) { - if( !vg_validf( rb->v[0] ) || - !vg_validf( rb->v[1] ) || - !vg_validf( rb->v[2] ) ) + if( !vg_validf(rb->v[0]) || !vg_validf(rb->v[1]) || !vg_validf(rb->v[2]) ) { - vg_fatal_error( "NaN velocity" ); + vg_fatal_error( + "Aborting the program because velocity has invalid value in one " + "or more components: %f %f %f\n", rb->v[0],rb->v[1],rb->v[2] ); } v3f gravity = { 0.0f, -9.8f, 0.0f }; diff --git a/vg_rigidbody_collision.c b/vg_rigidbody_collision.c index 1c1d058..2989a46 100644 --- a/vg_rigidbody_collision.c +++ b/vg_rigidbody_collision.c @@ -495,7 +495,7 @@ int rb_capsule__triangle( m4x3f mtxA, rb_capsule *c, v3f tri[3], rb_ct *buf ) int rb_global_has_space( void ) { - if( rb_contact_count + 16 > vg_list_size(rb_contact_buffer) ) + if( rb_contact_count + 16 > VG_ARRAY_LEN(rb_contact_buffer) ) return 0; return 1; diff --git a/vg_rigidbody_view.c b/vg_rigidbody_view.c index 962148f..f16f3c6 100644 --- a/vg_rigidbody_view.c +++ b/vg_rigidbody_view.c @@ -134,8 +134,6 @@ static void async_vg_rb_view_init( void *payload, u32 payload_size ) glVertexAttribPointer( 1, 3, GL_FLOAT, GL_FALSE, stride, (void *)offsetof(rb_view_vert, n) ); glEnableVertexAttribArray( 1 ); - - VG_CHECK_GL_ERR(); } void vg_rb_view_init(void) diff --git a/vg_shader.c b/vg_shader.c index b17c64a..ace5c17 100644 --- a/vg_shader.c +++ b/vg_shader.c @@ -21,13 +21,21 @@ struct vg_shaders } static vg_shaders; -static GLuint vg_shader_subshader( const char *src, GLint gliShaderType ) +/* + * Compile OpenGL subshader from GLSL source. Type is subshader type. + * If critical is set to 1, the program will fatal exit on compile failure. + */ +static GLuint vg_compile_opengl_subshader( GLint type, + const char *src, bool critical ) { - GLint shader = glCreateShader( gliShaderType ); + GLuint shader = glCreateShader( type ); - if( shader == GL_NONE ) + if( shader == 0 ) { - vg_error( "Could not 'glCreateShader()'\n" ); + vg_fatal_condition(); + vg_info( "glCreateShader returned 0.\n" ); + vg_opengl_log_errors(); + vg_fatal_exit(); return 0; } @@ -37,113 +45,139 @@ static GLuint vg_shader_subshader( const char *src, GLint gliShaderType ) GLint status; glGetShaderiv( shader, GL_COMPILE_STATUS, &status ); - if( status != GL_TRUE ) - { + if( status == GL_TRUE ) + { + return shader; + } + else + { + if( critical ) vg_fatal_condition(); + GLchar info[1024]; GLsizei len; + glGetShaderInfoLog( shader, sizeof(info), &len, info ); - glGetShaderInfoLog( shader, sizeof(info), &len, info ); - vg_error( "Error info:\n%s\n", info ); - return 0; - } + const char *type_str = "?"; + + if( type == GL_VERTEX_SHADER ) type_str = "GL_VERTEX_SHADER"; + else if( type == GL_FRAGMENT_SHADER ) type_str = "GL_FRAGMENT_SHADER"; + + vg_info( "%s subshader compile error:\n\n%s\n", type_str, info ); - return shader; + if( critical ) vg_fatal_exit(); + return 0; + } } -int vg_shader_compile( struct vg_shader *shader ) +/* + * Final compilation by linking, if critical is 1, a fatal exit will occur on + * link failure + */ +static int vg_link_opengl_program( GLuint program, bool critical ) { - GLuint program, vert, frag; - - /* If we are compiling this again, we obviously need to try to take the src - * from the disk instead. - * - * Only do this if we have filenames set on the shader, so engine shaders - * dont have to do it (text.. etc). - */ - - int use_source_files = 0; - if( shader->compiled ){ - if( shader->vs.orig_file && shader->fs.orig_file ){ - use_source_files = 1; - } - else { - vg_warn( "No source files for shader '%s'\n", shader->name ); - return 1; - } - } + glLinkProgram( program ); + + GLint success; + glGetProgramiv( program, GL_LINK_STATUS, &success ); - vg_info( "Compile shader '%s'\n", shader->name ); - - if( use_source_files ){ - char error[260]; - char path[260]; - - strcpy( path, "../../" ); - strcat( path, shader->vs.orig_file ); - char *vertex_src = stb_include_file( path, "", "../../shaders", error ); - - strcpy( path, "../../" ); - strcat( path, shader->fs.orig_file ); - char *fragment_src = stb_include_file( path, "", "../../shaders", error ); - - if( !vertex_src || !fragment_src ){ - const char *errstr = "Could not find shader source files (%s)\n"; - if( shader->compiled ){ - vg_warn( errstr, shader->vs.orig_file ); - free( vertex_src ); - free( fragment_src ); - return 1; - } - else{ - vg_error( errstr, shader->vs.orig_file ); - free( vertex_src ); - free( fragment_src ); - return 0; - } - } - - vert = vg_shader_subshader( vertex_src, GL_VERTEX_SHADER ); - frag = vg_shader_subshader( fragment_src, GL_FRAGMENT_SHADER ); - - free( vertex_src ); - free( fragment_src ); - } - else{ - vert = vg_shader_subshader( shader->vs.static_src, GL_VERTEX_SHADER ); - frag = vg_shader_subshader( shader->fs.static_src, GL_FRAGMENT_SHADER ); - } - - if( !vert || !frag ) + if( success ) return 1; + else + { + if( critical ) vg_fatal_condition(); + + char info[ 512 ]; + glGetProgramInfoLog( program, sizeof(info), NULL, info ); + vg_info( "Shader program link error:\n\n%s\n", info ); + + if( critical ) vg_fatal_exit(); return 0; - - program = glCreateProgram(); + } +} + +/* + * Compile vg_shader from static source code. Will fatal exit if there is a + * compile error + */ +void vg_compile_shader( struct vg_shader *shader ) +{ + VG_ASSERT( shader->compiled == 0 ); + + const char *vs = shader->vs.static_src, + *fs = shader->fs.static_src; + + GLuint vert = vg_compile_opengl_subshader( GL_VERTEX_SHADER, vs, 1 ), + frag = vg_compile_opengl_subshader( GL_FRAGMENT_SHADER, fs, 1 ), + program = glCreateProgram(); glAttachShader( program, vert ); glAttachShader( program, frag ); - glLinkProgram( program ); + + vg_link_opengl_program( program, 1 ); glDeleteShader( vert ); glDeleteShader( frag ); - - /* Check for link errors */ - char infoLog[ 512 ]; - int success_link = 1; - - glGetProgramiv( program, GL_LINK_STATUS, &success_link ); - if( !success_link ) - { - glGetProgramInfoLog( program, 512, NULL, infoLog ); - vg_error( "Link failed: %s\n", infoLog ); - glDeleteProgram( program ); - return 0; - } - - if( shader->compiled ) - glDeleteProgram( shader->id ); - + shader->id = program; - shader->compiled = 1; - return 1; + shader->compiled = 1; +} + +/* + * Recompile vg_shader from its original source files. This won't work in the + * shipped version of the engine. + */ +void vg_recompile_shader( struct vg_shader *shader ) +{ + VG_ASSERT( shader->compiled == 1 ); + + char error[260]; + char path[260]; + + strcpy( path, "../../" ); + strcat( path, shader->vs.orig_file ); + char *vs = stb_include_file( path, "", "../../shaders", error ); + + strcpy( path, "../../" ); + strcat( path, shader->fs.orig_file ); + char *fs = stb_include_file( path, "", "../../shaders", error ); + + if( !vs || !fs ) + { + vg_warn( "Could not recompile shader due to missing source files:\n" ); + + if( !vs ) vg_info( " Vertex: %s\n", shader->vs.orig_file ); + if( !fs ) vg_info( " Fragment: %s\n", shader->fs.orig_file ); + free( vs ); + free( fs ); + return; + } + + GLuint vert = vg_compile_opengl_subshader( GL_VERTEX_SHADER, vs, 0 ), + frag = vg_compile_opengl_subshader( GL_FRAGMENT_SHADER, fs, 0 ); + + free( vs ); + free( fs ); + + if( !vert || !frag ) return; + + GLuint program = glCreateProgram(); + + glAttachShader( program, vert ); + glAttachShader( program, frag ); + + if( vg_link_opengl_program( program, 0 ) ) + { + /* replace existing */ + glDeleteProgram( shader->id ); + shader->id = program; + } + else + { + /* womp womp */ + glDeleteProgram( program ); + } + + glDeleteShader( vert ); + glDeleteShader( frag ); } void vg_free_shader( struct vg_shader *shader ) @@ -151,6 +185,7 @@ void vg_free_shader( struct vg_shader *shader ) if( shader->compiled ) { glDeleteProgram( shader->id ); + shader->id = 0; shader->compiled = 0; } } @@ -163,25 +198,21 @@ void vg_shaders_compile(void) { vg_info( "Compiling shaders\n" ); - for( int i=0; icompiled = 0; - shader->id = 0; /* TODO: make this an error shader */ + shader->id = 0; /* TODO: make this an error shader */ vg_shaders.shaders[ vg_shaders.count ++ ] = shader; } diff --git a/vg_shader.h b/vg_shader.h index 1ea106c..9fff67d 100644 --- a/vg_shader.h +++ b/vg_shader.h @@ -18,5 +18,6 @@ struct vg_shader void vg_shaders_compile(void); int vg_shaders_live_recompile(int argc, const char *argv[]); void vg_shader_register( struct vg_shader *shader ); -int vg_shader_compile( struct vg_shader *shader ); +void vg_compile_shader( struct vg_shader *shader ); +void vg_recompile_shader( struct vg_shader *shader ); void vg_free_shader( struct vg_shader *shader ); diff --git a/vg_steam.c b/vg_steam.c index a021cb1..3c51338 100644 --- a/vg_steam.c +++ b/vg_steam.c @@ -6,7 +6,8 @@ struct vg_steam vg_steam; vg_steam_async_call *vg_alloc_async_steam_api_call(void) { - if( vg_steam.call_count == vg_list_size(vg_steam.calls) ){ + if( vg_steam.call_count == VG_ARRAY_LEN(vg_steam.calls) ) + { vg_fatal_error( "Maximum concurrent API calls exceeded (%u)\n", vg_steam.call_count ); } @@ -17,7 +18,7 @@ vg_steam_async_call *vg_alloc_async_steam_api_call(void) void steam_register_callback( u32 id, void (*p_handler)( CallbackMsg_t *msg ) ) { if( vg_steam.callback_handler_count == - vg_list_size(vg_steam.callback_handlers) ) + VG_ARRAY_LEN(vg_steam.callback_handlers) ) { vg_fatal_error( "Too many steam callback handlers registered (%u)\n", vg_steam.callback_handler_count ); diff --git a/vg_string.c b/vg_string.c index 61df5fe..34b98f7 100644 --- a/vg_string.c +++ b/vg_string.c @@ -24,7 +24,7 @@ i32 vg_str_storage( vg_str *str ) */ void vg_strnull( vg_str *str, char *buffer, i32 len ) { - if( len == -1 ) vg_fatal_error( "waaaa" ); + VG_ASSERT( len >= 0 ); str->buffer = buffer; if( buffer ) @@ -204,7 +204,10 @@ u32 vg_strncpy( const char *src, char *dst, u32 len, } else if( behaviour == k_strncpy_overflow_fatal ) { - vg_fatal_error( "Strncpy dest exceeded buffer length\n" ); + vg_fatal_condition(); + vg_info( "vg_strncpy to buffer with maximum length '%u' exceeded" + " the end of the buffer.\n", len ); + vg_fatal_exit(); } } } @@ -215,7 +218,7 @@ u32 vg_strncpy( const char *src, char *dst, u32 len, static void _vg_strcatf_va( vg_str *str, const char *fmt, va_list args ) { char buffer[4096]; - vsnprintf( buffer, vg_list_size(buffer), fmt, args ); + vsnprintf( buffer, VG_ARRAY_LEN(buffer), fmt, args ); vg_strcat( str, buffer ); } diff --git a/vg_tex.c b/vg_tex.c index 8791dd8..17db5f2 100644 --- a/vg_tex.c +++ b/vg_tex.c @@ -83,9 +83,7 @@ struct texture_load_info{ static void async_vg_tex2d_upload( void *payload, u32 size ) { - if( vg_thread_purpose() != k_thread_purpose_main ){ - vg_fatal_error( "Catastrophic programming error.\n" ); - } + VG_ASSERT( vg_thread_purpose() == k_thread_purpose_main ); struct texture_load_info *info = payload; @@ -277,7 +275,7 @@ void vg_tex2d_load_qoi_async( const u8 *bytes, u32 size, void vg_tex2d_load_qoi_async_file( const char *path, u32 flags, GLuint *dest ) { if( vg_thread_purpose() != k_thread_purpose_loader ) - vg_fatal_error( "wrong thread\n" ); + vg_fatal_error( "Called aync texture load from wrong thread (main)\n" ); vg_linear_clear( vg_mem.scratch ); diff --git a/vg_tool.c b/vg_tool.c index 8ac0832..ce45fa3 100644 --- a/vg_tool.c +++ b/vg_tool.c @@ -9,11 +9,19 @@ #include "vg_mem_queue.c" #include "vg_io.c" +void vg_fatal_exit(void) +{ + exit(1); +} + void vg_fatal_error( const char *fmt, ... ) { + vg_fatal_condition(); + va_list args; va_start( args, fmt ); _vg_logx_va( stderr, NULL, "fatal", KRED, fmt, args ); va_end( args ); - exit(1); + + vg_fatal_exit(); } diff --git a/vg_tool.h b/vg_tool.h index aa7a850..0449370 100644 --- a/vg_tool.h +++ b/vg_tool.h @@ -1,3 +1,2 @@ #pragma once #include "vg_log.h" -void vg_fatal_error( const char *fmt, ... ); diff --git a/vg_ui/imgui.c b/vg_ui/imgui.c index 30ccef2..0b63730 100644 --- a/vg_ui/imgui.c +++ b/vg_ui/imgui.c @@ -59,7 +59,7 @@ ui_vert *ui_fill_rect( ui_context *ctx, ui_rect rect, u32 colour, ui_px uv[4] ) u16 start = ctx->cur_vert; u32 mesh[] = { 0,2,1, 0,3,2 }; - for( u32 i=0; icur_indice += 6; @@ -115,7 +115,7 @@ void ui_outline( ui_context *ctx, mask = UI_TOP|UI_LEFT|UI_BOTTOM|UI_RIGHT; u32 c = 0; - for( u32 i=0; iarea[0]-256,0,256,ctx->area[1]}, swatch; - const char *names[vg_list_size(ctx->scheme)] = { + const char *names[VG_ARRAY_LEN(ctx->scheme)] = { [k_ui_bg] = "k_ui_bg", "k_ui_bg+1", "k_ui_bg+2", "k_ui_bg+3", "k_ui_bg+4", "k_ui_bg+5", "k_ui_bg+6", "k_ui_bg+7", @@ -1947,7 +1947,7 @@ void ui_dev_colourview( ui_context *ctx ) ui_rect col[2]; ui_split_ratio( window, k_ui_axis_v, 0.5f, 0, col[0], col[1] ); - for( int i=0; ischeme); i++ ) + for( int i=0; ischeme); i++ ) { int which = (i/8)%2; diff --git a/vg_ui/imgui_impl_opengl.c b/vg_ui/imgui_impl_opengl.c index 236789d..9c4dc32 100644 --- a/vg_ui/imgui_impl_opengl.c +++ b/vg_ui/imgui_impl_opengl.c @@ -331,7 +331,11 @@ void ui_impl_render_batch( ui_context *ctx, ui_batch *batch, glUniform1f( glGetUniformLocation(_shader_ui_hsv.id,"uHue"), inf->hue ); } else - vg_fatal_error( "Invalid UI shader (%d)\n", shader ); + { + vg_fatal_condition(); + vg_info( "Invalid UI shader (%d)\n", shader ); + vg_fatal_exit(); + } glDrawElements( GL_TRIANGLES, batch->indice_count, GL_UNSIGNED_SHORT, (void *)((size_t)batch->indice_offset) ); @@ -411,7 +415,7 @@ void vg_ui_handle_sdl_key( ui_context *ctx, SDL_Keysym ev ) if( ev.mod & KMOD_ALT ) mod |= KMOD_ALT; - for( int i=0; iw, sheet->h, 0, GL_RED, GL_UNSIGNED_BYTE, image ); - VG_CHECK_GL_ERR(); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );