static nir_src get_deref_reg_src(nir_deref_instr *deref, struct locals_to_regs_state *state) { nir_builder *b = &state->builder; nir_src src; src.is_ssa = false; src.reg.reg = get_reg_for_deref(deref, state); src.reg.base_offset = 0; src.reg.indirect = NULL; /* It is possible for a user to create a shader that has an array with a * single element and then proceed to access it indirectly. Indirectly * accessing a non-array register is not allowed in NIR. In order to * handle this case we just convert it to a direct reference. */ if (src.reg.reg->num_array_elems == 0) return src; unsigned inner_array_size = 1; for (const nir_deref_instr *d = deref; d; d = nir_deref_instr_parent(d)) { if (d->deref_type != nir_deref_type_array) continue; if (nir_src_is_const(d->arr.index) && !src.reg.indirect) { src.reg.base_offset += nir_src_as_uint(d->arr.index) * inner_array_size; } else { if (src.reg.indirect) { assert(src.reg.base_offset == 0); } else { src.reg.indirect = ralloc(b->shader, nir_src); *src.reg.indirect = nir_src_for_ssa(nir_imm_int(b, src.reg.base_offset)); src.reg.base_offset = 0; } assert(src.reg.indirect->is_ssa); nir_ssa_def *index = nir_i2i(b, nir_ssa_for_src(b, d->arr.index, 1), 32); src.reg.indirect->ssa = nir_iadd(b, src.reg.indirect->ssa, nir_imul(b, index, nir_imm_int(b, inner_array_size))); } inner_array_size *= glsl_get_length(nir_deref_instr_parent(d)->type); } return src; }
/* src[] = { buffer_index, offset }. No const_index */ static void emit_intrinsic_load_ssbo(struct ir3_context *ctx, nir_intrinsic_instr *intr, struct ir3_instruction **dst) { struct ir3_block *b = ctx->block; struct ir3_instruction *ldgb, *src0, *src1, *byte_offset, *offset; /* can this be non-const buffer_index? how do we handle that? */ int ibo_idx = ir3_ssbo_to_ibo(&ctx->so->image_mapping, nir_src_as_uint(intr->src[0])); byte_offset = ir3_get_src(ctx, &intr->src[1])[0]; offset = ir3_get_src(ctx, &intr->src[2])[0]; /* src0 is uvec2(offset*4, 0), src1 is offset.. nir already *= 4: */ src0 = ir3_create_collect(ctx, (struct ir3_instruction*[]){ byte_offset, create_immed(b, 0), }, 2);
static unsigned get_io_offset(nir_deref_instr *deref, bool is_vertex_input) { unsigned offset = 0; for (nir_deref_instr *d = deref; d; d = nir_deref_instr_parent(d)) { if (d->deref_type == nir_deref_type_array) { if (!nir_src_is_const(d->arr.index)) return -1; offset += glsl_count_attribute_slots(d->type, is_vertex_input) * nir_src_as_uint(d->arr.index); } /* TODO: we can get the offset for structs here see nir_lower_io() */ } return offset; }