diff options
author | Paul Berry <[email protected]> | 2013-07-31 11:25:13 -0700 |
---|---|---|
committer | Paul Berry <[email protected]> | 2013-08-01 20:19:39 -0700 |
commit | cea946e39d62b95139b2d16520bf7b9b509d5fbc (patch) | |
tree | c2a66ce2ed1f77f2e9044b0d61c5acbf411a63ea | |
parent | 1c789d8087327203d3dcf5c140bf9d9c65b86086 (diff) |
glsl: In ir_set_program_inouts, handle indexing outside array/matrix bounds.
According to GLSL, indexing into an array or matrix with an
out-of-range constant results in a compile error. However, indexing
with an out-of-range value that isn't constant merely results in
undefined results.
Since optimization passes (e.g. loop unrolling) can convert
non-constant array indices into constant array indices, it's possible
that ir_set_program_inouts will encounter a constant array index that
is out of range; if this happens, just mark the whole array as used.
Reviewed-by: Ian Romanick <[email protected]>
Reviewed-by: Kenneth Graunke <[email protected]>
-rw-r--r-- | src/glsl/ir_set_program_inouts.cpp | 31 |
1 files changed, 26 insertions, 5 deletions
diff --git a/src/glsl/ir_set_program_inouts.cpp b/src/glsl/ir_set_program_inouts.cpp index ea55447ea05..27c3ca70e5a 100644 --- a/src/glsl/ir_set_program_inouts.cpp +++ b/src/glsl/ir_set_program_inouts.cpp @@ -171,13 +171,34 @@ ir_set_program_inouts_visitor::try_mark_partial_variable(ir_variable *var, if (!index_as_constant) return false; - int width = 1; - if (type->is_array() && type->fields.array->is_matrix()) { - width = type->fields.array->matrix_columns; + unsigned elem_width; + unsigned num_elems; + if (type->is_array()) { + num_elems = type->length; + if (type->fields.array->is_matrix()) + elem_width = type->fields.array->matrix_columns; + else + elem_width = 1; + } else { + num_elems = type->matrix_columns; + elem_width = 1; } - mark(this->prog, var, index_as_constant->value.u[0] * width, width, - this->shader_type == GL_FRAGMENT_SHADER); + if (index_as_constant->value.u[0] >= num_elems) { + /* Constant index outside the bounds of the matrix/array. This could + * arise as a result of constant folding of a legal GLSL program. + * + * Even though the spec says that indexing outside the bounds of a + * matrix/array results in undefined behaviour, we don't want to pass + * out-of-range values to mark() (since this could result in slots that + * don't exist being marked as used), so just let the caller mark the + * whole variable as used. + */ + return false; + } + + mark(this->prog, var, index_as_constant->value.u[0] * elem_width, + elem_width, this->shader_type == GL_FRAGMENT_SHADER); return true; } |