YaGL: Patch texture2D, texture2DProj, etc. properly 89/17089/1
authorStanislav Vorobiov <s.vorobiov@samsung.com>
Mon, 3 Mar 2014 15:27:25 +0000 (19:27 +0400)
committerStanislav Vorobiov <s.vorobiov@samsung.com>
Mon, 3 Mar 2014 16:42:45 +0000 (20:42 +0400)
Replacing texture2D, texture2DProj, etc. with texture,
textureProj, etc. is not enough because there
might be things like this in the shader:

uniform sampler2D texture;
texture2D(texture, ...);

thus, after replacement this code will turn
into:

uniform sampler2D texture;
texture(texture, ...);

it'll lead to implementation-defined behavior in
most cases it'll just output blackness. Now we
workaround such situations by defining thunk
texture2D, texture2DProj, etc. at the top of the
shader, according to GLSL standard it's allowed
and it'll shadow builtin functions. Inside we
make a call to texture, textureProj, etc. Since
our function is just a thunk any decent GLSL
compiler will optimize it out, so no performance
penalty is introduced

Change-Id: I80449a6f9afdc17d1a6ab71e77501c84d41f3a25

GLESv2/yagl_glsl_lexer.l
GLESv2/yagl_glsl_parser.y
GLESv2/yagl_glsl_state.h

index 6c13d3c865e9c601b01d21831a5cd726f6c9fee1..97b4a4747339ba7b90dd5e6008ee358a49a7a49b 100644 (file)
@@ -101,85 +101,85 @@ STRING [^ \r\t\v\f\n()\[\]{},;?:/%*&|^!+\-=<>\.]+
 "texture1DProjLod" {
     struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner);
     yagl_glsl_state_new_str_token(state, yylval, yytext);
-    return TOK_TEXTUREPROJLOD;
+    return TOK_TEXTURE1DPROJLOD;
 }
 
 "texture1DProj" {
     struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner);
     yagl_glsl_state_new_str_token(state, yylval, yytext);
-    return TOK_TEXTUREPROJ;
+    return TOK_TEXTURE1DPROJ;
 }
 
 "texture1DLod" {
     struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner);
     yagl_glsl_state_new_str_token(state, yylval, yytext);
-    return TOK_TEXTURELOD;
+    return TOK_TEXTURE1DLOD;
 }
 
 "texture1D" {
     struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner);
     yagl_glsl_state_new_str_token(state, yylval, yytext);
-    return TOK_TEXTURE;
+    return TOK_TEXTURE1D;
 }
 
 "texture2DProjLod" {
     struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner);
     yagl_glsl_state_new_str_token(state, yylval, yytext);
-    return TOK_TEXTUREPROJLOD;
+    return TOK_TEXTURE2DPROJLOD;
 }
 
 "texture2DLod" {
     struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner);
     yagl_glsl_state_new_str_token(state, yylval, yytext);
-    return TOK_TEXTURELOD;
+    return TOK_TEXTURE2DLOD;
 }
 
 "texture2DProj" {
     struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner);
     yagl_glsl_state_new_str_token(state, yylval, yytext);
-    return TOK_TEXTUREPROJ;
+    return TOK_TEXTURE2DPROJ;
 }
 
 "texture2D" {
     struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner);
     yagl_glsl_state_new_str_token(state, yylval, yytext);
-    return TOK_TEXTURE;
+    return TOK_TEXTURE2D;
 }
 
 "texture3DProjLod" {
     struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner);
     yagl_glsl_state_new_str_token(state, yylval, yytext);
-    return TOK_TEXTUREPROJLOD;
+    return TOK_TEXTURE3DPROJLOD;
 }
 
 "texture3DLod" {
     struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner);
     yagl_glsl_state_new_str_token(state, yylval, yytext);
-    return TOK_TEXTURELOD;
+    return TOK_TEXTURE3DLOD;
 }
 
 "texture3DProj" {
     struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner);
     yagl_glsl_state_new_str_token(state, yylval, yytext);
