From c14e059d9fc5531a81bb42306dcd564f98251c19 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Fri, 26 Mar 2021 13:49:49 -0700 Subject: [PATCH] freedreno/a6xx: Fix indirect+patches draws Without TC, we'd get draw->count==0.. which is obviously not correct. With TC we get random garbage for draw->count. Which turns into exciting things like trying to allocate multi-gigabyte buffers for tess param/factor buffers. But we can just tell the CP to split up large tess draws, and put an upper bound on the tess param/factor buffer sizes. Signed-off-by: Rob Clark Part-of: --- src/gallium/drivers/freedreno/a6xx/fd6_draw.c | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_draw.c b/src/gallium/drivers/freedreno/a6xx/fd6_draw.c index 6904e1b6363..aea565459d1 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_draw.c +++ b/src/gallium/drivers/freedreno/a6xx/fd6_draw.c @@ -276,11 +276,28 @@ fd6_draw_vbo(struct fd_context *ctx, const struct pipe_draw_info *info, draw0.prim_type = DI_PT_PATCHES0 + info->vertices_per_patch; draw0.tess_enable = true; + const unsigned max_count = 2048; + unsigned count; + + /** + * We can cap tessparam/tessfactor buffer sizes at the sub-draw + * limit. But in the indirect-draw case we must assume the worst. + */ + if (indirect && indirect->buffer) { + count = ALIGN_NPOT(max_count, info->vertices_per_patch); + } else { + count = MIN2(max_count, draw->count); + count = ALIGN_NPOT(count, info->vertices_per_patch); + } + + OUT_PKT7(ring, CP_SET_SUBDRAW_SIZE, 1); + OUT_RING(ring, count); + ctx->batch->tessellation = true; ctx->batch->tessparam_size = MAX2(ctx->batch->tessparam_size, - emit.hs->output_size * 4 * draw->count); + emit.hs->output_size * 4 * count); ctx->batch->tessfactor_size = MAX2(ctx->batch->tessfactor_size, - factor_stride * draw->count); + factor_stride * count); if (!ctx->batch->tess_addrs_constobj) { /* Reserve space for the bo address - we'll write them later in