commit 75745ceafd53891ea769dfe3894d03a6b744e750 parent 00d4f02248b3c1b3a5a6338f9ef44ea49571d8c0 Author: Michael Savage <mikejsavage@gmail.com> Date: Sat Aug 26 16:29:53 +0100 Shader includes Diffstat:
renderer.cc | | | 27 | +++++++++++++++------------ |
renderer.h | | | 2 | +- |
shaders.cc | | | 84 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------- |
diff --git a/renderer.cc b/renderer.cc @@ -264,15 +264,20 @@ void renderer_delete_fb( FB fb ) { glDeleteTextures( 1, &fb.texture ); } -static GLuint new_gl_shader( GLenum type, const char * src ) { - const char * srcs[] = { - "#version 330\n", - type == GL_VERTEX_SHADER ? "#define VERTEX_SHADER 1\n" : "#define FRAGMENT_SHADER 1\n", - src - }; +static GLuint new_gl_shader( GLenum type, array< const char * > srcs ) { + StaticArray< const char *, 16 > full_srcs; + full_srcs[ 0 ] = "#version 330\n"; + full_srcs[ 1 ] = type == GL_VERTEX_SHADER ? "#define VERTEX_SHADER 1\n" : "#define FRAGMENT_SHADER 1\n"; + size_t n = 2; + for( size_t i = 0; i < srcs.n; i++ ) { + if( srcs[ i ] != NULL ) { + full_srcs[ n ] = srcs[ i ]; + n++; + } + } GLuint shader = glCreateShader( type ); - glShaderSource( shader, ARRAY_COUNT( srcs ), srcs, NULL ); + glShaderSource( shader, n, full_srcs.ptr(), NULL ); glCompileShader( shader ); GLint status; @@ -290,10 +295,8 @@ static GLuint new_gl_shader( GLenum type, const char * src ) { } Shader renderer_new_shader( ShaderConfig config ) { - ASSERT( config.src != NULL ); - - GLuint vs = new_gl_shader( GL_VERTEX_SHADER, config.src ); - GLuint fs = new_gl_shader( GL_FRAGMENT_SHADER, config.src ); + GLuint vs = new_gl_shader( GL_VERTEX_SHADER, config.srcs ); + GLuint fs = new_gl_shader( GL_FRAGMENT_SHADER, config.srcs ); if( vs == 0 || fs == 0 ) { if( vs != 0 ) glDeleteShader( vs ); @@ -366,7 +369,7 @@ Shader renderer_new_shader( ShaderConfig config ) { Shader renderer_new_shader( const char * src ) { ShaderConfig config; - config.src = src; + config.srcs[ 0 ] = src; return renderer_new_shader( config ); } diff --git a/renderer.h b/renderer.h @@ -158,7 +158,7 @@ struct MeshConfig { }; struct ShaderConfig { - const char * src = NULL; + StaticArray< const char *, 8 > srcs = { }; StaticArray< const char *, RENDERER_MAX_TEXTURES > texture_uniform_names = { }; StaticArray< const char *, RENDERER_MAX_TEXTURE_BUFFERS > texture_buffer_uniform_names = { }; }; diff --git a/shaders.cc b/shaders.cc @@ -14,7 +14,14 @@ struct HotloadShader { StaticArray< const char *, RENDERER_MAX_TEXTURE_BUFFERS > texture_buffer_uniform_names = { }; }; -StaticArray< HotloadShader, SHADER_COUNT > shaders; +struct ShaderInclude { + const char * path = NULL; + char * contents = NULL; + time_t last_modified = 0; +}; + +static StaticArray< ShaderInclude, 64 > includes; +static StaticArray< HotloadShader, SHADER_COUNT > shaders; static time_t file_last_write_time( const char * path ) { struct stat buf; @@ -26,6 +33,8 @@ static time_t file_last_write_time( const char * path ) { } void shaders_init() { + includes[ 0 ].path = "shaders/common.glsl"; + shaders[ SHADER_TEXT ].path = "shaders/text.glsl"; shaders[ SHADER_TEXT ].texture_uniform_names[ 0 ] = "atlas"; @@ -74,31 +83,66 @@ void shaders_term() { } } +static void reload_include( ShaderInclude & include, time_t t ) { + if( include.contents != NULL ) { + free( include.contents ); + } + + include.contents = ( char * ) file_get_contents( include.path ); + include.last_modified = t; +} + +static bool reload_shader( HotloadShader & shader, time_t t ) { + INFO( "loading {}", shader.path ); + char * contents = ( char * ) file_get_contents( shader.path ); + + ShaderConfig shader_config; + shader_config.texture_uniform_names = shader.texture_uniform_names; + shader_config.texture_buffer_uniform_names = shader.texture_buffer_uniform_names; + + size_t n = 0; + for( ShaderInclude & include : includes ) { + if( include.contents == NULL ) break; + shader_config.srcs[ n ] = include.contents; + n++; + } + shader_config.srcs[ n ] = contents; + + Shader new_shader = renderer_new_shader( shader_config ); + + if( new_shader != INVALID_SHADER ) { + renderer_delete_shader( shader.shader ); + shader.shader = new_shader; + } + else { + return false; + } + + shader.last_modified = t; + + free( contents ); + + return true; +} + int hotload_shaders() { int failed = 0; + bool reload_all = false; + + for( ShaderInclude & include : includes ) { + time_t t = file_last_write_time( include.path ); + if( t > include.last_modified ) { + reload_all = true; + reload_include( include, t ); + } + } + for( HotloadShader & shader : shaders ) { time_t t = file_last_write_time( shader.path ); - if( t > shader.last_modified ) { - INFO( "loading {}", shader.path ); - char * contents = ( char * ) file_get_contents( shader.path ); - - ShaderConfig shader_config; - shader_config.src = contents; - shader_config.texture_uniform_names = shader.texture_uniform_names; - shader_config.texture_buffer_uniform_names = shader.texture_buffer_uniform_names; - Shader new_shader = renderer_new_shader( shader_config ); - - if( new_shader != INVALID_SHADER ) { - renderer_delete_shader( shader.shader ); - shader.shader = new_shader; - } - else { + if( reload_all || t > shader.last_modified ) { + if( !reload_shader( shader, t ) ) { failed++; } - - shader.last_modified = t; - - free( contents ); } } return failed;