-    return TOK_TEXTUREPROJ;
+    return TOK_TEXTURE3DPROJ;
 }
 
 "texture3D" {
     struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner);
     yagl_glsl_state_new_str_token(state, yylval, yytext);
-    return TOK_TEXTURE;
+    return TOK_TEXTURE3D;
 }
 
 "textureCubeLod" {
     struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner);
     yagl_glsl_state_new_str_token(state, yylval, yytext);
-    return TOK_TEXTURELOD;
+    return TOK_TEXTURECUBELOD;
 }
 
 "textureCube" {
     struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner);
     yagl_glsl_state_new_str_token(state, yylval, yytext);
-    return TOK_TEXTURE;
+    return TOK_TEXTURECUBE;
 }
 
 "gl_FragColor" {
index d263545ef44d3f93ecb1bcc355db97a2f6431e18..9f91f23f42524908c567e796dc4b74f4c9946f21 100644 (file)
@@ -54,10 +54,20 @@ static int yagl_glsl_lex(union YYSTYPE *val, struct yagl_glsl_state *state)
 %token <str> TOK_MAXVARYINGFLOATS
 %token <str> TOK_ATTRIBUTE
 %token <str> TOK_VARYING
-%token <str> TOK_TEXTURE
-%token <str> TOK_TEXTUREPROJ
-%token <str> TOK_TEXTURELOD
-%token <str> TOK_TEXTUREPROJLOD
+%token <str> TOK_TEXTURE1D
+%token <str> TOK_TEXTURE1DPROJ
+%token <str> TOK_TEXTURE1DLOD
+%token <str> TOK_TEXTURE1DPROJLOD
+%token <str> TOK_TEXTURE2D
+%token <str> TOK_TEXTURE2DPROJ
+%token <str> TOK_TEXTURE2DLOD
+%token <str> TOK_TEXTURE2DPROJLOD
+%token <str> TOK_TEXTURE3D
+%token <str> TOK_TEXTURE3DPROJ
+%token <str> TOK_TEXTURE3DLOD
+%token <str> TOK_TEXTURE3DPROJLOD
+%token <str> TOK_TEXTURECUBE
+%token <str> TOK_TEXTURECUBELOD
 %token <str> TOK_GLFRAGCOLOR
 
 %%
@@ -320,44 +330,239 @@ expression
         yagl_glsl_state_append_output(state, $1.value);
     }
 }
-| TOK_TEXTURE
+| TOK_TEXTURE1D
 {
     yagl_glsl_state_flush_pending(state, $1.index);
+    yagl_glsl_state_append_output(state, $1.value);
 
     if (state->patch_gl2) {
-        yagl_glsl_state_append_output(state, "texture");
-    } else {
-        yagl_glsl_state_append_output(state, $1.value);
+        if (!state->texture1d_declared) {
+            yagl_glsl_state_append_header(state, "vec4 texture1D(sampler1D sampler, float coord, float bias) {\n");
+            yagl_glsl_state_append_header(state, "    return texture(sampler, coord, bias);\n");
+            yagl_glsl_state_append_header(state, "}\n");
+            yagl_glsl_state_append_header(state, "vec4 texture1D(sampler1D sampler, float coord) {\n");
+            yagl_glsl_state_append_header(state, "    return texture(sampler, coord);\n");
+            yagl_glsl_state_append_header(state, "}\n");
+            state->texture1d_declared = 1;
+        }        
+    }        
+}
+| TOK_TEXTURE1DPROJ
+{
+    yagl_glsl_state_flush_pending(state, $1.index);
+    yagl_glsl_state_append_output(state, $1.value);
+
+    if (state->patch_gl2) {
+        if (!state->texture1dproj_declared) {
+            yagl_glsl_state_append_header(state, "vec4 texture1DProj(sampler1D sampler, vec2 coord, float bias) {\n");
+            yagl_glsl_state_append_header(state, "    return textureProj(sampler, coord, bias);\n");
+            yagl_glsl_state_append_header(state, "}\n");
+            yagl_glsl_state_append_header(state, "vec4 texture1DProj(sampler1D sampler, vec2 coord) {\n");
+            yagl_glsl_state_append_header(state, "    return textureProj(sampler, coord);\n");
+            yagl_glsl_state_append_header(state, "}\n");
+            yagl_glsl_state_append_header(state, "vec4 texture1DProj(sampler1D sampler, vec4 coord, float bias) {\n");
+            yagl_glsl_state_append_header(state, "    return textureProj(sampler, coord, bias);\n");
+            yagl_glsl_state_append_header(state, "}\n");
+            yagl_glsl_state_append_header(state, "vec4 texture1DProj(sampler1D sampler, vec4 coord) {\n");
+            yagl_glsl_state_append_header(state, "    return textureProj(sampler, coord);\n");
+            yagl_glsl_state_append_header(state, "}\n");
+            state->texture1dproj_declared = 1;
+        }        
     }
 }
