1313#include "egl.h"
1414#include "proc.h"
1515
16+ struct def_uval {
17+ struct def_uval * next ;
18+ char name [128 ];
19+ char type ;
20+ int vector_len ;
21+ union {
22+ GLint iv [4 ];
23+ GLuint uv [4 ];
24+ GLfloat fv [4 ];
25+ };
26+ };
27+
28+ typedef struct {
29+ struct def_uval * first ;
30+ struct def_uval * last ;
31+ } uval_list_t ;
32+
1633typedef struct {
1734 GLenum shader_type ;
1835 const GLchar * source ;
36+ uval_list_t uval_list ;
1937} shader_info_t ;
2038
2139typedef struct {
2240 GLuint frag_shader ;
2341 GLchar * colorbindings [MAX_DRAWBUFFERS ];
42+ uval_list_t uval_list ;
2443} program_info_t ;
2544
45+ static void uval_list_add (uval_list_t * list , struct def_uval entry ) {
46+ const size_t struct_size = sizeof (struct def_uval );
47+ struct def_uval * new_entry = malloc (struct_size );
48+ memcpy (new_entry , & entry , struct_size );
49+ new_entry -> next = NULL ;
50+ if (list -> first == NULL ) {
51+ list -> first = list -> last = new_entry ;
52+ }else {
53+ list -> last -> next = new_entry ;
54+ list -> last = new_entry ;
55+ }
56+ }
57+
58+ static void uval_list_add_unique (uval_list_t * list , struct def_uval entry ) {
59+ for (struct def_uval * current = list -> first ; current != NULL ; current = current -> next ) {
60+ if (strcmp (current -> name , entry .name ) == 0 ) return ;
61+ }
62+ uval_list_add (list , entry );
63+ }
64+
65+ static void uval_list_free (uval_list_t * list ) {
66+ struct def_uval * current = list -> first ;
67+ for (;current != NULL ;) {
68+ void * old_current = current ;
69+ current = current -> next ;
70+ free (old_current );
71+ }
72+ }
73+
74+ static void uval_apply (GLint loc , const struct def_uval * uval ) {
75+ #define APPLY_4 (type , arr ) es3_functions.glUniform4##type(loc, uval->arr[0], uval->arr[1], uval->arr[2], uval->arr[3])
76+ #define APPLY_3 (type , arr ) es3_functions.glUniform3##type(loc, uval->arr[0], uval->arr[1], uval->arr[2])
77+ #define APPLY_2 (type , arr ) es3_functions.glUniform2##type(loc, uval->arr[0], uval->arr[1])
78+ #define APPLY_1 (type , arr ) es3_functions.glUniform1##type(loc, uval->arr[0])
79+ #define APPLY_LEN (len ) \
80+ case len: \
81+ switch (uval->type) { \
82+ case 'i': APPLY_##len(i, iv); break; \
83+ case 'f': APPLY_##len(f, fv); break; \
84+ case 'u': APPLY_##len(ui, uv); break; \
85+ } \
86+ break;
87+
88+ switch (uval -> vector_len ) {
89+ APPLY_LEN (1 )
90+ APPLY_LEN (2 )
91+ APPLY_LEN (3 )
92+ APPLY_LEN (4 )
93+ }
94+
95+ #undef APPLY_LEN
96+ #undef APPLY_1
97+ #undef APPLY_2
98+ #undef APPLY_3
99+ #undef APPLY_4
100+ }
101+
102+ static void uval_list_apply (uval_list_t * list , GLuint program ) {
103+ GLint oldprogram ;
104+ es3_functions .glGetIntegerv (GL_CURRENT_PROGRAM , & oldprogram );
105+ es3_functions .glUseProgram (program );
106+ for (struct def_uval * current = list -> first ; current != NULL ; current = current -> next ) {
107+ GLint location = es3_functions .glGetUniformLocation (program , current -> name );
108+ if (location == -1 ) continue ;
109+ uval_apply (location , current );
110+ }
111+ }
112+
113+
26114GLuint glCreateProgram (void ) {
27115 if (!current_context ) return 0 ;
28116 GLuint phys_program = es3_functions .glCreateProgram ();
@@ -45,6 +133,7 @@ void glDeleteProgram(GLuint program) {
45133 const GLchar * binding = old_programinfo -> colorbindings [i ];
46134 if (binding != NULL ) free ((void * )binding );
47135 }
136+ uval_list_free (& old_programinfo -> uval_list );
48137 free (old_programinfo );
49138}
50139
@@ -54,8 +143,13 @@ void glAttachShader( GLuint program,
54143 es3_functions .glAttachShader (program , shader );
55144 program_info_t * program_info = unordered_map_get (current_context -> program_map , (void * )program );
56145 shader_info_t * shader_info = unordered_map_get (current_context -> shader_map , (void * )shader );
57- if (program_info == NULL || shader_info == NULL || shader_info -> shader_type != GL_FRAGMENT_SHADER ) return ;
58- program_info -> frag_shader = shader ;
146+ if (program_info == NULL || shader_info == NULL ) return ;
147+ if (shader_info -> shader_type == GL_FRAGMENT_SHADER ) program_info -> frag_shader = shader ;
148+
149+ struct def_uval * current = shader_info -> uval_list .first ;
150+ for (;current != NULL ; current = current -> next ) {
151+ uval_list_add_unique (& program_info -> uval_list , * current );
152+ }
59153}
60154
61155void glBindFragDataLocation ( GLuint program ,
@@ -91,17 +185,12 @@ static void insert_fragout_pos(char* source, int* size, const char* name, GLuint
91185 gl4es_inplace_replace_simple (source , size , src_string , dst_string );
92186}
93187
94- void glLinkProgram (GLuint program ) {
95- if (!current_context ) return ;
96- program_info_t * program_info = unordered_map_get (current_context -> program_map , (void * )program );
97- if (program_info == NULL || program_info -> frag_shader == 0 ) {
98- // Don't have any fragment shader to patch the locations in, fall through.
99- goto fallthrough ;
100- }
188+ static GLuint patch_fragdata_loc (program_info_t * program_info ) {
189+ if (program_info -> frag_shader == 0 ) return 0 ;
101190 shader_info_t * shader = unordered_map_get (current_context -> shader_map , (void * )program_info -> frag_shader );
102191 if (shader == NULL ) {
103192 printf ("LTWShdrWp: failed to patch frag data location due to missing shader info\n" );
104- goto fallthrough ;
193+ return 0 ;
105194 }
106195 int nsrc_size = (int )(strlen (shader -> source ) + 1 );
107196 char * new_source = malloc (nsrc_size );
@@ -115,7 +204,7 @@ void glLinkProgram(GLuint program) {
115204 }
116205 if (!changesMade ) {
117206 free (new_source );
118- goto fallthrough ;
207+ return 0 ;
119208 }else {
120209 //printf("\n\n\nShader Result POST PATCH\n%s\n\n\n", new_source);
121210 }
@@ -124,7 +213,7 @@ void glLinkProgram(GLuint program) {
124213 if (patched_shader == 0 ) {
125214 free (new_source );
126215 printf ("LTWShdrWp: failed to initialize patched shader\n" );
127- goto fallthrough ;
216+ return 0 ;
128217 }
129218 es3_functions .glShaderSource (patched_shader , 1 , & const_source , NULL );
130219 es3_functions .glCompileShader (patched_shader );
@@ -136,16 +225,74 @@ void glLinkProgram(GLuint program) {
136225 es3_functions .glGetShaderiv (patched_shader , GL_INFO_LOG_LENGTH , & logSize );
137226 GLchar log [logSize ];
138227 es3_functions .glGetShaderInfoLog (patched_shader , logSize , NULL , log );
228+ es3_functions .glDeleteShader (patched_shader );
139229 printf ("LTWShdrWp: failed to compile patched fragment shader, using default. Log:\n\n%s\n\nShader content:\n\n%s\n\n" , log , const_source );
140- goto fallthrough ;
230+ return 0 ;
231+ }
232+ return patched_shader ;
233+ }
234+
235+ void glLinkProgram (GLuint program ) {
236+ if (!current_context ) return ;
237+ program_info_t * program_info = unordered_map_get (current_context -> program_map , (void * )program );
238+ if (program_info == NULL ) {
239+ printf ("LTWShdrWp: program info missing for program %u\n" , program );
240+ es3_functions .glLinkProgram (program );
241+ return ;
242+ }
243+ GLuint patched_frag_shader = patch_fragdata_loc (program_info );
244+ if (patched_frag_shader != 0 ) {
245+ es3_functions .glDetachShader (program , program_info -> frag_shader );
246+ es3_functions .glAttachShader (program , patched_frag_shader );
141247 }
142- es3_functions .glDetachShader (program , program_info -> frag_shader );
143- es3_functions .glAttachShader (program , patched_shader );
144248 es3_functions .glLinkProgram (program );
145- es3_functions .glDeleteShader (patched_shader );
249+ if (patched_frag_shader != 0 ) es3_functions .glDeleteShader (patched_frag_shader );
250+ uval_list_apply (& program_info -> uval_list , program );
146251 return ;
147- fallthrough :
148- es3_functions .glLinkProgram (program );
252+ }
253+
254+ static const char * vec1_initializer = " %%%c " ;
255+ static const char * vec2_initializer = " %svec2(%%%2$c, %%%2$c) " ;
256+ static const char * vec3_initializer = " %svec3(%%%2$c, %%%2$c, %%%2$c) " ;
257+ static const char * vec4_initializer = " %svec4(%%%2$c, %%%2$c, %%%2$c, %%%2$c) " ;
258+
259+ static void print_scan_template (char type , int veclen , char out [64 ]) {
260+ char type_str [] = {type , 0 };
261+ if (type == 'f' ) type_str [0 ] = 0 ;
262+ switch (veclen ) {
263+ case 1 : snprintf (out , sizeof (char ) * 64 , vec1_initializer , type ); break ;
264+ case 2 : snprintf (out , sizeof (char ) * 64 , vec2_initializer , type_str , type ); break ;
265+ case 3 : snprintf (out , sizeof (char ) * 64 , vec3_initializer , type_str , type ); break ;
266+ case 4 : snprintf (out , sizeof (char ) * 64 , vec4_initializer , type_str , type ); break ;
267+ default :
268+ abort ();
269+ }
270+ }
271+
272+ static void find_constant_uniforms (shader_info_t * programInfo , const char * source ) {
273+ char vector_scan_template [64 ] = { 0 }, var_value [128 ] = { 0 };
274+ float initval [4 ];
275+ for (;;) {
276+ source = strstr (source , "/* LTW UNIFORM INIT" );
277+ if (source == NULL ) break ;
278+ struct def_uval entry ;
279+ if (sscanf (source , "/* LTW UNIFORM INIT %c %i %127s %127s */" , & entry .type , & entry .vector_len , entry .name , var_value ) < 2 ) {
280+ abort ();
281+ }
282+ print_scan_template (entry .type , entry .vector_len , vector_scan_template );
283+ int scancnt = 0 ;
284+ switch (entry .type ) {
285+ case 'f' : scancnt = sscanf (var_value , vector_scan_template , & entry .fv [0 ], & entry .fv [1 ], & entry .fv [2 ], & entry .fv [3 ]); break ;
286+ case 'i' : scancnt = sscanf (var_value , vector_scan_template , & entry .iv [0 ], & entry .iv [1 ], & entry .iv [2 ], & entry .iv [3 ]); break ;
287+ case 'u' : scancnt = sscanf (var_value , vector_scan_template , & entry .uv [0 ], & entry .uv [1 ], & entry .uv [2 ], & entry .uv [3 ]); break ;
288+ }
289+ if (scancnt != entry .vector_len ) {
290+ printf ("LTWShdrWp: could not scan for initializer, value %s\n template %s\n" , var_value , vector_scan_template );
291+ abort ();
292+ }
293+ uval_list_add (& programInfo -> uval_list , entry );
294+ source = gl4es_next_line (source );
295+ }
149296}
150297
151298GLuint glCreateShader (GLenum shaderType ) {
@@ -168,6 +315,7 @@ void glDeleteShader(GLuint shader) {
168315 shader_info_t * old_shaderinfo = unordered_map_remove (current_context -> shader_map , (void * )shader );
169316 if (old_shaderinfo == NULL ) return ;
170317 if (old_shaderinfo -> source != NULL ) free ((void * )old_shaderinfo -> source );
318+ uval_list_free (& old_shaderinfo -> uval_list );
171319 free (old_shaderinfo );
172320}
173321
@@ -192,6 +340,9 @@ void glShaderSource(GLuint shader, GLsizei count, const GLchar *const*string, co
192340
193341#undef SRC_LEN
194342 GLchar * new_source = optimize_shader (target_string , shader_info -> shader_type , 460 , current_context -> shader_version );
343+ if (new_source != NULL ) {
344+ find_constant_uniforms (shader_info , new_source );
345+ }
195346 //printf("\n\n\nShader Result\n%s\n\n\n", new_source);
196347 if (shader_info -> source != NULL ) free ((void * )shader_info -> source );
197348 shader_info -> source = new_source ;
0 commit comments