nir_src *offset = nir_get_io_offset_src(instr);
assert(nir_src_is_const(*offset) && "no indirects");
unsigned imm_index = b->shader->varyings[nir_intrinsic_base(instr)];
- imm_index += nir_src_as_uint(*offset);
+ imm_index += nir_src_as_uint(*offset) * 4;
return agx_ld_vary_to(b, agx_dest_index(&instr->dest),
agx_immediate(imm_index), components, true);
base++;
packed++;
- nir_foreach_shader_in_variable(var, nir) {
- assert(var->data.driver_location <= AGX_MAX_VARYINGS);
- remap[var->data.driver_location] = base;
+ unsigned comps[MAX_VARYING] = { 0 };
- 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;
- }
+ nir_foreach_shader_in_variable(var, nir) {
+ unsigned loc = var->data.driver_location;
+ const struct glsl_type *column =
+ glsl_without_array_or_matrix(var->type);
+ unsigned chan = glsl_get_components(column);
+
+ /* If we have a fractional location added, we need to increase the size
+ * so it will fit, i.e. a vec3 in YZW requires us to allocate a vec4.
+ * We could do better but this is an edge case as it is, normally
+ * packed varyings will be aligned.
+ */
+ chan += var->data.location_frac;
+ comps[loc] = MAX2(comps[loc], chan);
+ }
- base += 4;
- packed++;
+ nir_foreach_shader_in_variable(var, nir) {
+ unsigned loc = var->data.driver_location;
+ unsigned sz = glsl_count_attribute_slots(var->type, FALSE);
+ unsigned channels = comps[loc];
+
+ assert(var->data.driver_location <= AGX_MAX_VARYINGS);
+ remap[var->data.driver_location] = base;
+
+ for (int c = 0; c < sz; ++c) {
+ agx_pack(packed, VARYING, cfg) {
+ cfg.type = (var->data.interpolation == INTERP_MODE_FLAT) ?
+ AGX_VARYING_TYPE_FLAT_LAST :
+ AGX_VARYING_TYPE_SMOOTH;
+ cfg.components = channels;
+ cfg.slot_1 = cfg.slot_2 = base;
+ }
+
+ base += channels;
+ packed++;
+ }
}
varyings->nr_descs = (packed - varyings->packed);