-| TOK_TEXTUREPROJ
+| TOK_TEXTURE1DLOD
 {
     yagl_glsl_state_flush_pending(state, $1.index);
+    yagl_glsl_state_append_output(state, $1.value);
 
     if (state->patch_gl2) {
-        yagl_glsl_state_append_output(state, "textureProj");
-    } else {
-        yagl_glsl_state_append_output(state, $1.value);
+        if (!state->texture1dlod_declared) {
+            yagl_glsl_state_append_header(state, "vec4 texture1DLod(sampler1D sampler, float coord, float lod) {\n");
+            yagl_glsl_state_append_header(state, "    return textureLod(sampler, coord, lod);\n");
+            yagl_glsl_state_append_header(state, "}\n");            
+            state->texture1dlod_declared = 1;
+        }        
     }
 }
-| TOK_TEXTURELOD
+| TOK_TEXTURE1DPROJLOD
+{
+    yagl_glsl_state_flush_pending(state, $1.index);
+    yagl_glsl_state_append_output(state, $1.value);
+    
+    if (state->patch_gl2) {
+        if (!state->texture1dprojlod_declared) {
+            yagl_glsl_state_append_header(state, "vec4 texture1DProjLod(sampler1D sampler, vec2 coord, float lod) {\n");
+            yagl_glsl_state_append_header(state, "    return textureProjLod(sampler, coord, lod);\n");
+            yagl_glsl_state_append_header(state, "}\n");
+            yagl_glsl_state_append_header(state, "vec4 texture1DProjLod(sampler1D sampler, vec4 coord, float lod) {\n");
+            yagl_glsl_state_append_header(state, "    return textureProjLod(sampler, coord, lod);\n");
+            yagl_glsl_state_append_header(state, "}\n");            
+            state->texture1dprojlod_declared = 1;
+        }        
+    }
+}
+| TOK_TEXTURE2D
+{
+    yagl_glsl_state_flush_pending(state, $1.index);
+    yagl_glsl_state_append_output(state, $1.value);
+
+    if (state->patch_gl2) {
+        if (!state->texture2d_declared) {
+            yagl_glsl_state_append_header(state, "vec4 texture2D(sampler2D sampler, vec2 coord, float bias) {\n");
+            yagl_glsl_state_append_header(state, "    return texture(sampler, coord, bias);\n");
+            yagl_glsl_state_append_header(state, "}\n");
+            yagl_glsl_state_append_header(state, "vec4 texture2D(sampler2D sampler, vec2 coord) {\n");
+            yagl_glsl_state_append_header(state, "    return texture(sampler, coord);\n");
+            yagl_glsl_state_append_header(state, "}\n");
+            state->texture2d_declared = 1;
+        }        
+    }        
+}
+| TOK_TEXTURE2DPROJ
 {
     yagl_glsl_state_flush_pending(state, $1.index);
+    yagl_glsl_state_append_output(state, $1.value);
 
     if (state->patch_gl2) {
-        yagl_glsl_state_append_output(state, "textureLod");
-    } else {
-        yagl_glsl_state_append_output(state, $1.value);
+        if (!state->texture2dproj_declared) {
+            yagl_glsl_state_append_header(state, "vec4 texture2DProj(sampler2D sampler, vec3 coord, float bias) {\n");
+            yagl_glsl_state_append_header(state, "    return textureProj(sampler, coord, bias);\n");
+            yagl_glsl_state_append_header(state, "}\n");
+            yagl_glsl_state_append_header(state, "vec4 texture2DProj(sampler2D sampler, vec3 coord) {\n");
+            yagl_glsl_state_append_header(state, "    return textureProj(sampler, coord);\n");
+            yagl_glsl_state_append_header(state, "}\n");
+            yagl_glsl_state_append_header(state, "vec4 texture2DProj(sampler2D sampler, vec4 coord, float bias) {\n");
+            yagl_glsl_state_append_header(state, "    return textureProj(sampler, coord, bias);\n");
+            yagl_glsl_state_append_header(state, "}\n");
+            yagl_glsl_state_append_header(state, "vec4 texture2DProj(sampler2D sampler, vec4 coord) {\n");
+            yagl_glsl_state_append_header(state, "    return textureProj(sampler, coord);\n");
+            yagl_glsl_state_append_header(state, "}\n");
+            state->texture2dproj_declared = 1;
+        }        
     }
 }
