From: Marek Olšák <marek.ol...@amd.com> --- src/gallium/drivers/radeon/r600_texture.c | 45 ++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 13 deletions(-)
diff --git a/src/gallium/drivers/radeon/r600_texture.c b/src/gallium/drivers/radeon/r600_texture.c index aee768f..074fed8 100644 --- a/src/gallium/drivers/radeon/r600_texture.c +++ b/src/gallium/drivers/radeon/r600_texture.c @@ -2193,112 +2193,127 @@ void vi_separate_dcc_process_and_reset_stats(struct pipe_context *ctx, /* FAST COLOR CLEAR */ static void evergreen_set_clear_color(struct r600_texture *rtex, enum pipe_format surface_format, const union pipe_color_union *color) { union util_color uc; memset(&uc, 0, sizeof(uc)); - if (util_format_is_pure_uint(surface_format)) { + if (util_format_get_blocksizebits(surface_format) == 128) { + /* DCC fast clear only: + * CLEAR_WORD0 = R = G = B + * CLEAR_WORD1 = A + */ + assert(color->ui[0] == color->ui[1] && + color->ui[0] == color->ui[2]); + uc.ui[0] = color->ui[0]; + uc.ui[1] = color->ui[3]; + } else if (util_format_is_pure_uint(surface_format)) { util_format_write_4ui(surface_format, color->ui, 0, &uc, 0, 0, 0, 1, 1); } else if (util_format_is_pure_sint(surface_format)) { util_format_write_4i(surface_format, color->i, 0, &uc, 0, 0, 0, 1, 1); } else { util_pack_color(color->f, surface_format, &uc); } memcpy(rtex->color_clear_value, &uc, 2 * sizeof(uint32_t)); } -static void vi_get_fast_clear_parameters(enum pipe_format surface_format, +static bool vi_get_fast_clear_parameters(enum pipe_format surface_format, const union pipe_color_union *color, uint32_t* reset_value, bool* clear_words_needed) { bool values[4] = {}; int i; bool main_value = false; bool extra_value = false; int extra_channel; const struct util_format_description *desc = util_format_description(surface_format); + if (desc->block.bits == 128 && + (color->ui[0] != color->ui[1] || + color->ui[0] != color->ui[2])) + return false; + *clear_words_needed = true; *reset_value = 0x20202020U; /* If we want to clear without needing a fast clear eliminate step, we * can set each channel to 0 or 1 (or 0/max for integer formats). We * have two sets of flags, one for the last or first channel(extra) and * one for the other channels(main). */ if (surface_format == PIPE_FORMAT_R11G11B10_FLOAT || surface_format == PIPE_FORMAT_B5G6R5_UNORM || surface_format == PIPE_FORMAT_B5G6R5_SRGB) { extra_channel = -1; } else if (desc->layout == UTIL_FORMAT_LAYOUT_PLAIN) { if(r600_translate_colorswap(surface_format, false) <= 1) extra_channel = desc->nr_channels - 1; else extra_channel = 0; } else - return; + return true; for (i = 0; i < 4; ++i) { int index = desc->swizzle[i] - PIPE_SWIZZLE_X; if (desc->swizzle[i] < PIPE_SWIZZLE_X || desc->swizzle[i] > PIPE_SWIZZLE_W) continue; if (desc->channel[i].pure_integer && desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED) { /* Use the maximum value for clamping the clear color. */ int max = u_bit_consecutive(0, desc->channel[i].size - 1); values[i] = color->i[i] != 0; if (color->i[i] != 0 && MIN2(color->i[i], max) != max) - return; + return true; } else if (desc->channel[i].pure_integer && desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED) { /* Use the maximum value for clamping the clear color. */ unsigned max = u_bit_consecutive(0, desc->channel[i].size); values[i] = color->ui[i] != 0U; if (color->ui[i] != 0U && MIN2(color->ui[i], max) != max) - return; + return true; } else { values[i] = color->f[i] != 0.0F; if (color->f[i] != 0.0F && color->f[i] != 1.0F) - return; + return true; } if (index == extra_channel) extra_value = values[i]; else main_value = values[i]; } for (int i = 0; i < 4; ++i) if (values[i] != main_value && desc->swizzle[i] - PIPE_SWIZZLE_X != extra_channel && desc->swizzle[i] >= PIPE_SWIZZLE_X && desc->swizzle[i] <= PIPE_SWIZZLE_W) - return; + return true; *clear_words_needed = false; if (main_value) *reset_value |= 0x80808080U; if (extra_value) *reset_value |= 0x40404040U; + return true; } void vi_dcc_clear_level(struct r600_common_context *rctx, struct r600_texture *rtex, unsigned level, unsigned clear_value) { struct pipe_resource *dcc_buffer; uint64_t dcc_offset; assert(rtex->dcc_offset && rtex->surface.level[level].dcc_enabled); @@ -2417,25 +2432,20 @@ void evergreen_do_fast_color_clear(struct r600_common_context *rctx, if (!fb->cbufs[i]) continue; /* if this colorbuffer is not being cleared */ if (!(*buffers & clear_bit)) continue; tex = (struct r600_texture *)fb->cbufs[i]->texture; - /* 128-bit formats are unusupported */ - if (util_format_get_blocksizebits(fb->cbufs[i]->format) > 64) { - continue; - } - /* the clear is allowed if all layers are bound */ if (fb->cbufs[i]->u.tex.first_layer != 0 || fb->cbufs[i]->u.tex.last_layer != util_max_layer(&tex->resource.b.b, 0)) { continue; } /* cannot clear mipmapped textures */ if (fb->cbufs[i]->texture->last_level != 0) { continue; } @@ -2482,27 +2492,36 @@ void evergreen_do_fast_color_clear(struct r600_common_context *rctx, uint32_t reset_value; bool clear_words_needed; if (rctx->screen->debug_flags & DBG_NO_DCC_CLEAR) continue; /* We can change the micro tile mode before a full clear. */ if (rctx->screen->chip_class >= SI) si_set_optimal_micro_tile_mode(rctx->screen, tex); - vi_get_fast_clear_parameters(fb->cbufs[i]->format, color, &reset_value, &clear_words_needed); + if (!vi_get_fast_clear_parameters(fb->cbufs[i]->format, + color, &reset_value, + &clear_words_needed)) + continue; + vi_dcc_clear_level(rctx, tex, 0, reset_value); if (clear_words_needed) tex->dirty_level_mask |= 1 << fb->cbufs[i]->u.tex.level; tex->separate_dcc_dirty = true; } else { + /* 128-bit formats are unusupported */ + if (util_format_get_blocksizebits(fb->cbufs[i]->format) > 64) { + continue; + } + /* Stoney/RB+ doesn't work with CMASK fast clear. */ if (rctx->family == CHIP_STONEY) continue; /* ensure CMASK is enabled */ r600_texture_alloc_cmask_separate(rctx->screen, tex); if (tex->cmask.size == 0) { continue; } -- 2.7.4 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev