glsl, nir: Make ir_triop_bitfield_extract a vectorized operation.
authorKenneth Graunke <kenneth@whitecape.org>
Fri, 8 Jan 2016 00:01:51 +0000 (16:01 -0800)
committerMatt Turner <mattst88@gmail.com>
Wed, 13 Jan 2016 18:35:12 +0000 (10:35 -0800)
We would like to be able to combine

   result.x = bitfieldExtract(src0.x, src1.x, src2.x);
   result.y = bitfieldExtract(src0.y, src1.y, src2.y);
   result.z = bitfieldExtract(src0.z, src1.z, src2.z);
   result.w = bitfieldExtract(src0.w, src1.w, src2.w);

into a single ivec4 bitfieldInsert operation.  This should be possible
with most drivers.

This patch changes the offset and bits parameters from scalar ints
to ivecN or uvecN.  The type of all three operands will be the same,
for simplicity.

Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Matt Turner <mattst88@gmail.com>
Reviewed-by: Ilia Mirkin <imirkin@alum.mit.edu>
src/glsl/builtin_functions.cpp
src/glsl/ir.h
src/glsl/ir_constant_expression.cpp
src/glsl/ir_validate.cpp
src/glsl/lower_packing_builtins.cpp
src/glsl/nir/nir_opcodes.py

index 38383bc1988791d39acafd58d75a56e692b05bc6..f2e2165e8c3af85b555549bbafd57addf5bb3984 100644 (file)
@@ -4889,12 +4889,18 @@ builtin_builder::_noise4(const glsl_type *type)
 ir_function_signature *
 builtin_builder::_bitfieldExtract(const glsl_type *type)
 {
+   bool is_uint = type->base_type == GLSL_TYPE_UINT;
    ir_variable *value  = in_var(type, "value");
    ir_variable *offset = in_var(glsl_type::int_type, "offset");
    ir_variable *bits   = in_var(glsl_type::int_type, "bits");
    MAKE_SIG(type, gpu_shader5_or_es31, 3, value, offset, bits);
 
-   body.emit(ret(expr(ir_triop_bitfield_extract, value, offset, bits)));
+   operand cast_offset = is_uint ? i2u(offset) : operand(offset);
+   operand cast_bits = is_uint ? i2u(bits) : operand(bits);
+
+   body.emit(ret(expr(ir_triop_bitfield_extract, value,
+      swizzle(cast_offset, SWIZZLE_XXXX, type->vector_elements),
+      swizzle(cast_bits, SWIZZLE_XXXX, type->vector_elements))));
 
    return sig;
 }
index 9af2fc16e16f9e8570c28ace99eb5e468eb1ff52..5b845c6e856354d5f938a4d14ff522724a34bdaa 100644 (file)
@@ -1708,9 +1708,7 @@ public:
              operation == ir_binop_dot ||
              operation == ir_binop_vector_extract ||
              operation == ir_triop_vector_insert ||
-             operation == ir_quadop_vector ||
-             /* TODO: these can't currently be vectorized */
-             operation == ir_triop_bitfield_extract;
+             operation == ir_quadop_vector;
    }
 
    /**
index f5b5bd87b6b13c962feb28dc1f7ff5191b3d24e9..7613139306ffc03c47dbb8e9124fa6dfa978389d 100644 (file)
@@ -1588,10 +1588,10 @@ ir_expression::constant_expression_value(struct hash_table *variable_context)
       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++) {
+         int offset = op[1]->value.i[c];
+         int bits = op[2]->value.i[c];
+
          if (bits == 0)
             data.u[c] = 0;
          else if (offset < 0 || bits < 0)
index fea9b760eca803ab3818f35feb52648b05a6c312..94814799b9b9734ebbde2d626261e00d42be7fc3 100644 (file)
@@ -632,9 +632,10 @@ ir_validate::visit_leave(ir_expression *ir)
       break;
 
    case ir_triop_bitfield_extract:
+      assert(ir->type->is_integer());
       assert(ir->operands[0]->type == ir->type);
-      assert(ir->operands[1]->type == glsl_type::int_type);
-      assert(ir->operands[2]->type == glsl_type::int_type);
+      assert(ir->operands[1]->type == ir->type);
+      assert(ir->operands[2]->type == ir->type);
       break;
 
    case ir_triop_vector_insert:
index 19eeaa3775c5928066d0fc50f10fa677dbfa3e72..7f18238bc6eb3333b864d704d0f62fdf4c0adb2b 100644 (file)
@@ -365,11 +365,11 @@ private:
 
       if (op_mask & LOWER_PACK_USE_BFE) {
          /* u4.y = bitfield_extract(u, 8, 8); */
-         factory.emit(assign(u4, bitfield_extract(u, constant(8), constant(8)),
+         factory.emit(assign(u4, bitfield_extract(u, constant(8u), constant(8u)),
                              WRITEMASK_Y));
 
          /* u4.z = bitfield_extract(u, 16, 8); */
-         factory.emit(assign(u4, bitfield_extract(u, constant(16), constant(8)),
+         factory.emit(assign(u4, bitfield_extract(u, constant(16u), constant(8u)),
                              WRITEMASK_Z));
       } else {
          /* u4.y = (u >> 8u) & 0xffu; */
index 3780628d1ea9faba25f3613ec5770be0558019a3..855095f1f35bb03b90576e13d4aedf8eb838915f 100644 (file)
@@ -570,9 +570,9 @@ if (mask == 0) {
 """)
 
 opcode("ubitfield_extract", 0, tuint,
-       [0, 1, 1], [tuint, tint, tint], "", """
+       [0, 0, 0], [tuint, tint, tint], "", """
 unsigned base = src0;
-int offset = src1.x, bits = src2.x;
+int offset = src1, bits = src2;
 if (bits == 0) {
    dst = 0;
 } else if (bits < 0 || offset < 0 || offset + bits > 32) {
@@ -582,9 +582,9 @@ if (bits == 0) {
 }
 """)
 opcode("ibitfield_extract", 0, tint,
-       [0, 1, 1], [tint, tint, tint], "", """
+       [0, 0, 0], [tint, tint, tint], "", """
 int base = src0;
-int offset = src1.x, bits = src2.x;
+int offset = src1, bits = src2;
 if (bits == 0) {
    dst = 0;
 } else if (offset < 0 || bits < 0 || offset + bits > 32) {