summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukasz Kostyra <l.kostyra@samsung.com>2021-01-08 11:59:47 +0100
committerLukasz Kostyra <l.kostyra@samsung.com>2021-01-08 12:56:08 +0100
commit5163a79760d43d4ccd016fa0b11a8051d1f53cc1 (patch)
tree7a04d397b98742835a887c7e56c42bd8d05c27a2
parente95a38294313e2cfdb8ca456f77eca219ac93055 (diff)
downloademulator-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.c9
-rw-r--r--GLES_common/yagl_gles_texture.c8
-rw-r--r--GLESv2/yagl_gles2_context.c4
-rw-r--r--GLESv2/yagl_glsl_lexer.l29
-rw-r--r--GLESv2/yagl_glsl_parser.y63
-rw-r--r--GLESv2/yagl_glsl_state.c27
-rw-r--r--GLESv2/yagl_glsl_state.h3
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);
/*
* @}
*/