Refactor, GLFW->SDL
[vg.git] / vg_shader.h
1 /* Copyright (C) 2021-2022 Harry Godden (hgn) - All Rights Reserved */
2
3 #ifndef VG_SHADER_H
4 #define VG_SHADER_H
5
6 #include "vg/vg.h"
7 #include "vg/vg_platform.h"
8
9 #if 0
10 #define STB_INCLUDE_IMPLEMENTATION
11 #define STB_INCLUDE_LINE_GLSL
12 #define STB_MALLOC vg_alloc
13 #define STB_FREE vg_free
14 #define STB_REALLOC vg_realloc
15 #include "stb/stb_include.h"
16 #endif
17
18 const char *vg_shader_gl_ver = "#version 330 core\n";
19
20 typedef struct vg_shader vg_shader;
21
22 struct
23 {
24 struct vg_shader
25 {
26 GLuint id;
27 const char *name;
28
29 struct vg_subshader
30 {
31 const char *orig_file,
32 *static_src;
33 }
34 vs, fs;
35
36 void (*link)(void);
37 int compiled;
38 }
39 * shaders[32];
40 u32 count;
41 }
42 static vg_shaders;
43
44 VG_STATIC GLuint vg_shader_subshader( const char *src, GLint gliShaderType )
45 {
46 GLint shader = glCreateShader( gliShaderType );
47
48 if( shader == GL_NONE )
49 {
50 vg_error( "Could not 'glCreateShader()'\n" );
51 return 0;
52 }
53
54 glShaderSource( shader, 2, (const char*[2]){ vg_shader_gl_ver, src }, NULL );
55 glCompileShader( shader );
56
57 GLint status;
58 glGetShaderiv( shader, GL_COMPILE_STATUS, &status );
59
60 if( status != GL_TRUE )
61 {
62 GLchar info[1024];
63 GLsizei len;
64
65 glGetShaderInfoLog( shader, sizeof(info), &len, info );
66 vg_error( "Error info:\n%s\n", info );
67 return 0;
68 }
69
70 return shader;
71 }
72
73 VG_STATIC int vg_shader_compile( struct vg_shader *shader )
74 {
75 vg_info( "Compile shader '%s'\n", shader->name );
76
77 GLuint program, vert, frag;
78 const char *svs, *sfs;
79 char *avs, *afs;
80
81 int static_src = 1;
82
83 /* If we are compiling this again, we obviously need to try to take the src
84 * from the disk instead.
85 *
86 * Only do this if we have filenames set on the shader, so engine shaders
87 * dont have to do it (text.. etc).
88 */
89 if( shader->compiled )
90 {
91 if( shader->vs.orig_file && shader->fs.orig_file )
92 static_src = 0;
93 else return 1;
94 }
95
96 if( static_src )
97 {
98 svs = shader->vs.static_src;
99 sfs = shader->fs.static_src;
100 }
101 else
102 {
103 vg_fatal_exit_loop( "Unimplemented" );
104
105 #if 0
106 char error[260];
107 char path[260];
108 strcpy( path, shader->vs.orig_file );
109 avs = stb_include_file( path, "", "../../shaders", error );
110
111 strcpy( path, shader->fs.orig_file );
112 afs = stb_include_file( path, "", "../../shaders", error );
113
114 if( !avs || !afs )
115 {
116 vg_error( "Could not find shader source files (%s)\n",
117 shader->vs.orig_file );
118
119 vg_free( avs );
120 vg_free( afs );
121 return 0;
122 }
123
124 svs = avs;
125 sfs = afs;
126 #endif
127 }
128
129 vert = vg_shader_subshader( svs, GL_VERTEX_SHADER );
130 frag = vg_shader_subshader( sfs, GL_FRAGMENT_SHADER );
131
132 #if 0
133 if( !static_src )
134 {
135 free( avs );
136 free( afs );
137 }
138 #endif
139
140 if( !vert || !frag )
141 return 0;
142
143 program = glCreateProgram();
144
145 glAttachShader( program, vert );
146 glAttachShader( program, frag );
147 glLinkProgram( program );
148
149 glDeleteShader( vert );
150 glDeleteShader( frag );
151
152 /* Check for link errors */
153 char infoLog[ 512 ];
154 int success_link = 1;
155
156 glGetProgramiv( program, GL_LINK_STATUS, &success_link );
157 if( !success_link )
158 {
159 glGetProgramInfoLog( program, 512, NULL, infoLog );
160 vg_error( "Link failed: %s\n", infoLog );
161 glDeleteProgram( program );
162 return 0;
163 }
164
165 if( shader->compiled )
166 glDeleteProgram( shader->id );
167
168 shader->id = program;
169 shader->compiled = 1;
170 if( shader->link )
171 shader->link();
172 return 1;
173 }
174
175 VG_STATIC void vg_free_shader( struct vg_shader *shader )
176 {
177 if( shader->compiled )
178 {
179 glDeleteProgram( shader->id );
180 shader->compiled = 0;
181 }
182 }
183
184 VG_STATIC void vg_shaders_compile(void)
185 {
186 vg_info( "Compiling shaders\n" );
187
188 for( int i=0; i<vg_shaders.count; i ++ )
189 {
190 vg_shader *shader = vg_shaders.shaders[i];
191
192 if( !vg_shader_compile( shader ) )
193 vg_fatal_exit_loop( "Failed to compile shader" );
194 }
195 }
196
197 VG_STATIC int vg_shaders_live_recompile(int argc, const char *argv[])
198 {
199 vg_info( "Recompiling shaders\n" );
200 for( int i=0; i<vg_shaders.count; i ++ )
201 {
202 struct vg_shader *shader = vg_shaders.shaders[i];
203 vg_shader_compile( shader );
204 }
205
206 return 0;
207 }
208
209 VG_STATIC void vg_shader_register( struct vg_shader *shader )
210 {
211 if( vg_shaders.count == vg_list_size(vg_shaders.shaders) )
212 vg_fatal_exit_loop( "Too many shaders" );
213
214 shader->compiled = 0;
215 shader->id = 0; /* TODO: make this an error shader */
216 vg_shaders.shaders[ vg_shaders.count ++ ] = shader;
217 }
218
219 #endif /* VG_SHADER_H */