summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukasz Kostyra <l.kostyra@samsung.com>2021-10-06 14:08:08 +0200
committerLukasz Kostyra <l.kostyra@samsung.com>2021-10-06 14:32:38 +0200
commit65212b82865b89729019b44f427f37e572ae8409 (patch)
tree6edd08bd54939eec5731a9125a756cdbe7380795
parent935ec8bb20022f37e387abb24cb12b3a02841c4a (diff)
downloademulator-yagl-65212b82865b89729019b44f427f37e572ae8409.tar.gz
emulator-yagl-65212b82865b89729019b44f427f37e572ae8409.tar.bz2
emulator-yagl-65212b82865b89729019b44f427f37e572ae8409.zip
yagl_glsl_parser: Fix support for uniform arrayssubmit/tizen/20211007.015901accepted/tizen/unified/20211007.052005
Uniform arrays were incorrectly processed by GLSL ES parser, which in some situations resulted in shader compilation errors. Uniform array support has been added and sampler replacement code has been slightly adjusted to read amount of sampler units from shader code. Note that this only fixes shader parsing code to allow successful compilation of shaders. This does NOT yet add full support for samplerExternalOES uniform arrays for GLES 2 and above. Change-Id: I24ead4473eb51e3e9d13b39fd98186763c6a5384
-rw-r--r--GLESv2/CMakeLists.txt7
-rw-r--r--GLESv2/yagl_gles2_calls.c6
-rw-r--r--GLESv2/yagl_glsl_lexer.l22
-rw-r--r--GLESv2/yagl_glsl_parser.y63
-rw-r--r--GLESv2/yagl_glsl_state.c57
-rw-r--r--GLESv2/yagl_glsl_state.h12
6 files changed, 122 insertions, 45 deletions
diff --git a/GLESv2/CMakeLists.txt b/GLESv2/CMakeLists.txt
index 5a97d53..c22c91d 100644
--- a/GLESv2/CMakeLists.txt
+++ b/GLESv2/CMakeLists.txt
@@ -27,11 +27,12 @@ include_directories(.)
include_directories(${CMAKE_CURRENT_BINARY_DIR})
link_directories(${CMAKE_ARCHIVE_OUTPUT_DIRECTORY})
-flex_target(GLESv2 ${CMAKE_CURRENT_SOURCE_DIR}/yagl_glsl_lexer.l ${CMAKE_CURRENT_BINARY_DIR}/yagl_glsl_lexer.c)
-bison_target(GLESv2 ${CMAKE_CURRENT_SOURCE_DIR}/yagl_glsl_parser.y ${CMAKE_CURRENT_BINARY_DIR}/yagl_glsl_parser.c
+flex_target(GLSL_lexer ${CMAKE_CURRENT_SOURCE_DIR}/yagl_glsl_lexer.l ${CMAKE_CURRENT_BINARY_DIR}/yagl_glsl_lexer.c)
+bison_target(GLSL_parser ${CMAKE_CURRENT_SOURCE_DIR}/yagl_glsl_parser.y ${CMAKE_CURRENT_BINARY_DIR}/yagl_glsl_parser.c
VERBOSE)
+add_flex_bison_dependency(GLSL_lexer GLSL_parser)
-add_library(GLESv2 SHARED ${SOURCES} ${FLEX_GLESv2_OUTPUTS} ${BISON_GLESv2_OUTPUTS})
+add_library(GLESv2 SHARED ${SOURCES} ${FLEX_GLSL_lexer_OUTPUTS} ${BISON_GLSL_parser_OUTPUTS})
set_target_properties(GLESv2 PROPERTIES VERSION 2.0 SOVERSION 2)
target_link_libraries(GLESv2 "-Wl,-whole-archive" GLES_common "-Wl,-no-whole-archive")
diff --git a/GLESv2/yagl_gles2_calls.c b/GLESv2/yagl_gles2_calls.c
index ba0468c..3978473 100644
--- a/GLESv2/yagl_gles2_calls.c
+++ b/GLESv2/yagl_gles2_calls.c
@@ -1482,14 +1482,16 @@ YAGL_API void glShaderSource(GLuint shader, GLsizei count, const GLchar * const
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_TRACE(" -> %s: at %d unit %d", samplers[i].name, samplers[i].location, samplers[i].value);
+ YAGL_LOG_TRACE(" -> %s: at %d unit %d count %d",
+ samplers[i].name, samplers[i].location, samplers[i].value, samplers[i].count);
}
YAGL_LOG_TRACE(" sampler2D uniforms:");
samplers = yagl_vector_data(&shader_obj->state.samplers_2D);
size = yagl_vector_size(&shader_obj->state.samplers_2D);
for (i = 0; i < size; ++i) {
- YAGL_LOG_TRACE(" -> %s: at %d unit %d", samplers[i].name, samplers[i].location, samplers[i].value);
+ YAGL_LOG_TRACE(" -> %s: at %d unit %d count %d",
+ samplers[i].name, samplers[i].location, samplers[i].value, samplers[i].count);
}
yagl_gles2_shader_source(shader_obj,
diff --git a/GLESv2/yagl_glsl_lexer.l b/GLESv2/yagl_glsl_lexer.l
index f71fb03..ac7271c 100644
--- a/GLESv2/yagl_glsl_lexer.l
+++ b/GLESv2/yagl_glsl_lexer.l
@@ -377,6 +377,14 @@ PP_FUNCTION {STRING}{WS}*\([^\n]+
return TOK_PP_IF_EOL;
}
+<PP_IF>\] {
+ // for handling expression resolution in-code
+ struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner);
+ BEGIN(UNIFORM);
+ yagl_glsl_state_new_character_token(state, yylval, *yytext);
+ return TOK_ARR_PAREN_CLOSE;
+}
+
<PP_IF>\/\/[^\n]* {
struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner);
yagl_glsl_state_new_comment(state, strlen(yytext));
@@ -552,22 +560,11 @@ PP_FUNCTION {STRING}{WS}*\([^\n]+
<UNIFORM>\[ {
struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner);
+ BEGIN(PP_IF);
yagl_glsl_state_new_character_token(state, yylval, *yytext);
return TOK_ARR_PAREN_OPEN;
}
-<UNIFORM>\] {
- struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner);
- yagl_glsl_state_new_character_token(state, yylval, *yytext);
- return TOK_ARR_PAREN_CLOSE;
-}
-
-<UNIFORM>[0-9]* {
- struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner);
- yagl_glsl_state_new_integer_token(state, yylval, strtol(yytext, NULL, 10));
- return TOK_INTEGER;
-}
-
<UNIFORM>{STRING} {
struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner);
yagl_glsl_state_new_str_token(state, yylval, yytext);
@@ -641,6 +638,7 @@ int yagl_glsl_state_init(struct yagl_glsl_state *state,
state->es3_supported = es3_supported;
state->scanner = scanner;
state->token_index = 1;
+ state->last_declared_sampler_externaloes = -1;
memset(&state->pp_conditions, 0, sizeof(int) * YAGL_GLSL_PP_CONDITION_STACK_SIZE);
state->pp_current_condition = 0;
state->pp_condition_parse_started = 0;
diff --git a/GLESv2/yagl_glsl_parser.y b/GLESv2/yagl_glsl_parser.y
index 095bd71..74e5246 100644
--- a/GLESv2/yagl_glsl_parser.y
+++ b/GLESv2/yagl_glsl_parser.y
@@ -329,7 +329,7 @@ expression
yagl_glsl_state_append_output_char(state, $1.c);
if (state->pp_condition_parse_started) {
- yagl_glsl_pp_condition_status status = yagl_glsl_state_pp_condition_resolve(state);
+ yagl_glsl_pp_condition_status status = yagl_glsl_state_pp_condition_resolve(state, NULL);
if (status == yagl_glsl_pp_condition_error) {
yyerror(state, "GLSL preprocessor condition resolution failure");
} else {
@@ -673,10 +673,8 @@ expression
yagl_glsl_state_append_output(state, $1.value);
}
}
-| TOK_UNIFORM TOK_STRING TOK_STRING TOK_STRING TOK_ARR_PAREN_OPEN TOK_INTEGER TOK_ARR_PAREN_CLOSE TOK_EOI
+| TOK_UNIFORM TOK_STRING TOK_STRING TOK_STRING TOK_EOI
{
- char s[100];
-
yagl_glsl_state_flush_pending(state, $1.index);
yagl_glsl_state_append_output(state, $1.value);
yagl_glsl_state_flush_pending(state, $2.index);
@@ -687,15 +685,7 @@ expression
yagl_glsl_state_append_output(state, $4.value);
yagl_glsl_state_flush_pending(state, $5.index);
yagl_glsl_state_append_output_char(state, $5.c);
- yagl_glsl_state_flush_pending(state, $6.index);
- snprintf(s, 100, "%d", $6.value);
- yagl_glsl_state_append_output(state, s);
- yagl_glsl_state_flush_pending(state, $7.index);
- yagl_glsl_state_append_output_char(state, $7.c);
- yagl_glsl_state_flush_pending(state, $8.index);
- yagl_glsl_state_append_output_char(state, $8.c);
- // TODO this should also take into account TOK_INTEGER, because it could be an array of samplers
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
@@ -715,14 +705,13 @@ expression
yagl_glsl_state_add_sampler_2D(state, $4.value);
}
+ yagl_glsl_state_set_last_sampler_array_count(state, 1);
free(type_resolved);
}
}
}
-| TOK_UNIFORM TOK_STRING TOK_STRING TOK_ARR_PAREN_OPEN TOK_INTEGER TOK_ARR_PAREN_CLOSE TOK_EOI
+| TOK_UNIFORM TOK_STRING TOK_STRING TOK_EOI
{
- char s[100];
-
yagl_glsl_state_flush_pending(state, $1.index);
yagl_glsl_state_append_output(state, $1.value);
yagl_glsl_state_flush_pending(state, $2.index);
@@ -731,15 +720,7 @@ expression
yagl_glsl_state_append_output(state, $3.value);
yagl_glsl_state_flush_pending(state, $4.index);
yagl_glsl_state_append_output_char(state, $4.c);
- yagl_glsl_state_flush_pending(state, $5.index);
- snprintf(s, 100, "%d", $5.value);
- yagl_glsl_state_append_output(state, s);
- yagl_glsl_state_flush_pending(state, $6.index);
- yagl_glsl_state_append_output_char(state, $6.c);
- yagl_glsl_state_flush_pending(state, $7.index);
- yagl_glsl_state_append_output_char(state, $7.c);
- // TODO this should also take into account TOK_INTEGER, because it is an array of samplers (not a single sampler)
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
@@ -759,11 +740,12 @@ expression
yagl_glsl_state_add_sampler_2D(state, $3.value);
}
+ yagl_glsl_state_set_last_sampler_array_count(state, 1);
free(type_resolved);
}
}
}
-| TOK_UNIFORM TOK_STRING TOK_STRING TOK_STRING TOK_EOI
+| TOK_UNIFORM TOK_STRING TOK_STRING TOK_STRING TOK_ARR_PAREN_OPEN
{
yagl_glsl_state_flush_pending(state, $1.index);
yagl_glsl_state_append_output(state, $1.value);
@@ -790,16 +772,19 @@ expression
state->have_samplerexternaloes = 1;
}
+ // TODO add how many samplers are added too - check resolution_value
yagl_glsl_state_add_sampler_ExternalOES(state, $4.value);
+ yagl_glsl_state_pp_condition_parse_start(state);
} else if (strcmp(type_resolved, "sampler2D") == 0) {
yagl_glsl_state_add_sampler_2D(state, $4.value);
+ yagl_glsl_state_pp_condition_parse_start(state);
}
free(type_resolved);
}
}
}
-| TOK_UNIFORM TOK_STRING TOK_STRING TOK_EOI
+| TOK_UNIFORM TOK_STRING TOK_STRING TOK_ARR_PAREN_OPEN
{
yagl_glsl_state_flush_pending(state, $1.index);
yagl_glsl_state_append_output(state, $1.value);
@@ -825,14 +810,42 @@ expression
}
yagl_glsl_state_add_sampler_ExternalOES(state, $3.value);
+ yagl_glsl_state_pp_condition_parse_start(state);
} else if (strcmp(type_resolved, "sampler2D") == 0) {
yagl_glsl_state_add_sampler_2D(state, $3.value);
+ yagl_glsl_state_pp_condition_parse_start(state);
}
free(type_resolved);
}
}
}
+| TOK_ARR_PAREN_CLOSE TOK_EOI
+{
+ yagl_glsl_state_flush_pending(state, $1.index);
+ yagl_glsl_state_append_output_char(state, $1.c);
+ yagl_glsl_state_flush_pending(state, $2.index);
+ yagl_glsl_state_append_output_char(state, $2.c);
+
+ // check our expression resolution result to know how many array items we have
+ if (state->pp_condition_parse_started) {
+ int resolution_value = 0;
+ yagl_glsl_pp_condition_status status = yagl_glsl_state_pp_condition_resolve(state, &resolution_value);
+ if (yagl_glsl_state_pp_is_condition_met(state)) {
+ if (status == yagl_glsl_pp_condition_error) {
+ yyerror(state, "GLSL preprocessor expression resolution failure");
+ }
+
+ if (resolution_value <= 0) {
+ yyerror(state, "GLSL declared uniform array of size less than (or equal) to 0");
+ }
+
+ // TODO sampler array is rarely used, but it still has to be properly processed
+ // at samplerExternalOES -> sampler2D substitution stage
+ yagl_glsl_state_set_last_sampler_array_count(state, resolution_value);
+ }
+ }
+}
| TOK_TEXTURE1D
{
yagl_glsl_state_flush_pending(state, $1.index);
diff --git a/GLESv2/yagl_glsl_state.c b/GLESv2/yagl_glsl_state.c
index c6e9f48..86190ec 100644
--- a/GLESv2/yagl_glsl_state.c
+++ b/GLESv2/yagl_glsl_state.c
@@ -408,8 +408,11 @@ void yagl_glsl_state_add_sampler_ExternalOES(struct yagl_glsl_state *state,
sampler.name = strdup(str);
sampler.location = YAGL_GLSL_SAMPLER_LOCATION_UNKNOWN;
sampler.value = 0; // GL spec predefines uniform value as 0
+ sampler.count = YAGL_GLSL_SAMPLER_DEFAULT_COUNT; // real count provided by yagl_glsl_state_set_last_sampler_array_count
sampler.replaced_tex2d = YAGL_GLSL_SAMPLER_VALUE_UNKNOWN;
yagl_vector_push_back(&state->samplers_ExternalOES, &sampler);
+
+ state->last_declared_sampler_externaloes = 1;
}
void yagl_glsl_state_add_sampler_2D(struct yagl_glsl_state *state,
@@ -419,8 +422,31 @@ void yagl_glsl_state_add_sampler_2D(struct yagl_glsl_state *state,
sampler.name = strdup(str);
sampler.location = YAGL_GLSL_SAMPLER_LOCATION_UNKNOWN;
sampler.value = 0; // GL spec predefines uniform value as 0
+ sampler.count = YAGL_GLSL_SAMPLER_DEFAULT_COUNT; // real count provided by yagl_glsl_state_set_last_sampler_array_count
sampler.replaced_tex2d = YAGL_GLSL_SAMPLER_VALUE_UNKNOWN;
yagl_vector_push_back(&state->samplers_2D, &sampler);
+
+ state->last_declared_sampler_externaloes = 0;
+}
+
+void yagl_glsl_state_set_last_sampler_array_count(struct yagl_glsl_state *state, int count)
+{
+ assert(state->last_declared_sampler_externaloes != -1);
+
+ struct yagl_vector *samplers = NULL;
+ if (state->last_declared_sampler_externaloes) {
+ samplers = &state->samplers_ExternalOES;
+ } else {
+ samplers = &state->samplers_2D;
+ }
+
+ int samplers_size = yagl_vector_size(samplers);
+ assert(samplers_size > 0);
+ struct yagl_glsl_sampler *samplers_data = (struct yagl_glsl_sampler *)yagl_vector_data(samplers);
+ samplers_data += samplers_size - 1;
+ samplers_data->count = count;
+
+ state->last_declared_sampler_externaloes = -1;
}
void yagl_glsl_state_pp_add_define_string(struct yagl_glsl_state *state,
@@ -583,6 +609,8 @@ int yagl_glsl_state_pp_is_condition_completed(struct yagl_glsl_state *state)
void yagl_glsl_state_pp_condition_parse_start(struct yagl_glsl_state *state)
{
+ assert(!state->pp_condition_parse_started);
+
// initialize expression stack and operation stack for RPN
memset(state->pp_exprs, 0, sizeof(struct yagl_glsl_pp_expr) * YAGL_GLSL_PP_EXPRESSION_STACK_SIZE);
state->pp_current_expr = 0;
@@ -785,7 +813,8 @@ static inline int yagl_glsl_pp_expr_op_is_unary(yagl_glsl_pp_expr_op op)
}
}
-yagl_glsl_pp_condition_status 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,
+ int *resolution_value)
{
struct yagl_glsl_pp_token res_stack[YAGL_GLSL_PP_EXPRESSION_STACK_SIZE];
int res_cur = 0;
@@ -794,6 +823,8 @@ yagl_glsl_pp_condition_status yagl_glsl_state_pp_condition_resolve(struct yagl_g
yagl_glsl_pp_condition_status result = yagl_glsl_pp_condition_not_met;
YAGL_LOG_FUNC_SET(yagl_glsl_state_pp_condition_resolve);
+ assert(state->pp_condition_parse_started);
+
// empty op stack into expression stack
while (state->pp_current_op > 0) {
assert(state->pp_current_expr < YAGL_GLSL_PP_EXPRESSION_STACK_SIZE);
@@ -837,7 +868,29 @@ yagl_glsl_pp_condition_status yagl_glsl_state_pp_condition_resolve(struct yagl_g
// there should be only one resolution on stack remaining - the result
assert(res_cur == 1);
- result = (res_stack[res_cur - 1].value > 0 ? yagl_glsl_pp_condition_met : yagl_glsl_pp_condition_not_met);
+
+ // in some cases resolution can be just a preprocessor macro - try resolving it
+ int result_value = 0;
+ if (res_stack[res_cur - 1].macro != NULL) {
+ char* define_resolution = NULL; // should stay null, but if it doesn't it's syntax error
+ yagl_glsl_state_pp_resolve_define(state, res_stack[res_cur - 1].macro, &define_resolution, &result_value);
+ if (define_resolution != NULL) {
+ // error - macro did not become a constant, cannot evaluate result
+ YAGL_LOG_ERROR("Expression resolution error - macro %s did not evaluate to integer constant", res_stack[res_cur - 1].macro);
+ result = yagl_glsl_pp_condition_error;
+ yagl_free(define_resolution);
+ goto clean;
+ }
+ } else {
+ result_value = res_stack[res_cur - 1].value;
+ }
+
+ // determine final result (and pass the value if it's needed)
+ result = (result_value > 0 ? yagl_glsl_pp_condition_met : yagl_glsl_pp_condition_not_met);
+ if (resolution_value != NULL) {
+ *resolution_value = result_value;
+ YAGL_LOG_TRACE("Expression resolution value: %d", *resolution_value);
+ }
clean:
// cleanup
diff --git a/GLESv2/yagl_glsl_state.h b/GLESv2/yagl_glsl_state.h
index 1d334da..fedd211 100644
--- a/GLESv2/yagl_glsl_state.h
+++ b/GLESv2/yagl_glsl_state.h
@@ -51,6 +51,7 @@ struct yagl_glsl_pending
#define YAGL_GLSL_SAMPLER_LOCATION_UNKNOWN (-1)
#define YAGL_GLSL_SAMPLER_VALUE_UNKNOWN (-1)
+#define YAGL_GLSL_SAMPLER_DEFAULT_COUNT (0)
#define YAGL_GLSL_PP_CONDITION_STACK_SIZE 32
#define YAGL_GLSL_PP_EXPRESSION_STACK_SIZE 128
#define YAGL_GLSL_PP_OPERATION_STACK_SIZE 64
@@ -67,6 +68,7 @@ struct yagl_glsl_sampler
char* name;
int location;
int value;
+ int count; // for uniform array support
int replaced_tex2d; // only used in samplerExternalOES handling
};
@@ -186,6 +188,9 @@ struct yagl_glsl_state
int texturecube_declared;
int texturecubelod_declared;
+ // used for determining which sampler group was used last
+ int last_declared_sampler_externaloes;
+
// Each token is assigned an index.
int token_index;
@@ -294,6 +299,10 @@ 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);
+// Reaches last added sampler (ExternalOES or 2D) and adds information on how many samplers there are
+// count can be 1 for singular samplers and more for sampler arrays
+void yagl_glsl_state_set_last_sampler_array_count(struct yagl_glsl_state *state, int count);
+
/*
* GLSL Preprocessor control functions
* @{
@@ -335,7 +344,8 @@ 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
-yagl_glsl_pp_condition_status yagl_glsl_state_pp_condition_resolve(struct yagl_glsl_state *state);
+// detailed information on resolution value can be optionally acquired via resolution_value param
+yagl_glsl_pp_condition_status yagl_glsl_state_pp_condition_resolve(struct yagl_glsl_state *state, int *resolution_value);
/*
* @}
*/