Parse GLSL #define preprocessor macros 73/251073/1
authorLukasz Kostyra <l.kostyra@samsung.com>
Tue, 29 Dec 2020 11:08:05 +0000 (12:08 +0100)
committerLukasz Kostyra <l.kostyra@samsung.com>
Thu, 7 Jan 2021 16:40:54 +0000 (17:40 +0100)
GLSL lexer/parser now handles #define macros in order to properly
discover samplerExternalOES/sampler2D type.

Change-Id: I77f01bb722d31f980bf8a1d6b00a717c108a15b0

GLESv2/yagl_gles2_calls.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 fec51f506cdb081702e803586eb30961bba3b37f..029a680b67cdd28e491949ef9786817ce9a092ef 100644 (file)
@@ -1438,11 +1438,30 @@ YAGL_API void glShaderSource(GLuint shader, GLsizei count, const GLchar * const
         ret = yagl_glsl_parse(&shader_obj->state);
 
         if ((ret == 0) && !shader_obj->state.have_error) {
+            struct yagl_glsl_sampler *samplers = NULL;
+            struct yagl_glsl_define *defines = NULL;
+            int i = 0, size = 0;
+
             patched_source = yagl_glsl_state_get_output(&shader_obj->state,
                                                         &patched_len);
 
             YAGL_LOG_TRACE("patched source = %s", patched_source);
 
+            YAGL_LOG_DEBUG("extract summary:");
+            YAGL_LOG_DEBUG("  defines extracted from source:");
+            defines = yagl_vector_data(&shader_obj->state.defines);
+            size = yagl_vector_size(&shader_obj->state.defines);
+            for (i = 0; i < size; ++i) {
+                YAGL_LOG_DEBUG("    -> %s => %s", defines[i].name_orig, defines[i].name_new);
+            }
+
+            YAGL_LOG_DEBUG("  samplersExternalOES extracted from source:");
+            samplers = yagl_vector_data(&shader_obj->state.samplers_ExternalOES);
+            size = yagl_vector_size(&shader_obj->state.samplers_ExternalOES);
+            for (i = 0; i < size; ++i) {
+                YAGL_LOG_DEBUG("    -> %s: at %d unit %d", samplers[i].name, samplers[i].location, samplers[i].value);
+            }
+
             yagl_gles2_shader_source(shader_obj,
                                      (GLchar*)tmp_buff,
                                      patched_source,
index b3018e2c562d0e91c3fa708bbdbc39440fb8c0ea..928d9003d80c81aaa125eff74da5bc22f4de7c90 100644 (file)
@@ -641,6 +641,13 @@ void yagl_gles2_context_pre_draw(struct yagl_gles2_context *ctx,
         struct yagl_glsl_sampler *samplers = NULL;
         int i = 0, samplers_size = 0;
 
+        YAGL_LOG_DEBUG("samplersExternalOES extracted from source:");
+        samplers = yagl_vector_data(&fragment_shader->state.samplers_ExternalOES);
+        samplers_size = yagl_vector_size(&fragment_shader->state.samplers_ExternalOES);
+        for (i = 0; i < samplers_size; ++i) {
+            YAGL_LOG_DEBUG("  -> %s: at %d unit %d", samplers[i].name, samplers[i].location, samplers[i].value);
+        }
+
         ctx->base.have_externaloes_rebinds = 1;
 
         // FIXME for now assume user is always right and there is no error cases.
index 84be821d94a18614716fadab77ae0135784ac128..8ec6599a99e3fcbe1b7b05d591055826d988cdf4 100644 (file)
@@ -264,26 +264,20 @@ STRING [^ \r\t\v\f\n()\[\]{},;?:/%*&|^!+\-=<>\.]+
     return TOK_STRING;
 }
 
-<UNIFORM>{WS}+ {
-    struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner);
-    yagl_glsl_state_new_pending(state, yytext);
-}
-
-<UNIFORM>"samplerExternalOES" {
+<UNIFORM>{WS}*; {
     struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner);
+    BEGIN(INITIAL);
     yagl_glsl_state_new_str_token(state, yylval, yytext);
-    return TOK_SAMPLEREXTERNALOES;
+    return TOK_EOI;
 }
 
-<UNIFORM>"sampler2D" {
+<UNIFORM>{WS}+ {
     struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner);
-    yagl_glsl_state_new_str_token(state, yylval, yytext);
-    return TOK_SAMPLER2D;
+    yagl_glsl_state_new_pending(state, yytext);
 }
 
 <UNIFORM>{STRING} {
     struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner);
-    BEGIN(INITIAL);
     yagl_glsl_state_new_str_token(state, yylval, yytext);
     return TOK_STRING;
 }
@@ -365,6 +359,7 @@ int yagl_glsl_state_init(struct yagl_glsl_state *state,
     yagl_vector_init(&state->strings, sizeof(char*), 0);
     yagl_vector_init(&state->samplers_ExternalOES, sizeof(struct yagl_glsl_sampler), 0);
     yagl_vector_init(&state->samplers_2D, sizeof(struct yagl_glsl_sampler), 0);
+    yagl_vector_init(&state->defines, sizeof(struct yagl_glsl_define), 0);
 
     return 1;
 }
index d42aafbe63353415419a7a8cab9808d94e43b886..d6ae2b1ee6bfe2a2529eb7f7a4a1d73765080af9 100644 (file)
@@ -41,6 +41,7 @@ static int yagl_glsl_lex(union YYSTYPE *val, struct yagl_glsl_state *state)
 }
 
 %token <str> TOK_EOL
