summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp52
-rw-r--r--src/mesa/drivers/dri/i965/brw_vs.c5
2 files changed, 55 insertions, 2 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
index 19001bfab29..8f697c401eb 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
+++ b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
@@ -830,6 +830,13 @@ vec4_visitor::visit(ir_variable *ir)
case ir_var_uniform:
reg = new(this->mem_ctx) dst_reg(UNIFORM, this->uniforms);
+ /* 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;
+
/* Track how big the whole uniform variable is, in case we need to put a
* copy of its data into pull constants for array access.
*/
@@ -1314,9 +1321,50 @@ vec4_visitor::visit(ir_expression *ir)
inst = emit(BRW_OPCODE_SHR, result_dst, op[0], op[1]);
break;
- case ir_binop_ubo_load:
- assert(!"not yet supported");
+ case ir_binop_ubo_load: {
+ ir_constant *uniform_block = ir->operands[0]->as_constant();
+ ir_constant *const_offset_ir = ir->operands[1]->as_constant();
+ unsigned const_offset = const_offset_ir ? const_offset_ir->value.u[0] : 0;
+ src_reg offset = op[1];
+
+ /* Now, load the vector from that offset. */
+ assert(ir->type->is_vector() || ir->type->is_scalar());
+
+ src_reg packed_consts = src_reg(this, glsl_type::vec4_type);
+ packed_consts.type = result.type;
+ src_reg surf_index =
+ src_reg(SURF_INDEX_VS_UBO(uniform_block->value.u[0]));
+ if (const_offset_ir) {
+ offset = src_reg(const_offset / 16);
+ } else {
+ emit(BRW_OPCODE_SHR, dst_reg(offset), offset, src_reg(4));
+ }
+
+ vec4_instruction *pull =
+ emit(new(mem_ctx) vec4_instruction(this,
+ VS_OPCODE_PULL_CONSTANT_LOAD,
+ dst_reg(packed_consts),
+ surf_index,
+ offset));
+ pull->base_mrf = 14;
+ pull->mlen = 1;
+
+ packed_consts.swizzle = swizzle_for_size(ir->type->vector_elements);
+ packed_consts.swizzle += BRW_SWIZZLE4(const_offset % 16 / 4,
+ const_offset % 16 / 4,
+ const_offset % 16 / 4,
+ const_offset % 16 / 4);
+
+ /* UBO bools are any nonzero int. We store bools as either 0 or 1. */
+ if (ir->type->base_type == GLSL_TYPE_BOOL) {
+ emit(CMP(result_dst, packed_consts, src_reg(0u),
+ BRW_CONDITIONAL_NZ));
+ emit(AND(result_dst, result, src_reg(0x1)));
+ } else {
+ emit(MOV(result_dst, packed_consts));
+ }
break;
+ }
case ir_quadop_vector:
assert(!"not reached: should be handled by lower_quadop_vector");
diff --git a/src/mesa/drivers/dri/i965/brw_vs.c b/src/mesa/drivers/dri/i965/brw_vs.c
index feec4558762..ba818fda353 100644
--- a/src/mesa/drivers/dri/i965/brw_vs.c
+++ b/src/mesa/drivers/dri/i965/brw_vs.c
@@ -251,6 +251,11 @@ do_vs_prog(struct brw_context *brw,
c.prog_data.num_surfaces = 1;
if (c.vp->program.Base.SamplersUsed)
c.prog_data.num_surfaces = SURF_INDEX_VS_TEXTURE(BRW_MAX_TEX_UNIT);
+ if (prog &&
+ prog->_LinkedShaders[MESA_SHADER_VERTEX]->NumUniformBlocks) {
+ c.prog_data.num_surfaces =
+ SURF_INDEX_VS_UBO(prog->_LinkedShaders[MESA_SHADER_VERTEX]->NumUniformBlocks);
+ }
/* Scratch space is used for register spilling */
if (c.last_scratch) {