diff options
author | Lukasz Kostyra <l.kostyra@samsung.com> | 2021-01-08 11:59:47 +0100 |
---|---|---|
committer | Lukasz Kostyra <l.kostyra@samsung.com> | 2021-01-08 12:56:08 +0100 |
commit | 5163a79760d43d4ccd016fa0b11a8051d1f53cc1 (patch) | |
tree | 7a04d397b98742835a887c7e56c42bd8d05c27a2 | |
parent | e95a38294313e2cfdb8ca456f77eca219ac93055 (diff) | |
download | emulator-yagl-5163a79760d43d4ccd016fa0b11a8051d1f53cc1.tar.gz emulator-yagl-5163a79760d43d4ccd016fa0b11a8051d1f53cc1.tar.bz2 emulator-yagl-5163a79760d43d4ccd016fa0b11a8051d1f53cc1.zip |
yagl_glsl_parser: Reorganize precision qualifier parsing
It is possible for uniforms to have precision qualifier assigned to
them. GLSL lexer/parser now properly discovers such situations.
Additionally, following issues were found and fixed:
* Invalid logging format for yagl_gles2_context_pre_draw warnings.
* Uninitialized variable issues with yagl_glsl_state_pp_resolve_define.
* GL_TEXTURE_EXTERNAL_OES targets having no texture target assigned,
causing debug assertions to fail on use.
Change-Id: Id01c84ed72f8c2a96a4f3d22bdc3c6a96eaaa803
-rw-r--r-- | GLES_common/yagl_gles_context.c | 9 | ||||
-rw-r--r-- | GLES_common/yagl_gles_texture.c | 8 | ||||
-rw-r--r-- | GLESv2/yagl_gles2_context.c | 4 | ||||
-rw-r--r-- | GLESv2/yagl_glsl_lexer.l | 29 | ||||
-rw-r--r-- | GLESv2/yagl_glsl_parser.y | 63 | ||||
-rw-r--r-- | GLESv2/yagl_glsl_state.c | 27 | ||||
-rw-r--r-- | GLESv2/yagl_glsl_state.h | 3 |
7 files changed, 101 insertions, 42 deletions
diff --git a/GLES_common/yagl_gles_context.c b/GLES_common/yagl_gles_context.c index dac2270..8c23e66 100644 --- a/GLES_common/yagl_gles_context.c +++ b/GLES_common/yagl_gles_context.c @@ -973,12 +973,9 @@ void yagl_gles_context_bind_texture(struct yagl_gles_context *ctx, texture = texture_target_state->texture_zero; } - // TEXTURE_EXTERNAL_OES is late bound, before drawing - if (target != GL_TEXTURE_EXTERNAL_OES) { - if (!yagl_gles_texture_bind(texture, target)) { - YAGL_SET_ERR(GL_INVALID_OPERATION); - return; - } + if (!yagl_gles_texture_bind(texture, target)) { + YAGL_SET_ERR(GL_INVALID_OPERATION); + return; } yagl_gles_texture_acquire(texture); diff --git a/GLES_common/yagl_gles_texture.c b/GLES_common/yagl_gles_texture.c index ab3f4e6..0a20e56 100644 --- a/GLES_common/yagl_gles_texture.c +++ b/GLES_common/yagl_gles_texture.c @@ -162,10 +162,10 @@ int yagl_gles_texture_bind(struct yagl_gles_texture *texture, // on host side. In order to not collide with what is bound there we'll // store the texture for later on guest side and do the temporary bind // on-demand, whenever app modifies TEXTURE_EXTERNAL_OES - // target via other GL APIs. - assert(target != GL_TEXTURE_EXTERNAL_OES); - - yagl_host_glBindTexture(target, texture->global_name); + // target via other GL APIs. See yagl_gles2_context_pre_draw(). + if (target != GL_TEXTURE_EXTERNAL_OES) { + yagl_host_glBindTexture(target, texture->global_name); + } texture->target = target; diff --git a/GLESv2/yagl_gles2_context.c b/GLESv2/yagl_gles2_context.c index ad54510..fdca4f8 100644 --- a/GLESv2/yagl_gles2_context.c +++ b/GLESv2/yagl_gles2_context.c @@ -659,13 +659,13 @@ void yagl_gles2_context_pre_draw(struct yagl_gles2_context *ctx, &ctx->base.texture_units[samplers[i].value].target_states[yagl_gles_texture_target_external_oes]; if (texture_external_state->texture == texture_external_state->texture_zero) { - YAGL_LOG_WARN(" #d: Trying to rebind unbound external texture at unit %d", i, samplers[i].value); + YAGL_LOG_WARN(" #%d: Trying to rebind unbound external texture at unit %d", i, samplers[i].value); continue; // TODO error GL_INVALID_OPERATION? } if (samplers[i].location == YAGL_GLSL_SAMPLER_LOCATION_UNKNOWN || samplers[i].value == YAGL_GLSL_SAMPLER_VALUE_UNKNOWN) { - YAGL_LOG_WARN(" #d: Unknown location/value of uniform %s - skipping", i, samplers[i].name); + YAGL_LOG_WARN(" #%d: Unknown location/value of uniform %s - skipping", i, samplers[i].name); continue; } diff --git a/GLESv2/yagl_glsl_lexer.l b/GLESv2/yagl_glsl_lexer.l index c5ee31a..de5d511 100644 --- a/GLESv2/yagl_glsl_lexer.l +++ b/GLESv2/yagl_glsl_lexer.l @@ -17,10 +17,11 @@ static yy_size_t string_input(char *buf, yy_size_t max_size, yyscan_t yyscanner) %option prefix="yagl_glsl_lexer_" %option extra-type="struct yagl_glsl_state *" -%x COMMENT PP PP_IFDEF PP_IF PP_DEFINE PP_UNDEF UNIFORM +%x COMMENT PP PP_IFDEF PP_IF PP_DEFINE PP_UNDEF UNIFORM PRECISION WS [ \r\t\v\f] -PRECISION "lowp"|"mediump"|"highp"|"precision"[^;\n]+;? +PRECISION_QUAL "lowp"|"mediump"|"highp" +PRECISION_ALL ${PRECISION_QUAL}|"precision"[^;\n]+;? CONTROL [()\[\]{},;?:/%*&|^!+\-=<>\.] STRING [^ \r\t\v\f\n()\[\]{},;?:/%*&|^!+\-=<>\.]+ @@ -253,12 +254,20 @@ STRING [^ \r\t\v\f\n()\[\]{},;?:/%*&|^!+\-=<>\.]+ return TOK_GLFRAGCOLOR; } -{PRECISION} { +"precision" { struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner); + BEGIN(PRECISION); yagl_glsl_state_new_str_token(state, yylval, yytext); return TOK_PRECISION; } +<PRECISION>{PRECISION_QUAL}[^;\n]+;? { + struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner); + BEGIN(INITIAL); + yagl_glsl_state_new_str_token(state, yylval, yytext); + return TOK_PRECISION_QUAL; +} + {CONTROL} { struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner); yagl_glsl_state_new_pending(state, yytext); @@ -293,10 +302,10 @@ STRING [^ \r\t\v\f\n()\[\]{},;?:/%*&|^!+\-=<>\.]+ return TOK_ES; } -<PP>{PRECISION} { +<PP>{PRECISION_ALL} { struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner); yagl_glsl_state_new_str_token(state, yylval, yytext); - return TOK_PRECISION; + return TOK_PRECISION_ALL; } <PP>{CONTROL} { @@ -537,6 +546,12 @@ STRING [^ \r\t\v\f\n()\[\]{},;?:/%*&|^!+\-=<>\.]+ yagl_glsl_state_new_pending(state, yytext); } +<UNIFORM>{PRECISION_QUAL} { + struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner); + yagl_glsl_state_new_str_token(state, yylval, yytext); + return TOK_PRECISION_QUAL; +} + <UNIFORM>{STRING} { struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner); yagl_glsl_state_new_str_token(state, yylval, yytext); @@ -586,7 +601,7 @@ static yy_size_t string_input(char *buf, yy_size_t max_size, yyscan_t yyscanner) return num_read; } -//extern int yagl_glsl_debug; +extern int yagl_glsl_debug; int yagl_glsl_state_init(struct yagl_glsl_state *state, GLenum shader_type, @@ -598,7 +613,7 @@ int yagl_glsl_state_init(struct yagl_glsl_state *state, memset(state, 0, sizeof(*state)); - //yagl_glsl_debug = 1; + yagl_glsl_debug = 1; if (yagl_glsl_lexer_lex_init_extra(state, &scanner)) { return 0; diff --git a/GLESv2/yagl_glsl_parser.y b/GLESv2/yagl_glsl_parser.y index f50022f..538f340 100644 --- a/GLESv2/yagl_glsl_parser.y +++ b/GLESv2/yagl_glsl_parser.y @@ -87,6 +87,8 @@ static int yagl_glsl_lex(union YYSTYPE *val, struct yagl_glsl_state *state) %token <integer> TOK_INTEGER %token <str> TOK_ES %token <str> TOK_PRECISION +%token <str> TOK_PRECISION_QUAL +%token <str> TOK_PRECISION_ALL %token <str> TOK_MAXVERTEXUNIFORMVECTORS %token <str> TOK_MAXFRAGMENTUNIFORMVECTORS %token <str> TOK_MAXVARYINGVECTORS @@ -217,7 +219,7 @@ expression yagl_glsl_state_flush_pending(state, $1.index); yagl_glsl_state_append_output(state, $1.value); } -| TOK_DEFINE TOK_PRECISION +| TOK_DEFINE TOK_PRECISION_ALL { yagl_glsl_state_flush_pending(state, $1.index); yagl_glsl_state_append_output(state, $1.value); @@ -314,17 +316,15 @@ expression yagl_glsl_state_append_output_char(state, $1.c); if (state->pp_condition_parse_started) { - int condition_result = yagl_glsl_state_pp_condition_resolve(state); - if (condition_result < 0) { + yagl_glsl_pp_condition_status status = yagl_glsl_state_pp_condition_resolve(state); + if (status == yagl_glsl_pp_condition_error) { yyerror(state, "GLSL preprocessor condition resolution failure"); } else { if (state->pp_elif_check) { - yagl_glsl_state_pp_set_condition_status(state, - (condition_result > 0) ? yagl_glsl_pp_condition_met : yagl_glsl_pp_condition_not_met); + yagl_glsl_state_pp_set_condition_status(state, status); state->pp_elif_check = 0; } else { - yagl_glsl_state_pp_start_condition(state, - (condition_result > 0) ? yagl_glsl_pp_condition_met : yagl_glsl_pp_condition_not_met); + yagl_glsl_state_pp_start_condition(state, status); } } } @@ -548,12 +548,17 @@ expression yagl_glsl_state_flush_pending(state, $1.index); } -| TOK_PRECISION +| TOK_PRECISION TOK_PRECISION_QUAL { yagl_glsl_state_flush_pending(state, $1.index); if (!state->patch_precision) { yagl_glsl_state_append_output(state, $1.value); } + + yagl_glsl_state_flush_pending(state, $2.index); + if (!state->patch_precision) { + yagl_glsl_state_append_output(state, $2.value); + } } | TOK_ES { @@ -647,6 +652,44 @@ expression yagl_glsl_state_append_output(state, $1.value); } } +| TOK_UNIFORM TOK_PRECISION_QUAL TOK_STRING TOK_STRING TOK_EOI +{ + yagl_glsl_state_flush_pending(state, $1.index); + yagl_glsl_state_append_output(state, $1.value); + + // precision qualifier should only be flushed here, GLSL non-ES does not support it + yagl_glsl_state_flush_pending(state, $2.index); + + yagl_glsl_state_flush_pending(state, $3.index); + yagl_glsl_state_append_output(state, $3.value); + yagl_glsl_state_flush_pending(state, $4.index); + yagl_glsl_state_append_output(state, $4.value); + yagl_glsl_state_flush_pending(state, $5.index); + yagl_glsl_state_append_output(state, $5.value); + + if (yagl_glsl_state_pp_is_condition_met(state)) { + // locally try to resolve the define based on current knowledge + // it won't matter if our type is not a macro but an actual sampler type + char* type_resolved = NULL; + int int_resolved = 0; + yagl_glsl_state_pp_resolve_define(state, $3.value, &type_resolved, &int_resolved); + + if (type_resolved != NULL) { + if (strcmp(type_resolved, "samplerExternalOES") == 0) { + if (!state->have_samplerexternaloes) { + yagl_glsl_state_append_header(state, "#define samplerExternalOES sampler2D\n"); + state->have_samplerexternaloes = 1; + } + + yagl_glsl_state_add_sampler_ExternalOES(state, $4.value); + } else if (strcmp(type_resolved, "sampler2D") == 0) { + yagl_glsl_state_add_sampler_2D(state, $4.value); + } + + free(type_resolved); + } + } +} | TOK_UNIFORM TOK_STRING TOK_STRING TOK_EOI { yagl_glsl_state_flush_pending(state, $1.index); @@ -661,8 +704,8 @@ expression if (yagl_glsl_state_pp_is_condition_met(state)) { // locally try to resolve the define based on current knowledge // it won't matter if our type is not a macro but an actual sampler type - char* type_resolved; - int int_resolved; + char* type_resolved = NULL; + int int_resolved = 0; yagl_glsl_state_pp_resolve_define(state, $2.value, &type_resolved, &int_resolved); if (type_resolved != NULL) { diff --git a/GLESv2/yagl_glsl_state.c b/GLESv2/yagl_glsl_state.c index 544b30d..6c12f68 100644 --- a/GLESv2/yagl_glsl_state.c +++ b/GLESv2/yagl_glsl_state.c @@ -571,7 +571,7 @@ void yagl_glsl_state_pp_condition_parse_add_op(struct yagl_glsl_state *state, ya if (op == yagl_glsl_pp_op_par_close) { // move ops from op stack to expr stack until we hit open parenthesis while (state->pp_ops[state->pp_current_op - 1] != yagl_glsl_pp_op_par_open) { - assert(state->pp_current_op > 0 && state->pp_curent_expr < YAGL_GLSL_PP_EXPRESSION_STACK_SIZE); + assert(state->pp_current_op > 0 && state->pp_current_expr < YAGL_GLSL_PP_EXPRESSION_STACK_SIZE); state->pp_current_op--; state->pp_exprs[state->pp_current_expr].op = state->pp_ops[state->pp_current_op]; state->pp_current_expr++; @@ -585,7 +585,7 @@ void yagl_glsl_state_pp_condition_parse_add_op(struct yagl_glsl_state *state, ya // move higher or equal priority operations to expression stack while (glsl_pp_op_prio[op] <= glsl_pp_op_prio[state->pp_ops[state->pp_current_op - 1]]) { - assert(state->pp_current_op > 0 && state->pp_curent_expr < YAGL_GLSL_PP_EXPRESSION_STACK_SIZE); + assert(state->pp_current_op > 0 && state->pp_current_expr < YAGL_GLSL_PP_EXPRESSION_STACK_SIZE); state->pp_current_op--; state->pp_exprs[state->pp_current_expr].op = state->pp_ops[state->pp_current_op]; state->pp_current_expr++; @@ -601,8 +601,8 @@ static int yagl_glsl_state_pp_solve_unary(struct yagl_glsl_state *state, struct yagl_glsl_pp_token token, int *result) { - char* tmp; - int v; + char* tmp = NULL; + int v = 0; assert(result != NULL); @@ -643,8 +643,8 @@ static int yagl_glsl_state_pp_solve_binary(struct yagl_glsl_state *state, struct yagl_glsl_pp_token tok_b, int *result) { - char *tmp; - int a, b; + char *tmp = NULL; + int a = 0, b = 0; assert(result != NULL); @@ -728,17 +728,18 @@ static inline int yagl_glsl_pp_expr_op_is_unary(yagl_glsl_pp_expr_op op) } } -int yagl_glsl_state_pp_condition_resolve(struct yagl_glsl_state *state) +yagl_glsl_pp_condition_status yagl_glsl_state_pp_condition_resolve(struct yagl_glsl_state *state) { struct yagl_glsl_pp_token res_stack[YAGL_GLSL_PP_EXPRESSION_STACK_SIZE]; int res_cur = 0; struct yagl_glsl_pp_token tok_a, tok_b; int i, tmp_result; - int result = 0; + yagl_glsl_pp_condition_status result = yagl_glsl_pp_condition_not_met; + YAGL_LOG_FUNC_SET(yagl_glsl_state_pp_condition_resolve); // empty op stack into expression stack while (state->pp_current_op > 0) { - assert(state->pp_current_op > 0 && state->pp_curent_expr < YAGL_GLSL_PP_EXPRESSION_STACK_SIZE); + assert(state->pp_current_op > 0 && state->pp_current_expr < YAGL_GLSL_PP_EXPRESSION_STACK_SIZE); state->pp_current_op--; state->pp_exprs[state->pp_current_expr].op = state->pp_ops[state->pp_current_op]; state->pp_current_expr++; @@ -754,7 +755,8 @@ int yagl_glsl_state_pp_condition_resolve(struct yagl_glsl_state *state) assert(res_cur > 0); if (!yagl_glsl_state_pp_solve_unary(state, state->pp_exprs[i].op, res_stack[res_cur - 1], &tmp_result)) { - result = -1; + YAGL_LOG_ERROR("Expression #%d: Unary operator %d (%s) failed", i, state->pp_exprs[i].op, glsl_pp_op_dbgstr[state->pp_exprs[i].op]); + result = yagl_glsl_pp_condition_error; goto clean; } } else { @@ -765,7 +767,8 @@ int yagl_glsl_state_pp_condition_resolve(struct yagl_glsl_state *state) res_cur--; if (!yagl_glsl_state_pp_solve_binary(state, state->pp_exprs[i].op, tok_a, tok_b, &tmp_result)) { - result = -1; + YAGL_LOG_ERROR("Expression #%d: Binary operator %d (%s) failed", i, state->pp_exprs[i].op, glsl_pp_op_dbgstr[state->pp_exprs[i].op]); + result = yagl_glsl_pp_condition_error; goto clean; } } @@ -777,7 +780,7 @@ int yagl_glsl_state_pp_condition_resolve(struct yagl_glsl_state *state) // there should be only one resolution on stack remaining - the result assert(res_cur == 1); - result = res_stack[res_cur - 1].value; + result = (res_stack[res_cur - 1].value > 0 ? yagl_glsl_pp_condition_met : yagl_glsl_pp_condition_not_met); clean: // cleanup diff --git a/GLESv2/yagl_glsl_state.h b/GLESv2/yagl_glsl_state.h index 9f3ef59..99dabb5 100644 --- a/GLESv2/yagl_glsl_state.h +++ b/GLESv2/yagl_glsl_state.h @@ -72,6 +72,7 @@ struct yagl_glsl_sampler typedef enum { + yagl_glsl_pp_condition_error = -1, yagl_glsl_pp_condition_not_met = 0, yagl_glsl_pp_condition_met, yagl_glsl_pp_condition_completed, @@ -326,7 +327,7 @@ void yagl_glsl_state_pp_condition_parse_add_expr(struct yagl_glsl_state *state, void yagl_glsl_state_pp_condition_parse_add_op(struct yagl_glsl_state *state, yagl_glsl_pp_expr_op op); // resolve preprocessor condition parser; 1 if met, 0 if not met, -1 on error -int yagl_glsl_state_pp_condition_resolve(struct yagl_glsl_state *state); +yagl_glsl_pp_condition_status yagl_glsl_state_pp_condition_resolve(struct yagl_glsl_state *state); /* * @} */ |