+%token <str> TOK_EOI
 %token <str> TOK_VERSION
 %token <str> TOK_DEFINE
 %token <str> TOK_EXTENSION
@@ -55,8 +56,6 @@ static int yagl_glsl_lex(union YYSTYPE *val, struct yagl_glsl_state *state)
 %token <str> TOK_ATTRIBUTE
 %token <str> TOK_VARYING
 %token <str> TOK_UNIFORM
-%token <str> TOK_SAMPLEREXTERNALOES
-%token <str> TOK_SAMPLER2D
 %token <str> TOK_TEXTURE1D
 %token <str> TOK_TEXTURE1DPROJ
 %token <str> TOK_TEXTURE1DLOD
@@ -187,6 +186,19 @@ expression
     yagl_glsl_state_flush_pending(state, $2.index);
     yagl_glsl_state_append_output(state, $2.value);
 }
+| TOK_DEFINE TOK_STRING TOK_STRING TOK_EOL
+{
+    yagl_glsl_state_flush_pending(state, $1.index);
+    yagl_glsl_state_append_output(state, $1.value);
+    yagl_glsl_state_flush_pending(state, $2.index);
+    yagl_glsl_state_append_output(state, $2.value);
+    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_add_define(state, $2.value, $3.value);
+}
 | TOK_DEFINE
 {
     yagl_glsl_state_flush_pending(state, $1.index);
@@ -330,14 +342,7 @@ expression
         yagl_glsl_state_append_output(state, $1.value);
     }
 }
-| TOK_UNIFORM TOK_STRING
-{
-    yagl_glsl_state_flush_pending(state, $1.index);
-    yagl_glsl_state_append_output(state, $1.value);
-    yagl_glsl_state_flush_pending(state, $2.index);
-    yagl_glsl_state_append_output(state, $2.value);
-}
-| TOK_UNIFORM TOK_SAMPLEREXTERNALOES TOK_STRING
+| TOK_UNIFORM TOK_STRING TOK_STRING TOK_EOI
 {
     yagl_glsl_state_flush_pending(state, $1.index);
     yagl_glsl_state_append_output(state, $1.value);
@@ -345,24 +350,26 @@ expression
     yagl_glsl_state_append_output(state, $2.value);
     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);
 
-    if (!state->have_samplerexternaloes) {
-        yagl_glsl_state_append_header(state, "#define samplerExternalOES sampler2D\n");
-        state->have_samplerexternaloes = 1;
-    }
+    // 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;
+    yagl_glsl_state_resolve_define(state, $2.value, &type_resolved);
 
