i965/fs: Add support for loading uniform buffer variables as pull constants.
authorEric Anholt <eric@anholt.net>
Wed, 20 Jun 2012 22:55:13 +0000 (15:55 -0700)
committerEric Anholt <eric@anholt.net>
Tue, 7 Aug 2012 20:54:51 +0000 (13:54 -0700)
Variable array indexing isn't finished, because the lowering pass
turns it all into conditional moves of constant index accesses so I
can't test it.

Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
src/mesa/drivers/dri/i965/brw_fs.cpp
src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
src/mesa/drivers/dri/i965/brw_shader.cpp

index cb89d746f34ab1b89bdff963a1556fa49ded5f73..90dddce8670743b6a93d2148ab9d8f6bd4fb67cc 100644 (file)
@@ -1378,6 +1378,11 @@ fs_visitor::propagate_constants()
               }
               break;
 
+            case FS_OPCODE_PULL_CONSTANT_LOAD:
+              scan_inst->src[i] = inst->src[0];
+              progress = true;
+              break;
+
            default:
               break;
            }
index 1e18e92de54ad294849775d1926a5d1272e32c83..7a2f77755679e23c4a1b1414fadcff92d91f5bac 100644 (file)
@@ -104,6 +104,13 @@ fs_visitor::visit(ir_variable *ir)
    } else if (ir->mode == ir_var_uniform) {
       int param_index = c->prog_data.nr_params;
 
+      /* Thanks to the lower_ubo_reference pass, we will see only
+       * ir_binop_ubo_load expressions and not ir_dereference_variable for UBO
+       * variables, so no need for them to be in variable_ht.
+       */
+      if (ir->uniform_block != -1)
+         return;
+
       if (c->dispatch_width == 16) {
         if (!variable_storage(ir)) {
            fail("Failed to find uniform '%s' in 16-wide\n", ir->name);
@@ -573,7 +580,41 @@ fs_visitor::visit(ir_expression *ir)
       break;
 
    case ir_binop_ubo_load:
-      assert(!"not yet supported");
+      ir_constant *uniform_block = ir->operands[0]->as_constant();
+      ir_constant *offset = ir->operands[1]->as_constant();
+
+      fs_reg packed_consts = fs_reg(this, glsl_type::float_type);
+      packed_consts.type = result.type;
+      fs_reg surf_index = fs_reg((unsigned)SURF_INDEX_WM_UBO(uniform_block->value.u[0]));
+      fs_inst *pull = emit(fs_inst(FS_OPCODE_PULL_CONSTANT_LOAD,
+                                   packed_consts,
+                                   surf_index,
+                                   fs_reg(offset->value.u[0])));
+      pull->base_mrf = 14;
+      pull->mlen = 1;
+
+      packed_consts.smear = offset->value.u[0] % 16 / 4;
+      for (int i = 0; i < ir->type->vector_elements; i++) {
+         /* UBO bools are any nonzero value.  We consider bools to be
+          * values with the low bit set to 1.  Convert them using CMP.
+          */
+         if (ir->type->base_type == GLSL_TYPE_BOOL) {
+            fs_inst *inst = emit(fs_inst(BRW_OPCODE_CMP, result,
+                                         packed_consts, fs_reg(0u)));
+            inst->conditional_mod = BRW_CONDITIONAL_NZ;
+         } else {
+            emit(fs_inst(BRW_OPCODE_MOV, result, packed_consts));
+         }
+
+         packed_consts.smear++;
+         result.reg_offset++;
+
+         /* The std140 packing rules don't allow vectors to cross 16-byte
+          * boundaries, and a reg is 32 bytes.
+          */
+         assert(packed_consts.smear < 8);
+      }
+      result.reg_offset = 0;
       break;
    }
 }
index 935671482c77dbc8942306571dc76c2dbb291289..86426e0cfea9c3a7e6d087e013532209425e9f6c 100644 (file)
@@ -146,6 +146,9 @@ brw_link_shader(struct gl_context *ctx, struct gl_shader_program *shProg)
       lower_variable_index_to_cond_assign(shader->ir,
                                          input, output, temp, uniform);
 
+      /* FINISHME: Do this before the variable index lowering. */
+      lower_ubo_reference(&shader->base, shader->ir);
+
       do {
         progress = false;