diff options
author | Olivier Galibert <[email protected]> | 2012-05-08 20:40:35 +0200 |
---|---|---|
committer | Kenneth Graunke <[email protected]> | 2012-06-07 00:06:18 -0700 |
commit | abe976755318fa9dd88a5c48289623ab7c12ce02 (patch) | |
tree | 6921bd0f129efc5e2c3ca41afe1f8b12d2ed2579 | |
parent | 1b8a3aad09d67e72903fdcc79beadfc3c77cae62 (diff) |
glsl: Bitwise conversion operator support in ir_constant_expression.
A "test_out = floatBitsToUint(-1.0);" fired through the GLSL compiler
gives a correct "(assign (x) (var_ref test_out)
(constant uint (3212836864)))"
Signed-off-by: Olivier Galibert <[email protected]>
Reviewed-by: Kenneth Graunke <[email protected]>
-rw-r--r-- | src/glsl/ir_constant_expression.cpp | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/src/glsl/ir_constant_expression.cpp b/src/glsl/ir_constant_expression.cpp index 08a33285b3a..7a4d15f43fb 100644 --- a/src/glsl/ir_constant_expression.cpp +++ b/src/glsl/ir_constant_expression.cpp @@ -71,6 +71,29 @@ dot(ir_constant *op0, ir_constant *op1) return result; } +/* This method is the only one supported by gcc. Unions in particular + * are iffy, and read-through-converted-pointer is killed by strict + * aliasing. OTOH, the compiler sees through the memcpy, so the + * resulting asm is reasonable. + */ +static float +bitcast_u2f(unsigned int u) +{ + assert(sizeof(float) == sizeof(unsigned int)); + float f; + memcpy(&f, &u, sizeof(f)); + return f; +} + +static unsigned int +bitcast_f2u(float f) +{ + assert(sizeof(float) == sizeof(unsigned int)); + unsigned int u; + memcpy(&u, &f, sizeof(f)); + return u; +} + ir_constant * ir_rvalue::constant_expression_value(struct hash_table *variable_context) { @@ -207,6 +230,30 @@ ir_expression::constant_expression_value(struct hash_table *variable_context) data.u[c] = op[0]->value.i[c]; } break; + case ir_unop_bitcast_i2f: + assert(op[0]->type->base_type == GLSL_TYPE_INT); + for (unsigned c = 0; c < op[0]->type->components(); c++) { + data.f[c] = bitcast_u2f(op[0]->value.i[c]); + } + break; + case ir_unop_bitcast_f2i: + assert(op[0]->type->base_type == GLSL_TYPE_FLOAT); + for (unsigned c = 0; c < op[0]->type->components(); c++) { + data.i[c] = bitcast_f2u(op[0]->value.f[c]); + } + break; + case ir_unop_bitcast_u2f: + assert(op[0]->type->base_type == GLSL_TYPE_UINT); + for (unsigned c = 0; c < op[0]->type->components(); c++) { + data.f[c] = bitcast_u2f(op[0]->value.u[c]); + } + break; + case ir_unop_bitcast_f2u: + assert(op[0]->type->base_type == GLSL_TYPE_FLOAT); + for (unsigned c = 0; c < op[0]->type->components(); c++) { + data.u[c] = bitcast_f2u(op[0]->value.f[c]); + } + break; case ir_unop_any: assert(op[0]->type->is_boolean()); data.b[0] = false; |