summaryrefslogtreecommitdiffstats
path: root/src/mesa/drivers
diff options
context:
space:
mode:
authorJason Ekstrand <[email protected]>2014-12-08 17:34:52 -0800
committerJason Ekstrand <[email protected]>2015-01-15 07:20:21 -0800
commit534d145e5ea039d57833395a36eed90721f6b272 (patch)
tree0e08819ec9aa87417e8a5fe499e75828cbfa1406 /src/mesa/drivers
parent6a5604ca6a7346278188cb05996444a5091070b5 (diff)
nir: Use a source for uniform buffer indices instead of an index
In GLSL-to-NIR we were just setting the base index to 0 whenever there was an indirect so having it expressed as a sum makes no sense. Also, while a base offset may make sense for the memory location (first element in the array, etc.) it makes less sense for the actual uniform buffer index. This may change later, but it seems to make more sense for now. Reviewed-by: Connor Abbott <[email protected]>
Diffstat (limited to 'src/mesa/drivers')
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs_nir.cpp96
1 files changed, 59 insertions, 37 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp
index 56e180a138a..a5360754648 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp
@@ -1344,52 +1344,74 @@ fs_visitor::nir_emit_intrinsic(nir_intrinsic_instr *instr)
break;
}
+ case nir_intrinsic_load_ubo_indirect:
+ has_indirect = true;
case nir_intrinsic_load_ubo: {
- fs_reg surf_index = fs_reg(prog_data->binding_table.ubo_start +
- (unsigned) instr->const_index[0]);
- fs_reg packed_consts = fs_reg(this, glsl_type::float_type);
- packed_consts.type = dest.type;
-
- fs_reg const_offset_reg = fs_reg((unsigned) instr->const_index[1] & ~15);
- emit(new(mem_ctx) fs_inst(FS_OPCODE_UNIFORM_PULL_CONSTANT_LOAD,
- packed_consts, surf_index, const_offset_reg));
+ nir_const_value *const_index = nir_src_as_const_value(instr->src[0]);
+ fs_reg surf_index;
- for (unsigned i = 0; i < instr->num_components; i++) {
- packed_consts.set_smear(instr->const_index[1] % 16 / 4 + i);
+ if (const_index) {
+ surf_index = fs_reg(stage_prog_data->binding_table.ubo_start +
+ const_index->u[0]);
+ } else {
+ /* The block index is not a constant. Evaluate the index expression
+ * per-channel and add the base UBO index; the generator will select
+ * a value from any live channel.
+ */
+ surf_index = fs_reg(this, glsl_type::uint_type);
+ emit(ADD(surf_index, get_nir_src(instr->src[0]),
+ fs_reg(stage_prog_data->binding_table.ubo_start)))
+ ->force_writemask_all = true;
- /* The std140 packing rules don't allow vectors to cross 16-byte
- * boundaries, and a reg is 32 bytes.
+ /* Assume this may touch any UBO. It would be nice to provide
+ * a tighter bound, but the array information is already lowered away.
*/
- assert(packed_consts.subreg_offset < 32);
+ brw_mark_surface_used(prog_data,
+ stage_prog_data->binding_table.ubo_start +
+ shader_prog->NumUniformBlocks - 1);
+ }
- fs_inst *inst = MOV(dest, packed_consts);
- if (instr->has_predicate)
- inst->predicate = BRW_PREDICATE_NORMAL;
- emit(inst);
+ if (has_indirect) {
+ /* Turn the byte offset into a dword offset. */
+ fs_reg base_offset = fs_reg(this, glsl_type::int_type);
+ emit(SHR(base_offset, retype(get_nir_src(instr->src[1]),
+ BRW_REGISTER_TYPE_D),
+ fs_reg(2)));
- dest.reg_offset++;
- }
- break;
- }
+ unsigned vec4_offset = instr->const_index[0] / 4;
+ for (int i = 0; i < instr->num_components; i++) {
+ exec_list list = VARYING_PULL_CONSTANT_LOAD(offset(dest, i),
+ surf_index, base_offset,
+ vec4_offset + i);
- case nir_intrinsic_load_ubo_indirect: {
- fs_reg surf_index = fs_reg(prog_data->binding_table.ubo_start +
- instr->const_index[0]);
- /* Turn the byte offset into a dword offset. */
- unsigned base_offset = instr->const_index[1] / 4;
- fs_reg offset = fs_reg(this, glsl_type::int_type);
- emit(SHR(offset, retype(get_nir_src(instr->src[0]), BRW_REGISTER_TYPE_D),
- fs_reg(2)));
+ fs_inst *last_inst = (fs_inst *) list.get_tail();
+ if (instr->has_predicate)
+ last_inst->predicate = BRW_PREDICATE_NORMAL;
+ emit(list);
+ }
+ } else {
+ fs_reg packed_consts = fs_reg(this, glsl_type::float_type);
+ packed_consts.type = dest.type;
- for (unsigned i = 0; i < instr->num_components; i++) {
- exec_list list = VARYING_PULL_CONSTANT_LOAD(dest, surf_index,
- offset, base_offset + i);
- fs_inst *last_inst = (fs_inst *) list.get_tail();
- if (instr->has_predicate)
- last_inst->predicate = BRW_PREDICATE_NORMAL;
- emit(list);
+ fs_reg const_offset_reg((unsigned) instr->const_index[0] & ~15);
+ emit(FS_OPCODE_UNIFORM_PULL_CONSTANT_LOAD, packed_consts,
+ surf_index, const_offset_reg);
- dest.reg_offset++;
+ for (unsigned i = 0; i < instr->num_components; i++) {
+ packed_consts.set_smear(instr->const_index[0] % 16 / 4 + i);
+
+ /* The std140 packing rules don't allow vectors to cross 16-byte
+ * boundaries, and a reg is 32 bytes.
+ */
+ assert(packed_consts.subreg_offset < 32);
+
+ fs_inst *inst = MOV(dest, packed_consts);
+ if (instr->has_predicate)
+ inst->predicate = BRW_PREDICATE_NORMAL;
+ emit(inst);
+
+ dest.reg_offset++;
+ }
}
break;
}