freedreno/a6xx: Do sparse setup of the TFB program.

We don't need to init the whole program RAM, just the locations we are
actually writing from.  Syncs this code up with tu a bit more.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/13747>
This commit is contained in:
Emma Anholt
2021-11-10 15:49:31 -08:00
committed by Marge Bot
parent 943449fb8e
commit 32b51d5e60
@@ -188,17 +188,17 @@ setup_stream_out(struct fd_context *ctx, struct fd6_program_state *state,
{
const struct ir3_stream_output_info *strmout = &v->shader->stream_output;
/* Note: 64 here comes from the HW layout of the program RAM. The program
* for stream N is at DWORD 64 * N.
*/
#define A6XX_SO_PROG_DWORDS 64
uint32_t prog[A6XX_SO_PROG_DWORDS * IR3_MAX_SO_STREAMS] = {};
BITSET_DECLARE(valid_dwords, A6XX_SO_PROG_DWORDS * IR3_MAX_SO_STREAMS) = {0};
uint32_t ncomp[PIPE_MAX_SO_BUFFERS];
uint32_t prog[256 / 2];
uint32_t prog_count;
memset(ncomp, 0, sizeof(ncomp));
memset(prog, 0, sizeof(prog));
prog_count = align(l->max_loc, 2) / 2;
debug_assert(prog_count < ARRAY_SIZE(prog));
for (unsigned i = 0; i < strmout->num_outputs; i++) {
const struct ir3_stream_output *out = &strmout->output[i];
unsigned k = out->register_index;
@@ -220,19 +220,28 @@ setup_stream_out(struct fd_context *ctx, struct fd6_program_state *state,
unsigned loc = l->var[idx].loc + c;
unsigned off = j + out->dst_offset; /* in dwords */
unsigned dword = out->stream * A6XX_SO_PROG_DWORDS + loc/2;
if (loc & 1) {
prog[loc / 2] |= A6XX_VPC_SO_PROG_B_EN |
A6XX_VPC_SO_PROG_B_BUF(out->output_buffer) |
A6XX_VPC_SO_PROG_B_OFF(off * 4);
prog[dword] |= A6XX_VPC_SO_PROG_B_EN |
A6XX_VPC_SO_PROG_B_BUF(out->output_buffer) |
A6XX_VPC_SO_PROG_B_OFF(off * 4);
} else {
prog[loc / 2] |= A6XX_VPC_SO_PROG_A_EN |
A6XX_VPC_SO_PROG_A_BUF(out->output_buffer) |
A6XX_VPC_SO_PROG_A_OFF(off * 4);
prog[dword] |= A6XX_VPC_SO_PROG_A_EN |
A6XX_VPC_SO_PROG_A_BUF(out->output_buffer) |
A6XX_VPC_SO_PROG_A_OFF(off * 4);
}
BITSET_SET(valid_dwords, dword);
}
}
unsigned sizedw = 12 + (2 * prog_count);
unsigned prog_count = 0;
unsigned start, end;
BITSET_FOREACH_RANGE (start, end, valid_dwords,
A6XX_SO_PROG_DWORDS * IR3_MAX_SO_STREAMS) {
prog_count += end - start + 1;
}
unsigned sizedw = 10 + (2 * prog_count);
if (ctx->screen->info->a6xx.tess_use_shared)
sizedw += 2;
@@ -255,12 +264,20 @@ setup_stream_out(struct fd_context *ctx, struct fd6_program_state *state,
OUT_RING(ring, ncomp[2]);
OUT_RING(ring, REG_A6XX_VPC_SO_NCOMP(3));
OUT_RING(ring, ncomp[3]);
OUT_RING(ring, REG_A6XX_VPC_SO_CNTL);
OUT_RING(ring, A6XX_VPC_SO_CNTL_RESET);
for (unsigned i = 0; i < prog_count; i++) {
OUT_RING(ring, REG_A6XX_VPC_SO_PROG);
OUT_RING(ring, prog[i]);
bool first = true;
BITSET_FOREACH_RANGE (start, end, valid_dwords,
A6XX_SO_PROG_DWORDS * IR3_MAX_SO_STREAMS) {
OUT_RING(ring, REG_A6XX_VPC_SO_CNTL);
OUT_RING(ring, COND(first, A6XX_VPC_SO_CNTL_RESET) |
A6XX_VPC_SO_CNTL_ADDR(start));
for (unsigned i = start; i < end; i++) {
OUT_RING(ring, REG_A6XX_VPC_SO_PROG);
OUT_RING(ring, prog[i]);
}
first = false;
}
if (ctx->screen->info->a6xx.tess_use_shared) {
/* Possibly not tess_use_shared related, but the combination of
* tess + xfb fails some tests if we don't emit this.