-    yagl_glsl_state_add_sampler_ExternalOES(state, $3.value);
-}
-| TOK_UNIFORM TOK_SAMPLER2D TOK_STRING
-{
-    yagl_glsl_state_flush_pending(state, $1.index);
-    yagl_glsl_state_append_output(state, $1.value);
-    yagl_glsl_state_flush_pending(state, $2.index);
-    yagl_glsl_state_append_output(state, $2.value);
-    yagl_glsl_state_flush_pending(state, $3.index);
-    yagl_glsl_state_append_output(state, $3.value);
+    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, $3.value);
+    } else if (strcmp(type_resolved, "sampler2D") == 0) {
+        yagl_glsl_state_add_sampler_2D(state, $3.value);
+    }
 
-    yagl_glsl_state_add_sampler_2D(state, $3.value);
+    free(type_resolved);
 }
 | TOK_TEXTURE1D
 {
index c1c3a5d5c96d2fe7ac739dcc015d3c190dfc3160..ee7f33feeef829124879bc1b4a380fa4f230dc94 100644 (file)
@@ -38,6 +38,7 @@
 #include "yagl_state.h"
 #include <string.h>
 #include <stdio.h>
+#include <assert.h>
 
 static void yagl_glsl_state_flush_version(struct yagl_glsl_state *state)
 {
@@ -324,3 +325,42 @@ void yagl_glsl_state_add_sampler_2D(struct yagl_glsl_state *state,
     sampler.replaced_tex2d = YAGL_GLSL_SAMPLER_VALUE_UNKNOWN;
     yagl_vector_push_back(&state->samplers_2D, &sampler);
 }
+
+void yagl_glsl_state_add_define(struct yagl_glsl_state *state,
+                                const char *tok_orig, const char *tok_new)
+{
+    struct yagl_glsl_define define;
+    define.name_orig = strdup(tok_orig);
+    define.name_new = strdup(tok_new);
+    yagl_vector_push_back(&state->defines, &define);
+}
+
+void yagl_glsl_state_resolve_define(struct yagl_glsl_state *state,
+                                    const char *token, char **resolved)
+{
+    struct yagl_glsl_define *defines = yagl_vector_data(&state->defines);
+    int i = 0, defines_size = yagl_vector_size(&state->defines);
+    const char* to_resolve = token;
+    YAGL_LOG_FUNC_SET(yagl_glsl_state_resolve_define);
+
+    assert(resolved != NULL);
+
+    YAGL_LOG_DEBUG("LKDEBUG resolving define %s", to_resolve);
+    while (1) {
+        for (i = 0; i < defines_size; ++i) {
+            if (strcmp(to_resolve, defines[i].name_orig) == 0) {
+                YAGL_LOG_DEBUG("    * %s -> %s", to_resolve, defines[i].name_new);
+                to_resolve = defines[i].name_new;
+                break;
+            }
+        }
+
+        if (i == defines_size)
+            // we went through everything we know and name did not appear
+            // assume this is the end
+            break;
+    }
+
+    *resolved = strdup(to_resolve);
+    YAGL_LOG_DEBUG("resolved as %s", *resolved);
+}
index 2f9184f6783e375759ec631363715267d99c7115..40913395ca9906d758d31f225d52955cdca8b69c 100644 (file)
@@ -52,6 +52,12 @@ struct yagl_glsl_pending
 #define YAGL_GLSL_SAMPLER_LOCATION_UNKNOWN (-1)
 #define YAGL_GLSL_SAMPLER_VALUE_UNKNOWN (-1)
 
+struct yagl_glsl_define
+{
+    char* name_orig;
+    char* name_new;
+};
+
 struct yagl_glsl_sampler
 {
     char* name;
@@ -134,6 +140,9 @@ struct yagl_glsl_state
     // strdup'ed strings.
     struct yagl_vector strings;
 
+    // preprocessor defines
+    struct yagl_vector defines;
+
     // names of samplerExternalOES uniforms
     struct yagl_vector samplers_ExternalOES;
 
@@ -196,6 +205,12 @@ void yagl_glsl_state_add_sampler_ExternalOES(struct yagl_glsl_state *state,
 void yagl_glsl_state_add_sampler_2D(struct yagl_glsl_state *state,
                                     const char *str);
 
+void yagl_glsl_state_add_define(struct yagl_glsl_state *state,
+                                const char *tok_orig, const char *tok_new);
+
+void yagl_glsl_state_resolve_define(struct yagl_glsl_state *state,
+                                    const char *token, char **resolved);
+
 int yagl_glsl_parse(struct yagl_glsl_state *state);
 
 #endif