From 6bdf999a1adcf14931325ebbd903a63e41f86541 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tapani=20P=C3=A4lli?= Date: Wed, 1 Apr 2015 11:17:42 +0300 Subject: [PATCH] glsl: detect sampler array indexing with loop variable WIP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Patch adds additional pass to array index checking, this pass detects if we are inside a loop and if the given array index references only one variable and if this variable is the loop induction variable. This makes is possible to allow 'constant index expression' in sampler arrays with OpenGL ES 2.0. Signed-off-by: Tapani Pälli Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=84225 --- src/glsl/ast_array_index.cpp | 98 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/src/glsl/ast_array_index.cpp b/src/glsl/ast_array_index.cpp index ecef651..e676827 100644 --- a/src/glsl/ast_array_index.cpp +++ b/src/glsl/ast_array_index.cpp @@ -25,6 +25,61 @@ #include "glsl_types.h" #include "ir.h" +#include "ir_hierarchical_visitor.h" + +/* Class to find if there is only one variable dereference + * in the traversed ir. + */ +class single_ref : public ir_hierarchical_visitor +{ +public: + explicit single_ref() : + dref(NULL) + { + } + + ir_visitor_status visit(ir_dereference_variable *ir) + { + /* "There can be only one." */ + if (dref) { + dref = NULL; + return visit_stop; + } + + dref = ir; + return visit_continue; + } + + ir_dereference_variable *dref; +}; + + +/* Class to find out if given variable is the only + * variable referenced in the traversed ir. + */ +class single_var_finder : public ir_hierarchical_visitor +{ +public: + explicit single_var_finder(ir_variable *var) : + other_vars(false), + var(var) + { + } + + ir_visitor_status visit(ir_dereference_variable *ir) + { + if (ir->variable_referenced() != var) { + other_vars = true; + return visit_stop; + } + + return visit_continue; + } + + bool other_vars; + ir_variable *var; +}; + void ast_array_specifier::print(void) const { @@ -106,6 +161,41 @@ update_max_array_access(ir_rvalue *ir, int idx, YYLTYPE *loc, } } +static bool +constant_expression_check(struct _mesa_glsl_parse_state *state, + ir_rvalue *idx) +{ + if (!state->loop_nesting_ast) + return false; + + /* First find out if idx contains only one variable dereference, + * if only one then we can continue to check if this is the loop + * induction variable. + */ + single_ref sref; + + exec_list tmp; + tmp.push_head(idx); + sref.run(&tmp); + + ir_dereference_variable *dref = sref.dref; + + if (!dref) + return false; + + /* Check if the parsed loop condition contains only single + * variable reference, same as referenced by idx. + */ + exec_list loop_cond; + state->loop_nesting_ast->condition_to_hir(&loop_cond, state); + single_var_finder finder(dref->variable_referenced()); + finder.run(&loop_cond); + + if (finder.other_vars) + return false; + + return true; +} ir_rvalue * _mesa_ast_array_index_to_hir(void *mem_ctx, @@ -226,6 +316,12 @@ _mesa_ast_array_index_to_hir(void *mem_ctx, * dynamically uniform expression is undefined. */ if (array->type->element_type()->is_sampler()) { + + /* Check if we are indexing with a loop induction variable. + */ + if (constant_expression_check(state, idx)) + goto generate_ir; + if (!state->is_version(130, 100)) { if (state->es_shader) { _mesa_glsl_warning(&loc, state, @@ -247,6 +343,8 @@ _mesa_ast_array_index_to_hir(void *mem_ctx, } } +generate_ir: + /* After performing all of the error checking, generate the IR for the * expression. */ -- 2.1.0