aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/glsl/ir_constant_expression.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src/glsl/ir_constant_expression.cpp')
-rw-r--r--mesalib/src/glsl/ir_constant_expression.cpp185
1 files changed, 182 insertions, 3 deletions
diff --git a/mesalib/src/glsl/ir_constant_expression.cpp b/mesalib/src/glsl/ir_constant_expression.cpp
index c09e56a3d..0a725b45b 100644
--- a/mesalib/src/glsl/ir_constant_expression.cpp
+++ b/mesalib/src/glsl/ir_constant_expression.cpp
@@ -391,9 +391,17 @@ ir_expression::constant_expression_value(struct hash_table *variable_context)
}
if (op[1] != NULL)
- assert(op[0]->type->base_type == op[1]->type->base_type ||
- this->operation == ir_binop_lshift ||
- this->operation == ir_binop_rshift);
+ switch (this->operation) {
+ case ir_binop_lshift:
+ case ir_binop_rshift:
+ case ir_binop_vector_extract:
+ case ir_triop_bitfield_extract:
+ break;
+
+ default:
+ assert(op[0]->type->base_type == op[1]->type->base_type);
+ break;
+ }
bool op0_scalar = op[0]->type->is_scalar();
bool op1_scalar = op[1] != NULL && op[1]->type->is_scalar();
@@ -1230,6 +1238,29 @@ ir_expression::constant_expression_value(struct hash_table *variable_context)
}
break;
+ case ir_binop_vector_extract: {
+ const int c = CLAMP(op[1]->value.i[0], 0,
+ (int) op[0]->type->vector_elements - 1);
+
+ switch (op[0]->type->base_type) {
+ case GLSL_TYPE_UINT:
+ data.u[0] = op[0]->value.u[c];
+ break;
+ case GLSL_TYPE_INT:
+ data.i[0] = op[0]->value.i[c];
+ break;
+ case GLSL_TYPE_FLOAT:
+ data.f[0] = op[0]->value.f[c];
+ break;
+ case GLSL_TYPE_BOOL:
+ data.b[0] = op[0]->value.b[c];
+ break;
+ default:
+ assert(0);
+ }
+ break;
+ }
+
case ir_binop_bit_xor:
for (unsigned c = 0, c0 = 0, c1 = 0;
c < components;
@@ -1248,6 +1279,102 @@ ir_expression::constant_expression_value(struct hash_table *variable_context)
}
break;
+ case ir_unop_bitfield_reverse:
+ /* http://graphics.stanford.edu/~seander/bithacks.html#BitReverseObvious */
+ for (unsigned c = 0; c < components; c++) {
+ unsigned int v = op[0]->value.u[c]; // input bits to be reversed
+ unsigned int r = v; // r will be reversed bits of v; first get LSB of v
+ int s = sizeof(v) * CHAR_BIT - 1; // extra shift needed at end
+
+ for (v >>= 1; v; v >>= 1) {
+ r <<= 1;
+ r |= v & 1;
+ s--;
+ }
+ r <<= s; // shift when v's highest bits are zero
+
+ data.u[c] = r;
+ }
+ break;
+
+ case ir_unop_bit_count:
+ for (unsigned c = 0; c < components; c++) {
+ unsigned count = 0;
+ unsigned v = op[0]->value.u[c];
+
+ for (; v; count++) {
+ v &= v - 1;
+ }
+ data.u[c] = count;
+ }
+ break;
+
+ case ir_unop_find_msb:
+ for (unsigned c = 0; c < components; c++) {
+ int v = op[0]->value.i[c];
+
+ if (v == 0 || (op[0]->type->base_type == GLSL_TYPE_INT && v == -1))
+ data.i[c] = -1;
+ else {
+ int count = 0;
+ int top_bit = op[0]->type->base_type == GLSL_TYPE_UINT
+ ? 0 : v & (1 << 31);
+
+ while (((v & (1 << 31)) == top_bit) && count != 32) {
+ count++;
+ v <<= 1;
+ }
+
+ data.i[c] = 31 - count;
+ }
+ }
+ break;
+
+ case ir_unop_find_lsb:
+ for (unsigned c = 0; c < components; c++) {
+ if (op[0]->value.i[c] == 0)
+ data.i[c] = -1;
+ else {
+ unsigned pos = 0;
+ unsigned v = op[0]->value.u[c];
+
+ for (; !(v & 1); v >>= 1) {
+ pos++;
+ }
+ data.u[c] = pos;
+ }
+ }
+ break;
+
+ case ir_triop_bitfield_extract: {
+ int offset = op[1]->value.i[0];
+ int bits = op[2]->value.i[0];
+
+ for (unsigned c = 0; c < components; c++) {
+ if (bits == 0)
+ data.u[c] = 0;
+ else if (offset < 0 || bits < 0)
+ data.u[c] = 0; /* Undefined, per spec. */
+ else if (offset + bits > 32)
+ data.u[c] = 0; /* Undefined, per spec. */
+ else {
+ if (op[0]->type->base_type == GLSL_TYPE_INT) {
+ /* int so that the right shift will sign-extend. */
+ int value = op[0]->value.i[c];
+ value <<= 32 - bits - offset;
+ value >>= 32 - bits;
+ data.i[c] = value;
+ } else {
+ unsigned value = op[0]->value.u[c];
+ value <<= 32 - bits - offset;
+ value >>= 32 - bits;
+ data.u[c] = value;
+ }
+ }
+ }
+ break;
+ }
+
case ir_triop_lrp: {
assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
assert(op[1]->type->base_type == GLSL_TYPE_FLOAT);
@@ -1261,6 +1388,58 @@ ir_expression::constant_expression_value(struct hash_table *variable_context)
break;
}
+ case ir_triop_vector_insert: {
+ const unsigned idx = op[2]->value.u[0];
+
+ memcpy(&data, &op[0]->value, sizeof(data));
+
+ switch (this->type->base_type) {
+ case GLSL_TYPE_INT:
+ data.i[idx] = op[1]->value.i[0];
+ break;
+ case GLSL_TYPE_UINT:
+ data.u[idx] = op[1]->value.u[0];
+ break;
+ case GLSL_TYPE_FLOAT:
+ data.f[idx] = op[1]->value.f[0];
+ break;
+ case GLSL_TYPE_BOOL:
+ data.b[idx] = op[1]->value.b[0];
+ break;
+ default:
+ assert(!"Should not get here.");
+ break;
+ }
+ break;
+ }
+
+ case ir_quadop_bitfield_insert: {
+ int offset = op[2]->value.i[0];
+ int bits = op[3]->value.i[0];
+
+ for (unsigned c = 0; c < components; c++) {
+ if (bits == 0)
+ data.u[c] = op[0]->value.u[c];
+ else if (offset < 0 || bits < 0)
+ data.u[c] = 0; /* Undefined, per spec. */
+ else if (offset + bits > 32)
+ data.u[c] = 0; /* Undefined, per spec. */
+ else {
+ unsigned insert_mask = ((1 << bits) - 1) << offset;
+
+ unsigned insert = op[1]->value.u[c];
+ insert <<= offset;
+ insert &= insert_mask;
+
+ unsigned base = op[0]->value.u[c];
+ base &= ~insert_mask;
+
+ data.u[c] = base | insert;
+ }
+ }
+ break;
+ }
+
case ir_quadop_vector:
for (unsigned c = 0; c < this->type->vector_elements; c++) {
switch (this->type->base_type) {