1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright 2010 Jerome Glisse <glisse@freedesktop.org>
3bf215546Sopenharmony_ci * Copyright 2015 Advanced Micro Devices, Inc.
4bf215546Sopenharmony_ci * All Rights Reserved.
5bf215546Sopenharmony_ci *
6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
8bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
9bf215546Sopenharmony_ci * on the rights to use, copy, modify, merge, publish, distribute, sub
10bf215546Sopenharmony_ci * license, and/or sell copies of the Software, and to permit persons to whom
11bf215546Sopenharmony_ci * the Software is furnished to do so, subject to the following conditions:
12bf215546Sopenharmony_ci *
13bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
14bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
15bf215546Sopenharmony_ci * Software.
16bf215546Sopenharmony_ci *
17bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
20bf215546Sopenharmony_ci * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
21bf215546Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
22bf215546Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
23bf215546Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE.
24bf215546Sopenharmony_ci */
25bf215546Sopenharmony_ci
26bf215546Sopenharmony_ci#include "si_compute.h"
27bf215546Sopenharmony_ci#include "si_pipe.h"
28bf215546Sopenharmony_ci#include "util/format/u_format.h"
29bf215546Sopenharmony_ci#include "util/u_log.h"
30bf215546Sopenharmony_ci#include "util/u_surface.h"
31bf215546Sopenharmony_ci
32bf215546Sopenharmony_cienum
33bf215546Sopenharmony_ci{
34bf215546Sopenharmony_ci   SI_COPY =
35bf215546Sopenharmony_ci      SI_SAVE_FRAMEBUFFER | SI_SAVE_TEXTURES | SI_SAVE_FRAGMENT_STATE | SI_DISABLE_RENDER_COND,
36bf215546Sopenharmony_ci
37bf215546Sopenharmony_ci   SI_BLIT = SI_SAVE_FRAMEBUFFER | SI_SAVE_TEXTURES | SI_SAVE_FRAGMENT_STATE,
38bf215546Sopenharmony_ci
39bf215546Sopenharmony_ci   SI_DECOMPRESS = SI_SAVE_FRAMEBUFFER | SI_SAVE_FRAGMENT_STATE | SI_DISABLE_RENDER_COND,
40bf215546Sopenharmony_ci
41bf215546Sopenharmony_ci   SI_COLOR_RESOLVE = SI_SAVE_FRAMEBUFFER | SI_SAVE_FRAGMENT_STATE
42bf215546Sopenharmony_ci};
43bf215546Sopenharmony_ci
44bf215546Sopenharmony_civoid si_blitter_begin(struct si_context *sctx, enum si_blitter_op op)
45bf215546Sopenharmony_ci{
46bf215546Sopenharmony_ci   util_blitter_save_vertex_shader(sctx->blitter, sctx->shader.vs.cso);
47bf215546Sopenharmony_ci   util_blitter_save_tessctrl_shader(sctx->blitter, sctx->shader.tcs.cso);
48bf215546Sopenharmony_ci   util_blitter_save_tesseval_shader(sctx->blitter, sctx->shader.tes.cso);
49bf215546Sopenharmony_ci   util_blitter_save_geometry_shader(sctx->blitter, sctx->shader.gs.cso);
50bf215546Sopenharmony_ci   util_blitter_save_so_targets(sctx->blitter, sctx->streamout.num_targets,
51bf215546Sopenharmony_ci                                (struct pipe_stream_output_target **)sctx->streamout.targets);
52bf215546Sopenharmony_ci   util_blitter_save_rasterizer(sctx->blitter, sctx->queued.named.rasterizer);
53bf215546Sopenharmony_ci
54bf215546Sopenharmony_ci   if (op & SI_SAVE_FRAGMENT_STATE) {
55bf215546Sopenharmony_ci      struct pipe_constant_buffer fs_cb = {};
56bf215546Sopenharmony_ci      si_get_pipe_constant_buffer(sctx, PIPE_SHADER_FRAGMENT, 0, &fs_cb);
57bf215546Sopenharmony_ci      util_blitter_save_fragment_constant_buffer_slot(sctx->blitter, &fs_cb);
58bf215546Sopenharmony_ci      pipe_resource_reference(&fs_cb.buffer, NULL);
59bf215546Sopenharmony_ci      util_blitter_save_blend(sctx->blitter, sctx->queued.named.blend);
60bf215546Sopenharmony_ci      util_blitter_save_depth_stencil_alpha(sctx->blitter, sctx->queued.named.dsa);
61bf215546Sopenharmony_ci      util_blitter_save_stencil_ref(sctx->blitter, &sctx->stencil_ref.state);
62bf215546Sopenharmony_ci      util_blitter_save_fragment_shader(sctx->blitter, sctx->shader.ps.cso);
63bf215546Sopenharmony_ci      util_blitter_save_sample_mask(sctx->blitter, sctx->sample_mask, sctx->ps_iter_samples);
64bf215546Sopenharmony_ci      util_blitter_save_scissor(sctx->blitter, &sctx->scissors[0]);
65bf215546Sopenharmony_ci      util_blitter_save_window_rectangles(sctx->blitter, sctx->window_rectangles_include,
66bf215546Sopenharmony_ci                                          sctx->num_window_rectangles, sctx->window_rectangles);
67bf215546Sopenharmony_ci   }
68bf215546Sopenharmony_ci
69bf215546Sopenharmony_ci   if (op & SI_SAVE_FRAMEBUFFER)
70bf215546Sopenharmony_ci      util_blitter_save_framebuffer(sctx->blitter, &sctx->framebuffer.state);
71bf215546Sopenharmony_ci
72bf215546Sopenharmony_ci   if (op & SI_SAVE_TEXTURES) {
73bf215546Sopenharmony_ci      util_blitter_save_fragment_sampler_states(
74bf215546Sopenharmony_ci         sctx->blitter, 2, (void **)sctx->samplers[PIPE_SHADER_FRAGMENT].sampler_states);
75bf215546Sopenharmony_ci
76bf215546Sopenharmony_ci      util_blitter_save_fragment_sampler_views(sctx->blitter, 2,
77bf215546Sopenharmony_ci                                               sctx->samplers[PIPE_SHADER_FRAGMENT].views);
78bf215546Sopenharmony_ci   }
79bf215546Sopenharmony_ci
80bf215546Sopenharmony_ci   if (op & SI_DISABLE_RENDER_COND)
81bf215546Sopenharmony_ci      sctx->render_cond_enabled = false;
82bf215546Sopenharmony_ci
83bf215546Sopenharmony_ci   if (sctx->screen->dpbb_allowed) {
84bf215546Sopenharmony_ci      sctx->dpbb_force_off = true;
85bf215546Sopenharmony_ci      si_mark_atom_dirty(sctx, &sctx->atoms.s.dpbb_state);
86bf215546Sopenharmony_ci   }
87bf215546Sopenharmony_ci
88bf215546Sopenharmony_ci   sctx->blitter_running = true;
89bf215546Sopenharmony_ci}
90bf215546Sopenharmony_ci
91bf215546Sopenharmony_civoid si_blitter_end(struct si_context *sctx)
92bf215546Sopenharmony_ci{
93bf215546Sopenharmony_ci   sctx->blitter_running = false;
94bf215546Sopenharmony_ci
95bf215546Sopenharmony_ci   if (sctx->screen->dpbb_allowed) {
96bf215546Sopenharmony_ci      sctx->dpbb_force_off = false;
97bf215546Sopenharmony_ci      si_mark_atom_dirty(sctx, &sctx->atoms.s.dpbb_state);
98bf215546Sopenharmony_ci   }
99bf215546Sopenharmony_ci
100bf215546Sopenharmony_ci   sctx->render_cond_enabled = sctx->render_cond;
101bf215546Sopenharmony_ci
102bf215546Sopenharmony_ci   /* Restore shader pointers because the VS blit shader changed all
103bf215546Sopenharmony_ci    * non-global VS user SGPRs. */
104bf215546Sopenharmony_ci   sctx->shader_pointers_dirty |= SI_DESCS_SHADER_MASK(VERTEX);
105bf215546Sopenharmony_ci
106bf215546Sopenharmony_ci   if (sctx->gfx_level >= GFX11)
107bf215546Sopenharmony_ci      sctx->gs_attribute_ring_pointer_dirty = true;
108bf215546Sopenharmony_ci
109bf215546Sopenharmony_ci   /* Reset SI_SGPR_SMALL_PRIM_CULL_INFO: */
110bf215546Sopenharmony_ci   if (sctx->screen->use_ngg_culling)
111bf215546Sopenharmony_ci      si_mark_atom_dirty(sctx, &sctx->atoms.s.ngg_cull_state);
112bf215546Sopenharmony_ci
113bf215546Sopenharmony_ci   unsigned num_vbos_in_user_sgprs = si_num_vbos_in_user_sgprs(sctx->screen);
114bf215546Sopenharmony_ci   sctx->vertex_buffer_pointer_dirty = sctx->vb_descriptors_buffer != NULL &&
115bf215546Sopenharmony_ci                                       sctx->num_vertex_elements >
116bf215546Sopenharmony_ci                                       num_vbos_in_user_sgprs;
117bf215546Sopenharmony_ci   sctx->vertex_buffer_user_sgprs_dirty = sctx->num_vertex_elements > 0 &&
118bf215546Sopenharmony_ci                                          num_vbos_in_user_sgprs;
119bf215546Sopenharmony_ci   si_mark_atom_dirty(sctx, &sctx->atoms.s.shader_pointers);
120bf215546Sopenharmony_ci}
121bf215546Sopenharmony_ci
122bf215546Sopenharmony_cistatic unsigned u_max_sample(struct pipe_resource *r)
123bf215546Sopenharmony_ci{
124bf215546Sopenharmony_ci   return r->nr_samples ? r->nr_samples - 1 : 0;
125bf215546Sopenharmony_ci}
126bf215546Sopenharmony_ci
127bf215546Sopenharmony_cistatic unsigned si_blit_dbcb_copy(struct si_context *sctx, struct si_texture *src,
128bf215546Sopenharmony_ci                                  struct si_texture *dst, unsigned planes, unsigned level_mask,
129bf215546Sopenharmony_ci                                  unsigned first_layer, unsigned last_layer, unsigned first_sample,
130bf215546Sopenharmony_ci                                  unsigned last_sample)
131bf215546Sopenharmony_ci{
132bf215546Sopenharmony_ci   struct pipe_surface surf_tmpl = {{0}};
133bf215546Sopenharmony_ci   unsigned layer, sample, checked_last_layer, max_layer;
134bf215546Sopenharmony_ci   unsigned fully_copied_levels = 0;
135bf215546Sopenharmony_ci
136bf215546Sopenharmony_ci   if (planes & PIPE_MASK_Z)
137bf215546Sopenharmony_ci      sctx->dbcb_depth_copy_enabled = true;
138bf215546Sopenharmony_ci   if (planes & PIPE_MASK_S)
139bf215546Sopenharmony_ci      sctx->dbcb_stencil_copy_enabled = true;
140bf215546Sopenharmony_ci   si_mark_atom_dirty(sctx, &sctx->atoms.s.db_render_state);
141bf215546Sopenharmony_ci
142bf215546Sopenharmony_ci   assert(sctx->dbcb_depth_copy_enabled || sctx->dbcb_stencil_copy_enabled);
143bf215546Sopenharmony_ci
144bf215546Sopenharmony_ci   sctx->decompression_enabled = true;
145bf215546Sopenharmony_ci
146bf215546Sopenharmony_ci   while (level_mask) {
147bf215546Sopenharmony_ci      unsigned level = u_bit_scan(&level_mask);
148bf215546Sopenharmony_ci
149bf215546Sopenharmony_ci      /* The smaller the mipmap level, the less layers there are
150bf215546Sopenharmony_ci       * as far as 3D textures are concerned. */
151bf215546Sopenharmony_ci      max_layer = util_max_layer(&src->buffer.b.b, level);
152bf215546Sopenharmony_ci      checked_last_layer = MIN2(last_layer, max_layer);
153bf215546Sopenharmony_ci
154bf215546Sopenharmony_ci      surf_tmpl.u.tex.level = level;
155bf215546Sopenharmony_ci
156bf215546Sopenharmony_ci      for (layer = first_layer; layer <= checked_last_layer; layer++) {
157bf215546Sopenharmony_ci         struct pipe_surface *zsurf, *cbsurf;
158bf215546Sopenharmony_ci
159bf215546Sopenharmony_ci         surf_tmpl.format = src->buffer.b.b.format;
160bf215546Sopenharmony_ci         surf_tmpl.u.tex.first_layer = layer;
161bf215546Sopenharmony_ci         surf_tmpl.u.tex.last_layer = layer;
162bf215546Sopenharmony_ci
163bf215546Sopenharmony_ci         zsurf = sctx->b.create_surface(&sctx->b, &src->buffer.b.b, &surf_tmpl);
164bf215546Sopenharmony_ci
165bf215546Sopenharmony_ci         surf_tmpl.format = dst->buffer.b.b.format;
166bf215546Sopenharmony_ci         cbsurf = sctx->b.create_surface(&sctx->b, &dst->buffer.b.b, &surf_tmpl);
167bf215546Sopenharmony_ci
168bf215546Sopenharmony_ci         for (sample = first_sample; sample <= last_sample; sample++) {
169bf215546Sopenharmony_ci            if (sample != sctx->dbcb_copy_sample) {
170bf215546Sopenharmony_ci               sctx->dbcb_copy_sample = sample;
171bf215546Sopenharmony_ci               si_mark_atom_dirty(sctx, &sctx->atoms.s.db_render_state);
172bf215546Sopenharmony_ci            }
173bf215546Sopenharmony_ci
174bf215546Sopenharmony_ci            si_blitter_begin(sctx, SI_DECOMPRESS);
175bf215546Sopenharmony_ci            util_blitter_custom_depth_stencil(sctx->blitter, zsurf, cbsurf, 1 << sample,
176bf215546Sopenharmony_ci                                              sctx->custom_dsa_flush, 1.0f);
177bf215546Sopenharmony_ci            si_blitter_end(sctx);
178bf215546Sopenharmony_ci         }
179bf215546Sopenharmony_ci
180bf215546Sopenharmony_ci         pipe_surface_reference(&zsurf, NULL);
181bf215546Sopenharmony_ci         pipe_surface_reference(&cbsurf, NULL);
182bf215546Sopenharmony_ci      }
183bf215546Sopenharmony_ci
184bf215546Sopenharmony_ci      if (first_layer == 0 && last_layer >= max_layer && first_sample == 0 &&
185bf215546Sopenharmony_ci          last_sample >= u_max_sample(&src->buffer.b.b))
186bf215546Sopenharmony_ci         fully_copied_levels |= 1u << level;
187bf215546Sopenharmony_ci   }
188bf215546Sopenharmony_ci
189bf215546Sopenharmony_ci   sctx->decompression_enabled = false;
190bf215546Sopenharmony_ci   sctx->dbcb_depth_copy_enabled = false;
191bf215546Sopenharmony_ci   sctx->dbcb_stencil_copy_enabled = false;
192bf215546Sopenharmony_ci   si_mark_atom_dirty(sctx, &sctx->atoms.s.db_render_state);
193bf215546Sopenharmony_ci
194bf215546Sopenharmony_ci   return fully_copied_levels;
195bf215546Sopenharmony_ci}
196bf215546Sopenharmony_ci
197bf215546Sopenharmony_ci/* Helper function for si_blit_decompress_zs_in_place.
198bf215546Sopenharmony_ci */
199bf215546Sopenharmony_cistatic void si_blit_decompress_zs_planes_in_place(struct si_context *sctx,
200bf215546Sopenharmony_ci                                                  struct si_texture *texture, unsigned planes,
201bf215546Sopenharmony_ci                                                  unsigned level_mask, unsigned first_layer,
202bf215546Sopenharmony_ci                                                  unsigned last_layer)
203bf215546Sopenharmony_ci{
204bf215546Sopenharmony_ci   struct pipe_surface *zsurf, surf_tmpl = {{0}};
205bf215546Sopenharmony_ci   unsigned layer, max_layer, checked_last_layer;
206bf215546Sopenharmony_ci   unsigned fully_decompressed_mask = 0;
207bf215546Sopenharmony_ci
208bf215546Sopenharmony_ci   if (!level_mask)
209bf215546Sopenharmony_ci      return;
210bf215546Sopenharmony_ci
211bf215546Sopenharmony_ci   if (planes & PIPE_MASK_S)
212bf215546Sopenharmony_ci      sctx->db_flush_stencil_inplace = true;
213bf215546Sopenharmony_ci   if (planes & PIPE_MASK_Z)
214bf215546Sopenharmony_ci      sctx->db_flush_depth_inplace = true;
215bf215546Sopenharmony_ci   si_mark_atom_dirty(sctx, &sctx->atoms.s.db_render_state);
216bf215546Sopenharmony_ci
217bf215546Sopenharmony_ci   surf_tmpl.format = texture->buffer.b.b.format;
218bf215546Sopenharmony_ci
219bf215546Sopenharmony_ci   sctx->decompression_enabled = true;
220bf215546Sopenharmony_ci
221bf215546Sopenharmony_ci   while (level_mask) {
222bf215546Sopenharmony_ci      unsigned level = u_bit_scan(&level_mask);
223bf215546Sopenharmony_ci
224bf215546Sopenharmony_ci      surf_tmpl.u.tex.level = level;
225bf215546Sopenharmony_ci
226bf215546Sopenharmony_ci      /* The smaller the mipmap level, the less layers there are
227bf215546Sopenharmony_ci       * as far as 3D textures are concerned. */
228bf215546Sopenharmony_ci      max_layer = util_max_layer(&texture->buffer.b.b, level);
229bf215546Sopenharmony_ci      checked_last_layer = MIN2(last_layer, max_layer);
230bf215546Sopenharmony_ci
231bf215546Sopenharmony_ci      for (layer = first_layer; layer <= checked_last_layer; layer++) {
232bf215546Sopenharmony_ci         surf_tmpl.u.tex.first_layer = layer;
233bf215546Sopenharmony_ci         surf_tmpl.u.tex.last_layer = layer;
234bf215546Sopenharmony_ci
235bf215546Sopenharmony_ci         zsurf = sctx->b.create_surface(&sctx->b, &texture->buffer.b.b, &surf_tmpl);
236bf215546Sopenharmony_ci
237bf215546Sopenharmony_ci         si_blitter_begin(sctx, SI_DECOMPRESS);
238bf215546Sopenharmony_ci         util_blitter_custom_depth_stencil(sctx->blitter, zsurf, NULL, ~0, sctx->custom_dsa_flush,
239bf215546Sopenharmony_ci                                           1.0f);
240bf215546Sopenharmony_ci         si_blitter_end(sctx);
241bf215546Sopenharmony_ci
242bf215546Sopenharmony_ci         pipe_surface_reference(&zsurf, NULL);
243bf215546Sopenharmony_ci      }
244bf215546Sopenharmony_ci
245bf215546Sopenharmony_ci      /* The texture will always be dirty if some layers aren't flushed.
246bf215546Sopenharmony_ci       * I don't think this case occurs often though. */
247bf215546Sopenharmony_ci      if (first_layer == 0 && last_layer >= max_layer) {
248bf215546Sopenharmony_ci         fully_decompressed_mask |= 1u << level;
249bf215546Sopenharmony_ci      }
250bf215546Sopenharmony_ci   }
251bf215546Sopenharmony_ci
252bf215546Sopenharmony_ci   if (planes & PIPE_MASK_Z)
253bf215546Sopenharmony_ci      texture->dirty_level_mask &= ~fully_decompressed_mask;
254bf215546Sopenharmony_ci   if (planes & PIPE_MASK_S)
255bf215546Sopenharmony_ci      texture->stencil_dirty_level_mask &= ~fully_decompressed_mask;
256bf215546Sopenharmony_ci
257bf215546Sopenharmony_ci   sctx->decompression_enabled = false;
258bf215546Sopenharmony_ci   sctx->db_flush_depth_inplace = false;
259bf215546Sopenharmony_ci   sctx->db_flush_stencil_inplace = false;
260bf215546Sopenharmony_ci   si_mark_atom_dirty(sctx, &sctx->atoms.s.db_render_state);
261bf215546Sopenharmony_ci}
262bf215546Sopenharmony_ci
263bf215546Sopenharmony_ci/* Helper function of si_flush_depth_texture: decompress the given levels
264bf215546Sopenharmony_ci * of Z and/or S planes in place.
265bf215546Sopenharmony_ci */
266bf215546Sopenharmony_cistatic void si_blit_decompress_zs_in_place(struct si_context *sctx, struct si_texture *texture,
267bf215546Sopenharmony_ci                                           unsigned levels_z, unsigned levels_s,
268bf215546Sopenharmony_ci                                           unsigned first_layer, unsigned last_layer)
269bf215546Sopenharmony_ci{
270bf215546Sopenharmony_ci   unsigned both = levels_z & levels_s;
271bf215546Sopenharmony_ci
272bf215546Sopenharmony_ci   /* First, do combined Z & S decompresses for levels that need it. */
273bf215546Sopenharmony_ci   if (both) {
274bf215546Sopenharmony_ci      si_blit_decompress_zs_planes_in_place(sctx, texture, PIPE_MASK_Z | PIPE_MASK_S, both,
275bf215546Sopenharmony_ci                                            first_layer, last_layer);
276bf215546Sopenharmony_ci      levels_z &= ~both;
277bf215546Sopenharmony_ci      levels_s &= ~both;
278bf215546Sopenharmony_ci   }
279bf215546Sopenharmony_ci
280bf215546Sopenharmony_ci   /* Now do separate Z and S decompresses. */
281bf215546Sopenharmony_ci   if (levels_z) {
282bf215546Sopenharmony_ci      si_blit_decompress_zs_planes_in_place(sctx, texture, PIPE_MASK_Z, levels_z, first_layer,
283bf215546Sopenharmony_ci                                            last_layer);
284bf215546Sopenharmony_ci   }
285bf215546Sopenharmony_ci
286bf215546Sopenharmony_ci   if (levels_s) {
287bf215546Sopenharmony_ci      si_blit_decompress_zs_planes_in_place(sctx, texture, PIPE_MASK_S, levels_s, first_layer,
288bf215546Sopenharmony_ci                                            last_layer);
289bf215546Sopenharmony_ci   }
290bf215546Sopenharmony_ci}
291bf215546Sopenharmony_ci
292bf215546Sopenharmony_cistatic void si_decompress_depth(struct si_context *sctx, struct si_texture *tex,
293bf215546Sopenharmony_ci                                unsigned required_planes, unsigned first_level, unsigned last_level,
294bf215546Sopenharmony_ci                                unsigned first_layer, unsigned last_layer)
295bf215546Sopenharmony_ci{
296bf215546Sopenharmony_ci   unsigned inplace_planes = 0;
297bf215546Sopenharmony_ci   unsigned copy_planes = 0;
298bf215546Sopenharmony_ci   unsigned level_mask = u_bit_consecutive(first_level, last_level - first_level + 1);
299bf215546Sopenharmony_ci   unsigned levels_z = 0;
300bf215546Sopenharmony_ci   unsigned levels_s = 0;
301bf215546Sopenharmony_ci
302bf215546Sopenharmony_ci   if (required_planes & PIPE_MASK_Z) {
303bf215546Sopenharmony_ci      levels_z = level_mask & tex->dirty_level_mask;
304bf215546Sopenharmony_ci
305bf215546Sopenharmony_ci      if (levels_z) {
306bf215546Sopenharmony_ci         if (si_can_sample_zs(tex, false))
307bf215546Sopenharmony_ci            inplace_planes |= PIPE_MASK_Z;
308bf215546Sopenharmony_ci         else
309bf215546Sopenharmony_ci            copy_planes |= PIPE_MASK_Z;
310bf215546Sopenharmony_ci      }
311bf215546Sopenharmony_ci   }
312bf215546Sopenharmony_ci   if (required_planes & PIPE_MASK_S) {
313bf215546Sopenharmony_ci      levels_s = level_mask & tex->stencil_dirty_level_mask;
314bf215546Sopenharmony_ci
315bf215546Sopenharmony_ci      if (levels_s) {
316bf215546Sopenharmony_ci         if (si_can_sample_zs(tex, true))
317bf215546Sopenharmony_ci            inplace_planes |= PIPE_MASK_S;
318bf215546Sopenharmony_ci         else
319bf215546Sopenharmony_ci            copy_planes |= PIPE_MASK_S;
320bf215546Sopenharmony_ci      }
321bf215546Sopenharmony_ci   }
322bf215546Sopenharmony_ci
323bf215546Sopenharmony_ci   if (unlikely(sctx->log))
324bf215546Sopenharmony_ci      u_log_printf(sctx->log,
325bf215546Sopenharmony_ci                   "\n------------------------------------------------\n"
326bf215546Sopenharmony_ci                   "Decompress Depth (levels %u - %u, levels Z: 0x%x S: 0x%x)\n\n",
327bf215546Sopenharmony_ci                   first_level, last_level, levels_z, levels_s);
328bf215546Sopenharmony_ci
329bf215546Sopenharmony_ci   /* We may have to allocate the flushed texture here when called from
330bf215546Sopenharmony_ci    * si_decompress_subresource.
331bf215546Sopenharmony_ci    */
332bf215546Sopenharmony_ci   if (copy_planes &&
333bf215546Sopenharmony_ci       (tex->flushed_depth_texture || si_init_flushed_depth_texture(&sctx->b, &tex->buffer.b.b))) {
334bf215546Sopenharmony_ci      struct si_texture *dst = tex->flushed_depth_texture;
335bf215546Sopenharmony_ci      unsigned fully_copied_levels;
336bf215546Sopenharmony_ci      unsigned levels = 0;
337bf215546Sopenharmony_ci
338bf215546Sopenharmony_ci      assert(tex->flushed_depth_texture);
339bf215546Sopenharmony_ci
340bf215546Sopenharmony_ci      if (util_format_is_depth_and_stencil(dst->buffer.b.b.format))
341bf215546Sopenharmony_ci         copy_planes = PIPE_MASK_Z | PIPE_MASK_S;
342bf215546Sopenharmony_ci
343bf215546Sopenharmony_ci      if (copy_planes & PIPE_MASK_Z) {
344bf215546Sopenharmony_ci         levels |= levels_z;
345bf215546Sopenharmony_ci         levels_z = 0;
346bf215546Sopenharmony_ci      }
347bf215546Sopenharmony_ci      if (copy_planes & PIPE_MASK_S) {
348bf215546Sopenharmony_ci         levels |= levels_s;
349bf215546Sopenharmony_ci         levels_s = 0;
350bf215546Sopenharmony_ci      }
351bf215546Sopenharmony_ci
352bf215546Sopenharmony_ci      fully_copied_levels = si_blit_dbcb_copy(sctx, tex, dst, copy_planes, levels, first_layer,
353bf215546Sopenharmony_ci                                              last_layer, 0, u_max_sample(&tex->buffer.b.b));
354bf215546Sopenharmony_ci
355bf215546Sopenharmony_ci      if (copy_planes & PIPE_MASK_Z)
356bf215546Sopenharmony_ci         tex->dirty_level_mask &= ~fully_copied_levels;
357bf215546Sopenharmony_ci      if (copy_planes & PIPE_MASK_S)
358bf215546Sopenharmony_ci         tex->stencil_dirty_level_mask &= ~fully_copied_levels;
359bf215546Sopenharmony_ci   }
360bf215546Sopenharmony_ci
361bf215546Sopenharmony_ci   if (inplace_planes) {
362bf215546Sopenharmony_ci      bool has_htile = si_htile_enabled(tex, first_level, inplace_planes);
363bf215546Sopenharmony_ci      bool tc_compat_htile = vi_tc_compat_htile_enabled(tex, first_level, inplace_planes);
364bf215546Sopenharmony_ci
365bf215546Sopenharmony_ci      /* Don't decompress if there is no HTILE or when HTILE is
366bf215546Sopenharmony_ci       * TC-compatible. */
367bf215546Sopenharmony_ci      if (has_htile && !tc_compat_htile) {
368bf215546Sopenharmony_ci         si_blit_decompress_zs_in_place(sctx, tex, levels_z, levels_s, first_layer, last_layer);
369bf215546Sopenharmony_ci      } else {
370bf215546Sopenharmony_ci         /* This is only a cache flush.
371bf215546Sopenharmony_ci          *
372bf215546Sopenharmony_ci          * Only clear the mask that we are flushing, because
373bf215546Sopenharmony_ci          * si_make_DB_shader_coherent() treats different levels
374bf215546Sopenharmony_ci          * and depth and stencil differently.
375bf215546Sopenharmony_ci          */
376bf215546Sopenharmony_ci         if (inplace_planes & PIPE_MASK_Z)
377bf215546Sopenharmony_ci            tex->dirty_level_mask &= ~levels_z;
378bf215546Sopenharmony_ci         if (inplace_planes & PIPE_MASK_S)
379bf215546Sopenharmony_ci            tex->stencil_dirty_level_mask &= ~levels_s;
380bf215546Sopenharmony_ci      }
381bf215546Sopenharmony_ci
382bf215546Sopenharmony_ci      /* We just had to completely decompress Z/S for texturing. Enable
383bf215546Sopenharmony_ci       * TC-compatible HTILE on the next clear, so that the decompression
384bf215546Sopenharmony_ci       * doesn't have to be done for this texture ever again.
385bf215546Sopenharmony_ci       *
386bf215546Sopenharmony_ci       * TC-compatible HTILE might slightly reduce Z/S performance, but
387bf215546Sopenharmony_ci       * the decompression is much worse.
388bf215546Sopenharmony_ci       */
389bf215546Sopenharmony_ci      if (has_htile && !tc_compat_htile &&
390bf215546Sopenharmony_ci          /* We can only transition the whole buffer in one clear, so no mipmapping: */
391bf215546Sopenharmony_ci          tex->buffer.b.b.last_level == 0 &&
392bf215546Sopenharmony_ci          tex->surface.flags & RADEON_SURF_TC_COMPATIBLE_HTILE &&
393bf215546Sopenharmony_ci          (inplace_planes & PIPE_MASK_Z || !tex->htile_stencil_disabled))
394bf215546Sopenharmony_ci         tex->enable_tc_compatible_htile_next_clear = true;
395bf215546Sopenharmony_ci
396bf215546Sopenharmony_ci      /* Only in-place decompression needs to flush DB caches, or
397bf215546Sopenharmony_ci       * when we don't decompress but TC-compatible planes are dirty.
398bf215546Sopenharmony_ci       */
399bf215546Sopenharmony_ci      si_make_DB_shader_coherent(sctx, tex->buffer.b.b.nr_samples, inplace_planes & PIPE_MASK_S,
400bf215546Sopenharmony_ci                                 tc_compat_htile);
401bf215546Sopenharmony_ci   }
402bf215546Sopenharmony_ci   /* set_framebuffer_state takes care of coherency for single-sample.
403bf215546Sopenharmony_ci    * The DB->CB copy uses CB for the final writes.
404bf215546Sopenharmony_ci    */
405bf215546Sopenharmony_ci   if (copy_planes && tex->buffer.b.b.nr_samples > 1)
406bf215546Sopenharmony_ci      si_make_CB_shader_coherent(sctx, tex->buffer.b.b.nr_samples, false, true /* no DCC */);
407bf215546Sopenharmony_ci}
408bf215546Sopenharmony_ci
409bf215546Sopenharmony_cistatic bool si_decompress_sampler_depth_textures(struct si_context *sctx,
410bf215546Sopenharmony_ci                                                 struct si_samplers *textures)
411bf215546Sopenharmony_ci{
412bf215546Sopenharmony_ci   unsigned i;
413bf215546Sopenharmony_ci   unsigned mask = textures->needs_depth_decompress_mask;
414bf215546Sopenharmony_ci   bool need_flush = false;
415bf215546Sopenharmony_ci
416bf215546Sopenharmony_ci   while (mask) {
417bf215546Sopenharmony_ci      struct pipe_sampler_view *view;
418bf215546Sopenharmony_ci      struct si_sampler_view *sview;
419bf215546Sopenharmony_ci      struct si_texture *tex;
420bf215546Sopenharmony_ci
421bf215546Sopenharmony_ci      i = u_bit_scan(&mask);
422bf215546Sopenharmony_ci
423bf215546Sopenharmony_ci      view = textures->views[i];
424bf215546Sopenharmony_ci      assert(view);
425bf215546Sopenharmony_ci      sview = (struct si_sampler_view *)view;
426bf215546Sopenharmony_ci
427bf215546Sopenharmony_ci      tex = (struct si_texture *)view->texture;
428bf215546Sopenharmony_ci      assert(tex->db_compatible);
429bf215546Sopenharmony_ci
430bf215546Sopenharmony_ci      si_decompress_depth(sctx, tex, sview->is_stencil_sampler ? PIPE_MASK_S : PIPE_MASK_Z,
431bf215546Sopenharmony_ci                          view->u.tex.first_level, view->u.tex.last_level, 0,
432bf215546Sopenharmony_ci                          util_max_layer(&tex->buffer.b.b, view->u.tex.first_level));
433bf215546Sopenharmony_ci
434bf215546Sopenharmony_ci      if (tex->need_flush_after_depth_decompression) {
435bf215546Sopenharmony_ci         need_flush = true;
436bf215546Sopenharmony_ci         tex->need_flush_after_depth_decompression = false;
437bf215546Sopenharmony_ci      }
438bf215546Sopenharmony_ci   }
439bf215546Sopenharmony_ci
440bf215546Sopenharmony_ci   return need_flush;
441bf215546Sopenharmony_ci}
442bf215546Sopenharmony_ci
443bf215546Sopenharmony_cistatic void si_blit_decompress_color(struct si_context *sctx, struct si_texture *tex,
444bf215546Sopenharmony_ci                                     unsigned first_level, unsigned last_level,
445bf215546Sopenharmony_ci                                     unsigned first_layer, unsigned last_layer,
446bf215546Sopenharmony_ci                                     bool need_dcc_decompress, bool need_fmask_expand)
447bf215546Sopenharmony_ci{
448bf215546Sopenharmony_ci   void *custom_blend;
449bf215546Sopenharmony_ci   unsigned layer, checked_last_layer, max_layer;
450bf215546Sopenharmony_ci   unsigned level_mask = u_bit_consecutive(first_level, last_level - first_level + 1);
451bf215546Sopenharmony_ci
452bf215546Sopenharmony_ci   if (!need_dcc_decompress)
453bf215546Sopenharmony_ci      level_mask &= tex->dirty_level_mask;
454bf215546Sopenharmony_ci   if (!level_mask)
455bf215546Sopenharmony_ci      goto expand_fmask;
456bf215546Sopenharmony_ci
457bf215546Sopenharmony_ci   /* No color decompression is needed on GFX11. */
458bf215546Sopenharmony_ci   assert(sctx->gfx_level < GFX11 || need_dcc_decompress);
459bf215546Sopenharmony_ci
460bf215546Sopenharmony_ci   if (unlikely(sctx->log))
461bf215546Sopenharmony_ci      u_log_printf(sctx->log,
462bf215546Sopenharmony_ci                   "\n------------------------------------------------\n"
463bf215546Sopenharmony_ci                   "Decompress Color (levels %u - %u, mask 0x%x)\n\n",
464bf215546Sopenharmony_ci                   first_level, last_level, level_mask);
465bf215546Sopenharmony_ci
466bf215546Sopenharmony_ci   if (need_dcc_decompress) {
467bf215546Sopenharmony_ci      custom_blend = sctx->custom_blend_dcc_decompress;
468bf215546Sopenharmony_ci
469bf215546Sopenharmony_ci      assert(vi_dcc_enabled(tex, first_level));
470bf215546Sopenharmony_ci
471bf215546Sopenharmony_ci      /* disable levels without DCC */
472bf215546Sopenharmony_ci      for (int i = first_level; i <= last_level; i++) {
473bf215546Sopenharmony_ci         if (!vi_dcc_enabled(tex, i))
474bf215546Sopenharmony_ci            level_mask &= ~(1 << i);
475bf215546Sopenharmony_ci      }
476bf215546Sopenharmony_ci   } else if (tex->surface.fmask_size) {
477bf215546Sopenharmony_ci      custom_blend = sctx->custom_blend_fmask_decompress;
478bf215546Sopenharmony_ci   } else {
479bf215546Sopenharmony_ci      custom_blend = sctx->custom_blend_eliminate_fastclear;
480bf215546Sopenharmony_ci   }
481bf215546Sopenharmony_ci
482bf215546Sopenharmony_ci   sctx->decompression_enabled = true;
483bf215546Sopenharmony_ci
484bf215546Sopenharmony_ci   while (level_mask) {
485bf215546Sopenharmony_ci      unsigned level = u_bit_scan(&level_mask);
486bf215546Sopenharmony_ci
487bf215546Sopenharmony_ci      /* The smaller the mipmap level, the less layers there are
488bf215546Sopenharmony_ci       * as far as 3D textures are concerned. */
489bf215546Sopenharmony_ci      max_layer = util_max_layer(&tex->buffer.b.b, level);
490bf215546Sopenharmony_ci      checked_last_layer = MIN2(last_layer, max_layer);
491bf215546Sopenharmony_ci
492bf215546Sopenharmony_ci      for (layer = first_layer; layer <= checked_last_layer; layer++) {
493bf215546Sopenharmony_ci         struct pipe_surface *cbsurf, surf_tmpl;
494bf215546Sopenharmony_ci
495bf215546Sopenharmony_ci         surf_tmpl.format = tex->buffer.b.b.format;
496bf215546Sopenharmony_ci         surf_tmpl.u.tex.level = level;
497bf215546Sopenharmony_ci         surf_tmpl.u.tex.first_layer = layer;
498bf215546Sopenharmony_ci         surf_tmpl.u.tex.last_layer = layer;
499bf215546Sopenharmony_ci         cbsurf = sctx->b.create_surface(&sctx->b, &tex->buffer.b.b, &surf_tmpl);
500bf215546Sopenharmony_ci
501bf215546Sopenharmony_ci         /* Required before and after FMASK and DCC_DECOMPRESS. */
502bf215546Sopenharmony_ci         if (custom_blend == sctx->custom_blend_fmask_decompress ||
503bf215546Sopenharmony_ci             custom_blend == sctx->custom_blend_dcc_decompress)
504bf215546Sopenharmony_ci            sctx->flags |= SI_CONTEXT_FLUSH_AND_INV_CB;
505bf215546Sopenharmony_ci
506bf215546Sopenharmony_ci         si_blitter_begin(sctx, SI_DECOMPRESS);
507bf215546Sopenharmony_ci         util_blitter_custom_color(sctx->blitter, cbsurf, custom_blend);
508bf215546Sopenharmony_ci         si_blitter_end(sctx);
509bf215546Sopenharmony_ci
510bf215546Sopenharmony_ci         if (custom_blend == sctx->custom_blend_fmask_decompress ||
511bf215546Sopenharmony_ci             custom_blend == sctx->custom_blend_dcc_decompress)
512bf215546Sopenharmony_ci            sctx->flags |= SI_CONTEXT_FLUSH_AND_INV_CB;
513bf215546Sopenharmony_ci
514bf215546Sopenharmony_ci         /* When running FMASK decompresion with DCC, we need to run the "eliminate fast clear" pass
515bf215546Sopenharmony_ci          * separately because FMASK decompression doesn't eliminate DCC fast clear. This makes
516bf215546Sopenharmony_ci          * render->texture transitions more expensive. It can be disabled by
517bf215546Sopenharmony_ci          * allow_dcc_msaa_clear_to_reg_for_bpp.
518bf215546Sopenharmony_ci          *
519bf215546Sopenharmony_ci          * TODO: When we get here, change the compression to TC-compatible on the next clear
520bf215546Sopenharmony_ci          *       to disable both the FMASK decompression and fast clear elimination passes.
521bf215546Sopenharmony_ci          */
522bf215546Sopenharmony_ci         if (sctx->screen->allow_dcc_msaa_clear_to_reg_for_bpp[util_logbase2(tex->surface.bpe)] &&
523bf215546Sopenharmony_ci             custom_blend == sctx->custom_blend_fmask_decompress &&
524bf215546Sopenharmony_ci             vi_dcc_enabled(tex, level)) {
525bf215546Sopenharmony_ci            si_blitter_begin(sctx, SI_DECOMPRESS);
526bf215546Sopenharmony_ci            util_blitter_custom_color(sctx->blitter, cbsurf, sctx->custom_blend_eliminate_fastclear);
527bf215546Sopenharmony_ci            si_blitter_end(sctx);
528bf215546Sopenharmony_ci         }
529bf215546Sopenharmony_ci
530bf215546Sopenharmony_ci         pipe_surface_reference(&cbsurf, NULL);
531bf215546Sopenharmony_ci      }
532bf215546Sopenharmony_ci
533bf215546Sopenharmony_ci      /* The texture will always be dirty if some layers aren't flushed.
534bf215546Sopenharmony_ci       * I don't think this case occurs often though. */
535bf215546Sopenharmony_ci      if (first_layer == 0 && last_layer >= max_layer) {
536bf215546Sopenharmony_ci         tex->dirty_level_mask &= ~(1 << level);
537bf215546Sopenharmony_ci      }
538bf215546Sopenharmony_ci   }
539bf215546Sopenharmony_ci
540bf215546Sopenharmony_ci   sctx->decompression_enabled = false;
541bf215546Sopenharmony_ci   si_make_CB_shader_coherent(sctx, tex->buffer.b.b.nr_samples, vi_dcc_enabled(tex, first_level),
542bf215546Sopenharmony_ci                              tex->surface.u.gfx9.color.dcc.pipe_aligned);
543bf215546Sopenharmony_ci
544bf215546Sopenharmony_ciexpand_fmask:
545bf215546Sopenharmony_ci   if (need_fmask_expand && tex->surface.fmask_offset && !tex->fmask_is_identity) {
546bf215546Sopenharmony_ci      assert(sctx->gfx_level < GFX11); /* no FMASK on gfx11 */
547bf215546Sopenharmony_ci      si_compute_expand_fmask(&sctx->b, &tex->buffer.b.b);
548bf215546Sopenharmony_ci      tex->fmask_is_identity = true;
549bf215546Sopenharmony_ci   }
550bf215546Sopenharmony_ci}
551bf215546Sopenharmony_ci
552bf215546Sopenharmony_cistatic void si_decompress_color_texture(struct si_context *sctx, struct si_texture *tex,
553bf215546Sopenharmony_ci                                        unsigned first_level, unsigned last_level,
554bf215546Sopenharmony_ci                                        bool need_fmask_expand)
555bf215546Sopenharmony_ci{
556bf215546Sopenharmony_ci   /* CMASK or DCC can be discarded and we can still end up here. */
557bf215546Sopenharmony_ci   if (!tex->cmask_buffer && !tex->surface.fmask_size &&
558bf215546Sopenharmony_ci       !vi_dcc_enabled(tex, first_level))
559bf215546Sopenharmony_ci      return;
560bf215546Sopenharmony_ci
561bf215546Sopenharmony_ci   si_blit_decompress_color(sctx, tex, first_level, last_level, 0,
562bf215546Sopenharmony_ci                            util_max_layer(&tex->buffer.b.b, first_level), false,
563bf215546Sopenharmony_ci                            need_fmask_expand);
564bf215546Sopenharmony_ci}
565bf215546Sopenharmony_ci
566bf215546Sopenharmony_cistatic void si_decompress_sampler_color_textures(struct si_context *sctx,
567bf215546Sopenharmony_ci                                                 struct si_samplers *textures)
568bf215546Sopenharmony_ci{
569bf215546Sopenharmony_ci   unsigned i;
570bf215546Sopenharmony_ci   unsigned mask = textures->needs_color_decompress_mask;
571bf215546Sopenharmony_ci
572bf215546Sopenharmony_ci   while (mask) {
573bf215546Sopenharmony_ci      struct pipe_sampler_view *view;
574bf215546Sopenharmony_ci      struct si_texture *tex;
575bf215546Sopenharmony_ci
576bf215546Sopenharmony_ci      i = u_bit_scan(&mask);
577bf215546Sopenharmony_ci
578bf215546Sopenharmony_ci      view = textures->views[i];
579bf215546Sopenharmony_ci      assert(view);
580bf215546Sopenharmony_ci
581bf215546Sopenharmony_ci      tex = (struct si_texture *)view->texture;
582bf215546Sopenharmony_ci
583bf215546Sopenharmony_ci      si_decompress_color_texture(sctx, tex, view->u.tex.first_level, view->u.tex.last_level,
584bf215546Sopenharmony_ci                                  false);
585bf215546Sopenharmony_ci   }
586bf215546Sopenharmony_ci}
587bf215546Sopenharmony_ci
588bf215546Sopenharmony_cistatic void si_decompress_image_color_textures(struct si_context *sctx, struct si_images *images)
589bf215546Sopenharmony_ci{
590bf215546Sopenharmony_ci   unsigned i;
591bf215546Sopenharmony_ci   unsigned mask = images->needs_color_decompress_mask;
592bf215546Sopenharmony_ci
593bf215546Sopenharmony_ci   while (mask) {
594bf215546Sopenharmony_ci      const struct pipe_image_view *view;
595bf215546Sopenharmony_ci      struct si_texture *tex;
596bf215546Sopenharmony_ci
597bf215546Sopenharmony_ci      i = u_bit_scan(&mask);
598bf215546Sopenharmony_ci
599bf215546Sopenharmony_ci      view = &images->views[i];
600bf215546Sopenharmony_ci      assert(view->resource->target != PIPE_BUFFER);
601bf215546Sopenharmony_ci
602bf215546Sopenharmony_ci      tex = (struct si_texture *)view->resource;
603bf215546Sopenharmony_ci
604bf215546Sopenharmony_ci      si_decompress_color_texture(sctx, tex, view->u.tex.level, view->u.tex.level,
605bf215546Sopenharmony_ci                                  view->access & PIPE_IMAGE_ACCESS_WRITE);
606bf215546Sopenharmony_ci   }
607bf215546Sopenharmony_ci}
608bf215546Sopenharmony_ci
609bf215546Sopenharmony_cistatic void si_check_render_feedback_texture(struct si_context *sctx, struct si_texture *tex,
610bf215546Sopenharmony_ci                                             unsigned first_level, unsigned last_level,
611bf215546Sopenharmony_ci                                             unsigned first_layer, unsigned last_layer)
612bf215546Sopenharmony_ci{
613bf215546Sopenharmony_ci   bool render_feedback = false;
614bf215546Sopenharmony_ci
615bf215546Sopenharmony_ci   if (!vi_dcc_enabled(tex, first_level))
616bf215546Sopenharmony_ci      return;
617bf215546Sopenharmony_ci
618bf215546Sopenharmony_ci   for (unsigned j = 0; j < sctx->framebuffer.state.nr_cbufs; ++j) {
619bf215546Sopenharmony_ci      struct si_surface *surf;
620bf215546Sopenharmony_ci
621bf215546Sopenharmony_ci      if (!sctx->framebuffer.state.cbufs[j])
622bf215546Sopenharmony_ci         continue;
623bf215546Sopenharmony_ci
624bf215546Sopenharmony_ci      surf = (struct si_surface *)sctx->framebuffer.state.cbufs[j];
625bf215546Sopenharmony_ci
626bf215546Sopenharmony_ci      if (tex == (struct si_texture *)surf->base.texture && surf->base.u.tex.level >= first_level &&
627bf215546Sopenharmony_ci          surf->base.u.tex.level <= last_level && surf->base.u.tex.first_layer <= last_layer &&
628bf215546Sopenharmony_ci          surf->base.u.tex.last_layer >= first_layer) {
629bf215546Sopenharmony_ci         render_feedback = true;
630bf215546Sopenharmony_ci         break;
631bf215546Sopenharmony_ci      }
632bf215546Sopenharmony_ci   }
633bf215546Sopenharmony_ci
634bf215546Sopenharmony_ci   if (render_feedback)
635bf215546Sopenharmony_ci      si_texture_disable_dcc(sctx, tex);
636bf215546Sopenharmony_ci}
637bf215546Sopenharmony_ci
638bf215546Sopenharmony_cistatic void si_check_render_feedback_textures(struct si_context *sctx, struct si_samplers *textures,
639bf215546Sopenharmony_ci                                              uint32_t in_use_mask)
640bf215546Sopenharmony_ci{
641bf215546Sopenharmony_ci   uint32_t mask = textures->enabled_mask & in_use_mask;
642bf215546Sopenharmony_ci
643bf215546Sopenharmony_ci   while (mask) {
644bf215546Sopenharmony_ci      const struct pipe_sampler_view *view;
645bf215546Sopenharmony_ci      struct si_texture *tex;
646bf215546Sopenharmony_ci
647bf215546Sopenharmony_ci      unsigned i = u_bit_scan(&mask);
648bf215546Sopenharmony_ci
649bf215546Sopenharmony_ci      view = textures->views[i];
650bf215546Sopenharmony_ci      if (view->texture->target == PIPE_BUFFER)
651bf215546Sopenharmony_ci         continue;
652bf215546Sopenharmony_ci
653bf215546Sopenharmony_ci      tex = (struct si_texture *)view->texture;
654bf215546Sopenharmony_ci
655bf215546Sopenharmony_ci      si_check_render_feedback_texture(sctx, tex, view->u.tex.first_level, view->u.tex.last_level,
656bf215546Sopenharmony_ci                                       view->u.tex.first_layer, view->u.tex.last_layer);
657bf215546Sopenharmony_ci   }
658bf215546Sopenharmony_ci}
659bf215546Sopenharmony_ci
660bf215546Sopenharmony_cistatic void si_check_render_feedback_images(struct si_context *sctx, struct si_images *images,
661bf215546Sopenharmony_ci                                            uint32_t in_use_mask)
662bf215546Sopenharmony_ci{
663bf215546Sopenharmony_ci   uint32_t mask = images->enabled_mask & in_use_mask;
664bf215546Sopenharmony_ci
665bf215546Sopenharmony_ci   while (mask) {
666bf215546Sopenharmony_ci      const struct pipe_image_view *view;
667bf215546Sopenharmony_ci      struct si_texture *tex;
668bf215546Sopenharmony_ci
669bf215546Sopenharmony_ci      unsigned i = u_bit_scan(&mask);
670bf215546Sopenharmony_ci
671bf215546Sopenharmony_ci      view = &images->views[i];
672bf215546Sopenharmony_ci      if (view->resource->target == PIPE_BUFFER)
673bf215546Sopenharmony_ci         continue;
674bf215546Sopenharmony_ci
675bf215546Sopenharmony_ci      tex = (struct si_texture *)view->resource;
676bf215546Sopenharmony_ci
677bf215546Sopenharmony_ci      si_check_render_feedback_texture(sctx, tex, view->u.tex.level, view->u.tex.level,
678bf215546Sopenharmony_ci                                       view->u.tex.first_layer, view->u.tex.last_layer);
679bf215546Sopenharmony_ci   }
680bf215546Sopenharmony_ci}
681bf215546Sopenharmony_ci
682bf215546Sopenharmony_cistatic void si_check_render_feedback_resident_textures(struct si_context *sctx)
683bf215546Sopenharmony_ci{
684bf215546Sopenharmony_ci   util_dynarray_foreach (&sctx->resident_tex_handles, struct si_texture_handle *, tex_handle) {
685bf215546Sopenharmony_ci      struct pipe_sampler_view *view;
686bf215546Sopenharmony_ci      struct si_texture *tex;
687bf215546Sopenharmony_ci
688bf215546Sopenharmony_ci      view = (*tex_handle)->view;
689bf215546Sopenharmony_ci      if (view->texture->target == PIPE_BUFFER)
690bf215546Sopenharmony_ci         continue;
691bf215546Sopenharmony_ci
692bf215546Sopenharmony_ci      tex = (struct si_texture *)view->texture;
693bf215546Sopenharmony_ci
694bf215546Sopenharmony_ci      si_check_render_feedback_texture(sctx, tex, view->u.tex.first_level, view->u.tex.last_level,
695bf215546Sopenharmony_ci                                       view->u.tex.first_layer, view->u.tex.last_layer);
696bf215546Sopenharmony_ci   }
697bf215546Sopenharmony_ci}
698bf215546Sopenharmony_ci
699bf215546Sopenharmony_cistatic void si_check_render_feedback_resident_images(struct si_context *sctx)
700bf215546Sopenharmony_ci{
701bf215546Sopenharmony_ci   util_dynarray_foreach (&sctx->resident_img_handles, struct si_image_handle *, img_handle) {
702bf215546Sopenharmony_ci      struct pipe_image_view *view;
703bf215546Sopenharmony_ci      struct si_texture *tex;
704bf215546Sopenharmony_ci
705bf215546Sopenharmony_ci      view = &(*img_handle)->view;
706bf215546Sopenharmony_ci      if (view->resource->target == PIPE_BUFFER)
707bf215546Sopenharmony_ci         continue;
708bf215546Sopenharmony_ci
709bf215546Sopenharmony_ci      tex = (struct si_texture *)view->resource;
710bf215546Sopenharmony_ci
711bf215546Sopenharmony_ci      si_check_render_feedback_texture(sctx, tex, view->u.tex.level, view->u.tex.level,
712bf215546Sopenharmony_ci                                       view->u.tex.first_layer, view->u.tex.last_layer);
713bf215546Sopenharmony_ci   }
714bf215546Sopenharmony_ci}
715bf215546Sopenharmony_ci
716bf215546Sopenharmony_cistatic void si_check_render_feedback(struct si_context *sctx)
717bf215546Sopenharmony_ci{
718bf215546Sopenharmony_ci   if (!sctx->need_check_render_feedback)
719bf215546Sopenharmony_ci      return;
720bf215546Sopenharmony_ci
721bf215546Sopenharmony_ci   /* There is no render feedback if color writes are disabled.
722bf215546Sopenharmony_ci    * (e.g. a pixel shader with image stores)
723bf215546Sopenharmony_ci    */
724bf215546Sopenharmony_ci   if (!si_get_total_colormask(sctx))
725bf215546Sopenharmony_ci      return;
726bf215546Sopenharmony_ci
727bf215546Sopenharmony_ci   for (int i = 0; i < SI_NUM_GRAPHICS_SHADERS; ++i) {
728bf215546Sopenharmony_ci      if (!sctx->shaders[i].cso)
729bf215546Sopenharmony_ci         continue;
730bf215546Sopenharmony_ci
731bf215546Sopenharmony_ci      struct si_shader_info *info = &sctx->shaders[i].cso->info;
732bf215546Sopenharmony_ci      si_check_render_feedback_images(sctx, &sctx->images[i],
733bf215546Sopenharmony_ci                                      u_bit_consecutive(0, info->base.num_images));
734bf215546Sopenharmony_ci      si_check_render_feedback_textures(sctx, &sctx->samplers[i],
735bf215546Sopenharmony_ci                                        info->base.textures_used[0]);
736bf215546Sopenharmony_ci   }
737bf215546Sopenharmony_ci
738bf215546Sopenharmony_ci   si_check_render_feedback_resident_images(sctx);
739bf215546Sopenharmony_ci   si_check_render_feedback_resident_textures(sctx);
740bf215546Sopenharmony_ci
741bf215546Sopenharmony_ci   sctx->need_check_render_feedback = false;
742bf215546Sopenharmony_ci}
743bf215546Sopenharmony_ci
744bf215546Sopenharmony_cistatic void si_decompress_resident_textures(struct si_context *sctx)
745bf215546Sopenharmony_ci{
746bf215546Sopenharmony_ci   util_dynarray_foreach (&sctx->resident_tex_needs_color_decompress, struct si_texture_handle *,
747bf215546Sopenharmony_ci                          tex_handle) {
748bf215546Sopenharmony_ci      struct pipe_sampler_view *view = (*tex_handle)->view;
749bf215546Sopenharmony_ci      struct si_texture *tex = (struct si_texture *)view->texture;
750bf215546Sopenharmony_ci
751bf215546Sopenharmony_ci      si_decompress_color_texture(sctx, tex, view->u.tex.first_level, view->u.tex.last_level,
752bf215546Sopenharmony_ci                                  false);
753bf215546Sopenharmony_ci   }
754bf215546Sopenharmony_ci
755bf215546Sopenharmony_ci   util_dynarray_foreach (&sctx->resident_tex_needs_depth_decompress, struct si_texture_handle *,
756bf215546Sopenharmony_ci                          tex_handle) {
757bf215546Sopenharmony_ci      struct pipe_sampler_view *view = (*tex_handle)->view;
758bf215546Sopenharmony_ci      struct si_sampler_view *sview = (struct si_sampler_view *)view;
759bf215546Sopenharmony_ci      struct si_texture *tex = (struct si_texture *)view->texture;
760bf215546Sopenharmony_ci
761bf215546Sopenharmony_ci      si_decompress_depth(sctx, tex, sview->is_stencil_sampler ? PIPE_MASK_S : PIPE_MASK_Z,
762bf215546Sopenharmony_ci                          view->u.tex.first_level, view->u.tex.last_level, 0,
763bf215546Sopenharmony_ci                          util_max_layer(&tex->buffer.b.b, view->u.tex.first_level));
764bf215546Sopenharmony_ci   }
765bf215546Sopenharmony_ci}
766bf215546Sopenharmony_ci
767bf215546Sopenharmony_cistatic void si_decompress_resident_images(struct si_context *sctx)
768bf215546Sopenharmony_ci{
769bf215546Sopenharmony_ci   util_dynarray_foreach (&sctx->resident_img_needs_color_decompress, struct si_image_handle *,
770bf215546Sopenharmony_ci                          img_handle) {
771bf215546Sopenharmony_ci      struct pipe_image_view *view = &(*img_handle)->view;
772bf215546Sopenharmony_ci      struct si_texture *tex = (struct si_texture *)view->resource;
773bf215546Sopenharmony_ci
774bf215546Sopenharmony_ci      si_decompress_color_texture(sctx, tex, view->u.tex.level, view->u.tex.level,
775bf215546Sopenharmony_ci                                  view->access & PIPE_IMAGE_ACCESS_WRITE);
776bf215546Sopenharmony_ci   }
777bf215546Sopenharmony_ci}
778bf215546Sopenharmony_ci
779bf215546Sopenharmony_civoid si_decompress_textures(struct si_context *sctx, unsigned shader_mask)
780bf215546Sopenharmony_ci{
781bf215546Sopenharmony_ci   unsigned compressed_colortex_counter, mask;
782bf215546Sopenharmony_ci   bool need_flush = false;
783bf215546Sopenharmony_ci
784bf215546Sopenharmony_ci   if (sctx->blitter_running)
785bf215546Sopenharmony_ci      return;
786bf215546Sopenharmony_ci
787bf215546Sopenharmony_ci   /* Update the compressed_colortex_mask if necessary. */
788bf215546Sopenharmony_ci   compressed_colortex_counter = p_atomic_read(&sctx->screen->compressed_colortex_counter);
789bf215546Sopenharmony_ci   if (compressed_colortex_counter != sctx->last_compressed_colortex_counter) {
790bf215546Sopenharmony_ci      sctx->last_compressed_colortex_counter = compressed_colortex_counter;
791bf215546Sopenharmony_ci      si_update_needs_color_decompress_masks(sctx);
792bf215546Sopenharmony_ci   }
793bf215546Sopenharmony_ci
794bf215546Sopenharmony_ci   /* Decompress color & depth textures if needed. */
795bf215546Sopenharmony_ci   mask = sctx->shader_needs_decompress_mask & shader_mask;
796bf215546Sopenharmony_ci   while (mask) {
797bf215546Sopenharmony_ci      unsigned i = u_bit_scan(&mask);
798bf215546Sopenharmony_ci
799bf215546Sopenharmony_ci      if (sctx->samplers[i].needs_depth_decompress_mask) {
800bf215546Sopenharmony_ci         need_flush |= si_decompress_sampler_depth_textures(sctx, &sctx->samplers[i]);
801bf215546Sopenharmony_ci      }
802bf215546Sopenharmony_ci      if (sctx->samplers[i].needs_color_decompress_mask) {
803bf215546Sopenharmony_ci         si_decompress_sampler_color_textures(sctx, &sctx->samplers[i]);
804bf215546Sopenharmony_ci      }
805bf215546Sopenharmony_ci      if (sctx->images[i].needs_color_decompress_mask) {
806bf215546Sopenharmony_ci         si_decompress_image_color_textures(sctx, &sctx->images[i]);
807bf215546Sopenharmony_ci      }
808bf215546Sopenharmony_ci   }
809bf215546Sopenharmony_ci
810bf215546Sopenharmony_ci   if (sctx->gfx_level == GFX10_3 && need_flush) {
811bf215546Sopenharmony_ci      /* This fixes a corruption with the following sequence:
812bf215546Sopenharmony_ci       *   - fast clear depth
813bf215546Sopenharmony_ci       *   - decompress depth
814bf215546Sopenharmony_ci       *   - draw
815bf215546Sopenharmony_ci       * (see https://gitlab.freedesktop.org/drm/amd/-/issues/1810#note_1170171)
816bf215546Sopenharmony_ci       */
817bf215546Sopenharmony_ci      sctx->b.flush(&sctx->b, NULL, RADEON_FLUSH_ASYNC_START_NEXT_GFX_IB_NOW);
818bf215546Sopenharmony_ci   }
819bf215546Sopenharmony_ci
820bf215546Sopenharmony_ci   if (shader_mask & u_bit_consecutive(0, SI_NUM_GRAPHICS_SHADERS)) {
821bf215546Sopenharmony_ci      if (sctx->uses_bindless_samplers)
822bf215546Sopenharmony_ci         si_decompress_resident_textures(sctx);
823bf215546Sopenharmony_ci      if (sctx->uses_bindless_images)
824bf215546Sopenharmony_ci         si_decompress_resident_images(sctx);
825bf215546Sopenharmony_ci
826bf215546Sopenharmony_ci      if (sctx->ps_uses_fbfetch) {
827bf215546Sopenharmony_ci         struct pipe_surface *cb0 = sctx->framebuffer.state.cbufs[0];
828bf215546Sopenharmony_ci         si_decompress_color_texture(sctx, (struct si_texture *)cb0->texture,
829bf215546Sopenharmony_ci                                     cb0->u.tex.first_layer, cb0->u.tex.last_layer, false);
830bf215546Sopenharmony_ci      }
831bf215546Sopenharmony_ci
832bf215546Sopenharmony_ci      si_check_render_feedback(sctx);
833bf215546Sopenharmony_ci   } else if (shader_mask & (1 << PIPE_SHADER_COMPUTE)) {
834bf215546Sopenharmony_ci      if (sctx->cs_shader_state.program->sel.info.uses_bindless_samplers)
835bf215546Sopenharmony_ci         si_decompress_resident_textures(sctx);
836bf215546Sopenharmony_ci      if (sctx->cs_shader_state.program->sel.info.uses_bindless_images)
837bf215546Sopenharmony_ci         si_decompress_resident_images(sctx);
838bf215546Sopenharmony_ci   }
839bf215546Sopenharmony_ci}
840bf215546Sopenharmony_ci
841bf215546Sopenharmony_ci/* Helper for decompressing a portion of a color or depth resource before
842bf215546Sopenharmony_ci * blitting if any decompression is needed.
843bf215546Sopenharmony_ci * The driver doesn't decompress resources automatically while u_blitter is
844bf215546Sopenharmony_ci * rendering. */
845bf215546Sopenharmony_civoid si_decompress_subresource(struct pipe_context *ctx, struct pipe_resource *tex, unsigned planes,
846bf215546Sopenharmony_ci                               unsigned level, unsigned first_layer, unsigned last_layer,
847bf215546Sopenharmony_ci                               bool need_fmask_expand)
848bf215546Sopenharmony_ci{
849bf215546Sopenharmony_ci   struct si_context *sctx = (struct si_context *)ctx;
850bf215546Sopenharmony_ci   struct si_texture *stex = (struct si_texture *)tex;
851bf215546Sopenharmony_ci
852bf215546Sopenharmony_ci   if (stex->db_compatible) {
853bf215546Sopenharmony_ci      planes &= PIPE_MASK_Z | PIPE_MASK_S;
854bf215546Sopenharmony_ci
855bf215546Sopenharmony_ci      if (!stex->surface.has_stencil)
856bf215546Sopenharmony_ci         planes &= ~PIPE_MASK_S;
857bf215546Sopenharmony_ci
858bf215546Sopenharmony_ci      /* If we've rendered into the framebuffer and it's a blitting
859bf215546Sopenharmony_ci       * source, make sure the decompression pass is invoked
860bf215546Sopenharmony_ci       * by dirtying the framebuffer.
861bf215546Sopenharmony_ci       */
862bf215546Sopenharmony_ci      if (sctx->framebuffer.state.zsbuf && sctx->framebuffer.state.zsbuf->u.tex.level == level &&
863bf215546Sopenharmony_ci          sctx->framebuffer.state.zsbuf->texture == tex)
864bf215546Sopenharmony_ci         si_update_fb_dirtiness_after_rendering(sctx);
865bf215546Sopenharmony_ci
866bf215546Sopenharmony_ci      si_decompress_depth(sctx, stex, planes, level, level, first_layer, last_layer);
867bf215546Sopenharmony_ci   } else if (stex->surface.fmask_size || stex->cmask_buffer ||
868bf215546Sopenharmony_ci              vi_dcc_enabled(stex, level)) {
869bf215546Sopenharmony_ci      /* If we've rendered into the framebuffer and it's a blitting
870bf215546Sopenharmony_ci       * source, make sure the decompression pass is invoked
871bf215546Sopenharmony_ci       * by dirtying the framebuffer.
872bf215546Sopenharmony_ci       */
873bf215546Sopenharmony_ci      for (unsigned i = 0; i < sctx->framebuffer.state.nr_cbufs; i++) {
874bf215546Sopenharmony_ci         if (sctx->framebuffer.state.cbufs[i] &&
875bf215546Sopenharmony_ci             sctx->framebuffer.state.cbufs[i]->u.tex.level == level &&
876bf215546Sopenharmony_ci             sctx->framebuffer.state.cbufs[i]->texture == tex) {
877bf215546Sopenharmony_ci            si_update_fb_dirtiness_after_rendering(sctx);
878bf215546Sopenharmony_ci            break;
879bf215546Sopenharmony_ci         }
880bf215546Sopenharmony_ci      }
881bf215546Sopenharmony_ci
882bf215546Sopenharmony_ci      si_blit_decompress_color(sctx, stex, level, level, first_layer, last_layer, false,
883bf215546Sopenharmony_ci                               need_fmask_expand);
884bf215546Sopenharmony_ci   }
885bf215546Sopenharmony_ci}
886bf215546Sopenharmony_ci
887bf215546Sopenharmony_cistruct texture_orig_info {
888bf215546Sopenharmony_ci   unsigned format;
889bf215546Sopenharmony_ci   unsigned width0;
890bf215546Sopenharmony_ci   unsigned height0;
891bf215546Sopenharmony_ci   unsigned npix_x;
892bf215546Sopenharmony_ci   unsigned npix_y;
893bf215546Sopenharmony_ci   unsigned npix0_x;
894bf215546Sopenharmony_ci   unsigned npix0_y;
895bf215546Sopenharmony_ci};
896bf215546Sopenharmony_ci
897bf215546Sopenharmony_civoid si_resource_copy_region(struct pipe_context *ctx, struct pipe_resource *dst,
898bf215546Sopenharmony_ci                             unsigned dst_level, unsigned dstx, unsigned dsty, unsigned dstz,
899bf215546Sopenharmony_ci                             struct pipe_resource *src, unsigned src_level,
900bf215546Sopenharmony_ci                             const struct pipe_box *src_box)
901bf215546Sopenharmony_ci{
902bf215546Sopenharmony_ci   struct si_context *sctx = (struct si_context *)ctx;
903bf215546Sopenharmony_ci   struct si_texture *ssrc = (struct si_texture *)src;
904bf215546Sopenharmony_ci   struct pipe_surface *dst_view, dst_templ;
905bf215546Sopenharmony_ci   struct pipe_sampler_view src_templ, *src_view;
906bf215546Sopenharmony_ci   struct pipe_box dstbox;
907bf215546Sopenharmony_ci
908bf215546Sopenharmony_ci   /* Handle buffers first. */
909bf215546Sopenharmony_ci   if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) {
910bf215546Sopenharmony_ci      si_copy_buffer(sctx, dst, src, dstx, src_box->x, src_box->width, SI_OP_SYNC_BEFORE_AFTER);
911bf215546Sopenharmony_ci      return;
912bf215546Sopenharmony_ci   }
913bf215546Sopenharmony_ci
914bf215546Sopenharmony_ci   if (si_compute_copy_image(sctx, dst, dst_level, src, src_level, dstx, dsty, dstz,
915bf215546Sopenharmony_ci                             src_box, SI_OP_SYNC_BEFORE_AFTER))
916bf215546Sopenharmony_ci      return;
917bf215546Sopenharmony_ci
918bf215546Sopenharmony_ci   assert(u_max_sample(dst) == u_max_sample(src));
919bf215546Sopenharmony_ci
920bf215546Sopenharmony_ci   /* The driver doesn't decompress resources automatically while
921bf215546Sopenharmony_ci    * u_blitter is rendering. */
922bf215546Sopenharmony_ci   si_decompress_subresource(ctx, src, PIPE_MASK_RGBAZS, src_level, src_box->z,
923bf215546Sopenharmony_ci                             src_box->z + src_box->depth - 1, false);
924bf215546Sopenharmony_ci
925bf215546Sopenharmony_ci   util_blitter_default_dst_texture(&dst_templ, dst, dst_level, dstz);
926bf215546Sopenharmony_ci   util_blitter_default_src_texture(sctx->blitter, &src_templ, src, src_level);
927bf215546Sopenharmony_ci
928bf215546Sopenharmony_ci   assert(!util_format_is_compressed(src->format) && !util_format_is_compressed(dst->format));
929bf215546Sopenharmony_ci   assert(!util_format_is_subsampled_422(src->format));
930bf215546Sopenharmony_ci
931bf215546Sopenharmony_ci   if (!util_blitter_is_copy_supported(sctx->blitter, dst, src)) {
932bf215546Sopenharmony_ci      switch (ssrc->surface.bpe) {
933bf215546Sopenharmony_ci      case 1:
934bf215546Sopenharmony_ci         dst_templ.format = PIPE_FORMAT_R8_UNORM;
935bf215546Sopenharmony_ci         src_templ.format = PIPE_FORMAT_R8_UNORM;
936bf215546Sopenharmony_ci         break;
937bf215546Sopenharmony_ci      case 2:
938bf215546Sopenharmony_ci         dst_templ.format = PIPE_FORMAT_R8G8_UNORM;
939bf215546Sopenharmony_ci         src_templ.format = PIPE_FORMAT_R8G8_UNORM;
940bf215546Sopenharmony_ci         break;
941bf215546Sopenharmony_ci      case 4:
942bf215546Sopenharmony_ci         dst_templ.format = PIPE_FORMAT_R8G8B8A8_UNORM;
943bf215546Sopenharmony_ci         src_templ.format = PIPE_FORMAT_R8G8B8A8_UNORM;
944bf215546Sopenharmony_ci         break;
945bf215546Sopenharmony_ci      case 8:
946bf215546Sopenharmony_ci         dst_templ.format = PIPE_FORMAT_R16G16B16A16_UINT;
947bf215546Sopenharmony_ci         src_templ.format = PIPE_FORMAT_R16G16B16A16_UINT;
948bf215546Sopenharmony_ci         break;
949bf215546Sopenharmony_ci      case 16:
950bf215546Sopenharmony_ci         dst_templ.format = PIPE_FORMAT_R32G32B32A32_UINT;
951bf215546Sopenharmony_ci         src_templ.format = PIPE_FORMAT_R32G32B32A32_UINT;
952bf215546Sopenharmony_ci         break;
953bf215546Sopenharmony_ci      default:
954bf215546Sopenharmony_ci         fprintf(stderr, "Unhandled format %s with blocksize %u\n",
955bf215546Sopenharmony_ci                 util_format_short_name(src->format), ssrc->surface.bpe);
956bf215546Sopenharmony_ci         assert(0);
957bf215546Sopenharmony_ci      }
958bf215546Sopenharmony_ci   }
959bf215546Sopenharmony_ci
960bf215546Sopenharmony_ci   /* SNORM blitting has precision issues on some chips. Use the SINT
961bf215546Sopenharmony_ci    * equivalent instead, which doesn't force DCC decompression.
962bf215546Sopenharmony_ci    */
963bf215546Sopenharmony_ci   if (util_format_is_snorm(dst_templ.format)) {
964bf215546Sopenharmony_ci      dst_templ.format = src_templ.format = util_format_snorm_to_sint(dst_templ.format);
965bf215546Sopenharmony_ci   }
966bf215546Sopenharmony_ci
967bf215546Sopenharmony_ci   vi_disable_dcc_if_incompatible_format(sctx, dst, dst_level, dst_templ.format);
968bf215546Sopenharmony_ci   vi_disable_dcc_if_incompatible_format(sctx, src, src_level, src_templ.format);
969bf215546Sopenharmony_ci
970bf215546Sopenharmony_ci   /* Initialize the surface. */
971bf215546Sopenharmony_ci   dst_view = ctx->create_surface(ctx, dst, &dst_templ);
972bf215546Sopenharmony_ci
973bf215546Sopenharmony_ci   /* Initialize the sampler view. */
974bf215546Sopenharmony_ci   src_view = ctx->create_sampler_view(ctx, src, &src_templ);
975bf215546Sopenharmony_ci
976bf215546Sopenharmony_ci   u_box_3d(dstx, dsty, dstz, abs(src_box->width), abs(src_box->height), abs(src_box->depth),
977bf215546Sopenharmony_ci            &dstbox);
978bf215546Sopenharmony_ci
979bf215546Sopenharmony_ci   /* Copy. */
980bf215546Sopenharmony_ci   si_blitter_begin(sctx, SI_COPY);
981bf215546Sopenharmony_ci   util_blitter_blit_generic(sctx->blitter, dst_view, &dstbox, src_view, src_box, src->width0,
982bf215546Sopenharmony_ci                             src->height0, PIPE_MASK_RGBAZS, PIPE_TEX_FILTER_NEAREST, NULL,
983bf215546Sopenharmony_ci                             false, false, 0);
984bf215546Sopenharmony_ci   si_blitter_end(sctx);
985bf215546Sopenharmony_ci
986bf215546Sopenharmony_ci   pipe_surface_reference(&dst_view, NULL);
987bf215546Sopenharmony_ci   pipe_sampler_view_reference(&src_view, NULL);
988bf215546Sopenharmony_ci}
989bf215546Sopenharmony_ci
990bf215546Sopenharmony_cistatic void si_do_CB_resolve(struct si_context *sctx, const struct pipe_blit_info *info,
991bf215546Sopenharmony_ci                             struct pipe_resource *dst, unsigned dst_level, unsigned dst_z,
992bf215546Sopenharmony_ci                             enum pipe_format format)
993bf215546Sopenharmony_ci{
994bf215546Sopenharmony_ci   /* Required before and after CB_RESOLVE. */
995bf215546Sopenharmony_ci   sctx->flags |= SI_CONTEXT_FLUSH_AND_INV_CB;
996bf215546Sopenharmony_ci
997bf215546Sopenharmony_ci   si_blitter_begin(
998bf215546Sopenharmony_ci      sctx, SI_COLOR_RESOLVE | (info->render_condition_enable ? 0 : SI_DISABLE_RENDER_COND));
999bf215546Sopenharmony_ci   util_blitter_custom_resolve_color(sctx->blitter, dst, dst_level, dst_z, info->src.resource,
1000bf215546Sopenharmony_ci                                     info->src.box.z, ~0, sctx->custom_blend_resolve, format);
1001bf215546Sopenharmony_ci   si_blitter_end(sctx);
1002bf215546Sopenharmony_ci
1003bf215546Sopenharmony_ci   /* Flush caches for possible texturing. */
1004bf215546Sopenharmony_ci   si_make_CB_shader_coherent(sctx, 1, false, true /* no DCC */);
1005bf215546Sopenharmony_ci}
1006bf215546Sopenharmony_ci
1007bf215546Sopenharmony_cistatic bool resolve_formats_compatible(enum pipe_format src, enum pipe_format dst,
1008bf215546Sopenharmony_ci                                       bool src_swaps_rgb_to_bgr, bool *need_rgb_to_bgr)
1009bf215546Sopenharmony_ci{
1010bf215546Sopenharmony_ci   *need_rgb_to_bgr = false;
1011bf215546Sopenharmony_ci
1012bf215546Sopenharmony_ci   if (src_swaps_rgb_to_bgr) {
1013bf215546Sopenharmony_ci      /* We must only check the swapped format. */
1014bf215546Sopenharmony_ci      enum pipe_format swapped_src = util_format_rgb_to_bgr(src);
1015bf215546Sopenharmony_ci      assert(swapped_src);
1016bf215546Sopenharmony_ci      return util_is_format_compatible(util_format_description(swapped_src),
1017bf215546Sopenharmony_ci                                       util_format_description(dst));
1018bf215546Sopenharmony_ci   }
1019bf215546Sopenharmony_ci
1020bf215546Sopenharmony_ci   if (util_is_format_compatible(util_format_description(src), util_format_description(dst)))
1021bf215546Sopenharmony_ci      return true;
1022bf215546Sopenharmony_ci
1023bf215546Sopenharmony_ci   enum pipe_format swapped_src = util_format_rgb_to_bgr(src);
1024bf215546Sopenharmony_ci   *need_rgb_to_bgr = util_is_format_compatible(util_format_description(swapped_src),
1025bf215546Sopenharmony_ci                                                util_format_description(dst));
1026bf215546Sopenharmony_ci   return *need_rgb_to_bgr;
1027bf215546Sopenharmony_ci}
1028bf215546Sopenharmony_ci
1029bf215546Sopenharmony_cibool si_msaa_resolve_blit_via_CB(struct pipe_context *ctx, const struct pipe_blit_info *info)
1030bf215546Sopenharmony_ci{
1031bf215546Sopenharmony_ci   struct si_context *sctx = (struct si_context *)ctx;
1032bf215546Sopenharmony_ci
1033bf215546Sopenharmony_ci   /* Gfx11 doesn't have CB_RESOLVE. */
1034bf215546Sopenharmony_ci   if (sctx->gfx_level >= GFX11)
1035bf215546Sopenharmony_ci      return false;
1036bf215546Sopenharmony_ci
1037bf215546Sopenharmony_ci   struct si_texture *src = (struct si_texture *)info->src.resource;
1038bf215546Sopenharmony_ci   struct si_texture *dst = (struct si_texture *)info->dst.resource;
1039bf215546Sopenharmony_ci   ASSERTED struct si_texture *stmp;
1040bf215546Sopenharmony_ci   unsigned dst_width = u_minify(info->dst.resource->width0, info->dst.level);
1041bf215546Sopenharmony_ci   unsigned dst_height = u_minify(info->dst.resource->height0, info->dst.level);
1042bf215546Sopenharmony_ci   enum pipe_format format = info->src.format;
1043bf215546Sopenharmony_ci   struct pipe_resource *tmp, templ;
1044bf215546Sopenharmony_ci   struct pipe_blit_info blit;
1045bf215546Sopenharmony_ci
1046bf215546Sopenharmony_ci   /* Gfx11 doesn't have CB_RESOLVE. */
1047bf215546Sopenharmony_ci   if (sctx->gfx_level >= GFX11)
1048bf215546Sopenharmony_ci      return false;
1049bf215546Sopenharmony_ci
1050bf215546Sopenharmony_ci   /* Check basic requirements for hw resolve. */
1051bf215546Sopenharmony_ci   if (!(info->src.resource->nr_samples > 1 && info->dst.resource->nr_samples <= 1 &&
1052bf215546Sopenharmony_ci         !util_format_is_pure_integer(format) && !util_format_is_depth_or_stencil(format) &&
1053bf215546Sopenharmony_ci         util_max_layer(info->src.resource, 0) == 0))
1054bf215546Sopenharmony_ci      return false;
1055bf215546Sopenharmony_ci
1056bf215546Sopenharmony_ci   /* Hardware MSAA resolve doesn't work if SPI format = NORM16_ABGR and
1057bf215546Sopenharmony_ci    * the format is R16G16. Use R16A16, which does work.
1058bf215546Sopenharmony_ci    */
1059bf215546Sopenharmony_ci   if (format == PIPE_FORMAT_R16G16_UNORM)
1060bf215546Sopenharmony_ci      format = PIPE_FORMAT_R16A16_UNORM;
1061bf215546Sopenharmony_ci   if (format == PIPE_FORMAT_R16G16_SNORM)
1062bf215546Sopenharmony_ci      format = PIPE_FORMAT_R16A16_SNORM;
1063bf215546Sopenharmony_ci
1064bf215546Sopenharmony_ci   bool need_rgb_to_bgr = false;
1065bf215546Sopenharmony_ci
1066bf215546Sopenharmony_ci   /* Check the remaining requirements for hw resolve. */
1067bf215546Sopenharmony_ci   if (util_max_layer(info->dst.resource, info->dst.level) == 0 && !info->scissor_enable &&
1068bf215546Sopenharmony_ci       (info->mask & PIPE_MASK_RGBA) == PIPE_MASK_RGBA &&
1069bf215546Sopenharmony_ci       resolve_formats_compatible(info->src.format, info->dst.format,
1070bf215546Sopenharmony_ci                                  src->swap_rgb_to_bgr, &need_rgb_to_bgr) &&
1071bf215546Sopenharmony_ci       dst_width == info->src.resource->width0 && dst_height == info->src.resource->height0 &&
1072bf215546Sopenharmony_ci       info->dst.box.x == 0 && info->dst.box.y == 0 && info->dst.box.width == dst_width &&
1073bf215546Sopenharmony_ci       info->dst.box.height == dst_height && info->dst.box.depth == 1 && info->src.box.x == 0 &&
1074bf215546Sopenharmony_ci       info->src.box.y == 0 && info->src.box.width == dst_width &&
1075bf215546Sopenharmony_ci       info->src.box.height == dst_height && info->src.box.depth == 1 && !dst->surface.is_linear &&
1076bf215546Sopenharmony_ci       (!dst->cmask_buffer || !dst->dirty_level_mask)) { /* dst cannot be fast-cleared */
1077bf215546Sopenharmony_ci      /* Check the remaining constraints. */
1078bf215546Sopenharmony_ci      if (src->surface.micro_tile_mode != dst->surface.micro_tile_mode ||
1079bf215546Sopenharmony_ci          need_rgb_to_bgr) {
1080bf215546Sopenharmony_ci         /* The next fast clear will switch to this mode to
1081bf215546Sopenharmony_ci          * get direct hw resolve next time if the mode is
1082bf215546Sopenharmony_ci          * different now.
1083bf215546Sopenharmony_ci          *
1084bf215546Sopenharmony_ci          * TODO-GFX10: This does not work in GFX10 because MSAA
1085bf215546Sopenharmony_ci          * is restricted to 64KB_R_X and 64KB_Z_X swizzle modes.
1086bf215546Sopenharmony_ci          * In some cases we could change the swizzle of the
1087bf215546Sopenharmony_ci          * destination texture instead, but the more general
1088bf215546Sopenharmony_ci          * solution is to implement compute shader resolve.
1089bf215546Sopenharmony_ci          */
1090bf215546Sopenharmony_ci         if (src->surface.micro_tile_mode != dst->surface.micro_tile_mode)
1091bf215546Sopenharmony_ci            src->last_msaa_resolve_target_micro_mode = dst->surface.micro_tile_mode;
1092bf215546Sopenharmony_ci         if (need_rgb_to_bgr)
1093bf215546Sopenharmony_ci            src->swap_rgb_to_bgr_on_next_clear = true;
1094bf215546Sopenharmony_ci
1095bf215546Sopenharmony_ci         goto resolve_to_temp;
1096bf215546Sopenharmony_ci      }
1097bf215546Sopenharmony_ci
1098bf215546Sopenharmony_ci      /* Resolving into a surface with DCC is unsupported. Since
1099bf215546Sopenharmony_ci       * it's being overwritten anyway, clear it to uncompressed.
1100bf215546Sopenharmony_ci       * This is still the fastest codepath even with this clear.
1101bf215546Sopenharmony_ci       */
1102bf215546Sopenharmony_ci      if (vi_dcc_enabled(dst, info->dst.level)) {
1103bf215546Sopenharmony_ci         struct si_clear_info clear_info;
1104bf215546Sopenharmony_ci
1105bf215546Sopenharmony_ci         if (!vi_dcc_get_clear_info(sctx, dst, info->dst.level, DCC_UNCOMPRESSED, &clear_info))
1106bf215546Sopenharmony_ci            goto resolve_to_temp;
1107bf215546Sopenharmony_ci
1108bf215546Sopenharmony_ci         si_execute_clears(sctx, &clear_info, 1, SI_CLEAR_TYPE_DCC);
1109bf215546Sopenharmony_ci         dst->dirty_level_mask &= ~(1 << info->dst.level);
1110bf215546Sopenharmony_ci      }
1111bf215546Sopenharmony_ci
1112bf215546Sopenharmony_ci      /* Resolve directly from src to dst. */
1113bf215546Sopenharmony_ci      si_do_CB_resolve(sctx, info, info->dst.resource, info->dst.level, info->dst.box.z, format);
1114bf215546Sopenharmony_ci      return true;
1115bf215546Sopenharmony_ci   }
1116bf215546Sopenharmony_ci
1117bf215546Sopenharmony_ciresolve_to_temp:
1118bf215546Sopenharmony_ci   /* Shader-based resolve is VERY SLOW. Instead, resolve into
1119bf215546Sopenharmony_ci    * a temporary texture and blit.
1120bf215546Sopenharmony_ci    */
1121bf215546Sopenharmony_ci   memset(&templ, 0, sizeof(templ));
1122bf215546Sopenharmony_ci   templ.target = PIPE_TEXTURE_2D;
1123bf215546Sopenharmony_ci   templ.format = info->src.resource->format;
1124bf215546Sopenharmony_ci   templ.width0 = info->src.resource->width0;
1125bf215546Sopenharmony_ci   templ.height0 = info->src.resource->height0;
1126bf215546Sopenharmony_ci   templ.depth0 = 1;
1127bf215546Sopenharmony_ci   templ.array_size = 1;
1128bf215546Sopenharmony_ci   templ.usage = PIPE_USAGE_DEFAULT;
1129bf215546Sopenharmony_ci   templ.flags = SI_RESOURCE_FLAG_FORCE_MSAA_TILING | SI_RESOURCE_FLAG_FORCE_MICRO_TILE_MODE |
1130bf215546Sopenharmony_ci                 SI_RESOURCE_FLAG_MICRO_TILE_MODE_SET(src->surface.micro_tile_mode) |
1131bf215546Sopenharmony_ci                 SI_RESOURCE_FLAG_DISABLE_DCC | SI_RESOURCE_FLAG_DRIVER_INTERNAL;
1132bf215546Sopenharmony_ci
1133bf215546Sopenharmony_ci   /* The src and dst microtile modes must be the same. */
1134bf215546Sopenharmony_ci   if (sctx->gfx_level <= GFX8 && src->surface.micro_tile_mode == RADEON_MICRO_MODE_DISPLAY)
1135bf215546Sopenharmony_ci      templ.bind = PIPE_BIND_SCANOUT;
1136bf215546Sopenharmony_ci   else
1137bf215546Sopenharmony_ci      templ.bind = 0;
1138bf215546Sopenharmony_ci
1139bf215546Sopenharmony_ci   tmp = ctx->screen->resource_create(ctx->screen, &templ);
1140bf215546Sopenharmony_ci   if (!tmp)
1141bf215546Sopenharmony_ci      return false;
1142bf215546Sopenharmony_ci   stmp = (struct si_texture *)tmp;
1143bf215546Sopenharmony_ci   /* Match the channel order of src. */
1144bf215546Sopenharmony_ci   stmp->swap_rgb_to_bgr = src->swap_rgb_to_bgr;
1145bf215546Sopenharmony_ci
1146bf215546Sopenharmony_ci   assert(!stmp->surface.is_linear);
1147bf215546Sopenharmony_ci   assert(src->surface.micro_tile_mode == stmp->surface.micro_tile_mode);
1148bf215546Sopenharmony_ci
1149bf215546Sopenharmony_ci   /* resolve */
1150bf215546Sopenharmony_ci   si_do_CB_resolve(sctx, info, tmp, 0, 0, format);
1151bf215546Sopenharmony_ci
1152bf215546Sopenharmony_ci   /* blit */
1153bf215546Sopenharmony_ci   blit = *info;
1154bf215546Sopenharmony_ci   blit.src.resource = tmp;
1155bf215546Sopenharmony_ci   blit.src.box.z = 0;
1156bf215546Sopenharmony_ci
1157bf215546Sopenharmony_ci   ctx->blit(ctx, &blit);
1158bf215546Sopenharmony_ci
1159bf215546Sopenharmony_ci   pipe_resource_reference(&tmp, NULL);
1160bf215546Sopenharmony_ci   return true;
1161bf215546Sopenharmony_ci}
1162bf215546Sopenharmony_ci
1163bf215546Sopenharmony_cistatic void si_blit(struct pipe_context *ctx, const struct pipe_blit_info *info)
1164bf215546Sopenharmony_ci{
1165bf215546Sopenharmony_ci   struct si_context *sctx = (struct si_context *)ctx;
1166bf215546Sopenharmony_ci   struct si_texture *sdst = (struct si_texture *)info->dst.resource;
1167bf215546Sopenharmony_ci
1168bf215546Sopenharmony_ci   if (sctx->gfx_level >= GFX7 &&
1169bf215546Sopenharmony_ci       (info->dst.resource->bind & PIPE_BIND_PRIME_BLIT_DST) && sdst->surface.is_linear &&
1170bf215546Sopenharmony_ci       /* Use SDMA or async compute when copying to a DRI_PRIME imported linear surface. */
1171bf215546Sopenharmony_ci       info->dst.box.x == 0 && info->dst.box.y == 0 && info->dst.box.z == 0 &&
1172bf215546Sopenharmony_ci       info->src.box.x == 0 && info->src.box.y == 0 && info->src.box.z == 0 &&
1173bf215546Sopenharmony_ci       info->dst.level == 0 && info->src.level == 0 &&
1174bf215546Sopenharmony_ci       info->src.box.width == info->dst.resource->width0 &&
1175bf215546Sopenharmony_ci       info->src.box.height == info->dst.resource->height0 &&
1176bf215546Sopenharmony_ci       info->src.box.depth == 1 &&
1177bf215546Sopenharmony_ci       util_can_blit_via_copy_region(info, true, sctx->render_cond != NULL)) {
1178bf215546Sopenharmony_ci      struct si_texture *ssrc = (struct si_texture *)info->src.resource;
1179bf215546Sopenharmony_ci
1180bf215546Sopenharmony_ci      /* Try SDMA first... */
1181bf215546Sopenharmony_ci      if (si_sdma_copy_image(sctx, sdst, ssrc))
1182bf215546Sopenharmony_ci         return;
1183bf215546Sopenharmony_ci
1184bf215546Sopenharmony_ci      /* ... and use async compute as the fallback. */
1185bf215546Sopenharmony_ci      struct si_screen *sscreen = sctx->screen;
1186bf215546Sopenharmony_ci
1187bf215546Sopenharmony_ci      simple_mtx_lock(&sscreen->async_compute_context_lock);
1188bf215546Sopenharmony_ci      if (!sscreen->async_compute_context)
1189bf215546Sopenharmony_ci         si_init_aux_async_compute_ctx(sscreen);
1190bf215546Sopenharmony_ci
1191bf215546Sopenharmony_ci      if (sscreen->async_compute_context) {
1192bf215546Sopenharmony_ci         si_compute_copy_image((struct si_context*)sctx->screen->async_compute_context,
1193bf215546Sopenharmony_ci                               info->dst.resource, 0, info->src.resource, 0, 0, 0, 0,
1194bf215546Sopenharmony_ci                               &info->src.box, 0);
1195bf215546Sopenharmony_ci         si_flush_gfx_cs((struct si_context*)sctx->screen->async_compute_context, 0, NULL);
1196bf215546Sopenharmony_ci         simple_mtx_unlock(&sscreen->async_compute_context_lock);
1197bf215546Sopenharmony_ci         return;
1198bf215546Sopenharmony_ci      }
1199bf215546Sopenharmony_ci
1200bf215546Sopenharmony_ci      simple_mtx_unlock(&sscreen->async_compute_context_lock);
1201bf215546Sopenharmony_ci   }
1202bf215546Sopenharmony_ci
1203bf215546Sopenharmony_ci   if (unlikely(sctx->thread_trace_enabled))
1204bf215546Sopenharmony_ci      sctx->sqtt_next_event = EventCmdResolveImage;
1205bf215546Sopenharmony_ci
1206bf215546Sopenharmony_ci   if (si_msaa_resolve_blit_via_CB(ctx, info))
1207bf215546Sopenharmony_ci      return;
1208bf215546Sopenharmony_ci
1209bf215546Sopenharmony_ci   if (unlikely(sctx->thread_trace_enabled))
1210bf215546Sopenharmony_ci      sctx->sqtt_next_event = EventCmdCopyImage;
1211bf215546Sopenharmony_ci
1212bf215546Sopenharmony_ci   /* Using compute for copying to a linear texture in GTT is much faster than
1213bf215546Sopenharmony_ci    * going through RBs (render backends). This improves DRI PRIME performance.
1214bf215546Sopenharmony_ci    */
1215bf215546Sopenharmony_ci   if (util_can_blit_via_copy_region(info, false, sctx->render_cond != NULL)) {
1216bf215546Sopenharmony_ci      si_resource_copy_region(ctx, info->dst.resource, info->dst.level,
1217bf215546Sopenharmony_ci                              info->dst.box.x, info->dst.box.y, info->dst.box.z,
1218bf215546Sopenharmony_ci                              info->src.resource, info->src.level, &info->src.box);
1219bf215546Sopenharmony_ci      return;
1220bf215546Sopenharmony_ci   }
1221bf215546Sopenharmony_ci
1222bf215546Sopenharmony_ci   si_gfx_blit(ctx, info);
1223bf215546Sopenharmony_ci}
1224bf215546Sopenharmony_ci
1225bf215546Sopenharmony_civoid si_gfx_blit(struct pipe_context *ctx, const struct pipe_blit_info *info)
1226bf215546Sopenharmony_ci{
1227bf215546Sopenharmony_ci   struct si_context *sctx = (struct si_context *)ctx;
1228bf215546Sopenharmony_ci
1229bf215546Sopenharmony_ci   assert(util_blitter_is_blit_supported(sctx->blitter, info));
1230bf215546Sopenharmony_ci
1231bf215546Sopenharmony_ci   /* The driver doesn't decompress resources automatically while
1232bf215546Sopenharmony_ci    * u_blitter is rendering. */
1233bf215546Sopenharmony_ci   vi_disable_dcc_if_incompatible_format(sctx, info->src.resource, info->src.level,
1234bf215546Sopenharmony_ci                                         info->src.format);
1235bf215546Sopenharmony_ci   vi_disable_dcc_if_incompatible_format(sctx, info->dst.resource, info->dst.level,
1236bf215546Sopenharmony_ci                                         info->dst.format);
1237bf215546Sopenharmony_ci   si_decompress_subresource(ctx, info->src.resource, PIPE_MASK_RGBAZS, info->src.level,
1238bf215546Sopenharmony_ci                             info->src.box.z, info->src.box.z + info->src.box.depth - 1,
1239bf215546Sopenharmony_ci                             false);
1240bf215546Sopenharmony_ci
1241bf215546Sopenharmony_ci   if (unlikely(sctx->thread_trace_enabled))
1242bf215546Sopenharmony_ci      sctx->sqtt_next_event = EventCmdBlitImage;
1243bf215546Sopenharmony_ci
1244bf215546Sopenharmony_ci   si_blitter_begin(sctx, SI_BLIT | (info->render_condition_enable ? 0 : SI_DISABLE_RENDER_COND));
1245bf215546Sopenharmony_ci   util_blitter_blit(sctx->blitter, info);
1246bf215546Sopenharmony_ci   si_blitter_end(sctx);
1247bf215546Sopenharmony_ci}
1248bf215546Sopenharmony_ci
1249bf215546Sopenharmony_cistatic bool si_generate_mipmap(struct pipe_context *ctx, struct pipe_resource *tex,
1250bf215546Sopenharmony_ci                               enum pipe_format format, unsigned base_level, unsigned last_level,
1251bf215546Sopenharmony_ci                               unsigned first_layer, unsigned last_layer)
1252bf215546Sopenharmony_ci{
1253bf215546Sopenharmony_ci   struct si_context *sctx = (struct si_context *)ctx;
1254bf215546Sopenharmony_ci   struct si_texture *stex = (struct si_texture *)tex;
1255bf215546Sopenharmony_ci
1256bf215546Sopenharmony_ci   if (!util_blitter_is_copy_supported(sctx->blitter, tex, tex))
1257bf215546Sopenharmony_ci      return false;
1258bf215546Sopenharmony_ci
1259bf215546Sopenharmony_ci   /* The driver doesn't decompress resources automatically while
1260bf215546Sopenharmony_ci    * u_blitter is rendering. */
1261bf215546Sopenharmony_ci   vi_disable_dcc_if_incompatible_format(sctx, tex, base_level, format);
1262bf215546Sopenharmony_ci   si_decompress_subresource(ctx, tex, PIPE_MASK_RGBAZS, base_level, first_layer, last_layer,
1263bf215546Sopenharmony_ci                             false);
1264bf215546Sopenharmony_ci
1265bf215546Sopenharmony_ci   /* Clear dirty_level_mask for the levels that will be overwritten. */
1266bf215546Sopenharmony_ci   assert(base_level < last_level);
1267bf215546Sopenharmony_ci   stex->dirty_level_mask &= ~u_bit_consecutive(base_level + 1, last_level - base_level);
1268bf215546Sopenharmony_ci
1269bf215546Sopenharmony_ci   sctx->generate_mipmap_for_depth = stex->is_depth;
1270bf215546Sopenharmony_ci
1271bf215546Sopenharmony_ci   si_blitter_begin(sctx, SI_BLIT | SI_DISABLE_RENDER_COND);
1272bf215546Sopenharmony_ci   util_blitter_generate_mipmap(sctx->blitter, tex, format, base_level, last_level, first_layer,
1273bf215546Sopenharmony_ci                                last_layer);
1274bf215546Sopenharmony_ci   si_blitter_end(sctx);
1275bf215546Sopenharmony_ci
1276bf215546Sopenharmony_ci   sctx->generate_mipmap_for_depth = false;
1277bf215546Sopenharmony_ci   return true;
1278bf215546Sopenharmony_ci}
1279bf215546Sopenharmony_ci
1280bf215546Sopenharmony_cistatic void si_flush_resource(struct pipe_context *ctx, struct pipe_resource *res)
1281bf215546Sopenharmony_ci{
1282bf215546Sopenharmony_ci   struct si_context *sctx = (struct si_context *)ctx;
1283bf215546Sopenharmony_ci   struct si_texture *tex = (struct si_texture *)res;
1284bf215546Sopenharmony_ci
1285bf215546Sopenharmony_ci   if (res->target == PIPE_BUFFER)
1286bf215546Sopenharmony_ci      return;
1287bf215546Sopenharmony_ci
1288bf215546Sopenharmony_ci   if (!tex->is_depth && (tex->cmask_buffer || vi_dcc_enabled(tex, 0))) {
1289bf215546Sopenharmony_ci      si_blit_decompress_color(sctx, tex, 0, res->last_level, 0, util_max_layer(res, 0),
1290bf215546Sopenharmony_ci                               false, false);
1291bf215546Sopenharmony_ci
1292bf215546Sopenharmony_ci      if (tex->surface.display_dcc_offset && tex->displayable_dcc_dirty) {
1293bf215546Sopenharmony_ci         si_retile_dcc(sctx, tex);
1294bf215546Sopenharmony_ci         tex->displayable_dcc_dirty = false;
1295bf215546Sopenharmony_ci      }
1296bf215546Sopenharmony_ci   }
1297bf215546Sopenharmony_ci}
1298bf215546Sopenharmony_ci
1299bf215546Sopenharmony_civoid si_flush_implicit_resources(struct si_context *sctx)
1300bf215546Sopenharmony_ci{
1301bf215546Sopenharmony_ci   hash_table_foreach(sctx->dirty_implicit_resources, entry) {
1302bf215546Sopenharmony_ci      si_flush_resource(&sctx->b, entry->data);
1303bf215546Sopenharmony_ci      pipe_resource_reference((struct pipe_resource **)&entry->data, NULL);
1304bf215546Sopenharmony_ci   }
1305bf215546Sopenharmony_ci   _mesa_hash_table_clear(sctx->dirty_implicit_resources, NULL);
1306bf215546Sopenharmony_ci}
1307bf215546Sopenharmony_ci
1308bf215546Sopenharmony_civoid si_decompress_dcc(struct si_context *sctx, struct si_texture *tex)
1309bf215546Sopenharmony_ci{
1310bf215546Sopenharmony_ci   assert(!tex->is_depth);
1311bf215546Sopenharmony_ci
1312bf215546Sopenharmony_ci   /* If graphics is disabled, we can't decompress DCC, but it shouldn't
1313bf215546Sopenharmony_ci    * be compressed either. The caller should simply discard it.
1314bf215546Sopenharmony_ci    */
1315bf215546Sopenharmony_ci   if (!tex->surface.meta_offset || !sctx->has_graphics)
1316bf215546Sopenharmony_ci      return;
1317bf215546Sopenharmony_ci
1318bf215546Sopenharmony_ci   si_blit_decompress_color(sctx, tex, 0, tex->buffer.b.b.last_level, 0,
1319bf215546Sopenharmony_ci                            util_max_layer(&tex->buffer.b.b, 0), true, false);
1320bf215546Sopenharmony_ci}
1321bf215546Sopenharmony_ci
1322bf215546Sopenharmony_civoid si_init_blit_functions(struct si_context *sctx)
1323bf215546Sopenharmony_ci{
1324bf215546Sopenharmony_ci   sctx->b.resource_copy_region = si_resource_copy_region;
1325bf215546Sopenharmony_ci
1326bf215546Sopenharmony_ci   if (sctx->has_graphics) {
1327bf215546Sopenharmony_ci      sctx->b.blit = si_blit;
1328bf215546Sopenharmony_ci      sctx->b.flush_resource = si_flush_resource;
1329bf215546Sopenharmony_ci      sctx->b.generate_mipmap = si_generate_mipmap;
1330bf215546Sopenharmony_ci   }
1331bf215546Sopenharmony_ci}
1332