summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs.cpp5
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs_visitor.cpp43
-rw-r--r--src/mesa/drivers/dri/i965/brw_shader.cpp3
3 files changed, 50 insertions, 1 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp
index cb89d746f34..90dddce8670 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs.cpp
@@ -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;
}
diff --git a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
index 1e18e92de54..7a2f7775567 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
@@ -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;
}
}
diff --git a/src/mesa/drivers/dri/i965/brw_shader.cpp b/src/mesa/drivers/dri/i965/brw_shader.cpp
index 935671482c7..86426e0cfea 100644
--- a/src/mesa/drivers/dri/i965/brw_shader.cpp
+++ b/src/mesa/drivers/dri/i965/brw_shader.cpp
@@ -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;