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