yagl_glsl_parser: Reorganize precision qualifier parsing 39/251139/1
authorLukasz Kostyra <l.kostyra@samsung.com>
Fri, 8 Jan 2021 10:59:47 +0000 (11:59 +0100)
committerLukasz Kostyra <l.kostyra@samsung.com>
Fri, 8 Jan 2021 11:56:08 +0000 (12:56 +0100)
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

GLES_common/yagl_gles_context.c
GLES_common/yagl_gles_texture.c
GLESv2/yagl_gles2_context.c
GLESv2/yagl_glsl_lexer.l
GLESv2/yagl_glsl_parser.y
GLESv2/yagl_glsl_state.c
GLESv2/yagl_glsl_state.h

index dac2270d8649154781476702a698908a42b2fd01..8c23e661c23f51c4413bc423f92c947427ff85bc 100644 (file)
@@ -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);
index ab3f4e656f06f3c9bc776b1429fba5ecbaf841c9..0a20e56978fc39a3184b2cd8d46c4358c163b043 100644 (file)
@@ -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;
 
index ad54510551cec4b7981265d9a9527b76a788b96c..fdca4f83451b09d12b37e4f218266052bdd72771 100644 (file)
@@ -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;
             }
 
index c5ee31a786b4763b5ed263eebdd6fb757907b37f..de5d5116d4e44bcec535f55433a0cc1bbdb07df4 100644 (file)
@@ -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;
index f50022f035df26eab1e5bf8458362376df0a7d03..538f3405788ccc4eaf84813033d3d6352dbd8855 100644 (file)
@@ -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) {
index 544b30dc22cbf33029d664bd1500723d289ad48e..6c12f684e1df6a08cfc3fbf1516dc119f7e87cac 100644 (file)
@@ -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
index 9f3ef5901f98da062749d6818ef61406606ad467..99dabb50e66354d223a14fdd77f46b6786013efd 100644 (file)
@@ -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);
 /*
  * @}
  */