radeonsi: implement per-level DCC and CMASK fast clears for gfx10+
Fast clears are only used for level 0. This enables clearing level 0 of CMASK and DCC on gfx10+ when there are multiple mipmap levels. vi_dcc_clear_level can also clear any level now. Mipmapped array textures are still cleared slowly. Acked-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10003>
This commit is contained in:
parent
059f042fb1
commit
6434b0b652
|
@ -279,8 +279,32 @@ bool vi_dcc_get_clear_info(struct si_context *sctx, struct si_texture *tex, unsi
|
||||||
dcc_offset = tex->surface.meta_offset;
|
dcc_offset = tex->surface.meta_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sctx->chip_class >= GFX9) {
|
if (sctx->chip_class >= GFX10) {
|
||||||
/* Mipmap level clears aren't implemented. */
|
/* 4x and 8x MSAA needs a sophisticated compute shader for
|
||||||
|
* the clear. */
|
||||||
|
if (tex->buffer.b.b.nr_storage_samples >= 4)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
unsigned num_layers = util_num_layers(&tex->buffer.b.b, level);
|
||||||
|
|
||||||
|
if (num_layers == 1) {
|
||||||
|
/* Clear a specific level. */
|
||||||
|
dcc_offset += tex->surface.u.gfx9.meta_levels[level].offset;
|
||||||
|
clear_size = tex->surface.u.gfx9.meta_levels[level].size;
|
||||||
|
} else if (tex->buffer.b.b.last_level == 0) {
|
||||||
|
/* Clear all layers having only 1 level. */
|
||||||
|
clear_size = tex->surface.meta_size;
|
||||||
|
} else {
|
||||||
|
/* Clearing DCC with both multiple levels and multiple layers is not
|
||||||
|
* implemented.
|
||||||
|
*/
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (sctx->chip_class == GFX9) {
|
||||||
|
/* TODO: Implement DCC fast clear for level 0 of mipmapped textures. Mipmapped
|
||||||
|
* DCC has to clear a rectangular area of DCC for level 0 (because the whole miptree
|
||||||
|
* is organized in a 2D plane).
|
||||||
|
*/
|
||||||
if (tex->buffer.b.b.last_level > 0)
|
if (tex->buffer.b.b.last_level > 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -445,15 +469,6 @@ static void si_do_fast_color_clear(struct si_context *sctx, unsigned *buffers,
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
struct si_texture *tex = (struct si_texture *)fb->cbufs[i]->texture;
|
struct si_texture *tex = (struct si_texture *)fb->cbufs[i]->texture;
|
||||||
|
|
||||||
/* TODO: GFX9: Implement DCC fast clear for level 0 of
|
|
||||||
* mipmapped textures. Mipmapped DCC has to clear a rectangular
|
|
||||||
* area of DCC for level 0 (because the whole miptree is
|
|
||||||
* organized in a 2D plane).
|
|
||||||
*/
|
|
||||||
if (sctx->chip_class >= GFX9 && tex->buffer.b.b.last_level > 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
unsigned num_layers = util_num_layers(&tex->buffer.b.b, level);
|
unsigned num_layers = util_num_layers(&tex->buffer.b.b, level);
|
||||||
|
|
||||||
/* the clear is allowed if all layers are bound */
|
/* the clear is allowed if all layers are bound */
|
||||||
|
@ -584,14 +599,58 @@ static void si_do_fast_color_clear(struct si_context *sctx, unsigned *buffers,
|
||||||
if (tex->buffer.flags & RADEON_FLAG_ENCRYPTED)
|
if (tex->buffer.flags & RADEON_FLAG_ENCRYPTED)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* ensure CMASK is enabled */
|
uint64_t cmask_offset = 0;
|
||||||
|
unsigned clear_size = 0;
|
||||||
|
|
||||||
|
if (sctx->chip_class >= GFX10) {
|
||||||
|
assert(level == 0);
|
||||||
|
|
||||||
|
/* Clearing CMASK with both multiple levels and multiple layers is not
|
||||||
|
* implemented.
|
||||||
|
*/
|
||||||
|
if (num_layers > 1 && tex->buffer.b.b.last_level > 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (!si_alloc_separate_cmask(sctx->screen, tex))
|
if (!si_alloc_separate_cmask(sctx->screen, tex))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (num_layers == 1) {
|
||||||
|
/* Clear level 0. */
|
||||||
|
cmask_offset = tex->surface.cmask_offset + tex->surface.u.gfx9.color.cmask_level0.offset;
|
||||||
|
clear_size = tex->surface.u.gfx9.color.cmask_level0.size;
|
||||||
|
} else if (tex->buffer.b.b.last_level == 0) {
|
||||||
|
/* Clear all layers having only 1 level. */
|
||||||
|
cmask_offset = tex->surface.cmask_offset;
|
||||||
|
clear_size = tex->surface.cmask_size;
|
||||||
|
} else {
|
||||||
|
assert(0); /* this is prevented above */
|
||||||
|
}
|
||||||
|
} else if (sctx->chip_class == GFX9) {
|
||||||
|
/* TODO: Implement CMASK fast clear for level 0 of mipmapped textures. Mipmapped
|
||||||
|
* CMASK has to clear a rectangular area of CMASK for level 0 (because the whole
|
||||||
|
* miptree is organized in a 2D plane).
|
||||||
|
*/
|
||||||
|
if (tex->buffer.b.b.last_level > 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!si_alloc_separate_cmask(sctx->screen, tex))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
cmask_offset = tex->surface.cmask_offset;
|
||||||
|
clear_size = tex->surface.cmask_size;
|
||||||
|
} else {
|
||||||
|
if (!si_alloc_separate_cmask(sctx->screen, tex))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* GFX6-8: This only covers mipmap level 0. */
|
||||||
|
cmask_offset = tex->surface.cmask_offset;
|
||||||
|
clear_size = tex->surface.cmask_size;
|
||||||
|
}
|
||||||
|
|
||||||
/* Do the fast clear. */
|
/* Do the fast clear. */
|
||||||
assert(num_clears < ARRAY_SIZE(info));
|
assert(num_clears < ARRAY_SIZE(info));
|
||||||
si_init_buffer_clear(&info[num_clears++], &tex->cmask_buffer->b.b,
|
si_init_buffer_clear(&info[num_clears++], &tex->cmask_buffer->b.b,
|
||||||
tex->surface.cmask_offset, tex->surface.cmask_size, 0);
|
cmask_offset, clear_size, 0);
|
||||||
clear_types |= SI_CLEAR_TYPE_CMASK;
|
clear_types |= SI_CLEAR_TYPE_CMASK;
|
||||||
eliminate_needed = true;
|
eliminate_needed = true;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue