summaryrefslogtreecommitdiff
path: root/src/mesa/drivers/dri
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2012-06-25 14:55:01 -0700
committerEric Anholt <eric@anholt.net>2012-08-07 13:54:52 -0700
commit04871058eb01c5b51a0180055e7dbdc967f56604 (patch)
treea96922d05ccda01c4aaeeb51dfa822cc5964f669 /src/mesa/drivers/dri
parent90de96ff0d6d54ba0f9a337a6a107acf4134682d (diff)
i965/vs: Add support for loading uniform buffer variables as pull constants.
Unlike the FS side in the previous commit, this does variable indexing just fine, using the same code as we used for other variable-indexed pull constants. Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Diffstat (limited to 'src/mesa/drivers/dri')
-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 19001bfab2..8f697c401e 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 feec455876..ba818fda35 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) {