-| TOK_TEXTUREPROJLOD
+| TOK_TEXTURE2DLOD
 {
     yagl_glsl_state_flush_pending(state, $1.index);
+    yagl_glsl_state_append_output(state, $1.value);
 
     if (state->patch_gl2) {
-        yagl_glsl_state_append_output(state, "textureProjLod");
-    } else {
-        yagl_glsl_state_append_output(state, $1.value);
+        if (!state->texture2dlod_declared) {
+            yagl_glsl_state_append_header(state, "vec4 texture2DLod(sampler2D sampler, vec2 coord, float lod) {\n");
+            yagl_glsl_state_append_header(state, "    return textureLod(sampler, coord, lod);\n");
+            yagl_glsl_state_append_header(state, "}\n");            
+            state->texture2dlod_declared = 1;
+        }        
+    }
+}
+| TOK_TEXTURE2DPROJLOD
+{
+    yagl_glsl_state_flush_pending(state, $1.index);
+    yagl_glsl_state_append_output(state, $1.value);
+    
+    if (state->patch_gl2) {
+        if (!state->texture2dprojlod_declared) {
+            yagl_glsl_state_append_header(state, "vec4 texture2DProjLod(sampler2D sampler, vec3 coord, float lod) {\n");
+            yagl_glsl_state_append_header(state, "    return textureProjLod(sampler, coord, lod);\n");
+            yagl_glsl_state_append_header(state, "}\n");
+            yagl_glsl_state_append_header(state, "vec4 texture2DProjLod(sampler2D sampler, vec4 coord, float lod) {\n");
+            yagl_glsl_state_append_header(state, "    return textureProjLod(sampler, coord, lod);\n");
+            yagl_glsl_state_append_header(state, "}\n");            
+            state->texture2dprojlod_declared = 1;
+        }        
+    }
+}
+| TOK_TEXTURE3D
+{
+    yagl_glsl_state_flush_pending(state, $1.index);
+    yagl_glsl_state_append_output(state, $1.value);
+
+    if (state->patch_gl2) {
+        if (!state->texture3d_declared) {
+            yagl_glsl_state_append_header(state, "vec4 texture3D(sampler3D sampler, vec3 coord, float bias) {\n");
+            yagl_glsl_state_append_header(state, "    return texture(sampler, coord, bias);\n");
+            yagl_glsl_state_append_header(state, "}\n");
+            yagl_glsl_state_append_header(state, "vec4 texture3D(sampler3D sampler, vec3 coord) {\n");
+            yagl_glsl_state_append_header(state, "    return texture(sampler, coord);\n");
+            yagl_glsl_state_append_header(state, "}\n");
+            state->texture3d_declared = 1;
+        }        
+    }        
+}
+| TOK_TEXTURE3DPROJ
+{
+    yagl_glsl_state_flush_pending(state, $1.index);
+    yagl_glsl_state_append_output(state, $1.value);
+
+    if (state->patch_gl2) {
+        if (!state->texture3dproj_declared) {            
+            yagl_glsl_state_append_header(state, "vec4 texture3DProj(sampler3D sampler, vec4 coord, float bias) {\n");
+            yagl_glsl_state_append_header(state, "    return textureProj(sampler, coord, bias);\n");
+            yagl_glsl_state_append_header(state, "}\n");
+            yagl_glsl_state_append_header(state, "vec4 texture3DProj(sampler3D sampler, vec4 coord) {\n");
+            yagl_glsl_state_append_header(state, "    return textureProj(sampler, coord);\n");
+            yagl_glsl_state_append_header(state, "}\n");
+            state->texture3dproj_declared = 1;
+        }        
+    }
+}
+| TOK_TEXTURE3DLOD
+{
+    yagl_glsl_state_flush_pending(state, $1.index);
+    yagl_glsl_state_append_output(state, $1.value);
+
+    if (state->patch_gl2) {
+        if (!state->texture3dlod_declared) {
+            yagl_glsl_state_append_header(state, "vec4 texture3DLod(sampler3D sampler, vec3 coord, float lod) {\n");
+            yagl_glsl_state_append_header(state, "    return textureLod(sampler, coord, lod);\n");
+            yagl_glsl_state_append_header(state, "}\n");            
+            state->texture3dlod_declared = 1;
+        }        
+    }
+}
+| TOK_TEXTURE3DPROJLOD
+{
+    yagl_glsl_state_flush_pending(state, $1.index);
+    yagl_glsl_state_append_output(state, $1.value);
+    
+    if (state->patch_gl2) {
+        if (!state->texture3dprojlod_declared) {            
+            yagl_glsl_state_append_header(state, "vec4 texture3DProjLod(sampler3D sampler, vec4 coord, float lod) {\n");
+            yagl_glsl_state_append_header(state, "    return textureProjLod(sampler, coord, lod);\n");
+            yagl_glsl_state_append_header(state, "}\n");            
+            state->texture3dprojlod_declared = 1;
+        }        
+    }
+}
+| TOK_TEXTURECUBE
+{
+    yagl_glsl_state_flush_pending(state, $1.index);
+    yagl_glsl_state_append_output(state, $1.value);
+
+    if (state->patch_gl2) {
+        if (!state->texturecube_declared) {
+            yagl_glsl_state_append_header(state, "vec4 textureCube(samplerCube sampler, vec3 coord, float bias) {\n");
+            yagl_glsl_state_append_header(state, "    return texture(sampler, coord, bias);\n");
+            yagl_glsl_state_append_header(state, "}\n");
+            yagl_glsl_state_append_header(state, "vec4 textureCube(samplerCube sampler, vec3 coord) {\n");
+            yagl_glsl_state_append_header(state, "    return texture(sampler, coord);\n");
+            yagl_glsl_state_append_header(state, "}\n");
+            state->texturecube_declared = 1;
+        }        
+    }        
+}
+| TOK_TEXTURECUBELOD
+{
+    yagl_glsl_state_flush_pending(state, $1.index);
+    yagl_glsl_state_append_output(state, $1.value);
+
+    if (state->patch_gl2) {
+        if (!state->texturecubelod_declared) {
+            yagl_glsl_state_append_header(state, "vec4 textureCubeLod(samplerCube sampler, vec3 coord, float lod) {\n");
+            yagl_glsl_state_append_header(state, "    return textureLod(sampler, coord, lod);\n");
+            yagl_glsl_state_append_header(state, "}\n");            
+            state->texturecubelod_declared = 1;
+        }        
     }
 }
 | TOK_GLFRAGCOLOR
index 8e837d7c079444dedad22c89626a5257d8177645..4a4653030194815dd68b6190792564df43ce28a0 100644 (file)
@@ -57,6 +57,20 @@ struct yagl_glsl_state
     int have_extensions;
 
     int frag_color_declared;
+    int texture1d_declared;
+    int texture1dproj_declared;
+    int texture1dlod_declared;
+    int texture1dprojlod_declared;
+    int texture2d_declared;
+    int texture2dproj_declared;
+    int texture2dlod_declared;
+    int texture2dprojlod_declared;
+    int texture3d_declared;
+    int texture3dproj_declared;
+    int texture3dlod_declared;
+    int texture3dprojlod_declared;
+    int texturecube_declared;
+    int texturecubelod_declared;
 
     // Each token is assigned an index.
     int token_index;