nir_src *offset = nir_get_io_offset_src(instr);
assert(nir_src_is_const(*offset) && "no indirects");
- unsigned imm_index = nir_intrinsic_base(instr) + nir_src_as_uint(*offset);
+ unsigned imm_index = b->shader->varyings[nir_intrinsic_base(instr)];
+ imm_index += nir_src_as_uint(*offset);
agx_index chan[4] = { agx_null() };
nir_src *offset = nir_get_io_offset_src(instr);
assert(nir_src_is_const(*offset) && "no indirects");
- unsigned imm_index = (4 * nir_intrinsic_base(instr)) + nir_src_as_uint(*offset);
- imm_index += 1;
+ unsigned imm_index = b->shader->varyings[nir_intrinsic_base(instr)];
+ imm_index += nir_src_as_uint(*offset);
return agx_ld_vary_to(b, agx_dest_index(&instr->dest),
agx_immediate(imm_index), components, true);
}
}
+static void
+agx_remap_varyings_fs(nir_shader *nir, struct agx_varyings *varyings,
+ unsigned *remap)
+{
+ struct agx_varying_packed *packed = varyings->packed;
+ unsigned base = 0;
+
+ agx_pack(packed, VARYING, cfg) {
+ cfg.type = AGX_VARYING_TYPE_FRAGCOORD_W;
+ cfg.components = 1;
+ cfg.slot_1 = cfg.slot_2 = base;
+ }
+
+ base++;
+ packed++;
+
+ agx_pack(packed, VARYING, cfg) {
+ cfg.type = AGX_VARYING_TYPE_FRAGCOORD_Z;
+ cfg.components = 1;
+ cfg.slot_1 = cfg.slot_2 = base;
+ }
+
+ base++;
+ packed++;
+
+ nir_foreach_shader_in_variable(var, nir) {
+ assert(var->data.driver_location <= AGX_MAX_VARYINGS);
+ remap[var->data.driver_location] = base;
+
+ agx_pack(packed, VARYING, cfg) {
+ cfg.type = (var->data.interpolation == INTERP_MODE_FLAT) ?
+ AGX_VARYING_TYPE_FLAT_LAST :
+ AGX_VARYING_TYPE_SMOOTH;
+ cfg.components = 4;
+ cfg.slot_1 = cfg.slot_2 = base;
+ }
+
+ base += 4;
+ packed++;
+ }
+
+ varyings->nr_descs = (packed - varyings->packed);
+ varyings->nr_slots = base;
+}
+
void
agx_compile_shader_nir(nir_shader *nir,
struct agx_shader_key *key,
agx_optimize_nir(nir);
+ /* Must be last since NIR passes can remap driver_location freely */
+ if (ctx->stage == MESA_SHADER_FRAGMENT) {
+ agx_remap_varyings_fs(nir, &out->varyings, ctx->varyings);
+ }
+
bool skip_internal = nir->info.internal;
skip_internal &= !(agx_debug & AGX_DBG_INTERNAL);
nir_variable_mode varying_mode = (nir->info.stage == MESA_SHADER_FRAGMENT) ?
nir_var_shader_in : nir_var_shader_out;
+ struct agx_varyings *varyings = &compiled->info.varyings;
unsigned varying_count = 0;
nir_foreach_variable_with_modes(var, nir, varying_mode) {
varying_count = MAX2(varying_count, loc + sz);
}
- compiled->varying_count = varying_count;
+ if (nir->info.stage == MESA_SHADER_VERTEX)
+ compiled->varying_count = varying_count;
- unsigned varying_desc_len = AGX_VARYING_HEADER_LENGTH + (1 + varying_count) * AGX_VARYING_LENGTH;
- uint8_t *varying_desc = calloc(1, varying_desc_len);
+ unsigned packed_varying_sz = (AGX_VARYING_HEADER_LENGTH + varyings->nr_descs * AGX_VARYING_LENGTH);
+ uint8_t *packed_varyings = alloca(packed_varying_sz);
- agx_pack(varying_desc, VARYING_HEADER, cfg) {
- cfg.slots_1 = 1 + (4 * varying_count);
- cfg.slots_2 = 1 + (4 * varying_count);
+ agx_pack(packed_varyings, VARYING_HEADER, cfg) {
+ cfg.slots_1 = cfg.slots_2 = varyings->nr_slots;
}
- agx_pack(varying_desc + AGX_VARYING_HEADER_LENGTH, VARYING, cfg) {
- cfg.type = AGX_VARYING_TYPE_FRAGCOORD_W;
- cfg.slot_1 = 0;
- cfg.slot_2 = 0;
- cfg.components = 4;
- }
+ if (varyings->nr_slots)
+ compiled->varying_count = varyings->nr_slots;
- for (unsigned i = 0; i < varying_count; ++i) {
- agx_pack(varying_desc + AGX_VARYING_HEADER_LENGTH + ((i + 1) * AGX_VARYING_LENGTH), VARYING, cfg) {
- cfg.slot_1 = 1 + (4 * i);
- cfg.slot_2 = 1 + (4 * i);
- cfg.components = 4;
- }
- }
+ memcpy(packed_varyings + AGX_VARYING_HEADER_LENGTH, varyings->packed,
+ varyings->nr_descs * AGX_VARYING_LENGTH);
if (binary.size) {
struct agx_device *dev = agx_device(ctx->base.screen);
compiled->bo = agx_bo_create(dev,
- ALIGN_POT(binary.size, 256) + ((3 * (AGX_VARYING_HEADER_LENGTH + varying_count * AGX_VARYING_LENGTH)) + 20),
+ ALIGN_POT(binary.size, 256) + ((3 * packed_varying_sz) + 20),
AGX_MEMORY_TYPE_SHADER);
memcpy(compiled->bo->ptr.cpu, binary.data, binary.size);
unsigned offs = ALIGN_POT(binary.size, 256);
unsigned unk_offs = offs + 0x40;
for (unsigned copy = 0; copy < 3; ++copy) {
- memcpy(((uint8_t *) compiled->bo->ptr.cpu) + offs, varying_desc, varying_desc_len);
- offs += varying_desc_len;
+ memcpy(((uint8_t *) compiled->bo->ptr.cpu) + offs, packed_varyings, packed_varying_sz);
+ offs += packed_varying_sz;
}
uint16_t *map = (uint16_t *) (((uint8_t *) compiled->bo->ptr.cpu) + unk_offs);
/* Varying related */
uint32_t unk[] = {
/* interpolated count */
- 0x100c0000, fs->varying_count * 4, 0x0, 0x0, 0x0,
+ 0x100c0000, fs->info.varyings.nr_slots, 0x0, 0x0, 0x0,
};
return agx_pool_upload(pool, unk, sizeof(unk));
agx_pack(t.cpu, LINKAGE, cfg) {
cfg.varying_count = 4 * vs->varying_count;
- cfg.unk_1 = 0x10000; // varyings otherwise wrong
+ cfg.unk_1 = 0x210000; // varyings otherwise wrong
};
return t.gpu;
agx_push_record(&out, 0, zero.gpu);
agx_push_record(&out, 5, demo_unk8(ctx->fs, pool));
- agx_push_record(&out, 5, demo_launch_fragment(pool, pipeline_fragment, varyings, ctx->fs->varying_count + 1));
+ agx_push_record(&out, 5, demo_launch_fragment(pool, pipeline_fragment, varyings, ctx->fs->info.varyings.nr_descs));
agx_push_record(&out, 4, demo_linkage(ctx->vs, pool));
agx_push_record(&out, 7, demo_rasterizer(ctx, pool));
agx_push_record(&out, 5, demo_unk11(pool, is_lines, reads_tib));