Skip to content

Commit e562251

Browse files
committed
Feat[shader_wrapper]: "support" uniform initializer
1 parent e929640 commit e562251

5 files changed

Lines changed: 212 additions & 22 deletions

File tree

ltw/src/main/tinywrapper/Android.mk

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,6 @@ LOCAL_SRC_FILES := \
412412
LOCAL_STATIC_LIBRARIES := glsl_optimizer
413413
LOCAL_LDFLAGS := -ffunction-sections -fdata-sections -Wl,--version-script=$(LOCAL_PATH)/version.script
414414
# Comment for debugging
415-
#LOCAL_LDFLAGS += -flto -Wl,--gc-sections
416-
LOCAL_LDLIBS := -llog -lEGL
415+
LOCAL_LDFLAGS += -flto -Wl,--gc-sections
416+
LOCAL_LDLIBS := -llog
417417
include $(BUILD_SHARED_LIBRARY)

ltw/src/main/tinywrapper/glsl_optimizer/src/code/ir_print_glsl_visitor.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -691,6 +691,45 @@ IR_TO_GLSL::visit(ir_variable* ir)
691691
print_var_name(ir);
692692
print_type_post(generated_source, ir->type, false);
693693

694+
if(ir->data.mode == ir_var_uniform) {
695+
ir_constant* const_val = ir->constant_value;
696+
if(const_val == NULL) const_val = ir->constant_initializer;
697+
if(const_val != NULL) {
698+
const glsl_type* assign_type = const_val->type;
699+
const glsl_base_type base_type = assign_type->base_type;
700+
if(assign_type->is_array() || assign_type->is_struct() || assign_type->is_matrix()) {
701+
printf("shader_print: %s default value is array, struct or matrix\n", ir->name);
702+
abort();
703+
}
704+
char type;
705+
switch (base_type) {
706+
case GLSL_TYPE_FLOAT:
707+
case GLSL_TYPE_FLOAT16:
708+
type = 'f';
709+
break;
710+
case GLSL_TYPE_INT:
711+
case GLSL_TYPE_INT8:
712+
case GLSL_TYPE_INT16:
713+
case GLSL_TYPE_INT64:
714+
type = 'i';
715+
break;
716+
case GLSL_TYPE_UINT:
717+
case GLSL_TYPE_UINT8:
718+
case GLSL_TYPE_UINT16:
719+
case GLSL_TYPE_UINT64:
720+
type = 'u';
721+
default:
722+
printf("shader_print: %s default value is not float, int or uint\n", ir->name);
723+
abort();
724+
break;
725+
}
726+
727+
generated_source.append("/* LTW UNIFORM INIT %c %i %s ", type, assign_type->vector_elements, ir->name);
728+
visit(const_val);
729+
generated_source.append(" */");
730+
}
731+
}
732+
694733
if (ir->constant_value &&
695734
ir->data.mode != ir_var_shader_in &&
696735
ir->data.mode != ir_var_shader_out &&

ltw/src/main/tinywrapper/shader_wrapper.c

Lines changed: 169 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,104 @@
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+
1633
typedef struct {
1734
GLenum shader_type;
1835
const GLchar* source;
36+
uval_list_t uval_list;
1937
} shader_info_t;
2038

2139
typedef 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+
26114
GLuint 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

61155
void 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

151298
GLuint 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;

ltw/src/main/tinywrapper/string_utils.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ char* gl4es_next_blank(char* pBuffer) {
248248
return pBuffer;
249249
}
250250

251-
char* gl4es_next_line(char* pBuffer) {
251+
char* gl4es_next_line(const char* pBuffer) {
252252
if(!pBuffer) return NULL;
253253
while(*pBuffer && *pBuffer!='\n')
254254
++pBuffer;

ltw/src/main/tinywrapper/string_utils.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ char* gl4es_str_next(char *pBuffer, const char* S); // mostly as strstr, but go
2626
char* gl4es_next_str(char* pBuffer); // go to next non "blank"
2727
char* gl4es_prev_str(char* Str, char* pBuffer); // go to previous non "blank"
2828
char* gl4es_next_blank(char* pBuffer); // go to next "blank"
29-
char* gl4es_next_line(char* pBuffer); // go to next new line (crlf not included)
29+
char* gl4es_next_line(const char* pBuffer); // go to next new line (crlf not included)
3030

3131
const char* gl4es_get_next_str(char* pBuffer); // get a (static) copy of next str (until next separator), can be a simple number or separator also
3232

0 commit comments

Comments
 (0)