summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEric Anholt <[email protected]>2012-06-25 14:55:01 -0700
committerEric Anholt <[email protected]>2012-08-07 13:54:52 -0700
commit04871058eb01c5b51a0180055e7dbdc967f56604 (patch)
treea96922d05ccda01c4aaeeb51dfa822cc5964f669 /src
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 <[email protected]>
Diffstat (limited to 'src')
-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) {