1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright 2017 Advanced Micro Devices, Inc. 3bf215546Sopenharmony_ci * All Rights Reserved. 4bf215546Sopenharmony_ci * 5bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 6bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 7bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 8bf215546Sopenharmony_ci * on the rights to use, copy, modify, merge, publish, distribute, sub 9bf215546Sopenharmony_ci * license, and/or sell copies of the Software, and to permit persons to whom 10bf215546Sopenharmony_ci * the Software is furnished to do so, subject to the following conditions: 11bf215546Sopenharmony_ci * 12bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 13bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 14bf215546Sopenharmony_ci * Software. 15bf215546Sopenharmony_ci * 16bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 19bf215546Sopenharmony_ci * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 20bf215546Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 21bf215546Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 22bf215546Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE. 23bf215546Sopenharmony_ci */ 24bf215546Sopenharmony_ci 25bf215546Sopenharmony_ci#include "si_pipe.h" 26bf215546Sopenharmony_ci#include "sid.h" 27bf215546Sopenharmony_ci#include "util/format/u_format.h" 28bf215546Sopenharmony_ci#include "util/u_pack_color.h" 29bf215546Sopenharmony_ci#include "util/u_surface.h" 30bf215546Sopenharmony_ci 31bf215546Sopenharmony_cienum 32bf215546Sopenharmony_ci{ 33bf215546Sopenharmony_ci SI_CLEAR = SI_SAVE_FRAGMENT_STATE, 34bf215546Sopenharmony_ci SI_CLEAR_SURFACE = SI_SAVE_FRAMEBUFFER | SI_SAVE_FRAGMENT_STATE, 35bf215546Sopenharmony_ci}; 36bf215546Sopenharmony_ci 37bf215546Sopenharmony_civoid si_init_buffer_clear(struct si_clear_info *info, 38bf215546Sopenharmony_ci struct pipe_resource *resource, uint64_t offset, 39bf215546Sopenharmony_ci uint32_t size, uint32_t clear_value) 40bf215546Sopenharmony_ci{ 41bf215546Sopenharmony_ci info->resource = resource; 42bf215546Sopenharmony_ci info->offset = offset; 43bf215546Sopenharmony_ci info->size = size; 44bf215546Sopenharmony_ci info->clear_value = clear_value; 45bf215546Sopenharmony_ci info->writemask = 0xffffffff; 46bf215546Sopenharmony_ci info->is_dcc_msaa = false; 47bf215546Sopenharmony_ci} 48bf215546Sopenharmony_ci 49bf215546Sopenharmony_cistatic void si_init_buffer_clear_rmw(struct si_clear_info *info, 50bf215546Sopenharmony_ci struct pipe_resource *resource, uint64_t offset, 51bf215546Sopenharmony_ci uint32_t size, uint32_t clear_value, uint32_t writemask) 52bf215546Sopenharmony_ci{ 53bf215546Sopenharmony_ci si_init_buffer_clear(info, resource, offset, size, clear_value); 54bf215546Sopenharmony_ci info->writemask = writemask; 55bf215546Sopenharmony_ci} 56bf215546Sopenharmony_ci 57bf215546Sopenharmony_civoid si_execute_clears(struct si_context *sctx, struct si_clear_info *info, 58bf215546Sopenharmony_ci unsigned num_clears, unsigned types) 59bf215546Sopenharmony_ci{ 60bf215546Sopenharmony_ci if (!num_clears) 61bf215546Sopenharmony_ci return; 62bf215546Sopenharmony_ci 63bf215546Sopenharmony_ci /* Flush caches and wait for idle. */ 64bf215546Sopenharmony_ci if (types & (SI_CLEAR_TYPE_CMASK | SI_CLEAR_TYPE_DCC)) 65bf215546Sopenharmony_ci sctx->flags |= si_get_flush_flags(sctx, SI_COHERENCY_CB_META, L2_LRU); 66bf215546Sopenharmony_ci 67bf215546Sopenharmony_ci if (types & SI_CLEAR_TYPE_HTILE) 68bf215546Sopenharmony_ci sctx->flags |= si_get_flush_flags(sctx, SI_COHERENCY_DB_META, L2_LRU); 69bf215546Sopenharmony_ci 70bf215546Sopenharmony_ci /* Flush caches in case we use compute. */ 71bf215546Sopenharmony_ci sctx->flags |= SI_CONTEXT_INV_VCACHE; 72bf215546Sopenharmony_ci 73bf215546Sopenharmony_ci /* GFX6-8: CB and DB don't use L2. */ 74bf215546Sopenharmony_ci if (sctx->gfx_level <= GFX8) 75bf215546Sopenharmony_ci sctx->flags |= SI_CONTEXT_INV_L2; 76bf215546Sopenharmony_ci 77bf215546Sopenharmony_ci /* Execute clears. */ 78bf215546Sopenharmony_ci for (unsigned i = 0; i < num_clears; i++) { 79bf215546Sopenharmony_ci if (info[i].is_dcc_msaa) { 80bf215546Sopenharmony_ci gfx9_clear_dcc_msaa(sctx, info[i].resource, info[i].clear_value, 81bf215546Sopenharmony_ci SI_OP_SKIP_CACHE_INV_BEFORE, SI_COHERENCY_CP); 82bf215546Sopenharmony_ci continue; 83bf215546Sopenharmony_ci } 84bf215546Sopenharmony_ci 85bf215546Sopenharmony_ci assert(info[i].size > 0); 86bf215546Sopenharmony_ci 87bf215546Sopenharmony_ci if (info[i].writemask != 0xffffffff) { 88bf215546Sopenharmony_ci si_compute_clear_buffer_rmw(sctx, info[i].resource, info[i].offset, info[i].size, 89bf215546Sopenharmony_ci info[i].clear_value, info[i].writemask, 90bf215546Sopenharmony_ci SI_OP_SKIP_CACHE_INV_BEFORE, SI_COHERENCY_CP); 91bf215546Sopenharmony_ci } else { 92bf215546Sopenharmony_ci /* Compute shaders are much faster on both dGPUs and APUs. Don't use CP DMA. */ 93bf215546Sopenharmony_ci si_clear_buffer(sctx, info[i].resource, info[i].offset, info[i].size, 94bf215546Sopenharmony_ci &info[i].clear_value, 4, SI_OP_SKIP_CACHE_INV_BEFORE, 95bf215546Sopenharmony_ci SI_COHERENCY_CP, SI_COMPUTE_CLEAR_METHOD); 96bf215546Sopenharmony_ci } 97bf215546Sopenharmony_ci } 98bf215546Sopenharmony_ci 99bf215546Sopenharmony_ci /* Wait for idle. */ 100bf215546Sopenharmony_ci sctx->flags |= SI_CONTEXT_CS_PARTIAL_FLUSH; 101bf215546Sopenharmony_ci 102bf215546Sopenharmony_ci /* GFX6-8: CB and DB don't use L2. */ 103bf215546Sopenharmony_ci if (sctx->gfx_level <= GFX8) 104bf215546Sopenharmony_ci sctx->flags |= SI_CONTEXT_WB_L2; 105bf215546Sopenharmony_ci} 106bf215546Sopenharmony_ci 107bf215546Sopenharmony_cistatic bool si_alloc_separate_cmask(struct si_screen *sscreen, struct si_texture *tex) 108bf215546Sopenharmony_ci{ 109bf215546Sopenharmony_ci assert(sscreen->info.gfx_level < GFX11); 110bf215546Sopenharmony_ci 111bf215546Sopenharmony_ci /* CMASK for MSAA is allocated in advance or always disabled 112bf215546Sopenharmony_ci * by "nofmask" option. 113bf215546Sopenharmony_ci */ 114bf215546Sopenharmony_ci if (tex->cmask_buffer) 115bf215546Sopenharmony_ci return true; 116bf215546Sopenharmony_ci 117bf215546Sopenharmony_ci if (!tex->surface.cmask_size) 118bf215546Sopenharmony_ci return false; 119bf215546Sopenharmony_ci 120bf215546Sopenharmony_ci tex->cmask_buffer = 121bf215546Sopenharmony_ci si_aligned_buffer_create(&sscreen->b, PIPE_RESOURCE_FLAG_UNMAPPABLE, PIPE_USAGE_DEFAULT, 122bf215546Sopenharmony_ci tex->surface.cmask_size, 1 << tex->surface.cmask_alignment_log2); 123bf215546Sopenharmony_ci if (tex->cmask_buffer == NULL) 124bf215546Sopenharmony_ci return false; 125bf215546Sopenharmony_ci 126bf215546Sopenharmony_ci tex->cmask_base_address_reg = tex->cmask_buffer->gpu_address >> 8; 127bf215546Sopenharmony_ci tex->cb_color_info |= S_028C70_FAST_CLEAR(1); 128bf215546Sopenharmony_ci 129bf215546Sopenharmony_ci p_atomic_inc(&sscreen->compressed_colortex_counter); 130bf215546Sopenharmony_ci return true; 131bf215546Sopenharmony_ci} 132bf215546Sopenharmony_ci 133bf215546Sopenharmony_cistatic bool si_set_clear_color(struct si_texture *tex, enum pipe_format surface_format, 134bf215546Sopenharmony_ci const union pipe_color_union *color) 135bf215546Sopenharmony_ci{ 136bf215546Sopenharmony_ci union util_color uc; 137bf215546Sopenharmony_ci 138bf215546Sopenharmony_ci memset(&uc, 0, sizeof(uc)); 139bf215546Sopenharmony_ci 140bf215546Sopenharmony_ci if (tex->surface.bpe == 16) { 141bf215546Sopenharmony_ci /* DCC fast clear only: 142bf215546Sopenharmony_ci * CLEAR_WORD0 = R = G = B 143bf215546Sopenharmony_ci * CLEAR_WORD1 = A 144bf215546Sopenharmony_ci */ 145bf215546Sopenharmony_ci assert(color->ui[0] == color->ui[1] && color->ui[0] == color->ui[2]); 146bf215546Sopenharmony_ci uc.ui[0] = color->ui[0]; 147bf215546Sopenharmony_ci uc.ui[1] = color->ui[3]; 148bf215546Sopenharmony_ci } else { 149bf215546Sopenharmony_ci if (tex->swap_rgb_to_bgr) 150bf215546Sopenharmony_ci surface_format = util_format_rgb_to_bgr(surface_format); 151bf215546Sopenharmony_ci 152bf215546Sopenharmony_ci util_pack_color_union(surface_format, &uc, color); 153bf215546Sopenharmony_ci } 154bf215546Sopenharmony_ci 155bf215546Sopenharmony_ci if (memcmp(tex->color_clear_value, &uc, 2 * sizeof(uint32_t)) == 0) 156bf215546Sopenharmony_ci return false; 157bf215546Sopenharmony_ci 158bf215546Sopenharmony_ci memcpy(tex->color_clear_value, &uc, 2 * sizeof(uint32_t)); 159bf215546Sopenharmony_ci return true; 160bf215546Sopenharmony_ci} 161bf215546Sopenharmony_ci 162bf215546Sopenharmony_ci/** Linearize and convert luminance/intensity to red. */ 163bf215546Sopenharmony_cienum pipe_format si_simplify_cb_format(enum pipe_format format) 164bf215546Sopenharmony_ci{ 165bf215546Sopenharmony_ci format = util_format_linear(format); 166bf215546Sopenharmony_ci format = util_format_luminance_to_red(format); 167bf215546Sopenharmony_ci return util_format_intensity_to_red(format); 168bf215546Sopenharmony_ci} 169bf215546Sopenharmony_ci 170bf215546Sopenharmony_cibool vi_alpha_is_on_msb(struct si_screen *sscreen, enum pipe_format format) 171bf215546Sopenharmony_ci{ 172bf215546Sopenharmony_ci format = si_simplify_cb_format(format); 173bf215546Sopenharmony_ci const struct util_format_description *desc = util_format_description(format); 174bf215546Sopenharmony_ci unsigned comp_swap = si_translate_colorswap(sscreen->info.gfx_level, format, false); 175bf215546Sopenharmony_ci 176bf215546Sopenharmony_ci /* The following code matches the hw behavior. */ 177bf215546Sopenharmony_ci if (desc->nr_channels == 1) { 178bf215546Sopenharmony_ci return (comp_swap == V_028C70_SWAP_ALT_REV) != (sscreen->info.family == CHIP_RAVEN2 || 179bf215546Sopenharmony_ci sscreen->info.family == CHIP_RENOIR); 180bf215546Sopenharmony_ci } 181bf215546Sopenharmony_ci 182bf215546Sopenharmony_ci return comp_swap != V_028C70_SWAP_STD_REV && comp_swap != V_028C70_SWAP_ALT_REV; 183bf215546Sopenharmony_ci} 184bf215546Sopenharmony_ci 185bf215546Sopenharmony_cistatic bool gfx8_get_dcc_clear_parameters(struct si_screen *sscreen, enum pipe_format base_format, 186bf215546Sopenharmony_ci enum pipe_format surface_format, 187bf215546Sopenharmony_ci const union pipe_color_union *color, uint32_t *clear_value, 188bf215546Sopenharmony_ci bool *eliminate_needed) 189bf215546Sopenharmony_ci{ 190bf215546Sopenharmony_ci /* If we want to clear without needing a fast clear eliminate step, we 191bf215546Sopenharmony_ci * can set color and alpha independently to 0 or 1 (or 0/max for integer 192bf215546Sopenharmony_ci * formats). 193bf215546Sopenharmony_ci */ 194bf215546Sopenharmony_ci bool values[4] = {}; /* whether to clear to 0 or 1 */ 195bf215546Sopenharmony_ci bool color_value = false; /* clear color to 0 or 1 */ 196bf215546Sopenharmony_ci bool alpha_value = false; /* clear alpha to 0 or 1 */ 197bf215546Sopenharmony_ci int alpha_channel; /* index of the alpha component */ 198bf215546Sopenharmony_ci bool has_color = false; 199bf215546Sopenharmony_ci bool has_alpha = false; 200bf215546Sopenharmony_ci 201bf215546Sopenharmony_ci const struct util_format_description *desc = 202bf215546Sopenharmony_ci util_format_description(si_simplify_cb_format(surface_format)); 203bf215546Sopenharmony_ci 204bf215546Sopenharmony_ci /* 128-bit fast clear with different R,G,B values is unsupported. */ 205bf215546Sopenharmony_ci if (desc->block.bits == 128 && (color->ui[0] != color->ui[1] || color->ui[0] != color->ui[2])) 206bf215546Sopenharmony_ci return false; 207bf215546Sopenharmony_ci 208bf215546Sopenharmony_ci *eliminate_needed = true; 209bf215546Sopenharmony_ci *clear_value = GFX8_DCC_CLEAR_REG; 210bf215546Sopenharmony_ci 211bf215546Sopenharmony_ci if (desc->layout != UTIL_FORMAT_LAYOUT_PLAIN) 212bf215546Sopenharmony_ci return true; /* need ELIMINATE_FAST_CLEAR */ 213bf215546Sopenharmony_ci 214bf215546Sopenharmony_ci bool base_alpha_is_on_msb = vi_alpha_is_on_msb(sscreen, base_format); 215bf215546Sopenharmony_ci bool surf_alpha_is_on_msb = vi_alpha_is_on_msb(sscreen, surface_format); 216bf215546Sopenharmony_ci 217bf215546Sopenharmony_ci /* Formats with 3 channels can't have alpha. */ 218bf215546Sopenharmony_ci if (desc->nr_channels == 3) 219bf215546Sopenharmony_ci alpha_channel = -1; 220bf215546Sopenharmony_ci else if (surf_alpha_is_on_msb) 221bf215546Sopenharmony_ci alpha_channel = desc->nr_channels - 1; 222bf215546Sopenharmony_ci else 223bf215546Sopenharmony_ci alpha_channel = 0; 224bf215546Sopenharmony_ci 225bf215546Sopenharmony_ci for (int i = 0; i < 4; ++i) { 226bf215546Sopenharmony_ci if (desc->swizzle[i] >= PIPE_SWIZZLE_0) 227bf215546Sopenharmony_ci continue; 228bf215546Sopenharmony_ci 229bf215546Sopenharmony_ci if (desc->channel[i].pure_integer && desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED) { 230bf215546Sopenharmony_ci /* Use the maximum value for clamping the clear color. */ 231bf215546Sopenharmony_ci int max = u_bit_consecutive(0, desc->channel[i].size - 1); 232bf215546Sopenharmony_ci 233bf215546Sopenharmony_ci values[i] = color->i[i] != 0; 234bf215546Sopenharmony_ci if (color->i[i] != 0 && MIN2(color->i[i], max) != max) 235bf215546Sopenharmony_ci return true; /* need ELIMINATE_FAST_CLEAR */ 236bf215546Sopenharmony_ci } else if (desc->channel[i].pure_integer && 237bf215546Sopenharmony_ci desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED) { 238bf215546Sopenharmony_ci /* Use the maximum value for clamping the clear color. */ 239bf215546Sopenharmony_ci unsigned max = u_bit_consecutive(0, desc->channel[i].size); 240bf215546Sopenharmony_ci 241bf215546Sopenharmony_ci values[i] = color->ui[i] != 0U; 242bf215546Sopenharmony_ci if (color->ui[i] != 0U && MIN2(color->ui[i], max) != max) 243bf215546Sopenharmony_ci return true; /* need ELIMINATE_FAST_CLEAR */ 244bf215546Sopenharmony_ci } else { 245bf215546Sopenharmony_ci values[i] = color->f[i] != 0.0F; 246bf215546Sopenharmony_ci if (color->f[i] != 0.0F && color->f[i] != 1.0F) 247bf215546Sopenharmony_ci return true; /* need ELIMINATE_FAST_CLEAR */ 248bf215546Sopenharmony_ci } 249bf215546Sopenharmony_ci 250bf215546Sopenharmony_ci if (desc->swizzle[i] == alpha_channel) { 251bf215546Sopenharmony_ci alpha_value = values[i]; 252bf215546Sopenharmony_ci has_alpha = true; 253bf215546Sopenharmony_ci } else { 254bf215546Sopenharmony_ci color_value = values[i]; 255bf215546Sopenharmony_ci has_color = true; 256bf215546Sopenharmony_ci } 257bf215546Sopenharmony_ci } 258bf215546Sopenharmony_ci 259bf215546Sopenharmony_ci /* If alpha isn't present, make it the same as color, and vice versa. */ 260bf215546Sopenharmony_ci if (!has_alpha) 261bf215546Sopenharmony_ci alpha_value = color_value; 262bf215546Sopenharmony_ci else if (!has_color) 263bf215546Sopenharmony_ci color_value = alpha_value; 264bf215546Sopenharmony_ci 265bf215546Sopenharmony_ci if (color_value != alpha_value && base_alpha_is_on_msb != surf_alpha_is_on_msb) 266bf215546Sopenharmony_ci return true; /* require ELIMINATE_FAST_CLEAR */ 267bf215546Sopenharmony_ci 268bf215546Sopenharmony_ci /* Check if all color values are equal if they are present. */ 269bf215546Sopenharmony_ci for (int i = 0; i < 4; ++i) { 270bf215546Sopenharmony_ci if (desc->swizzle[i] <= PIPE_SWIZZLE_W && desc->swizzle[i] != alpha_channel && 271bf215546Sopenharmony_ci values[i] != color_value) 272bf215546Sopenharmony_ci return true; /* require ELIMINATE_FAST_CLEAR */ 273bf215546Sopenharmony_ci } 274bf215546Sopenharmony_ci 275bf215546Sopenharmony_ci /* This doesn't need ELIMINATE_FAST_CLEAR. 276bf215546Sopenharmony_ci * On chips predating Raven2, the DCC clear codes and the CB clear 277bf215546Sopenharmony_ci * color registers must match. 278bf215546Sopenharmony_ci */ 279bf215546Sopenharmony_ci *eliminate_needed = false; 280bf215546Sopenharmony_ci 281bf215546Sopenharmony_ci if (color_value) { 282bf215546Sopenharmony_ci if (alpha_value) 283bf215546Sopenharmony_ci *clear_value = GFX8_DCC_CLEAR_1111; 284bf215546Sopenharmony_ci else 285bf215546Sopenharmony_ci *clear_value = GFX8_DCC_CLEAR_1110; 286bf215546Sopenharmony_ci } else { 287bf215546Sopenharmony_ci if (alpha_value) 288bf215546Sopenharmony_ci *clear_value = GFX8_DCC_CLEAR_0001; 289bf215546Sopenharmony_ci else 290bf215546Sopenharmony_ci *clear_value = GFX8_DCC_CLEAR_0000; 291bf215546Sopenharmony_ci } 292bf215546Sopenharmony_ci return true; 293bf215546Sopenharmony_ci} 294bf215546Sopenharmony_ci 295bf215546Sopenharmony_cistatic bool gfx11_get_dcc_clear_parameters(struct si_screen *sscreen, enum pipe_format surface_format, 296bf215546Sopenharmony_ci const union pipe_color_union *color, uint32_t *clear_value) 297bf215546Sopenharmony_ci{ 298bf215546Sopenharmony_ci const struct util_format_description *desc = 299bf215546Sopenharmony_ci util_format_description(si_simplify_cb_format(surface_format)); 300bf215546Sopenharmony_ci unsigned start_bit = UINT_MAX; 301bf215546Sopenharmony_ci unsigned end_bit = 0; 302bf215546Sopenharmony_ci 303bf215546Sopenharmony_ci /* TODO: 8bpp and 16bpp fast DCC clears don't work. */ 304bf215546Sopenharmony_ci if (desc->block.bits <= 16) 305bf215546Sopenharmony_ci return false; 306bf215546Sopenharmony_ci 307bf215546Sopenharmony_ci /* Find the used bit range. */ 308bf215546Sopenharmony_ci for (unsigned i = 0; i < 4; i++) { 309bf215546Sopenharmony_ci unsigned swizzle = desc->swizzle[i]; 310bf215546Sopenharmony_ci 311bf215546Sopenharmony_ci if (swizzle >= PIPE_SWIZZLE_0) 312bf215546Sopenharmony_ci continue; 313bf215546Sopenharmony_ci 314bf215546Sopenharmony_ci start_bit = MIN2(start_bit, desc->channel[swizzle].shift); 315bf215546Sopenharmony_ci end_bit = MAX2(end_bit, desc->channel[swizzle].shift + desc->channel[swizzle].size); 316bf215546Sopenharmony_ci } 317bf215546Sopenharmony_ci 318bf215546Sopenharmony_ci union { 319bf215546Sopenharmony_ci uint8_t ub[16]; 320bf215546Sopenharmony_ci uint16_t us[8]; 321bf215546Sopenharmony_ci uint32_t ui[4]; 322bf215546Sopenharmony_ci } value = {}; 323bf215546Sopenharmony_ci util_pack_color_union(surface_format, (union util_color*)&value, color); 324bf215546Sopenharmony_ci 325bf215546Sopenharmony_ci /* Check the cases where all components or bits are either all 0 or all 1. */ 326bf215546Sopenharmony_ci bool all_bits_are_0 = true; 327bf215546Sopenharmony_ci bool all_bits_are_1 = true; 328bf215546Sopenharmony_ci bool all_words_are_fp16_1 = false; 329bf215546Sopenharmony_ci bool all_words_are_fp32_1 = false; 330bf215546Sopenharmony_ci 331bf215546Sopenharmony_ci for (unsigned i = start_bit; i < end_bit; i++) { 332bf215546Sopenharmony_ci bool bit = value.ub[i / 8] & BITFIELD_BIT(i % 8); 333bf215546Sopenharmony_ci 334bf215546Sopenharmony_ci all_bits_are_0 &= !bit; 335bf215546Sopenharmony_ci all_bits_are_1 &= bit; 336bf215546Sopenharmony_ci } 337bf215546Sopenharmony_ci 338bf215546Sopenharmony_ci if (start_bit % 16 == 0 && end_bit % 16 == 0) { 339bf215546Sopenharmony_ci all_words_are_fp16_1 = true; 340bf215546Sopenharmony_ci for (unsigned i = start_bit / 16; i < end_bit / 16; i++) 341bf215546Sopenharmony_ci all_words_are_fp16_1 &= value.us[i] == 0x3c00; 342bf215546Sopenharmony_ci } 343bf215546Sopenharmony_ci 344bf215546Sopenharmony_ci if (start_bit % 32 == 0 && end_bit % 32 == 0) { 345bf215546Sopenharmony_ci all_words_are_fp32_1 = true; 346bf215546Sopenharmony_ci for (unsigned i = start_bit / 32; i < end_bit / 32; i++) 347bf215546Sopenharmony_ci all_words_are_fp32_1 &= value.ui[i] == 0x3f800000; 348bf215546Sopenharmony_ci } 349bf215546Sopenharmony_ci 350bf215546Sopenharmony_ci#if 0 /* debug code */ 351bf215546Sopenharmony_ci int i = util_format_get_first_non_void_channel(surface_format); 352bf215546Sopenharmony_ci if (desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED && desc->channel[i].pure_integer) { 353bf215546Sopenharmony_ci printf("%i %i %i %i\n", color->i[0], color->i[1], color->i[2], color->i[3]); 354bf215546Sopenharmony_ci } else if (desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED && desc->channel[i].pure_integer) { 355bf215546Sopenharmony_ci printf("%u %u %u %u\n", color->ui[0], color->ui[1], color->ui[2], color->ui[3]); 356bf215546Sopenharmony_ci } else { 357bf215546Sopenharmony_ci printf("%f %f %f %f\n", color->f[0], color->f[1], color->f[2], color->f[3]); 358bf215546Sopenharmony_ci } 359bf215546Sopenharmony_ci for (unsigned i = 0; i < end_bit / 8; i++) 360bf215546Sopenharmony_ci printf("%02x", value.ub[i]); 361bf215546Sopenharmony_ci printf("\n"); 362bf215546Sopenharmony_ci printf("bits=[%u..%u)%s%s%s%s\n", start_bit, end_bit, 363bf215546Sopenharmony_ci all_bits_are_0 ? ", all 0" : "", 364bf215546Sopenharmony_ci all_bits_are_1 ? ", all 1" : "", 365bf215546Sopenharmony_ci all_words_are_fp16_1 ? ", all fp16 1" : "", 366bf215546Sopenharmony_ci all_words_are_fp32_1 ? ", all fp32 1" : ""); 367bf215546Sopenharmony_ci#endif 368bf215546Sopenharmony_ci 369bf215546Sopenharmony_ci *clear_value = 0; 370bf215546Sopenharmony_ci 371bf215546Sopenharmony_ci if (all_bits_are_0 || all_bits_are_1 || all_words_are_fp16_1 || all_words_are_fp32_1) { 372bf215546Sopenharmony_ci if (all_bits_are_0) 373bf215546Sopenharmony_ci *clear_value = GFX11_DCC_CLEAR_0000; 374bf215546Sopenharmony_ci else if (all_bits_are_1) 375bf215546Sopenharmony_ci *clear_value = GFX11_DCC_CLEAR_1111_UNORM; 376bf215546Sopenharmony_ci else if (all_words_are_fp16_1) 377bf215546Sopenharmony_ci *clear_value = GFX11_DCC_CLEAR_1111_FP16; 378bf215546Sopenharmony_ci else if (all_words_are_fp32_1) 379bf215546Sopenharmony_ci *clear_value = GFX11_DCC_CLEAR_1111_FP32; 380bf215546Sopenharmony_ci 381bf215546Sopenharmony_ci return true; 382bf215546Sopenharmony_ci } 383bf215546Sopenharmony_ci 384bf215546Sopenharmony_ci /* Check 0001 and 1110 cases. */ 385bf215546Sopenharmony_ci if (vi_alpha_is_on_msb(sscreen, surface_format)) { 386bf215546Sopenharmony_ci if (desc->nr_channels == 2 && desc->channel[0].size == 8) { 387bf215546Sopenharmony_ci if (value.ub[0] == 0x00 && value.ub[1] == 0xff) { 388bf215546Sopenharmony_ci *clear_value = GFX11_DCC_CLEAR_0001_UNORM; 389bf215546Sopenharmony_ci return true; 390bf215546Sopenharmony_ci } else if (value.ub[0] == 0xff && value.ub[1] == 0x00) { 391bf215546Sopenharmony_ci *clear_value = GFX11_DCC_CLEAR_1110_UNORM; 392bf215546Sopenharmony_ci return true; 393bf215546Sopenharmony_ci } 394bf215546Sopenharmony_ci } else if (desc->nr_channels == 4 && desc->channel[0].size == 8) { 395bf215546Sopenharmony_ci if (value.ub[0] == 0x00 && value.ub[1] == 0x00 && 396bf215546Sopenharmony_ci value.ub[2] == 0x00 && value.ub[3] == 0xff) { 397bf215546Sopenharmony_ci *clear_value = GFX11_DCC_CLEAR_0001_UNORM; 398bf215546Sopenharmony_ci return true; 399bf215546Sopenharmony_ci } else if (value.ub[0] == 0xff && value.ub[1] == 0xff && 400bf215546Sopenharmony_ci value.ub[2] == 0xff && value.ub[3] == 0x00) { 401bf215546Sopenharmony_ci *clear_value = GFX11_DCC_CLEAR_1110_UNORM; 402bf215546Sopenharmony_ci return true; 403bf215546Sopenharmony_ci } 404bf215546Sopenharmony_ci } else if (desc->nr_channels == 4 && desc->channel[0].size == 16) { 405bf215546Sopenharmony_ci if (value.us[0] == 0x0000 && value.us[1] == 0x0000 && 406bf215546Sopenharmony_ci value.us[2] == 0x0000 && value.us[3] == 0xffff) { 407bf215546Sopenharmony_ci *clear_value = GFX11_DCC_CLEAR_0001_UNORM; 408bf215546Sopenharmony_ci return true; 409bf215546Sopenharmony_ci } else if (value.us[0] == 0xffff && value.us[1] == 0xffff && 410bf215546Sopenharmony_ci value.us[2] == 0xffff && value.us[3] == 0x0000) { 411bf215546Sopenharmony_ci *clear_value = GFX11_DCC_CLEAR_1110_UNORM; 412bf215546Sopenharmony_ci return true; 413bf215546Sopenharmony_ci } 414bf215546Sopenharmony_ci } 415bf215546Sopenharmony_ci } 416bf215546Sopenharmony_ci 417bf215546Sopenharmony_ci return false; 418bf215546Sopenharmony_ci} 419bf215546Sopenharmony_ci 420bf215546Sopenharmony_cibool vi_dcc_get_clear_info(struct si_context *sctx, struct si_texture *tex, unsigned level, 421bf215546Sopenharmony_ci unsigned clear_value, struct si_clear_info *out) 422bf215546Sopenharmony_ci{ 423bf215546Sopenharmony_ci struct pipe_resource *dcc_buffer = &tex->buffer.b.b; 424bf215546Sopenharmony_ci uint64_t dcc_offset = tex->surface.meta_offset; 425bf215546Sopenharmony_ci uint32_t clear_size; 426bf215546Sopenharmony_ci 427bf215546Sopenharmony_ci assert(vi_dcc_enabled(tex, level)); 428bf215546Sopenharmony_ci 429bf215546Sopenharmony_ci if (sctx->gfx_level >= GFX10) { 430bf215546Sopenharmony_ci /* 4x and 8x MSAA needs a sophisticated compute shader for 431bf215546Sopenharmony_ci * the clear. GFX11 doesn't need that. 432bf215546Sopenharmony_ci */ 433bf215546Sopenharmony_ci if (sctx->gfx_level < GFX11 && tex->buffer.b.b.nr_storage_samples >= 4) 434bf215546Sopenharmony_ci return false; 435bf215546Sopenharmony_ci 436bf215546Sopenharmony_ci unsigned num_layers = util_num_layers(&tex->buffer.b.b, level); 437bf215546Sopenharmony_ci 438bf215546Sopenharmony_ci if (num_layers == 1) { 439bf215546Sopenharmony_ci /* Clear a specific level. */ 440bf215546Sopenharmony_ci dcc_offset += tex->surface.u.gfx9.meta_levels[level].offset; 441bf215546Sopenharmony_ci clear_size = tex->surface.u.gfx9.meta_levels[level].size; 442bf215546Sopenharmony_ci } else if (tex->buffer.b.b.last_level == 0) { 443bf215546Sopenharmony_ci /* Clear all layers having only 1 level. */ 444bf215546Sopenharmony_ci clear_size = tex->surface.meta_size; 445bf215546Sopenharmony_ci } else { 446bf215546Sopenharmony_ci /* Clearing DCC with both multiple levels and multiple layers is not 447bf215546Sopenharmony_ci * implemented. 448bf215546Sopenharmony_ci */ 449bf215546Sopenharmony_ci return false; 450bf215546Sopenharmony_ci } 451bf215546Sopenharmony_ci } else if (sctx->gfx_level == GFX9) { 452bf215546Sopenharmony_ci /* TODO: Implement DCC fast clear for level 0 of mipmapped textures. Mipmapped 453bf215546Sopenharmony_ci * DCC has to clear a rectangular area of DCC for level 0 (because the whole miptree 454bf215546Sopenharmony_ci * is organized in a 2D plane). 455bf215546Sopenharmony_ci */ 456bf215546Sopenharmony_ci if (tex->buffer.b.b.last_level > 0) 457bf215546Sopenharmony_ci return false; 458bf215546Sopenharmony_ci 459bf215546Sopenharmony_ci /* 4x and 8x MSAA need to clear only sample 0 and 1 in a compute shader and leave other 460bf215546Sopenharmony_ci * samples untouched. (only the first 2 samples are compressed) */ 461bf215546Sopenharmony_ci if (tex->buffer.b.b.nr_storage_samples >= 4) { 462bf215546Sopenharmony_ci si_init_buffer_clear(out, dcc_buffer, 0, 0, clear_value); 463bf215546Sopenharmony_ci out->is_dcc_msaa = true; 464bf215546Sopenharmony_ci return true; 465bf215546Sopenharmony_ci } 466bf215546Sopenharmony_ci 467bf215546Sopenharmony_ci clear_size = tex->surface.meta_size; 468bf215546Sopenharmony_ci } else { 469bf215546Sopenharmony_ci unsigned num_layers = util_num_layers(&tex->buffer.b.b, level); 470bf215546Sopenharmony_ci 471bf215546Sopenharmony_ci /* If this is 0, fast clear isn't possible. (can occur with MSAA) */ 472bf215546Sopenharmony_ci if (!tex->surface.u.legacy.color.dcc_level[level].dcc_fast_clear_size) 473bf215546Sopenharmony_ci return false; 474bf215546Sopenharmony_ci 475bf215546Sopenharmony_ci /* Layered 4x and 8x MSAA DCC fast clears need to clear 476bf215546Sopenharmony_ci * dcc_fast_clear_size bytes for each layer. A compute shader 477bf215546Sopenharmony_ci * would be more efficient than separate per-layer clear operations. 478bf215546Sopenharmony_ci */ 479bf215546Sopenharmony_ci if (tex->buffer.b.b.nr_storage_samples >= 4 && num_layers > 1) 480bf215546Sopenharmony_ci return false; 481bf215546Sopenharmony_ci 482bf215546Sopenharmony_ci dcc_offset += tex->surface.u.legacy.color.dcc_level[level].dcc_offset; 483bf215546Sopenharmony_ci clear_size = tex->surface.u.legacy.color.dcc_level[level].dcc_fast_clear_size; 484bf215546Sopenharmony_ci } 485bf215546Sopenharmony_ci 486bf215546Sopenharmony_ci si_init_buffer_clear(out, dcc_buffer, dcc_offset, clear_size, clear_value); 487bf215546Sopenharmony_ci return true; 488bf215546Sopenharmony_ci} 489bf215546Sopenharmony_ci 490bf215546Sopenharmony_ci/* Set the same micro tile mode as the destination of the last MSAA resolve. 491bf215546Sopenharmony_ci * This allows hitting the MSAA resolve fast path, which requires that both 492bf215546Sopenharmony_ci * src and dst micro tile modes match. 493bf215546Sopenharmony_ci */ 494bf215546Sopenharmony_cistatic void si_set_optimal_micro_tile_mode(struct si_screen *sscreen, struct si_texture *tex) 495bf215546Sopenharmony_ci{ 496bf215546Sopenharmony_ci if (sscreen->info.gfx_level >= GFX10 || tex->buffer.b.is_shared || 497bf215546Sopenharmony_ci tex->buffer.b.b.nr_samples <= 1 || 498bf215546Sopenharmony_ci tex->surface.micro_tile_mode == tex->last_msaa_resolve_target_micro_mode) 499bf215546Sopenharmony_ci return; 500bf215546Sopenharmony_ci 501bf215546Sopenharmony_ci assert(sscreen->info.gfx_level >= GFX9 || 502bf215546Sopenharmony_ci tex->surface.u.legacy.level[0].mode == RADEON_SURF_MODE_2D); 503bf215546Sopenharmony_ci assert(tex->buffer.b.b.last_level == 0); 504bf215546Sopenharmony_ci 505bf215546Sopenharmony_ci if (sscreen->info.gfx_level >= GFX9) { 506bf215546Sopenharmony_ci /* 4K or larger tiles only. 0 is linear. 1-3 are 256B tiles. */ 507bf215546Sopenharmony_ci assert(tex->surface.u.gfx9.swizzle_mode >= 4); 508bf215546Sopenharmony_ci 509bf215546Sopenharmony_ci /* If you do swizzle_mode % 4, you'll get: 510bf215546Sopenharmony_ci * 0 = Depth 511bf215546Sopenharmony_ci * 1 = Standard, 512bf215546Sopenharmony_ci * 2 = Displayable 513bf215546Sopenharmony_ci * 3 = Rotated 514bf215546Sopenharmony_ci * 515bf215546Sopenharmony_ci * Depth-sample order isn't allowed: 516bf215546Sopenharmony_ci */ 517bf215546Sopenharmony_ci assert(tex->surface.u.gfx9.swizzle_mode % 4 != 0); 518bf215546Sopenharmony_ci 519bf215546Sopenharmony_ci switch (tex->last_msaa_resolve_target_micro_mode) { 520bf215546Sopenharmony_ci case RADEON_MICRO_MODE_DISPLAY: 521bf215546Sopenharmony_ci tex->surface.u.gfx9.swizzle_mode &= ~0x3; 522bf215546Sopenharmony_ci tex->surface.u.gfx9.swizzle_mode += 2; /* D */ 523bf215546Sopenharmony_ci break; 524bf215546Sopenharmony_ci case RADEON_MICRO_MODE_STANDARD: 525bf215546Sopenharmony_ci tex->surface.u.gfx9.swizzle_mode &= ~0x3; 526bf215546Sopenharmony_ci tex->surface.u.gfx9.swizzle_mode += 1; /* S */ 527bf215546Sopenharmony_ci break; 528bf215546Sopenharmony_ci case RADEON_MICRO_MODE_RENDER: 529bf215546Sopenharmony_ci tex->surface.u.gfx9.swizzle_mode &= ~0x3; 530bf215546Sopenharmony_ci tex->surface.u.gfx9.swizzle_mode += 3; /* R */ 531bf215546Sopenharmony_ci break; 532bf215546Sopenharmony_ci default: /* depth */ 533bf215546Sopenharmony_ci assert(!"unexpected micro mode"); 534bf215546Sopenharmony_ci return; 535bf215546Sopenharmony_ci } 536bf215546Sopenharmony_ci } else if (sscreen->info.gfx_level >= GFX7) { 537bf215546Sopenharmony_ci /* These magic numbers were copied from addrlib. It doesn't use 538bf215546Sopenharmony_ci * any definitions for them either. They are all 2D_TILED_THIN1 539bf215546Sopenharmony_ci * modes with different bpp and micro tile mode. 540bf215546Sopenharmony_ci */ 541bf215546Sopenharmony_ci switch (tex->last_msaa_resolve_target_micro_mode) { 542bf215546Sopenharmony_ci case RADEON_MICRO_MODE_DISPLAY: 543bf215546Sopenharmony_ci tex->surface.u.legacy.tiling_index[0] = 10; 544bf215546Sopenharmony_ci break; 545bf215546Sopenharmony_ci case RADEON_MICRO_MODE_STANDARD: 546bf215546Sopenharmony_ci tex->surface.u.legacy.tiling_index[0] = 14; 547bf215546Sopenharmony_ci break; 548bf215546Sopenharmony_ci case RADEON_MICRO_MODE_RENDER: 549bf215546Sopenharmony_ci tex->surface.u.legacy.tiling_index[0] = 28; 550bf215546Sopenharmony_ci break; 551bf215546Sopenharmony_ci default: /* depth, thick */ 552bf215546Sopenharmony_ci assert(!"unexpected micro mode"); 553bf215546Sopenharmony_ci return; 554bf215546Sopenharmony_ci } 555bf215546Sopenharmony_ci } else { /* GFX6 */ 556bf215546Sopenharmony_ci switch (tex->last_msaa_resolve_target_micro_mode) { 557bf215546Sopenharmony_ci case RADEON_MICRO_MODE_DISPLAY: 558bf215546Sopenharmony_ci switch (tex->surface.bpe) { 559bf215546Sopenharmony_ci case 1: 560bf215546Sopenharmony_ci tex->surface.u.legacy.tiling_index[0] = 10; 561bf215546Sopenharmony_ci break; 562bf215546Sopenharmony_ci case 2: 563bf215546Sopenharmony_ci tex->surface.u.legacy.tiling_index[0] = 11; 564bf215546Sopenharmony_ci break; 565bf215546Sopenharmony_ci default: /* 4, 8 */ 566bf215546Sopenharmony_ci tex->surface.u.legacy.tiling_index[0] = 12; 567bf215546Sopenharmony_ci break; 568bf215546Sopenharmony_ci } 569bf215546Sopenharmony_ci break; 570bf215546Sopenharmony_ci case RADEON_MICRO_MODE_STANDARD: 571bf215546Sopenharmony_ci switch (tex->surface.bpe) { 572bf215546Sopenharmony_ci case 1: 573bf215546Sopenharmony_ci tex->surface.u.legacy.tiling_index[0] = 14; 574bf215546Sopenharmony_ci break; 575bf215546Sopenharmony_ci case 2: 576bf215546Sopenharmony_ci tex->surface.u.legacy.tiling_index[0] = 15; 577bf215546Sopenharmony_ci break; 578bf215546Sopenharmony_ci case 4: 579bf215546Sopenharmony_ci tex->surface.u.legacy.tiling_index[0] = 16; 580bf215546Sopenharmony_ci break; 581bf215546Sopenharmony_ci default: /* 8, 16 */ 582bf215546Sopenharmony_ci tex->surface.u.legacy.tiling_index[0] = 17; 583bf215546Sopenharmony_ci break; 584bf215546Sopenharmony_ci } 585bf215546Sopenharmony_ci break; 586bf215546Sopenharmony_ci default: /* depth, thick */ 587bf215546Sopenharmony_ci assert(!"unexpected micro mode"); 588bf215546Sopenharmony_ci return; 589bf215546Sopenharmony_ci } 590bf215546Sopenharmony_ci } 591bf215546Sopenharmony_ci 592bf215546Sopenharmony_ci tex->surface.micro_tile_mode = tex->last_msaa_resolve_target_micro_mode; 593bf215546Sopenharmony_ci 594bf215546Sopenharmony_ci p_atomic_inc(&sscreen->dirty_tex_counter); 595bf215546Sopenharmony_ci} 596bf215546Sopenharmony_ci 597bf215546Sopenharmony_cistatic uint32_t si_get_htile_clear_value(struct si_texture *tex, float depth) 598bf215546Sopenharmony_ci{ 599bf215546Sopenharmony_ci /* Maximum 14-bit UINT value. */ 600bf215546Sopenharmony_ci const uint32_t max_z_value = 0x3FFF; 601bf215546Sopenharmony_ci 602bf215546Sopenharmony_ci /* For clears, Zmask and Smem will always be set to zero. */ 603bf215546Sopenharmony_ci const uint32_t zmask = 0; 604bf215546Sopenharmony_ci const uint32_t smem = 0; 605bf215546Sopenharmony_ci 606bf215546Sopenharmony_ci /* Convert depthValue to 14-bit zmin/zmax uint values. */ 607bf215546Sopenharmony_ci const uint32_t zmin = lroundf(depth * max_z_value); 608bf215546Sopenharmony_ci const uint32_t zmax = zmin; 609bf215546Sopenharmony_ci 610bf215546Sopenharmony_ci if (tex->htile_stencil_disabled) { 611bf215546Sopenharmony_ci /* Z-only HTILE is laid out as follows: 612bf215546Sopenharmony_ci * |31 18|17 4|3 0| 613bf215546Sopenharmony_ci * +---------+---------+-------+ 614bf215546Sopenharmony_ci * | Max Z | Min Z | ZMask | 615bf215546Sopenharmony_ci */ 616bf215546Sopenharmony_ci return ((zmax & 0x3FFF) << 18) | 617bf215546Sopenharmony_ci ((zmin & 0x3FFF) << 4) | 618bf215546Sopenharmony_ci ((zmask & 0xF) << 0); 619bf215546Sopenharmony_ci } else { 620bf215546Sopenharmony_ci /* Z+S HTILE is laid out as-follows: 621bf215546Sopenharmony_ci * |31 12|11 10|9 8|7 6|5 4|3 0| 622bf215546Sopenharmony_ci * +-----------+-----+------+-----+-----+-------+ 623bf215546Sopenharmony_ci * | Z Range | | SMem | SR1 | SR0 | ZMask | 624bf215546Sopenharmony_ci * 625bf215546Sopenharmony_ci * The base value for zRange is either zMax or zMin, depending on ZRANGE_PRECISION. 626bf215546Sopenharmony_ci * For a fast clear, zMin == zMax == clearValue. This means that the base will 627bf215546Sopenharmony_ci * always be the clear value (converted to 14-bit UINT). 628bf215546Sopenharmony_ci * 629bf215546Sopenharmony_ci * When abs(zMax-zMin) < 16, the delta is equal to the difference. In the case of 630bf215546Sopenharmony_ci * fast clears, where zMax == zMin, the delta is always zero. 631bf215546Sopenharmony_ci */ 632bf215546Sopenharmony_ci const uint32_t delta = 0; 633bf215546Sopenharmony_ci const uint32_t zrange = (zmax << 6) | delta; 634bf215546Sopenharmony_ci 635bf215546Sopenharmony_ci /* SResults 0 & 1 are set based on the stencil compare state. 636bf215546Sopenharmony_ci * For fast-clear, the default value of sr0 and sr1 are both 0x3. 637bf215546Sopenharmony_ci */ 638bf215546Sopenharmony_ci const uint32_t sresults = 0xf; 639bf215546Sopenharmony_ci 640bf215546Sopenharmony_ci return ((zrange & 0xFFFFF) << 12) | 641bf215546Sopenharmony_ci ((smem & 0x3) << 8) | 642bf215546Sopenharmony_ci ((sresults & 0xF) << 4) | 643bf215546Sopenharmony_ci ((zmask & 0xF) << 0); 644bf215546Sopenharmony_ci } 645bf215546Sopenharmony_ci} 646bf215546Sopenharmony_ci 647bf215546Sopenharmony_cistatic bool si_can_fast_clear_depth(struct si_texture *zstex, unsigned level, float depth, 648bf215546Sopenharmony_ci unsigned buffers) 649bf215546Sopenharmony_ci{ 650bf215546Sopenharmony_ci /* TC-compatible HTILE only supports depth clears to 0 or 1. */ 651bf215546Sopenharmony_ci return buffers & PIPE_CLEAR_DEPTH && 652bf215546Sopenharmony_ci si_htile_enabled(zstex, level, PIPE_MASK_Z) && 653bf215546Sopenharmony_ci (!zstex->tc_compatible_htile || depth == 0 || depth == 1); 654bf215546Sopenharmony_ci} 655bf215546Sopenharmony_ci 656bf215546Sopenharmony_cistatic bool si_can_fast_clear_stencil(struct si_texture *zstex, unsigned level, uint8_t stencil, 657bf215546Sopenharmony_ci unsigned buffers) 658bf215546Sopenharmony_ci{ 659bf215546Sopenharmony_ci /* TC-compatible HTILE only supports stencil clears to 0. */ 660bf215546Sopenharmony_ci return buffers & PIPE_CLEAR_STENCIL && 661bf215546Sopenharmony_ci si_htile_enabled(zstex, level, PIPE_MASK_S) && 662bf215546Sopenharmony_ci (!zstex->tc_compatible_htile || stencil == 0); 663bf215546Sopenharmony_ci} 664bf215546Sopenharmony_ci 665bf215546Sopenharmony_cistatic void si_fast_clear(struct si_context *sctx, unsigned *buffers, 666bf215546Sopenharmony_ci const union pipe_color_union *color, float depth, uint8_t stencil) 667bf215546Sopenharmony_ci{ 668bf215546Sopenharmony_ci struct pipe_framebuffer_state *fb = &sctx->framebuffer.state; 669bf215546Sopenharmony_ci struct si_clear_info info[8 * 2 + 1]; /* MRTs * (CMASK + DCC) + ZS */ 670bf215546Sopenharmony_ci unsigned num_clears = 0; 671bf215546Sopenharmony_ci unsigned clear_types = 0; 672bf215546Sopenharmony_ci unsigned num_pixels = fb->width * fb->height; 673bf215546Sopenharmony_ci 674bf215546Sopenharmony_ci /* This function is broken in BE, so just disable this path for now */ 675bf215546Sopenharmony_ci#if UTIL_ARCH_BIG_ENDIAN 676bf215546Sopenharmony_ci return; 677bf215546Sopenharmony_ci#endif 678bf215546Sopenharmony_ci 679bf215546Sopenharmony_ci if (sctx->render_cond) 680bf215546Sopenharmony_ci return; 681bf215546Sopenharmony_ci 682bf215546Sopenharmony_ci /* Gather information about what to clear. */ 683bf215546Sopenharmony_ci unsigned color_buffer_mask = (*buffers & PIPE_CLEAR_COLOR) >> util_logbase2(PIPE_CLEAR_COLOR0); 684bf215546Sopenharmony_ci while (color_buffer_mask) { 685bf215546Sopenharmony_ci unsigned i = u_bit_scan(&color_buffer_mask); 686bf215546Sopenharmony_ci 687bf215546Sopenharmony_ci struct si_texture *tex = (struct si_texture *)fb->cbufs[i]->texture; 688bf215546Sopenharmony_ci unsigned level = fb->cbufs[i]->u.tex.level; 689bf215546Sopenharmony_ci unsigned num_layers = util_num_layers(&tex->buffer.b.b, level); 690bf215546Sopenharmony_ci 691bf215546Sopenharmony_ci /* the clear is allowed if all layers are bound */ 692bf215546Sopenharmony_ci if (fb->cbufs[i]->u.tex.first_layer != 0 || 693bf215546Sopenharmony_ci fb->cbufs[i]->u.tex.last_layer != num_layers - 1) { 694bf215546Sopenharmony_ci continue; 695bf215546Sopenharmony_ci } 696bf215546Sopenharmony_ci 697bf215546Sopenharmony_ci /* We can change the micro tile mode before a full clear. */ 698bf215546Sopenharmony_ci /* This is only used for MSAA textures when clearing all layers. */ 699bf215546Sopenharmony_ci si_set_optimal_micro_tile_mode(sctx->screen, tex); 700bf215546Sopenharmony_ci 701bf215546Sopenharmony_ci if (tex->swap_rgb_to_bgr_on_next_clear) { 702bf215546Sopenharmony_ci assert(!tex->swap_rgb_to_bgr); 703bf215546Sopenharmony_ci assert(tex->buffer.b.b.nr_samples >= 2); 704bf215546Sopenharmony_ci tex->swap_rgb_to_bgr = true; 705bf215546Sopenharmony_ci tex->swap_rgb_to_bgr_on_next_clear = false; 706bf215546Sopenharmony_ci 707bf215546Sopenharmony_ci /* Update all sampler views and images. */ 708bf215546Sopenharmony_ci p_atomic_inc(&sctx->screen->dirty_tex_counter); 709bf215546Sopenharmony_ci } 710bf215546Sopenharmony_ci 711bf215546Sopenharmony_ci /* only supported on tiled surfaces */ 712bf215546Sopenharmony_ci if (tex->surface.is_linear) { 713bf215546Sopenharmony_ci continue; 714bf215546Sopenharmony_ci } 715bf215546Sopenharmony_ci 716bf215546Sopenharmony_ci /* Use a slow clear for small surfaces where the cost of 717bf215546Sopenharmony_ci * the eliminate pass can be higher than the benefit of fast 718bf215546Sopenharmony_ci * clear. The closed driver does this, but the numbers may differ. 719bf215546Sopenharmony_ci * 720bf215546Sopenharmony_ci * This helps on both dGPUs and APUs, even small APUs like Mullins. 721bf215546Sopenharmony_ci */ 722bf215546Sopenharmony_ci bool fb_too_small = num_pixels * num_layers <= 512 * 512; 723bf215546Sopenharmony_ci bool too_small = tex->buffer.b.b.nr_samples <= 1 && fb_too_small; 724bf215546Sopenharmony_ci bool eliminate_needed = false; 725bf215546Sopenharmony_ci bool fmask_decompress_needed = false; 726bf215546Sopenharmony_ci 727bf215546Sopenharmony_ci /* Try to clear DCC first, otherwise try CMASK. */ 728bf215546Sopenharmony_ci if (vi_dcc_enabled(tex, level)) { 729bf215546Sopenharmony_ci uint32_t reset_value; 730bf215546Sopenharmony_ci 731bf215546Sopenharmony_ci if (sctx->screen->debug_flags & DBG(NO_DCC_CLEAR)) 732bf215546Sopenharmony_ci continue; 733bf215546Sopenharmony_ci 734bf215546Sopenharmony_ci if (sctx->gfx_level >= GFX11) { 735bf215546Sopenharmony_ci if (!gfx11_get_dcc_clear_parameters(sctx->screen, fb->cbufs[i]->format, color, 736bf215546Sopenharmony_ci &reset_value)) 737bf215546Sopenharmony_ci continue; 738bf215546Sopenharmony_ci } else { 739bf215546Sopenharmony_ci if (!gfx8_get_dcc_clear_parameters(sctx->screen, tex->buffer.b.b.format, 740bf215546Sopenharmony_ci fb->cbufs[i]->format, color, &reset_value, 741bf215546Sopenharmony_ci &eliminate_needed)) 742bf215546Sopenharmony_ci continue; 743bf215546Sopenharmony_ci } 744bf215546Sopenharmony_ci 745bf215546Sopenharmony_ci /* Shared textures can't use fast clear without an explicit flush 746bf215546Sopenharmony_ci * because the clear color is not exported. 747bf215546Sopenharmony_ci * 748bf215546Sopenharmony_ci * Chips without DCC constant encoding must set the clear color registers 749bf215546Sopenharmony_ci * correctly even if the fast clear eliminate pass is not needed. 750bf215546Sopenharmony_ci */ 751bf215546Sopenharmony_ci if ((eliminate_needed || !sctx->screen->info.has_dcc_constant_encode) && 752bf215546Sopenharmony_ci tex->buffer.b.is_shared && 753bf215546Sopenharmony_ci !(tex->buffer.external_usage & PIPE_HANDLE_USAGE_EXPLICIT_FLUSH)) 754bf215546Sopenharmony_ci continue; 755bf215546Sopenharmony_ci 756bf215546Sopenharmony_ci if (eliminate_needed && too_small) 757bf215546Sopenharmony_ci continue; 758bf215546Sopenharmony_ci 759bf215546Sopenharmony_ci /* We can clear any level, but we only set up the clear value registers for the first 760bf215546Sopenharmony_ci * level. Therefore, all other levels can be cleared only if the clear value registers 761bf215546Sopenharmony_ci * are not used, which is only the case with DCC constant encoding and 0/1 clear values. 762bf215546Sopenharmony_ci */ 763bf215546Sopenharmony_ci if (level > 0 && (eliminate_needed || !sctx->screen->info.has_dcc_constant_encode)) 764bf215546Sopenharmony_ci continue; 765bf215546Sopenharmony_ci 766bf215546Sopenharmony_ci if (tex->buffer.b.b.nr_samples >= 2 && eliminate_needed && 767bf215546Sopenharmony_ci !sctx->screen->allow_dcc_msaa_clear_to_reg_for_bpp[util_logbase2(tex->surface.bpe)]) 768bf215546Sopenharmony_ci continue; 769bf215546Sopenharmony_ci 770bf215546Sopenharmony_ci assert(num_clears < ARRAY_SIZE(info)); 771bf215546Sopenharmony_ci 772bf215546Sopenharmony_ci if (!vi_dcc_get_clear_info(sctx, tex, level, reset_value, &info[num_clears])) 773bf215546Sopenharmony_ci continue; 774bf215546Sopenharmony_ci 775bf215546Sopenharmony_ci num_clears++; 776bf215546Sopenharmony_ci clear_types |= SI_CLEAR_TYPE_DCC; 777bf215546Sopenharmony_ci 778bf215546Sopenharmony_ci si_mark_display_dcc_dirty(sctx, tex); 779bf215546Sopenharmony_ci 780bf215546Sopenharmony_ci /* DCC fast clear with MSAA should clear CMASK to 0xC. */ 781bf215546Sopenharmony_ci if (tex->buffer.b.b.nr_samples >= 2 && tex->cmask_buffer) { 782bf215546Sopenharmony_ci assert(sctx->gfx_level < GFX11); /* no FMASK/CMASK on GFX11 */ 783bf215546Sopenharmony_ci assert(num_clears < ARRAY_SIZE(info)); 784bf215546Sopenharmony_ci si_init_buffer_clear(&info[num_clears++], &tex->cmask_buffer->b.b, 785bf215546Sopenharmony_ci tex->surface.cmask_offset, tex->surface.cmask_size, 0xCCCCCCCC); 786bf215546Sopenharmony_ci clear_types |= SI_CLEAR_TYPE_CMASK; 787bf215546Sopenharmony_ci fmask_decompress_needed = true; 788bf215546Sopenharmony_ci } 789bf215546Sopenharmony_ci } else { 790bf215546Sopenharmony_ci /* No CMASK on GFX11. */ 791bf215546Sopenharmony_ci if (sctx->gfx_level >= GFX11) 792bf215546Sopenharmony_ci continue; 793bf215546Sopenharmony_ci 794bf215546Sopenharmony_ci if (level > 0) 795bf215546Sopenharmony_ci continue; 796bf215546Sopenharmony_ci 797bf215546Sopenharmony_ci /* Shared textures can't use fast clear without an explicit flush 798bf215546Sopenharmony_ci * because the clear color is not exported. 799bf215546Sopenharmony_ci */ 800bf215546Sopenharmony_ci if (tex->buffer.b.is_shared && 801bf215546Sopenharmony_ci !(tex->buffer.external_usage & PIPE_HANDLE_USAGE_EXPLICIT_FLUSH)) 802bf215546Sopenharmony_ci continue; 803bf215546Sopenharmony_ci 804bf215546Sopenharmony_ci if (too_small) 805bf215546Sopenharmony_ci continue; 806bf215546Sopenharmony_ci 807bf215546Sopenharmony_ci /* 128-bit formats are unsupported */ 808bf215546Sopenharmony_ci if (tex->surface.bpe > 8) { 809bf215546Sopenharmony_ci continue; 810bf215546Sopenharmony_ci } 811bf215546Sopenharmony_ci 812bf215546Sopenharmony_ci /* RB+ doesn't work with CMASK fast clear on Stoney. */ 813bf215546Sopenharmony_ci if (sctx->family == CHIP_STONEY) 814bf215546Sopenharmony_ci continue; 815bf215546Sopenharmony_ci 816bf215546Sopenharmony_ci /* Disable fast clear if tex is encrypted */ 817bf215546Sopenharmony_ci if (tex->buffer.flags & RADEON_FLAG_ENCRYPTED) 818bf215546Sopenharmony_ci continue; 819bf215546Sopenharmony_ci 820bf215546Sopenharmony_ci uint64_t cmask_offset = 0; 821bf215546Sopenharmony_ci unsigned clear_size = 0; 822bf215546Sopenharmony_ci 823bf215546Sopenharmony_ci if (sctx->gfx_level >= GFX10) { 824bf215546Sopenharmony_ci assert(level == 0); 825bf215546Sopenharmony_ci 826bf215546Sopenharmony_ci /* Clearing CMASK with both multiple levels and multiple layers is not 827bf215546Sopenharmony_ci * implemented. 828bf215546Sopenharmony_ci */ 829bf215546Sopenharmony_ci if (num_layers > 1 && tex->buffer.b.b.last_level > 0) 830bf215546Sopenharmony_ci continue; 831bf215546Sopenharmony_ci 832bf215546Sopenharmony_ci if (!si_alloc_separate_cmask(sctx->screen, tex)) 833bf215546Sopenharmony_ci continue; 834bf215546Sopenharmony_ci 835bf215546Sopenharmony_ci if (num_layers == 1) { 836bf215546Sopenharmony_ci /* Clear level 0. */ 837bf215546Sopenharmony_ci cmask_offset = tex->surface.cmask_offset + tex->surface.u.gfx9.color.cmask_level0.offset; 838bf215546Sopenharmony_ci clear_size = tex->surface.u.gfx9.color.cmask_level0.size; 839bf215546Sopenharmony_ci } else if (tex->buffer.b.b.last_level == 0) { 840bf215546Sopenharmony_ci /* Clear all layers having only 1 level. */ 841bf215546Sopenharmony_ci cmask_offset = tex->surface.cmask_offset; 842bf215546Sopenharmony_ci clear_size = tex->surface.cmask_size; 843bf215546Sopenharmony_ci } else { 844bf215546Sopenharmony_ci assert(0); /* this is prevented above */ 845bf215546Sopenharmony_ci } 846bf215546Sopenharmony_ci } else if (sctx->gfx_level == GFX9) { 847bf215546Sopenharmony_ci /* TODO: Implement CMASK fast clear for level 0 of mipmapped textures. Mipmapped 848bf215546Sopenharmony_ci * CMASK has to clear a rectangular area of CMASK for level 0 (because the whole 849bf215546Sopenharmony_ci * miptree is organized in a 2D plane). 850bf215546Sopenharmony_ci */ 851bf215546Sopenharmony_ci if (tex->buffer.b.b.last_level > 0) 852bf215546Sopenharmony_ci continue; 853bf215546Sopenharmony_ci 854bf215546Sopenharmony_ci if (!si_alloc_separate_cmask(sctx->screen, tex)) 855bf215546Sopenharmony_ci continue; 856bf215546Sopenharmony_ci 857bf215546Sopenharmony_ci cmask_offset = tex->surface.cmask_offset; 858bf215546Sopenharmony_ci clear_size = tex->surface.cmask_size; 859bf215546Sopenharmony_ci } else { 860bf215546Sopenharmony_ci if (!si_alloc_separate_cmask(sctx->screen, tex)) 861bf215546Sopenharmony_ci continue; 862bf215546Sopenharmony_ci 863bf215546Sopenharmony_ci /* GFX6-8: This only covers mipmap level 0. */ 864bf215546Sopenharmony_ci cmask_offset = tex->surface.cmask_offset; 865bf215546Sopenharmony_ci clear_size = tex->surface.cmask_size; 866bf215546Sopenharmony_ci } 867bf215546Sopenharmony_ci 868bf215546Sopenharmony_ci /* Do the fast clear. */ 869bf215546Sopenharmony_ci assert(num_clears < ARRAY_SIZE(info)); 870bf215546Sopenharmony_ci si_init_buffer_clear(&info[num_clears++], &tex->cmask_buffer->b.b, 871bf215546Sopenharmony_ci cmask_offset, clear_size, 0); 872bf215546Sopenharmony_ci clear_types |= SI_CLEAR_TYPE_CMASK; 873bf215546Sopenharmony_ci eliminate_needed = true; 874bf215546Sopenharmony_ci } 875bf215546Sopenharmony_ci 876bf215546Sopenharmony_ci if ((eliminate_needed || fmask_decompress_needed) && 877bf215546Sopenharmony_ci !(tex->dirty_level_mask & (1 << level))) { 878bf215546Sopenharmony_ci assert(sctx->gfx_level < GFX11); /* no decompression needed on GFX11 */ 879bf215546Sopenharmony_ci tex->dirty_level_mask |= 1 << level; 880bf215546Sopenharmony_ci si_set_sampler_depth_decompress_mask(sctx, tex); 881bf215546Sopenharmony_ci p_atomic_inc(&sctx->screen->compressed_colortex_counter); 882bf215546Sopenharmony_ci } 883bf215546Sopenharmony_ci 884bf215546Sopenharmony_ci *buffers &= ~(PIPE_CLEAR_COLOR0 << i); 885bf215546Sopenharmony_ci 886bf215546Sopenharmony_ci /* Chips with DCC constant encoding don't need to set the clear 887bf215546Sopenharmony_ci * color registers for DCC clear values 0 and 1. 888bf215546Sopenharmony_ci */ 889bf215546Sopenharmony_ci if (sctx->screen->info.has_dcc_constant_encode && !eliminate_needed) 890bf215546Sopenharmony_ci continue; 891bf215546Sopenharmony_ci 892bf215546Sopenharmony_ci /* There are no clear color registers on GFX11. */ 893bf215546Sopenharmony_ci assert(sctx->gfx_level < GFX11); 894bf215546Sopenharmony_ci 895bf215546Sopenharmony_ci if (si_set_clear_color(tex, fb->cbufs[i]->format, color)) { 896bf215546Sopenharmony_ci sctx->framebuffer.dirty_cbufs |= 1 << i; 897bf215546Sopenharmony_ci si_mark_atom_dirty(sctx, &sctx->atoms.s.framebuffer); 898bf215546Sopenharmony_ci } 899bf215546Sopenharmony_ci } 900bf215546Sopenharmony_ci 901bf215546Sopenharmony_ci /* Depth/stencil clears. */ 902bf215546Sopenharmony_ci struct pipe_surface *zsbuf = fb->zsbuf; 903bf215546Sopenharmony_ci struct si_texture *zstex = zsbuf ? (struct si_texture *)zsbuf->texture : NULL; 904bf215546Sopenharmony_ci unsigned zs_num_layers = zstex ? util_num_layers(&zstex->buffer.b.b, zsbuf->u.tex.level) : 0; 905bf215546Sopenharmony_ci 906bf215546Sopenharmony_ci if (zstex && zsbuf->u.tex.first_layer == 0 && 907bf215546Sopenharmony_ci zsbuf->u.tex.last_layer == zs_num_layers - 1 && 908bf215546Sopenharmony_ci si_htile_enabled(zstex, zsbuf->u.tex.level, PIPE_MASK_ZS)) { 909bf215546Sopenharmony_ci unsigned level = zsbuf->u.tex.level; 910bf215546Sopenharmony_ci bool update_db_depth_clear = false; 911bf215546Sopenharmony_ci bool update_db_stencil_clear = false; 912bf215546Sopenharmony_ci bool fb_too_small = num_pixels * zs_num_layers <= 512 * 512; 913bf215546Sopenharmony_ci 914bf215546Sopenharmony_ci /* Transition from TC-incompatible to TC-compatible HTILE if requested. */ 915bf215546Sopenharmony_ci if (zstex->enable_tc_compatible_htile_next_clear) { 916bf215546Sopenharmony_ci /* If both depth and stencil are present, they must be cleared together. */ 917bf215546Sopenharmony_ci if ((*buffers & PIPE_CLEAR_DEPTHSTENCIL) == PIPE_CLEAR_DEPTHSTENCIL || 918bf215546Sopenharmony_ci (*buffers & PIPE_CLEAR_DEPTH && (!zstex->surface.has_stencil || 919bf215546Sopenharmony_ci zstex->htile_stencil_disabled))) { 920bf215546Sopenharmony_ci /* The conversion from TC-incompatible to TC-compatible can only be done in one clear. */ 921bf215546Sopenharmony_ci assert(zstex->buffer.b.b.last_level == 0); 922bf215546Sopenharmony_ci assert(!zstex->tc_compatible_htile); 923bf215546Sopenharmony_ci 924bf215546Sopenharmony_ci /* Enable TC-compatible HTILE. */ 925bf215546Sopenharmony_ci zstex->enable_tc_compatible_htile_next_clear = false; 926bf215546Sopenharmony_ci zstex->tc_compatible_htile = true; 927bf215546Sopenharmony_ci 928bf215546Sopenharmony_ci /* Update the framebuffer state to reflect the change. */ 929bf215546Sopenharmony_ci sctx->framebuffer.DB_has_shader_readable_metadata = true; 930bf215546Sopenharmony_ci sctx->framebuffer.dirty_zsbuf = true; 931bf215546Sopenharmony_ci si_mark_atom_dirty(sctx, &sctx->atoms.s.framebuffer); 932bf215546Sopenharmony_ci 933bf215546Sopenharmony_ci /* Update all sampler views and shader images in all contexts. */ 934bf215546Sopenharmony_ci p_atomic_inc(&sctx->screen->dirty_tex_counter); 935bf215546Sopenharmony_ci 936bf215546Sopenharmony_ci /* Perform the clear here if possible, else clear to uncompressed. */ 937bf215546Sopenharmony_ci uint32_t clear_value; 938bf215546Sopenharmony_ci 939bf215546Sopenharmony_ci if (zstex->htile_stencil_disabled || !zstex->surface.has_stencil) { 940bf215546Sopenharmony_ci if (si_can_fast_clear_depth(zstex, level, depth, *buffers)) { 941bf215546Sopenharmony_ci /* Z-only clear. */ 942bf215546Sopenharmony_ci clear_value = si_get_htile_clear_value(zstex, depth); 943bf215546Sopenharmony_ci *buffers &= ~PIPE_CLEAR_DEPTH; 944bf215546Sopenharmony_ci zstex->depth_cleared_level_mask_once |= BITFIELD_BIT(level); 945bf215546Sopenharmony_ci zstex->depth_cleared_level_mask |= BITFIELD_BIT(level); 946bf215546Sopenharmony_ci update_db_depth_clear = true; 947bf215546Sopenharmony_ci } 948bf215546Sopenharmony_ci } else if ((*buffers & PIPE_CLEAR_DEPTHSTENCIL) == PIPE_CLEAR_DEPTHSTENCIL) { 949bf215546Sopenharmony_ci if (si_can_fast_clear_depth(zstex, level, depth, *buffers) && 950bf215546Sopenharmony_ci si_can_fast_clear_stencil(zstex, level, stencil, *buffers)) { 951bf215546Sopenharmony_ci /* Combined Z+S clear. */ 952bf215546Sopenharmony_ci clear_value = si_get_htile_clear_value(zstex, depth); 953bf215546Sopenharmony_ci *buffers &= ~PIPE_CLEAR_DEPTHSTENCIL; 954bf215546Sopenharmony_ci zstex->depth_cleared_level_mask_once |= BITFIELD_BIT(level); 955bf215546Sopenharmony_ci zstex->depth_cleared_level_mask |= BITFIELD_BIT(level); 956bf215546Sopenharmony_ci zstex->stencil_cleared_level_mask_once |= BITFIELD_BIT(level); 957bf215546Sopenharmony_ci update_db_depth_clear = true; 958bf215546Sopenharmony_ci update_db_stencil_clear = true; 959bf215546Sopenharmony_ci } 960bf215546Sopenharmony_ci } 961bf215546Sopenharmony_ci 962bf215546Sopenharmony_ci if (!update_db_depth_clear) { 963bf215546Sopenharmony_ci /* Clear to uncompressed, so that it doesn't contain values incompatible 964bf215546Sopenharmony_ci * with the new TC-compatible HTILE setting. 965bf215546Sopenharmony_ci * 966bf215546Sopenharmony_ci * 0xfffff30f = uncompressed Z + S 967bf215546Sopenharmony_ci * 0xfffc000f = uncompressed Z only 968bf215546Sopenharmony_ci */ 969bf215546Sopenharmony_ci clear_value = !zstex->htile_stencil_disabled ? 0xfffff30f : 0xfffc000f; 970bf215546Sopenharmony_ci } 971bf215546Sopenharmony_ci 972bf215546Sopenharmony_ci zstex->need_flush_after_depth_decompression = sctx->gfx_level == GFX10_3; 973bf215546Sopenharmony_ci 974bf215546Sopenharmony_ci assert(num_clears < ARRAY_SIZE(info)); 975bf215546Sopenharmony_ci si_init_buffer_clear(&info[num_clears++], &zstex->buffer.b.b, 976bf215546Sopenharmony_ci zstex->surface.meta_offset, zstex->surface.meta_size, clear_value); 977bf215546Sopenharmony_ci clear_types |= SI_CLEAR_TYPE_HTILE; 978bf215546Sopenharmony_ci } 979bf215546Sopenharmony_ci } else if (num_clears || !fb_too_small) { 980bf215546Sopenharmony_ci /* This is where the HTILE buffer clear is done. 981bf215546Sopenharmony_ci * 982bf215546Sopenharmony_ci * If there is no clear scheduled and the framebuffer size is too small, we should use 983bf215546Sopenharmony_ci * the draw-based clear that is without waits. If there is some other clear scheduled, 984bf215546Sopenharmony_ci * we will have to wait anyway, so add the HTILE buffer clear to the batch here. 985bf215546Sopenharmony_ci * If the framebuffer size is large enough, use this codepath too. 986bf215546Sopenharmony_ci */ 987bf215546Sopenharmony_ci uint64_t htile_offset = zstex->surface.meta_offset; 988bf215546Sopenharmony_ci unsigned htile_size = 0; 989bf215546Sopenharmony_ci 990bf215546Sopenharmony_ci /* Determine the HTILE subset to clear. */ 991bf215546Sopenharmony_ci if (sctx->gfx_level >= GFX10) { 992bf215546Sopenharmony_ci /* This can only clear a layered texture with 1 level or a mipmap texture 993bf215546Sopenharmony_ci * with 1 layer. Other cases are unimplemented. 994bf215546Sopenharmony_ci */ 995bf215546Sopenharmony_ci if (zs_num_layers == 1) { 996bf215546Sopenharmony_ci /* Clear a specific level. */ 997bf215546Sopenharmony_ci htile_offset += zstex->surface.u.gfx9.meta_levels[level].offset; 998bf215546Sopenharmony_ci htile_size = zstex->surface.u.gfx9.meta_levels[level].size; 999bf215546Sopenharmony_ci } else if (zstex->buffer.b.b.last_level == 0) { 1000bf215546Sopenharmony_ci /* Clear all layers having only 1 level. */ 1001bf215546Sopenharmony_ci htile_size = zstex->surface.meta_size; 1002bf215546Sopenharmony_ci } 1003bf215546Sopenharmony_ci } else { 1004bf215546Sopenharmony_ci /* This can only clear a layered texture with 1 level. Other cases are 1005bf215546Sopenharmony_ci * unimplemented. 1006bf215546Sopenharmony_ci */ 1007bf215546Sopenharmony_ci if (zstex->buffer.b.b.last_level == 0) 1008bf215546Sopenharmony_ci htile_size = zstex->surface.meta_size; 1009bf215546Sopenharmony_ci } 1010bf215546Sopenharmony_ci 1011bf215546Sopenharmony_ci /* Perform the clear if it's possible. */ 1012bf215546Sopenharmony_ci if (zstex->htile_stencil_disabled || !zstex->surface.has_stencil) { 1013bf215546Sopenharmony_ci if (htile_size && 1014bf215546Sopenharmony_ci si_can_fast_clear_depth(zstex, level, depth, *buffers)) { 1015bf215546Sopenharmony_ci /* Z-only clear. */ 1016bf215546Sopenharmony_ci assert(num_clears < ARRAY_SIZE(info)); 1017bf215546Sopenharmony_ci si_init_buffer_clear(&info[num_clears++], &zstex->buffer.b.b, htile_offset, 1018bf215546Sopenharmony_ci htile_size, si_get_htile_clear_value(zstex, depth)); 1019bf215546Sopenharmony_ci clear_types |= SI_CLEAR_TYPE_HTILE; 1020bf215546Sopenharmony_ci *buffers &= ~PIPE_CLEAR_DEPTH; 1021bf215546Sopenharmony_ci zstex->depth_cleared_level_mask_once |= BITFIELD_BIT(level); 1022bf215546Sopenharmony_ci zstex->depth_cleared_level_mask |= BITFIELD_BIT(level); 1023bf215546Sopenharmony_ci update_db_depth_clear = true; 1024bf215546Sopenharmony_ci } 1025bf215546Sopenharmony_ci } else if ((*buffers & PIPE_CLEAR_DEPTHSTENCIL) == PIPE_CLEAR_DEPTHSTENCIL) { 1026bf215546Sopenharmony_ci if (htile_size && 1027bf215546Sopenharmony_ci si_can_fast_clear_depth(zstex, level, depth, *buffers) && 1028bf215546Sopenharmony_ci si_can_fast_clear_stencil(zstex, level, stencil, *buffers)) { 1029bf215546Sopenharmony_ci /* Combined Z+S clear. */ 1030bf215546Sopenharmony_ci assert(num_clears < ARRAY_SIZE(info)); 1031bf215546Sopenharmony_ci si_init_buffer_clear(&info[num_clears++], &zstex->buffer.b.b, htile_offset, 1032bf215546Sopenharmony_ci htile_size, si_get_htile_clear_value(zstex, depth)); 1033bf215546Sopenharmony_ci clear_types |= SI_CLEAR_TYPE_HTILE; 1034bf215546Sopenharmony_ci *buffers &= ~PIPE_CLEAR_DEPTHSTENCIL; 1035bf215546Sopenharmony_ci zstex->depth_cleared_level_mask_once |= BITFIELD_BIT(level); 1036bf215546Sopenharmony_ci zstex->depth_cleared_level_mask |= BITFIELD_BIT(level); 1037bf215546Sopenharmony_ci zstex->stencil_cleared_level_mask_once |= BITFIELD_BIT(level); 1038bf215546Sopenharmony_ci update_db_depth_clear = true; 1039bf215546Sopenharmony_ci update_db_stencil_clear = true; 1040bf215546Sopenharmony_ci } 1041bf215546Sopenharmony_ci } else { 1042bf215546Sopenharmony_ci /* Z-only or S-only clear when both Z/S are present using a read-modify-write 1043bf215546Sopenharmony_ci * compute shader. 1044bf215546Sopenharmony_ci * 1045bf215546Sopenharmony_ci * If we get both clears but only one of them can be fast-cleared, we use 1046bf215546Sopenharmony_ci * the draw-based fast clear to do both at the same time. 1047bf215546Sopenharmony_ci */ 1048bf215546Sopenharmony_ci const uint32_t htile_depth_writemask = 0xfffffc0f; 1049bf215546Sopenharmony_ci const uint32_t htile_stencil_writemask = 0x000003f0; 1050bf215546Sopenharmony_ci 1051bf215546Sopenharmony_ci if (htile_size && 1052bf215546Sopenharmony_ci !(*buffers & PIPE_CLEAR_STENCIL) && 1053bf215546Sopenharmony_ci si_can_fast_clear_depth(zstex, level, depth, *buffers)) { 1054bf215546Sopenharmony_ci /* Z-only clear with stencil left intact. */ 1055bf215546Sopenharmony_ci assert(num_clears < ARRAY_SIZE(info)); 1056bf215546Sopenharmony_ci si_init_buffer_clear_rmw(&info[num_clears++], &zstex->buffer.b.b, htile_offset, 1057bf215546Sopenharmony_ci htile_size, si_get_htile_clear_value(zstex, depth), 1058bf215546Sopenharmony_ci htile_depth_writemask); 1059bf215546Sopenharmony_ci clear_types |= SI_CLEAR_TYPE_HTILE; 1060bf215546Sopenharmony_ci *buffers &= ~PIPE_CLEAR_DEPTH; 1061bf215546Sopenharmony_ci zstex->depth_cleared_level_mask_once |= BITFIELD_BIT(level); 1062bf215546Sopenharmony_ci zstex->depth_cleared_level_mask |= BITFIELD_BIT(level); 1063bf215546Sopenharmony_ci update_db_depth_clear = true; 1064bf215546Sopenharmony_ci } else if (htile_size && 1065bf215546Sopenharmony_ci !(*buffers & PIPE_CLEAR_DEPTH) && 1066bf215546Sopenharmony_ci si_can_fast_clear_stencil(zstex, level, stencil, *buffers)) { 1067bf215546Sopenharmony_ci /* Stencil-only clear with depth left intact. */ 1068bf215546Sopenharmony_ci assert(num_clears < ARRAY_SIZE(info)); 1069bf215546Sopenharmony_ci si_init_buffer_clear_rmw(&info[num_clears++], &zstex->buffer.b.b, htile_offset, 1070bf215546Sopenharmony_ci htile_size, si_get_htile_clear_value(zstex, depth), 1071bf215546Sopenharmony_ci htile_stencil_writemask); 1072bf215546Sopenharmony_ci clear_types |= SI_CLEAR_TYPE_HTILE; 1073bf215546Sopenharmony_ci *buffers &= ~PIPE_CLEAR_STENCIL; 1074bf215546Sopenharmony_ci zstex->stencil_cleared_level_mask_once |= BITFIELD_BIT(level); 1075bf215546Sopenharmony_ci update_db_stencil_clear = true; 1076bf215546Sopenharmony_ci } 1077bf215546Sopenharmony_ci } 1078bf215546Sopenharmony_ci 1079bf215546Sopenharmony_ci zstex->need_flush_after_depth_decompression = update_db_depth_clear && sctx->gfx_level == GFX10_3; 1080bf215546Sopenharmony_ci 1081bf215546Sopenharmony_ci /* Update DB_DEPTH_CLEAR. */ 1082bf215546Sopenharmony_ci if (update_db_depth_clear && 1083bf215546Sopenharmony_ci zstex->depth_clear_value[level] != (float)depth) { 1084bf215546Sopenharmony_ci zstex->depth_clear_value[level] = depth; 1085bf215546Sopenharmony_ci sctx->framebuffer.dirty_zsbuf = true; 1086bf215546Sopenharmony_ci si_mark_atom_dirty(sctx, &sctx->atoms.s.framebuffer); 1087bf215546Sopenharmony_ci } 1088bf215546Sopenharmony_ci 1089bf215546Sopenharmony_ci /* Update DB_STENCIL_CLEAR. */ 1090bf215546Sopenharmony_ci if (update_db_stencil_clear && 1091bf215546Sopenharmony_ci zstex->stencil_clear_value[level] != stencil) { 1092bf215546Sopenharmony_ci zstex->stencil_clear_value[level] = stencil; 1093bf215546Sopenharmony_ci sctx->framebuffer.dirty_zsbuf = true; 1094bf215546Sopenharmony_ci si_mark_atom_dirty(sctx, &sctx->atoms.s.framebuffer); 1095bf215546Sopenharmony_ci } 1096bf215546Sopenharmony_ci } 1097bf215546Sopenharmony_ci } 1098bf215546Sopenharmony_ci 1099bf215546Sopenharmony_ci si_execute_clears(sctx, info, num_clears, clear_types); 1100bf215546Sopenharmony_ci} 1101bf215546Sopenharmony_ci 1102bf215546Sopenharmony_cistatic void si_clear(struct pipe_context *ctx, unsigned buffers, 1103bf215546Sopenharmony_ci const struct pipe_scissor_state *scissor_state, 1104bf215546Sopenharmony_ci const union pipe_color_union *color, double depth, unsigned stencil) 1105bf215546Sopenharmony_ci{ 1106bf215546Sopenharmony_ci struct si_context *sctx = (struct si_context *)ctx; 1107bf215546Sopenharmony_ci struct pipe_framebuffer_state *fb = &sctx->framebuffer.state; 1108bf215546Sopenharmony_ci struct pipe_surface *zsbuf = fb->zsbuf; 1109bf215546Sopenharmony_ci struct si_texture *zstex = zsbuf ? (struct si_texture *)zsbuf->texture : NULL; 1110bf215546Sopenharmony_ci bool needs_db_flush = false; 1111bf215546Sopenharmony_ci 1112bf215546Sopenharmony_ci /* Unset clear flags for non-existent buffers. */ 1113bf215546Sopenharmony_ci for (unsigned i = 0; i < 8; i++) { 1114bf215546Sopenharmony_ci if (i >= fb->nr_cbufs || !fb->cbufs[i]) 1115bf215546Sopenharmony_ci buffers &= ~(PIPE_CLEAR_COLOR0 << i); 1116bf215546Sopenharmony_ci } 1117bf215546Sopenharmony_ci if (!zsbuf) 1118bf215546Sopenharmony_ci buffers &= ~PIPE_CLEAR_DEPTHSTENCIL; 1119bf215546Sopenharmony_ci else if (!util_format_has_stencil(util_format_description(zsbuf->format))) 1120bf215546Sopenharmony_ci buffers &= ~PIPE_CLEAR_STENCIL; 1121bf215546Sopenharmony_ci 1122bf215546Sopenharmony_ci si_fast_clear(sctx, &buffers, color, depth, stencil); 1123bf215546Sopenharmony_ci if (!buffers) 1124bf215546Sopenharmony_ci return; /* all buffers have been cleared */ 1125bf215546Sopenharmony_ci 1126bf215546Sopenharmony_ci if (buffers & PIPE_CLEAR_COLOR) { 1127bf215546Sopenharmony_ci /* These buffers cannot use fast clear, make sure to disable expansion. */ 1128bf215546Sopenharmony_ci unsigned color_buffer_mask = (buffers & PIPE_CLEAR_COLOR) >> util_logbase2(PIPE_CLEAR_COLOR0); 1129bf215546Sopenharmony_ci while (color_buffer_mask) { 1130bf215546Sopenharmony_ci unsigned i = u_bit_scan(&color_buffer_mask); 1131bf215546Sopenharmony_ci struct si_texture *tex = (struct si_texture *)fb->cbufs[i]->texture; 1132bf215546Sopenharmony_ci if (tex->surface.fmask_size == 0) 1133bf215546Sopenharmony_ci tex->dirty_level_mask &= ~(1 << fb->cbufs[i]->u.tex.level); 1134bf215546Sopenharmony_ci } 1135bf215546Sopenharmony_ci } 1136bf215546Sopenharmony_ci 1137bf215546Sopenharmony_ci if (zstex && zsbuf->u.tex.first_layer == 0 && 1138bf215546Sopenharmony_ci zsbuf->u.tex.last_layer == util_max_layer(&zstex->buffer.b.b, 0)) { 1139bf215546Sopenharmony_ci unsigned level = zsbuf->u.tex.level; 1140bf215546Sopenharmony_ci 1141bf215546Sopenharmony_ci if (si_can_fast_clear_depth(zstex, level, depth, buffers)) { 1142bf215546Sopenharmony_ci /* Need to disable EXPCLEAR temporarily if clearing 1143bf215546Sopenharmony_ci * to a new value. */ 1144bf215546Sopenharmony_ci if (!(zstex->depth_cleared_level_mask_once & BITFIELD_BIT(level)) || 1145bf215546Sopenharmony_ci zstex->depth_clear_value[level] != depth) { 1146bf215546Sopenharmony_ci sctx->db_depth_disable_expclear = true; 1147bf215546Sopenharmony_ci } 1148bf215546Sopenharmony_ci 1149bf215546Sopenharmony_ci if (zstex->depth_clear_value[level] != (float)depth) { 1150bf215546Sopenharmony_ci if ((zstex->depth_clear_value[level] != 0) != (depth != 0)) { 1151bf215546Sopenharmony_ci /* ZRANGE_PRECISION register of a bound surface will change so we 1152bf215546Sopenharmony_ci * must flush the DB caches. */ 1153bf215546Sopenharmony_ci needs_db_flush = true; 1154bf215546Sopenharmony_ci } 1155bf215546Sopenharmony_ci /* Update DB_DEPTH_CLEAR. */ 1156bf215546Sopenharmony_ci zstex->depth_clear_value[level] = depth; 1157bf215546Sopenharmony_ci sctx->framebuffer.dirty_zsbuf = true; 1158bf215546Sopenharmony_ci si_mark_atom_dirty(sctx, &sctx->atoms.s.framebuffer); 1159bf215546Sopenharmony_ci } 1160bf215546Sopenharmony_ci sctx->db_depth_clear = true; 1161bf215546Sopenharmony_ci si_mark_atom_dirty(sctx, &sctx->atoms.s.db_render_state); 1162bf215546Sopenharmony_ci } 1163bf215546Sopenharmony_ci 1164bf215546Sopenharmony_ci if (si_can_fast_clear_stencil(zstex, level, stencil, buffers)) { 1165bf215546Sopenharmony_ci stencil &= 0xff; 1166bf215546Sopenharmony_ci 1167bf215546Sopenharmony_ci /* Need to disable EXPCLEAR temporarily if clearing 1168bf215546Sopenharmony_ci * to a new value. */ 1169bf215546Sopenharmony_ci if (!(zstex->stencil_cleared_level_mask_once & BITFIELD_BIT(level)) || 1170bf215546Sopenharmony_ci zstex->stencil_clear_value[level] != stencil) { 1171bf215546Sopenharmony_ci sctx->db_stencil_disable_expclear = true; 1172bf215546Sopenharmony_ci } 1173bf215546Sopenharmony_ci 1174bf215546Sopenharmony_ci if (zstex->stencil_clear_value[level] != (uint8_t)stencil) { 1175bf215546Sopenharmony_ci /* Update DB_STENCIL_CLEAR. */ 1176bf215546Sopenharmony_ci zstex->stencil_clear_value[level] = stencil; 1177bf215546Sopenharmony_ci sctx->framebuffer.dirty_zsbuf = true; 1178bf215546Sopenharmony_ci si_mark_atom_dirty(sctx, &sctx->atoms.s.framebuffer); 1179bf215546Sopenharmony_ci } 1180bf215546Sopenharmony_ci sctx->db_stencil_clear = true; 1181bf215546Sopenharmony_ci si_mark_atom_dirty(sctx, &sctx->atoms.s.db_render_state); 1182bf215546Sopenharmony_ci } 1183bf215546Sopenharmony_ci 1184bf215546Sopenharmony_ci if (needs_db_flush) 1185bf215546Sopenharmony_ci sctx->flags |= SI_CONTEXT_FLUSH_AND_INV_DB; 1186bf215546Sopenharmony_ci } 1187bf215546Sopenharmony_ci 1188bf215546Sopenharmony_ci if (unlikely(sctx->thread_trace_enabled)) { 1189bf215546Sopenharmony_ci if (buffers & PIPE_CLEAR_COLOR) 1190bf215546Sopenharmony_ci sctx->sqtt_next_event = EventCmdClearColorImage; 1191bf215546Sopenharmony_ci else if (buffers & PIPE_CLEAR_DEPTHSTENCIL) 1192bf215546Sopenharmony_ci sctx->sqtt_next_event = EventCmdClearDepthStencilImage; 1193bf215546Sopenharmony_ci } 1194bf215546Sopenharmony_ci 1195bf215546Sopenharmony_ci si_blitter_begin(sctx, SI_CLEAR); 1196bf215546Sopenharmony_ci util_blitter_clear(sctx->blitter, fb->width, fb->height, util_framebuffer_get_num_layers(fb), 1197bf215546Sopenharmony_ci buffers, color, depth, stencil, sctx->framebuffer.nr_samples > 1); 1198bf215546Sopenharmony_ci si_blitter_end(sctx); 1199bf215546Sopenharmony_ci 1200bf215546Sopenharmony_ci if (sctx->db_depth_clear) { 1201bf215546Sopenharmony_ci sctx->db_depth_clear = false; 1202bf215546Sopenharmony_ci sctx->db_depth_disable_expclear = false; 1203bf215546Sopenharmony_ci zstex->depth_cleared_level_mask_once |= BITFIELD_BIT(zsbuf->u.tex.level); 1204bf215546Sopenharmony_ci zstex->depth_cleared_level_mask |= BITFIELD_BIT(zsbuf->u.tex.level); 1205bf215546Sopenharmony_ci si_mark_atom_dirty(sctx, &sctx->atoms.s.db_render_state); 1206bf215546Sopenharmony_ci } 1207bf215546Sopenharmony_ci 1208bf215546Sopenharmony_ci if (sctx->db_stencil_clear) { 1209bf215546Sopenharmony_ci sctx->db_stencil_clear = false; 1210bf215546Sopenharmony_ci sctx->db_stencil_disable_expclear = false; 1211bf215546Sopenharmony_ci zstex->stencil_cleared_level_mask_once |= BITFIELD_BIT(zsbuf->u.tex.level); 1212bf215546Sopenharmony_ci si_mark_atom_dirty(sctx, &sctx->atoms.s.db_render_state); 1213bf215546Sopenharmony_ci } 1214bf215546Sopenharmony_ci} 1215bf215546Sopenharmony_ci 1216bf215546Sopenharmony_cistatic bool si_try_normal_clear(struct si_context *sctx, struct pipe_surface *dst, 1217bf215546Sopenharmony_ci unsigned dstx, unsigned dsty, unsigned width, unsigned height, 1218bf215546Sopenharmony_ci bool render_condition_enabled, unsigned buffers, 1219bf215546Sopenharmony_ci const union pipe_color_union *color, 1220bf215546Sopenharmony_ci float depth, unsigned stencil) 1221bf215546Sopenharmony_ci{ 1222bf215546Sopenharmony_ci /* This is worth it only if it's a whole image clear, so that we just clear DCC/HTILE. */ 1223bf215546Sopenharmony_ci if (dstx == 0 && dsty == 0 && 1224bf215546Sopenharmony_ci width == dst->width && 1225bf215546Sopenharmony_ci height == dst->height && 1226bf215546Sopenharmony_ci dst->u.tex.first_layer == 0 && 1227bf215546Sopenharmony_ci dst->u.tex.last_layer == util_max_layer(dst->texture, dst->u.tex.level) && 1228bf215546Sopenharmony_ci /* pipe->clear honors render_condition, so only use it if it's unset or if it's set and enabled. */ 1229bf215546Sopenharmony_ci (!sctx->render_cond || render_condition_enabled) && 1230bf215546Sopenharmony_ci sctx->has_graphics) { 1231bf215546Sopenharmony_ci struct pipe_context *ctx = &sctx->b; 1232bf215546Sopenharmony_ci struct pipe_framebuffer_state saved_fb = {}, fb = {}; 1233bf215546Sopenharmony_ci 1234bf215546Sopenharmony_ci util_copy_framebuffer_state(&saved_fb, &sctx->framebuffer.state); 1235bf215546Sopenharmony_ci 1236bf215546Sopenharmony_ci if (buffers & PIPE_CLEAR_COLOR) { 1237bf215546Sopenharmony_ci fb.cbufs[0] = dst; 1238bf215546Sopenharmony_ci fb.nr_cbufs = 1; 1239bf215546Sopenharmony_ci } else { 1240bf215546Sopenharmony_ci fb.zsbuf = dst; 1241bf215546Sopenharmony_ci } 1242bf215546Sopenharmony_ci 1243bf215546Sopenharmony_ci fb.width = dst->width; 1244bf215546Sopenharmony_ci fb.height = dst->height; 1245bf215546Sopenharmony_ci 1246bf215546Sopenharmony_ci ctx->set_framebuffer_state(ctx, &fb); 1247bf215546Sopenharmony_ci ctx->clear(ctx, buffers, NULL, color, depth, stencil); 1248bf215546Sopenharmony_ci ctx->set_framebuffer_state(ctx, &saved_fb); 1249bf215546Sopenharmony_ci 1250bf215546Sopenharmony_ci util_copy_framebuffer_state(&saved_fb, NULL); 1251bf215546Sopenharmony_ci 1252bf215546Sopenharmony_ci return true; 1253bf215546Sopenharmony_ci } 1254bf215546Sopenharmony_ci 1255bf215546Sopenharmony_ci return false; 1256bf215546Sopenharmony_ci} 1257bf215546Sopenharmony_ci 1258bf215546Sopenharmony_cistatic void si_clear_render_target(struct pipe_context *ctx, struct pipe_surface *dst, 1259bf215546Sopenharmony_ci const union pipe_color_union *color, unsigned dstx, 1260bf215546Sopenharmony_ci unsigned dsty, unsigned width, unsigned height, 1261bf215546Sopenharmony_ci bool render_condition_enabled) 1262bf215546Sopenharmony_ci{ 1263bf215546Sopenharmony_ci struct si_context *sctx = (struct si_context *)ctx; 1264bf215546Sopenharmony_ci struct si_texture *sdst = (struct si_texture *)dst->texture; 1265bf215546Sopenharmony_ci 1266bf215546Sopenharmony_ci /* Fast path that just clears DCC. */ 1267bf215546Sopenharmony_ci if (si_try_normal_clear(sctx, dst, dstx, dsty, width, height, render_condition_enabled, 1268bf215546Sopenharmony_ci PIPE_CLEAR_COLOR0, color, 0, 0)) 1269bf215546Sopenharmony_ci return; 1270bf215546Sopenharmony_ci 1271bf215546Sopenharmony_ci if (dst->texture->nr_samples <= 1 && 1272bf215546Sopenharmony_ci (sctx->gfx_level >= GFX10 || !vi_dcc_enabled(sdst, dst->u.tex.level))) { 1273bf215546Sopenharmony_ci si_compute_clear_render_target(ctx, dst, color, dstx, dsty, width, height, 1274bf215546Sopenharmony_ci render_condition_enabled); 1275bf215546Sopenharmony_ci return; 1276bf215546Sopenharmony_ci } 1277bf215546Sopenharmony_ci 1278bf215546Sopenharmony_ci si_blitter_begin(sctx, 1279bf215546Sopenharmony_ci SI_CLEAR_SURFACE | (render_condition_enabled ? 0 : SI_DISABLE_RENDER_COND)); 1280bf215546Sopenharmony_ci util_blitter_clear_render_target(sctx->blitter, dst, color, dstx, dsty, width, height); 1281bf215546Sopenharmony_ci si_blitter_end(sctx); 1282bf215546Sopenharmony_ci} 1283bf215546Sopenharmony_ci 1284bf215546Sopenharmony_cistatic void si_clear_depth_stencil(struct pipe_context *ctx, struct pipe_surface *dst, 1285bf215546Sopenharmony_ci unsigned clear_flags, double depth, unsigned stencil, 1286bf215546Sopenharmony_ci unsigned dstx, unsigned dsty, unsigned width, unsigned height, 1287bf215546Sopenharmony_ci bool render_condition_enabled) 1288bf215546Sopenharmony_ci{ 1289bf215546Sopenharmony_ci struct si_context *sctx = (struct si_context *)ctx; 1290bf215546Sopenharmony_ci union pipe_color_union unused = {}; 1291bf215546Sopenharmony_ci 1292bf215546Sopenharmony_ci /* Fast path that just clears HTILE. */ 1293bf215546Sopenharmony_ci if (si_try_normal_clear(sctx, dst, dstx, dsty, width, height, render_condition_enabled, 1294bf215546Sopenharmony_ci clear_flags, &unused, depth, stencil)) 1295bf215546Sopenharmony_ci return; 1296bf215546Sopenharmony_ci 1297bf215546Sopenharmony_ci si_blitter_begin(sctx, 1298bf215546Sopenharmony_ci SI_CLEAR_SURFACE | (render_condition_enabled ? 0 : SI_DISABLE_RENDER_COND)); 1299bf215546Sopenharmony_ci util_blitter_clear_depth_stencil(sctx->blitter, dst, clear_flags, depth, stencil, dstx, dsty, 1300bf215546Sopenharmony_ci width, height); 1301bf215546Sopenharmony_ci si_blitter_end(sctx); 1302bf215546Sopenharmony_ci} 1303bf215546Sopenharmony_ci 1304bf215546Sopenharmony_cistatic void si_clear_texture(struct pipe_context *pipe, struct pipe_resource *tex, unsigned level, 1305bf215546Sopenharmony_ci const struct pipe_box *box, const void *data) 1306bf215546Sopenharmony_ci{ 1307bf215546Sopenharmony_ci struct pipe_screen *screen = pipe->screen; 1308bf215546Sopenharmony_ci struct si_texture *stex = (struct si_texture *)tex; 1309bf215546Sopenharmony_ci struct pipe_surface tmpl = {{0}}; 1310bf215546Sopenharmony_ci struct pipe_surface *sf; 1311bf215546Sopenharmony_ci 1312bf215546Sopenharmony_ci tmpl.format = tex->format; 1313bf215546Sopenharmony_ci tmpl.u.tex.first_layer = box->z; 1314bf215546Sopenharmony_ci tmpl.u.tex.last_layer = box->z + box->depth - 1; 1315bf215546Sopenharmony_ci tmpl.u.tex.level = level; 1316bf215546Sopenharmony_ci sf = pipe->create_surface(pipe, tex, &tmpl); 1317bf215546Sopenharmony_ci if (!sf) 1318bf215546Sopenharmony_ci return; 1319bf215546Sopenharmony_ci 1320bf215546Sopenharmony_ci if (stex->is_depth) { 1321bf215546Sopenharmony_ci unsigned clear; 1322bf215546Sopenharmony_ci float depth; 1323bf215546Sopenharmony_ci uint8_t stencil = 0; 1324bf215546Sopenharmony_ci 1325bf215546Sopenharmony_ci /* Depth is always present. */ 1326bf215546Sopenharmony_ci clear = PIPE_CLEAR_DEPTH; 1327bf215546Sopenharmony_ci util_format_unpack_z_float(tex->format, &depth, data, 1); 1328bf215546Sopenharmony_ci 1329bf215546Sopenharmony_ci if (stex->surface.has_stencil) { 1330bf215546Sopenharmony_ci clear |= PIPE_CLEAR_STENCIL; 1331bf215546Sopenharmony_ci util_format_unpack_s_8uint(tex->format, &stencil, data, 1); 1332bf215546Sopenharmony_ci } 1333bf215546Sopenharmony_ci 1334bf215546Sopenharmony_ci si_clear_depth_stencil(pipe, sf, clear, depth, stencil, box->x, box->y, box->width, 1335bf215546Sopenharmony_ci box->height, false); 1336bf215546Sopenharmony_ci } else { 1337bf215546Sopenharmony_ci union pipe_color_union color; 1338bf215546Sopenharmony_ci 1339bf215546Sopenharmony_ci util_format_unpack_rgba(tex->format, color.ui, data, 1); 1340bf215546Sopenharmony_ci 1341bf215546Sopenharmony_ci if (screen->is_format_supported(screen, tex->format, tex->target, 0, 0, 1342bf215546Sopenharmony_ci PIPE_BIND_RENDER_TARGET)) { 1343bf215546Sopenharmony_ci si_clear_render_target(pipe, sf, &color, box->x, box->y, box->width, box->height, false); 1344bf215546Sopenharmony_ci } else { 1345bf215546Sopenharmony_ci /* Software fallback - just for R9G9B9E5_FLOAT */ 1346bf215546Sopenharmony_ci util_clear_render_target(pipe, sf, &color, box->x, box->y, box->width, box->height); 1347bf215546Sopenharmony_ci } 1348bf215546Sopenharmony_ci } 1349bf215546Sopenharmony_ci pipe_surface_reference(&sf, NULL); 1350bf215546Sopenharmony_ci} 1351bf215546Sopenharmony_ci 1352bf215546Sopenharmony_civoid si_init_clear_functions(struct si_context *sctx) 1353bf215546Sopenharmony_ci{ 1354bf215546Sopenharmony_ci sctx->b.clear_render_target = si_clear_render_target; 1355bf215546Sopenharmony_ci sctx->b.clear_texture = si_clear_texture; 1356bf215546Sopenharmony_ci 1357bf215546Sopenharmony_ci if (sctx->has_graphics) { 1358bf215546Sopenharmony_ci sctx->b.clear = si_clear; 1359bf215546Sopenharmony_ci sctx->b.clear_depth_stencil = si_clear_depth_stencil; 1360bf215546Sopenharmony_ci } 1361bf215546Sopenharmony_ci} 1362