From: Tapani Pälli Date: Tue, 19 May 2015 12:01:49 +0000 (+0300) Subject: glsl: validate sampler array indexing for 'constant-index-expression' X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=9350ea6979c48772e1fb55d4f1c7c5a3cfa987b0;p=mesa.git glsl: validate sampler array indexing for 'constant-index-expression' Desktop GLSL < 130 and GLSL ES < 300 allow sampler array indexing where index can contain a loop induction variable. This extra check will warn during linking if some of the indexes could not be turned in to constant expressions. v2: warning instead of error for backends that did not enable EmitNoIndirectSampler option (have dynamic indexing) Signed-off-by: Tapani Pälli Reviewed-by: Francisco Jerez Cc: "10.5" and "10.6" --- diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp index 4a726d4e2e7..74c2f2d4c92 100644 --- a/src/glsl/linker.cpp +++ b/src/glsl/linker.cpp @@ -346,6 +346,39 @@ private: bool uses_non_zero_stream; }; +/* Class that finds array derefs and check if indexes are dynamic. */ +class dynamic_sampler_array_indexing_visitor : public ir_hierarchical_visitor +{ +public: + dynamic_sampler_array_indexing_visitor() : + dynamic_sampler_array_indexing(false) + { + } + + ir_visitor_status visit_enter(ir_dereference_array *ir) + { + if (!ir->variable_referenced()) + return visit_continue; + + if (!ir->variable_referenced()->type->contains_sampler()) + return visit_continue; + + if (!ir->array_index->constant_expression_value()) { + dynamic_sampler_array_indexing = true; + return visit_stop; + } + return visit_continue; + } + + bool uses_dynamic_sampler_array_indexing() + { + return dynamic_sampler_array_indexing; + } + +private: + bool dynamic_sampler_array_indexing; +}; + } /* anonymous namespace */ void @@ -2743,6 +2776,40 @@ build_program_resource_list(struct gl_context *ctx, */ } +/** + * This check is done to make sure we allow only constant expression + * indexing and "constant-index-expression" (indexing with an expression + * that includes loop induction variable). + */ +static bool +validate_sampler_array_indexing(struct gl_context *ctx, + struct gl_shader_program *prog) +{ + dynamic_sampler_array_indexing_visitor v; + for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { + if (prog->_LinkedShaders[i] == NULL) + continue; + + bool no_dynamic_indexing = + ctx->Const.ShaderCompilerOptions[i].EmitNoIndirectSampler; + + /* Search for array derefs in shader. */ + v.run(prog->_LinkedShaders[i]->ir); + if (v.uses_dynamic_sampler_array_indexing()) { + const char *msg = "sampler arrays indexed with non-constant " + "expressions is forbidden in GLSL %s %u"; + /* Backend has indicated that it has no dynamic indexing support. */ + if (no_dynamic_indexing) { + linker_error(prog, msg, prog->IsES ? "ES" : "", prog->Version); + return false; + } else { + linker_warning(prog, msg, prog->IsES ? "ES" : "", prog->Version); + } + } + } + return true; +} + void link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) @@ -2961,6 +3028,16 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) lower_const_arrays_to_uniforms(prog->_LinkedShaders[i]->ir); } + /* Validation for special cases where we allow sampler array indexing + * with loop induction variable. This check emits a warning or error + * depending if backend can handle dynamic indexing. + */ + if ((!prog->IsES && prog->Version < 130) || + (prog->IsES && prog->Version < 300)) { + if (!validate_sampler_array_indexing(ctx, prog)) + goto done; + } + /* Check and validate stream emissions in geometry shaders */ validate_geometry_shader_emissions(ctx, prog);