summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Romanick <ian.d.romanick@intel.com>2011-11-07 10:58:00 -0800
committerIan Romanick <ian.d.romanick@intel.com>2012-01-03 19:23:15 -0800
commitbc507471db615be3638aaf779316debe91542180 (patch)
tree816ccd4c90b655d524b74d40ff127d9634657c74
parent42d1a7b3de0907945a09ecc797afb01450da321e (diff)
glsl: Clamp vector indices when lowering to swizzles
This prevents other code from seeing a swizzle of the 16th component of a vector, for example. NOTE: This is a candidate for the 7.11 branch. Signed-off-by: Ian Romanick <ian.d.romanick@intel.com> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=42517 Reviewed-by: Kenneth Graunke <kenneth@whitecape.org> Reviewed-by: Paul Berry <stereotype441@gmail.com> Tested-by: Christian Holler <choller@mozilla.com> (cherry picked from commit 6f5c73797087c6e7842665f84e41caedea59bb65)
-rw-r--r--src/glsl/lower_vec_index_to_swizzle.cpp22
1 files changed, 20 insertions, 2 deletions
diff --git a/src/glsl/lower_vec_index_to_swizzle.cpp b/src/glsl/lower_vec_index_to_swizzle.cpp
index c7630c28a83..46fd6ace1b6 100644
--- a/src/glsl/lower_vec_index_to_swizzle.cpp
+++ b/src/glsl/lower_vec_index_to_swizzle.cpp
@@ -33,6 +33,7 @@
#include "ir_visitor.h"
#include "ir_optimization.h"
#include "glsl_types.h"
+#include "main/macros.h"
/**
* Visitor class for replacing expressions with ir_constant values.
@@ -76,8 +77,25 @@ ir_vec_index_to_swizzle_visitor::convert_vec_index_to_swizzle(ir_rvalue *ir)
void *ctx = ralloc_parent(ir);
this->progress = true;
- return new(ctx) ir_swizzle(deref->array,
- ir_constant->value.i[0], 0, 0, 0, 1);
+
+ /* Page 40 of the GLSL 1.20 spec says:
+ *
+ * "When indexing with non-constant expressions, behavior is undefined
+ * if the index is negative, or greater than or equal to the size of
+ * the vector."
+ *
+ * The quoted spec text mentions non-constant expressions, but this code
+ * operates on constants. These constants are the result of non-constant
+ * expressions that have been optimized to constants. The common case here
+ * is a loop counter from an unrolled loop that is used to index a vector.
+ *
+ * The ir_swizzle constructor gets angry if the index is negative or too
+ * large. For simplicity sake, just clamp the index to [0, size-1].
+ */
+ const int i = MIN2(MAX2(ir_constant->value.i[0], 0),
+ (deref->array->type->vector_elements - 1));
+
+ return new(ctx) ir_swizzle(deref->array, i, 0, 0, 0, 1);
}
ir_visitor_status