From 174e11c3f5440ad1e22354816fe2ccc5b7a970e9 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Mon, 16 Apr 2018 16:34:56 -0400 Subject: [PATCH] ac/surface: handle DCC subresource fast clear restriction on VI MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit v2: require the previous level to be clearable for determining whether the last unaligned level is clearable Reviewed-by: Nicolai Hähnle --- src/amd/common/ac_surface.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/amd/common/ac_surface.c b/src/amd/common/ac_surface.c index a23952717e3..f14fa1c8b5e 100644 --- a/src/amd/common/ac_surface.c +++ b/src/amd/common/ac_surface.c @@ -343,6 +343,9 @@ static int gfx6_compute_level(ADDR_HANDLE addrlib, /* The previous level's flag tells us if we can use DCC for this level. */ if (AddrSurfInfoIn->flags.dccCompatible && (level == 0 || AddrDccOut->subLvlCompressible)) { + bool prev_level_clearable = level == 0 || + AddrDccOut->dccRamSizeAligned; + AddrDccIn->colorSurfSize = AddrSurfInfoOut->surfSize; AddrDccIn->tileMode = AddrSurfInfoOut->tileMode; AddrDccIn->tileInfo = *AddrSurfInfoOut->pTileInfo; @@ -355,10 +358,26 @@ static int gfx6_compute_level(ADDR_HANDLE addrlib, if (ret == ADDR_OK) { surf_level->dcc_offset = surf->dcc_size; - surf_level->dcc_fast_clear_size = AddrDccOut->dccFastClearSize; surf->num_dcc_levels = level + 1; surf->dcc_size = surf_level->dcc_offset + AddrDccOut->dccRamSize; surf->dcc_alignment = MAX2(surf->dcc_alignment, AddrDccOut->dccRamBaseAlign); + + /* If the DCC size of a subresource (1 mip level or 1 slice) + * is not aligned, the DCC memory layout is not contiguous for + * that subresource, which means we can't use fast clear. + * + * We only do fast clears for whole mipmap levels. If we did + * per-slice fast clears, the same restriction would apply. + * (i.e. only compute the slice size and see if it's aligned) + * + * The last level can be non-contiguous and still be clearable + * if it's interleaved with the next level that doesn't exist. + */ + if (AddrDccOut->dccRamSizeAligned || + (prev_level_clearable && level == config->info.levels - 1)) + surf_level->dcc_fast_clear_size = AddrDccOut->dccFastClearSize; + else + surf_level->dcc_fast_clear_size = 0; } } -- 2.30.2