shaders.cc (3710B)
1 #include <sys/types.h> 2 #include <sys/stat.h> 3 4 #include "intrinsics.h" 5 #include "array.h" 6 #include "renderer.h" 7 #include "shaders.h" 8 9 struct HotloadShader { 10 const char * path = NULL; 11 Shader shader = { }; 12 time_t last_modified = 0; 13 }; 14 15 struct ShaderInclude { 16 const char * path = NULL; 17 char * contents = NULL; 18 time_t last_modified = 0; 19 }; 20 21 static StaticArray< ShaderInclude, 64 > includes; 22 static StaticArray< HotloadShader, SHADER_COUNT > shaders; 23 24 static time_t file_last_write_time( const char * path ) { 25 struct stat buf; 26 if( stat( path, &buf ) == -1 ) { 27 return 0; 28 } 29 30 return buf.st_mtime; 31 } 32 33 void shaders_init() { 34 includes[ 0 ].path = "shaders/common.glsl"; 35 includes[ 1 ].path = "shaders/pbr.glsl"; 36 37 shaders[ SHADER_TEXT ].path = "shaders/text.glsl"; 38 39 shaders[ SHADER_MSDF ].path = "shaders/msdf.glsl"; 40 41 shaders[ SHADER_SKYBOX ].path = "shaders/skybox.glsl"; 42 43 shaders[ SHADER_FLAT_VERTEX_COLOURS ].path = "shaders/flat_vertex_colours.glsl"; 44 45 shaders[ SHADER_FLAT_TEXTURED ].path = "shaders/flat_textured.glsl"; 46 47 shaders[ SHADER_UI ].path = "shaders/ui.glsl"; 48 49 shaders[ SHADER_TREE ].path = "shaders/tree.glsl"; 50 51 shaders[ SHADER_WRITE_SHADOW_MAP ].path = "shaders/write_shadow_map.glsl"; 52 53 shaders[ SHADER_DEBUG_RENDER_SHADOW_MAP ].path = "shaders/debug_render_shadow_map.glsl"; 54 55 shaders[ SHADER_SHADOWED_VERTEX_COLOURS ].path = "shaders/shadowed_vertex_colours.glsl"; 56 57 shaders[ SHADER_WIREFRAME ].path = "shaders/wireframe.glsl"; 58 59 shaders[ SHADER_CLIPMAP ].path = "shaders/clipmap.glsl"; 60 61 shaders[ SHADER_CLIPMAP_SKIRT ].path = "shaders/clipmap_skirt.glsl"; 62 63 shaders[ SHADER_SHADOWED_VERTEX_COLOURS_TO_GBUFFER ].path = "shaders/shadowed_vertex_colours_to_gbuffer.glsl"; 64 65 shaders[ SHADER_FLAT_VERTEX_COLOURS_TO_GBUFFER ].path = "shaders/flat_vertex_colours_to_gbuffer.glsl"; 66 67 shaders[ SHADER_GBUFFER ].path = "shaders/gbuffer.glsl"; 68 69 shaders[ SHADER_DEPTH_EDGE ].path = "shaders/depth_edge.glsl"; 70 71 shaders[ SHADER_SKINNED_FLAT_VERTEX_COLOURS ].path = "shaders/skinned_flat_vertex_colours.glsl"; 72 73 int failed = hotload_shaders(); 74 if( failed != 0 ) { 75 FATAL( "failed to load shaders" ); 76 } 77 } 78 79 const Shader * get_shader( ShaderID id ) { 80 return &shaders[ id ].shader; 81 } 82 83 void shaders_term() { 84 for( HotloadShader & shader : shaders ) { 85 renderer_delete_shader( shader.shader ); 86 } 87 } 88 89 static void reload_include( ShaderInclude & include, time_t t ) { 90 if( include.contents != NULL ) { 91 free( include.contents ); 92 } 93 94 include.contents = ( char * ) file_get_contents( include.path ); 95 include.last_modified = t; 96 } 97 98 static bool reload_shader( HotloadShader & shader, time_t t ) { 99 INFO( "loading {}", shader.path ); 100 char * contents = ( char * ) file_get_contents( shader.path ); 101 102 StaticArray< const char *, 8 > srcs; 103 104 size_t n = 0; 105 for( ShaderInclude & include : includes ) { 106 if( include.contents == NULL ) break; 107 srcs[ n ] = include.contents; 108 n++; 109 } 110 srcs[ n ] = contents; 111 n++; 112 113 Shader new_shader = renderer_new_shader( srcs.slice( 0, n ) ); 114 115 if( new_shader.program != 0 ) { 116 renderer_delete_shader( shader.shader ); 117 shader.shader = new_shader; 118 } 119 else { 120 return false; 121 } 122 123 shader.last_modified = t; 124 125 free( contents ); 126 127 return true; 128 } 129 130 int hotload_shaders() { 131 int failed = 0; 132 bool reload_all = false; 133 134 for( ShaderInclude & include : includes ) { 135 if( include.path == NULL ) break; 136 137 time_t t = file_last_write_time( include.path ); 138 if( t > include.last_modified ) { 139 reload_all = true; 140 reload_include( include, t ); 141 } 142 } 143 144 for( HotloadShader & shader : shaders ) { 145 time_t t = file_last_write_time( shader.path ); 146 if( reload_all || t > shader.last_modified ) { 147 if( !reload_shader( shader, t ) ) { 148 failed++; 149 } 150 } 151 } 152 return failed; 153 }