diff --git a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp index 6b6820f7a55..1230383c480 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp @@ -1131,6 +1131,28 @@ fs_visitor::nir_emit_undef(const fs_builder &bld, nir_ssa_undef_instr *instr) instr->def.num_components); } +static fs_reg +fs_reg_for_nir_reg(fs_visitor *v, nir_register *nir_reg, + unsigned base_offset, nir_src *indirect) +{ + fs_reg reg; + + assert(!nir_reg->is_global); + + reg = v->nir_locals[nir_reg->index]; + + reg = offset(reg, v->bld, base_offset * nir_reg->num_components); + if (indirect) { + int multiplier = nir_reg->num_components * (v->dispatch_width / 8); + + reg.reladdr = new(v->mem_ctx) fs_reg(v->vgrf(glsl_type::int_type)); + v->bld.MUL(*reg.reladdr, v->get_nir_src(*indirect), + fs_reg(multiplier)); + } + + return reg; +} + fs_reg fs_visitor::get_nir_src(nir_src src) { @@ -1138,10 +1160,8 @@ fs_visitor::get_nir_src(nir_src src) if (src.is_ssa) { reg = nir_ssa_values[src.ssa->index]; } else { - /* We don't handle indirects on locals */ - assert(src.reg.indirect == NULL); - reg = offset(nir_locals[src.reg.reg->index], bld, - src.reg.base_offset * src.reg.reg->num_components); + reg = fs_reg_for_nir_reg(this, src.reg.reg, src.reg.base_offset, + src.reg.indirect); } /* to avoid floating-point denorm flushing problems, set the type by @@ -1158,12 +1178,10 @@ fs_visitor::get_nir_dest(nir_dest dest) nir_ssa_values[dest.ssa.index] = bld.vgrf(BRW_REGISTER_TYPE_F, dest.ssa.num_components); return nir_ssa_values[dest.ssa.index]; - } else { - /* We don't handle indirects on locals */ - assert(dest.reg.indirect == NULL); - return offset(nir_locals[dest.reg.reg->index], bld, - dest.reg.base_offset * dest.reg.reg->num_components); } + + return fs_reg_for_nir_reg(this, dest.reg.reg, dest.reg.base_offset, + dest.reg.indirect); } fs_reg @@ -1601,13 +1619,15 @@ fs_visitor::nir_emit_intrinsic(const fs_builder &bld, nir_intrinsic_instr *instr } case nir_intrinsic_load_input_indirect: - unreachable("Not allowed"); + has_indirect = true; /* fallthrough */ case nir_intrinsic_load_input: { unsigned index = 0; for (unsigned j = 0; j < instr->num_components; j++) { fs_reg src = offset(retype(nir_inputs, dest.type), bld, instr->const_index[0] + index); + if (has_indirect) + src.reladdr = new(mem_ctx) fs_reg(get_nir_src(instr->src[0])); index++; bld.MOV(dest, src); @@ -1733,7 +1753,7 @@ fs_visitor::nir_emit_intrinsic(const fs_builder &bld, nir_intrinsic_instr *instr } case nir_intrinsic_store_output_indirect: - unreachable("Not allowed"); + has_indirect = true; /* fallthrough */ case nir_intrinsic_store_output: { fs_reg src = get_nir_src(instr->src[0]); @@ -1741,6 +1761,8 @@ fs_visitor::nir_emit_intrinsic(const fs_builder &bld, nir_intrinsic_instr *instr for (unsigned j = 0; j < instr->num_components; j++) { fs_reg new_dest = offset(retype(nir_outputs, src.type), bld, instr->const_index[0] + index); + if (has_indirect) + src.reladdr = new(mem_ctx) fs_reg(get_nir_src(instr->src[1])); index++; bld.MOV(new_dest, src); src = offset(src, bld, 1);