freedreno: add support for aliased render target components

a7xx introduced support for aliasing render target components using
alias.rt. This allows components to be bound to uniform (const or
immediate) values in the preamble:

alias.rt.f32.0 rt0.y, c0.x
alias.rt.f32.0 rt1.z, (1.000000)

This aliases the 2nd component of RT0 to c0.x and the 3rd component of
RT1 to the immediate 1.0. All components of all 8 render targets can be
aliased.

In addition to using alias.rt, the hardware needs to be informed about
which render target components are being aliased using the
SP_PS_ALIASED_COMPONENTS{_CONTROL} registers. This commit implements
those registers.

Signed-off-by: Job Noorman <jnoorman@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/31222>
This commit is contained in:
Job Noorman 2025-01-22 15:33:48 +01:00 committed by Marge Bot
parent 38f5fd66de
commit 90b512c4ef

View file

@ -1130,12 +1130,28 @@ emit_fs_outputs(struct fd_ringbuffer *ring, const struct program_builder *b)
int output_reg_count = 0;
uint32_t fragdata_regid[8];
uint32_t fragdata_aliased_components = 0;
for (uint32_t i = 0; i < ARRAY_SIZE(fragdata_regid); i++) {
unsigned slot = fs->color0_mrt ? FRAG_RESULT_COLOR : FRAG_RESULT_DATA0 + i;
fragdata_regid[i] = ir3_find_output_regid(fs, slot);
if (VALIDREG(fragdata_regid[i]))
int output_idx = ir3_find_output(fs, (gl_varying_slot)slot);
if (output_idx < 0) {
fragdata_regid[i] = INVALID_REG;
continue;
}
const struct ir3_shader_output *fragdata = &fs->outputs[output_idx];
fragdata_regid[i] = ir3_get_output_regid(fragdata);
if (VALIDREG(fragdata_regid[i]) || fragdata->aliased_components) {
/* An invalid reg is only allowed if all components are aliased. */
assert(
VALIDREG(fragdata_regid[i] || fragdata->aliased_components == 0xf));
output_reg_count = i + 1;
fragdata_aliased_components |= fragdata->aliased_components << (i * 4);
}
}
OUT_PKT4(ring, REG_A6XX_SP_FS_OUTPUT_CNTL0, 1);
@ -1150,10 +1166,21 @@ emit_fs_outputs(struct fd_ringbuffer *ring, const struct program_builder *b)
COND(fragdata_regid[i] & HALF_REG_ID,
A6XX_SP_FS_OUTPUT_REG_HALF_PRECISION));
if (VALIDREG(fragdata_regid[i])) {
if (VALIDREG(fragdata_regid[i]) ||
(fragdata_aliased_components & (0xf << (i * 4)))) {
b->state->mrt_components |= 0xf << (i * 4);
}
}
if (CHIP >= A7XX) {
OUT_REG(
ring,
A7XX_SP_PS_ALIASED_COMPONENTS_CONTROL(
.enabled = fragdata_aliased_components != 0),
A7XX_SP_PS_ALIASED_COMPONENTS(.dword = fragdata_aliased_components));
} else {
assert(fragdata_aliased_components == 0);
}
}
template <chip CHIP>