1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © 2017 Intel Corporation
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be included
12bf215546Sopenharmony_ci * in all copies or substantial portions of the Software.
13bf215546Sopenharmony_ci *
14bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20bf215546Sopenharmony_ci * DEALINGS IN THE SOFTWARE.
21bf215546Sopenharmony_ci */
22bf215546Sopenharmony_ci
23bf215546Sopenharmony_ci#include <stdio.h>
24bf215546Sopenharmony_ci#include <errno.h>
25bf215546Sopenharmony_ci#include "pipe/p_defines.h"
26bf215546Sopenharmony_ci#include "pipe/p_state.h"
27bf215546Sopenharmony_ci#include "pipe/p_context.h"
28bf215546Sopenharmony_ci#include "pipe/p_screen.h"
29bf215546Sopenharmony_ci#include "util/u_inlines.h"
30bf215546Sopenharmony_ci#include "util/format/u_format.h"
31bf215546Sopenharmony_ci#include "util/u_upload_mgr.h"
32bf215546Sopenharmony_ci#include "util/ralloc.h"
33bf215546Sopenharmony_ci#include "iris_context.h"
34bf215546Sopenharmony_ci#include "iris_resource.h"
35bf215546Sopenharmony_ci#include "iris_screen.h"
36bf215546Sopenharmony_ci#include "intel/compiler/brw_compiler.h"
37bf215546Sopenharmony_ci
38bf215546Sopenharmony_cistatic bool
39bf215546Sopenharmony_ciiris_is_color_fast_clear_compatible(struct iris_context *ice,
40bf215546Sopenharmony_ci                                    enum isl_format format,
41bf215546Sopenharmony_ci                                    const union isl_color_value color)
42bf215546Sopenharmony_ci{
43bf215546Sopenharmony_ci   struct iris_batch *batch = &ice->batches[IRIS_BATCH_RENDER];
44bf215546Sopenharmony_ci   const struct intel_device_info *devinfo = &batch->screen->devinfo;
45bf215546Sopenharmony_ci
46bf215546Sopenharmony_ci   if (isl_format_has_int_channel(format)) {
47bf215546Sopenharmony_ci      perf_debug(&ice->dbg, "Integer fast clear not enabled for %s\n",
48bf215546Sopenharmony_ci                 isl_format_get_name(format));
49bf215546Sopenharmony_ci      return false;
50bf215546Sopenharmony_ci   }
51bf215546Sopenharmony_ci
52bf215546Sopenharmony_ci   for (int i = 0; i < 4; i++) {
53bf215546Sopenharmony_ci      if (!isl_format_has_color_component(format, i)) {
54bf215546Sopenharmony_ci         continue;
55bf215546Sopenharmony_ci      }
56bf215546Sopenharmony_ci
57bf215546Sopenharmony_ci      if (devinfo->ver < 9 &&
58bf215546Sopenharmony_ci          color.f32[i] != 0.0f && color.f32[i] != 1.0f) {
59bf215546Sopenharmony_ci         return false;
60bf215546Sopenharmony_ci      }
61bf215546Sopenharmony_ci   }
62bf215546Sopenharmony_ci
63bf215546Sopenharmony_ci   return true;
64bf215546Sopenharmony_ci}
65bf215546Sopenharmony_ci
66bf215546Sopenharmony_cistatic bool
67bf215546Sopenharmony_cican_fast_clear_color(struct iris_context *ice,
68bf215546Sopenharmony_ci                     struct pipe_resource *p_res,
69bf215546Sopenharmony_ci                     unsigned level,
70bf215546Sopenharmony_ci                     const struct pipe_box *box,
71bf215546Sopenharmony_ci                     bool render_condition_enabled,
72bf215546Sopenharmony_ci                     enum isl_format render_format,
73bf215546Sopenharmony_ci                     union isl_color_value color)
74bf215546Sopenharmony_ci{
75bf215546Sopenharmony_ci   struct iris_resource *res = (void *) p_res;
76bf215546Sopenharmony_ci
77bf215546Sopenharmony_ci   if (INTEL_DEBUG(DEBUG_NO_FAST_CLEAR))
78bf215546Sopenharmony_ci      return false;
79bf215546Sopenharmony_ci
80bf215546Sopenharmony_ci   if (!isl_aux_usage_has_fast_clears(res->aux.usage))
81bf215546Sopenharmony_ci      return false;
82bf215546Sopenharmony_ci
83bf215546Sopenharmony_ci   /* Check for partial clear */
84bf215546Sopenharmony_ci   if (box->x > 0 || box->y > 0 ||
85bf215546Sopenharmony_ci       box->width < u_minify(p_res->width0, level) ||
86bf215546Sopenharmony_ci       box->height < u_minify(p_res->height0, level)) {
87bf215546Sopenharmony_ci      return false;
88bf215546Sopenharmony_ci   }
89bf215546Sopenharmony_ci
90bf215546Sopenharmony_ci   /* Avoid conditional fast clears to maintain correct tracking of the aux
91bf215546Sopenharmony_ci    * state (see iris_resource_finish_write for more info). Note that partial
92bf215546Sopenharmony_ci    * fast clears (if they existed) would not pose a problem with conditional
93bf215546Sopenharmony_ci    * rendering.
94bf215546Sopenharmony_ci    */
95bf215546Sopenharmony_ci   if (render_condition_enabled &&
96bf215546Sopenharmony_ci       ice->state.predicate == IRIS_PREDICATE_STATE_USE_BIT) {
97bf215546Sopenharmony_ci      return false;
98bf215546Sopenharmony_ci   }
99bf215546Sopenharmony_ci
100bf215546Sopenharmony_ci   /* Disable sRGB fast-clears for non-0/1 color values. For texturing and
101bf215546Sopenharmony_ci    * draw calls, HW expects the clear color to be in two different color
102bf215546Sopenharmony_ci    * spaces after sRGB fast-clears - sRGB in the former and linear in the
103bf215546Sopenharmony_ci    * latter. By limiting the allowable values to 0/1, both color space
104bf215546Sopenharmony_ci    * requirements are satisfied.
105bf215546Sopenharmony_ci    */
106bf215546Sopenharmony_ci   if (isl_format_is_srgb(render_format) &&
107bf215546Sopenharmony_ci       !isl_color_value_is_zero_one(color, render_format)) {
108bf215546Sopenharmony_ci      return false;
109bf215546Sopenharmony_ci   }
110bf215546Sopenharmony_ci
111bf215546Sopenharmony_ci   /* We store clear colors as floats or uints as needed.  If there are
112bf215546Sopenharmony_ci    * texture views in play, the formats will not properly be respected
113bf215546Sopenharmony_ci    * during resolves because the resolve operations only know about the
114bf215546Sopenharmony_ci    * resource and not the renderbuffer.
115bf215546Sopenharmony_ci    */
116bf215546Sopenharmony_ci   if (!iris_render_formats_color_compatible(render_format, res->surf.format,
117bf215546Sopenharmony_ci                                             color, false)) {
118bf215546Sopenharmony_ci      return false;
119bf215546Sopenharmony_ci   }
120bf215546Sopenharmony_ci
121bf215546Sopenharmony_ci   if (!iris_is_color_fast_clear_compatible(ice, res->surf.format, color))
122bf215546Sopenharmony_ci      return false;
123bf215546Sopenharmony_ci
124bf215546Sopenharmony_ci   /* The RENDER_SURFACE_STATE page for TGL says:
125bf215546Sopenharmony_ci    *
126bf215546Sopenharmony_ci    *   For an 8 bpp surface with NUM_MULTISAMPLES = 1, Surface Width not
127bf215546Sopenharmony_ci    *   multiple of 64 pixels and more than 1 mip level in the view, Fast Clear
128bf215546Sopenharmony_ci    *   is not supported when AUX_CCS_E is set in this field.
129bf215546Sopenharmony_ci    *
130bf215546Sopenharmony_ci    * The granularity of a fast-clear is one CCS element. For an 8 bpp primary
131bf215546Sopenharmony_ci    * surface, this maps to 32px x 4rows. Due to the surface layout parameters,
132bf215546Sopenharmony_ci    * if LOD0's width isn't a multiple of 64px, LOD1 and LOD2+ will share CCS
133bf215546Sopenharmony_ci    * elements. Assuming LOD2 exists, don't fast-clear any level above LOD0
134bf215546Sopenharmony_ci    * to avoid stomping on other LODs.
135bf215546Sopenharmony_ci    */
136bf215546Sopenharmony_ci   if (level > 0 && util_format_get_blocksizebits(p_res->format) == 8 &&
137bf215546Sopenharmony_ci       res->aux.usage == ISL_AUX_USAGE_GFX12_CCS_E && p_res->width0 % 64) {
138bf215546Sopenharmony_ci      return false;
139bf215546Sopenharmony_ci   }
140bf215546Sopenharmony_ci
141bf215546Sopenharmony_ci   return true;
142bf215546Sopenharmony_ci}
143bf215546Sopenharmony_ci
144bf215546Sopenharmony_cistatic union isl_color_value
145bf215546Sopenharmony_ciconvert_clear_color(enum pipe_format format,
146bf215546Sopenharmony_ci                    const union pipe_color_union *color)
147bf215546Sopenharmony_ci{
148bf215546Sopenharmony_ci   uint32_t pixel[4];
149bf215546Sopenharmony_ci   util_format_pack_rgba(format, pixel, color, 1);
150bf215546Sopenharmony_ci
151bf215546Sopenharmony_ci   union isl_color_value converted_color;
152bf215546Sopenharmony_ci   util_format_unpack_rgba(format, &converted_color, pixel, 1);
153bf215546Sopenharmony_ci
154bf215546Sopenharmony_ci   /* The converted clear color has channels that are:
155bf215546Sopenharmony_ci    *   - clamped
156bf215546Sopenharmony_ci    *   - quantized
157bf215546Sopenharmony_ci    *   - filled with 0/1 if missing from the format
158bf215546Sopenharmony_ci    *   - swizzled for luminance and intensity formats
159bf215546Sopenharmony_ci    */
160bf215546Sopenharmony_ci   return converted_color;
161bf215546Sopenharmony_ci}
162bf215546Sopenharmony_ci
163bf215546Sopenharmony_cistatic void
164bf215546Sopenharmony_cifast_clear_color(struct iris_context *ice,
165bf215546Sopenharmony_ci                 struct iris_resource *res,
166bf215546Sopenharmony_ci                 unsigned level,
167bf215546Sopenharmony_ci                 const struct pipe_box *box,
168bf215546Sopenharmony_ci                 union isl_color_value color)
169bf215546Sopenharmony_ci{
170bf215546Sopenharmony_ci   struct iris_batch *batch = &ice->batches[IRIS_BATCH_RENDER];
171bf215546Sopenharmony_ci   const struct intel_device_info *devinfo = &batch->screen->devinfo;
172bf215546Sopenharmony_ci   struct pipe_resource *p_res = (void *) res;
173bf215546Sopenharmony_ci
174bf215546Sopenharmony_ci   bool color_changed = res->aux.clear_color_unknown ||
175bf215546Sopenharmony_ci      memcmp(&res->aux.clear_color, &color, sizeof(color)) != 0;
176bf215546Sopenharmony_ci
177bf215546Sopenharmony_ci   if (color_changed) {
178bf215546Sopenharmony_ci      /* If we are clearing to a new clear value, we need to resolve fast
179bf215546Sopenharmony_ci       * clears from other levels/layers first, since we can't have different
180bf215546Sopenharmony_ci       * levels/layers with different fast clear colors.
181bf215546Sopenharmony_ci       */
182bf215546Sopenharmony_ci      for (unsigned res_lvl = 0; res_lvl < res->surf.levels; res_lvl++) {
183bf215546Sopenharmony_ci         const unsigned level_layers =
184bf215546Sopenharmony_ci            iris_get_num_logical_layers(res, res_lvl);
185bf215546Sopenharmony_ci         for (unsigned layer = 0; layer < level_layers; layer++) {
186bf215546Sopenharmony_ci            if (res_lvl == level &&
187bf215546Sopenharmony_ci                layer >= box->z &&
188bf215546Sopenharmony_ci                layer < box->z + box->depth) {
189bf215546Sopenharmony_ci               /* We're going to clear this layer anyway.  Leave it alone. */
190bf215546Sopenharmony_ci               continue;
191bf215546Sopenharmony_ci            }
192bf215546Sopenharmony_ci
193bf215546Sopenharmony_ci            enum isl_aux_state aux_state =
194bf215546Sopenharmony_ci               iris_resource_get_aux_state(res, res_lvl, layer);
195bf215546Sopenharmony_ci
196bf215546Sopenharmony_ci            if (aux_state != ISL_AUX_STATE_CLEAR &&
197bf215546Sopenharmony_ci                aux_state != ISL_AUX_STATE_PARTIAL_CLEAR &&
198bf215546Sopenharmony_ci                aux_state != ISL_AUX_STATE_COMPRESSED_CLEAR) {
199bf215546Sopenharmony_ci               /* This slice doesn't have any fast-cleared bits. */
200bf215546Sopenharmony_ci               continue;
201bf215546Sopenharmony_ci            }
202bf215546Sopenharmony_ci
203bf215546Sopenharmony_ci            /* If we got here, then the level may have fast-clear bits that use
204bf215546Sopenharmony_ci             * the old clear value.  We need to do a color resolve to get rid
205bf215546Sopenharmony_ci             * of their use of the clear color before we can change it.
206bf215546Sopenharmony_ci             * Fortunately, few applications ever change their clear color at
207bf215546Sopenharmony_ci             * different levels/layers, so this shouldn't happen often.
208bf215546Sopenharmony_ci             */
209bf215546Sopenharmony_ci            iris_resource_prepare_access(ice, res,
210bf215546Sopenharmony_ci                                         res_lvl, 1, layer, 1,
211bf215546Sopenharmony_ci                                         res->aux.usage,
212bf215546Sopenharmony_ci                                         false);
213bf215546Sopenharmony_ci            if (res->aux.clear_color_unknown) {
214bf215546Sopenharmony_ci               perf_debug(&ice->dbg,
215bf215546Sopenharmony_ci                          "Resolving resource (%p) level %d, layer %d: color changing from "
216bf215546Sopenharmony_ci                          "(unknown) to (%0.2f, %0.2f, %0.2f, %0.2f)\n",
217bf215546Sopenharmony_ci                          res, res_lvl, layer,
218bf215546Sopenharmony_ci                          color.f32[0], color.f32[1], color.f32[2], color.f32[3]);
219bf215546Sopenharmony_ci            } else {
220bf215546Sopenharmony_ci               perf_debug(&ice->dbg,
221bf215546Sopenharmony_ci                          "Resolving resource (%p) level %d, layer %d: color changing from "
222bf215546Sopenharmony_ci                          "(%0.2f, %0.2f, %0.2f, %0.2f) to "
223bf215546Sopenharmony_ci                          "(%0.2f, %0.2f, %0.2f, %0.2f)\n",
224bf215546Sopenharmony_ci                          res, res_lvl, layer,
225bf215546Sopenharmony_ci                          res->aux.clear_color.f32[0],
226bf215546Sopenharmony_ci                          res->aux.clear_color.f32[1],
227bf215546Sopenharmony_ci                          res->aux.clear_color.f32[2],
228bf215546Sopenharmony_ci                          res->aux.clear_color.f32[3],
229bf215546Sopenharmony_ci                          color.f32[0], color.f32[1], color.f32[2], color.f32[3]);
230bf215546Sopenharmony_ci            }
231bf215546Sopenharmony_ci         }
232bf215546Sopenharmony_ci      }
233bf215546Sopenharmony_ci   }
234bf215546Sopenharmony_ci
235bf215546Sopenharmony_ci   iris_resource_set_clear_color(ice, res, color);
236bf215546Sopenharmony_ci
237bf215546Sopenharmony_ci   /* If the buffer is already in ISL_AUX_STATE_CLEAR, and the color hasn't
238bf215546Sopenharmony_ci    * changed, the clear is redundant and can be skipped.
239bf215546Sopenharmony_ci    */
240bf215546Sopenharmony_ci   const enum isl_aux_state aux_state =
241bf215546Sopenharmony_ci      iris_resource_get_aux_state(res, level, box->z);
242bf215546Sopenharmony_ci   if (!color_changed && box->depth == 1 && aux_state == ISL_AUX_STATE_CLEAR)
243bf215546Sopenharmony_ci      return;
244bf215546Sopenharmony_ci
245bf215546Sopenharmony_ci   /* Ivybridge PRM Vol 2, Part 1, "11.7 MCS Buffer for Render Target(s)":
246bf215546Sopenharmony_ci    *
247bf215546Sopenharmony_ci    *    "Any transition from any value in {Clear, Render, Resolve} to a
248bf215546Sopenharmony_ci    *    different value in {Clear, Render, Resolve} requires end of pipe
249bf215546Sopenharmony_ci    *    synchronization."
250bf215546Sopenharmony_ci    *
251bf215546Sopenharmony_ci    * In other words, fast clear ops are not properly synchronized with
252bf215546Sopenharmony_ci    * other drawing.  We need to use a PIPE_CONTROL to ensure that the
253bf215546Sopenharmony_ci    * contents of the previous draw hit the render target before we resolve
254bf215546Sopenharmony_ci    * and again afterwards to ensure that the resolve is complete before we
255bf215546Sopenharmony_ci    * do any more regular drawing.
256bf215546Sopenharmony_ci    */
257bf215546Sopenharmony_ci   iris_emit_end_of_pipe_sync(batch,
258bf215546Sopenharmony_ci                              "fast clear: pre-flush",
259bf215546Sopenharmony_ci                              PIPE_CONTROL_RENDER_TARGET_FLUSH |
260bf215546Sopenharmony_ci                              PIPE_CONTROL_TILE_CACHE_FLUSH |
261bf215546Sopenharmony_ci                              (devinfo->verx10 == 120 ?
262bf215546Sopenharmony_ci                                 PIPE_CONTROL_DEPTH_STALL : 0) |
263bf215546Sopenharmony_ci                              (devinfo->verx10 == 125 ?
264bf215546Sopenharmony_ci                                 PIPE_CONTROL_FLUSH_HDC |
265bf215546Sopenharmony_ci                                 PIPE_CONTROL_DATA_CACHE_FLUSH : 0) |
266bf215546Sopenharmony_ci                              PIPE_CONTROL_PSS_STALL_SYNC);
267bf215546Sopenharmony_ci
268bf215546Sopenharmony_ci   iris_batch_sync_region_start(batch);
269bf215546Sopenharmony_ci
270bf215546Sopenharmony_ci   /* If we reach this point, we need to fast clear to change the state to
271bf215546Sopenharmony_ci    * ISL_AUX_STATE_CLEAR, or to update the fast clear color (or both).
272bf215546Sopenharmony_ci    */
273bf215546Sopenharmony_ci   enum blorp_batch_flags blorp_flags = 0;
274bf215546Sopenharmony_ci   blorp_flags |= color_changed ? 0 : BLORP_BATCH_NO_UPDATE_CLEAR_COLOR;
275bf215546Sopenharmony_ci
276bf215546Sopenharmony_ci   struct blorp_batch blorp_batch;
277bf215546Sopenharmony_ci   blorp_batch_init(&ice->blorp, &blorp_batch, batch, blorp_flags);
278bf215546Sopenharmony_ci
279bf215546Sopenharmony_ci   struct blorp_surf surf;
280bf215546Sopenharmony_ci   iris_blorp_surf_for_resource(&batch->screen->isl_dev, &surf,
281bf215546Sopenharmony_ci                                p_res, res->aux.usage, level, true);
282bf215546Sopenharmony_ci
283bf215546Sopenharmony_ci   blorp_fast_clear(&blorp_batch, &surf, res->surf.format,
284bf215546Sopenharmony_ci                    ISL_SWIZZLE_IDENTITY,
285bf215546Sopenharmony_ci                    level, box->z, box->depth,
286bf215546Sopenharmony_ci                    box->x, box->y, box->x + box->width,
287bf215546Sopenharmony_ci                    box->y + box->height);
288bf215546Sopenharmony_ci   blorp_batch_finish(&blorp_batch);
289bf215546Sopenharmony_ci   iris_emit_end_of_pipe_sync(batch,
290bf215546Sopenharmony_ci                              "fast clear: post flush",
291bf215546Sopenharmony_ci                              PIPE_CONTROL_RENDER_TARGET_FLUSH |
292bf215546Sopenharmony_ci                              (devinfo->verx10 == 120 ?
293bf215546Sopenharmony_ci                                 PIPE_CONTROL_TILE_CACHE_FLUSH |
294bf215546Sopenharmony_ci                                 PIPE_CONTROL_DEPTH_STALL : 0) |
295bf215546Sopenharmony_ci                              PIPE_CONTROL_PSS_STALL_SYNC);
296bf215546Sopenharmony_ci   iris_batch_sync_region_end(batch);
297bf215546Sopenharmony_ci
298bf215546Sopenharmony_ci   iris_resource_set_aux_state(ice, res, level, box->z,
299bf215546Sopenharmony_ci                               box->depth, ISL_AUX_STATE_CLEAR);
300bf215546Sopenharmony_ci   ice->state.dirty |= IRIS_DIRTY_RENDER_BUFFER;
301bf215546Sopenharmony_ci   ice->state.stage_dirty |= IRIS_ALL_STAGE_DIRTY_BINDINGS;
302bf215546Sopenharmony_ci   return;
303bf215546Sopenharmony_ci}
304bf215546Sopenharmony_ci
305bf215546Sopenharmony_cistatic void
306bf215546Sopenharmony_ciclear_color(struct iris_context *ice,
307bf215546Sopenharmony_ci            struct pipe_resource *p_res,
308bf215546Sopenharmony_ci            unsigned level,
309bf215546Sopenharmony_ci            const struct pipe_box *box,
310bf215546Sopenharmony_ci            bool render_condition_enabled,
311bf215546Sopenharmony_ci            enum isl_format format,
312bf215546Sopenharmony_ci            struct isl_swizzle swizzle,
313bf215546Sopenharmony_ci            union isl_color_value color)
314bf215546Sopenharmony_ci{
315bf215546Sopenharmony_ci   struct iris_resource *res = (void *) p_res;
316bf215546Sopenharmony_ci
317bf215546Sopenharmony_ci   struct iris_batch *batch = &ice->batches[IRIS_BATCH_RENDER];
318bf215546Sopenharmony_ci   const struct intel_device_info *devinfo = &batch->screen->devinfo;
319bf215546Sopenharmony_ci   enum blorp_batch_flags blorp_flags = iris_blorp_flags_for_batch(batch);
320bf215546Sopenharmony_ci
321bf215546Sopenharmony_ci   if (render_condition_enabled) {
322bf215546Sopenharmony_ci      if (ice->state.predicate == IRIS_PREDICATE_STATE_DONT_RENDER)
323bf215546Sopenharmony_ci         return;
324bf215546Sopenharmony_ci
325bf215546Sopenharmony_ci      if (ice->state.predicate == IRIS_PREDICATE_STATE_USE_BIT)
326bf215546Sopenharmony_ci         blorp_flags |= BLORP_BATCH_PREDICATE_ENABLE;
327bf215546Sopenharmony_ci   }
328bf215546Sopenharmony_ci
329bf215546Sopenharmony_ci   if (p_res->target == PIPE_BUFFER)
330bf215546Sopenharmony_ci      util_range_add(&res->base.b, &res->valid_buffer_range, box->x, box->x + box->width);
331bf215546Sopenharmony_ci
332bf215546Sopenharmony_ci   iris_batch_maybe_flush(batch, 1500);
333bf215546Sopenharmony_ci
334bf215546Sopenharmony_ci   bool can_fast_clear = can_fast_clear_color(ice, p_res, level, box,
335bf215546Sopenharmony_ci                                              render_condition_enabled,
336bf215546Sopenharmony_ci                                              format, color);
337bf215546Sopenharmony_ci   if (can_fast_clear) {
338bf215546Sopenharmony_ci      fast_clear_color(ice, res, level, box, color);
339bf215546Sopenharmony_ci      return;
340bf215546Sopenharmony_ci   }
341bf215546Sopenharmony_ci
342bf215546Sopenharmony_ci   enum isl_aux_usage aux_usage =
343bf215546Sopenharmony_ci      iris_resource_render_aux_usage(ice, res, level, format, false);
344bf215546Sopenharmony_ci
345bf215546Sopenharmony_ci   iris_resource_prepare_render(ice, res, level, box->z, box->depth,
346bf215546Sopenharmony_ci                                aux_usage);
347bf215546Sopenharmony_ci   iris_emit_buffer_barrier_for(batch, res->bo, IRIS_DOMAIN_RENDER_WRITE);
348bf215546Sopenharmony_ci
349bf215546Sopenharmony_ci   struct blorp_surf surf;
350bf215546Sopenharmony_ci   iris_blorp_surf_for_resource(&batch->screen->isl_dev, &surf,
351bf215546Sopenharmony_ci                                p_res, aux_usage, level, true);
352bf215546Sopenharmony_ci
353bf215546Sopenharmony_ci   iris_batch_sync_region_start(batch);
354bf215546Sopenharmony_ci
355bf215546Sopenharmony_ci   struct blorp_batch blorp_batch;
356bf215546Sopenharmony_ci   blorp_batch_init(&ice->blorp, &blorp_batch, batch, blorp_flags);
357bf215546Sopenharmony_ci
358bf215546Sopenharmony_ci   if (!isl_format_supports_rendering(devinfo, format) &&
359bf215546Sopenharmony_ci       isl_format_is_rgbx(format))
360bf215546Sopenharmony_ci      format = isl_format_rgbx_to_rgba(format);
361bf215546Sopenharmony_ci
362bf215546Sopenharmony_ci   blorp_clear(&blorp_batch, &surf, format, swizzle,
363bf215546Sopenharmony_ci               level, box->z, box->depth, box->x, box->y,
364bf215546Sopenharmony_ci               box->x + box->width, box->y + box->height,
365bf215546Sopenharmony_ci               color, 0 /* color_write_disable */);
366bf215546Sopenharmony_ci
367bf215546Sopenharmony_ci   blorp_batch_finish(&blorp_batch);
368bf215546Sopenharmony_ci   iris_batch_sync_region_end(batch);
369bf215546Sopenharmony_ci
370bf215546Sopenharmony_ci   iris_dirty_for_history(ice, res);
371bf215546Sopenharmony_ci
372bf215546Sopenharmony_ci   iris_resource_finish_render(ice, res, level,
373bf215546Sopenharmony_ci                               box->z, box->depth, aux_usage);
374bf215546Sopenharmony_ci}
375bf215546Sopenharmony_ci
376bf215546Sopenharmony_cistatic bool
377bf215546Sopenharmony_cican_fast_clear_depth(struct iris_context *ice,
378bf215546Sopenharmony_ci                     struct iris_resource *res,
379bf215546Sopenharmony_ci                     unsigned level,
380bf215546Sopenharmony_ci                     const struct pipe_box *box,
381bf215546Sopenharmony_ci                     bool render_condition_enabled,
382bf215546Sopenharmony_ci                     float depth)
383bf215546Sopenharmony_ci{
384bf215546Sopenharmony_ci   struct pipe_resource *p_res = (void *) res;
385bf215546Sopenharmony_ci   struct pipe_context *ctx = (void *) ice;
386bf215546Sopenharmony_ci   struct iris_screen *screen = (void *) ctx->screen;
387bf215546Sopenharmony_ci   const struct intel_device_info *devinfo = &screen->devinfo;
388bf215546Sopenharmony_ci
389bf215546Sopenharmony_ci   if (INTEL_DEBUG(DEBUG_NO_FAST_CLEAR))
390bf215546Sopenharmony_ci      return false;
391bf215546Sopenharmony_ci
392bf215546Sopenharmony_ci   /* Check for partial clears */
393bf215546Sopenharmony_ci   if (box->x > 0 || box->y > 0 ||
394bf215546Sopenharmony_ci       box->width < u_minify(p_res->width0, level) ||
395bf215546Sopenharmony_ci       box->height < u_minify(p_res->height0, level)) {
396bf215546Sopenharmony_ci      return false;
397bf215546Sopenharmony_ci   }
398bf215546Sopenharmony_ci
399bf215546Sopenharmony_ci   /* Avoid conditional fast clears to maintain correct tracking of the aux
400bf215546Sopenharmony_ci    * state (see iris_resource_finish_write for more info). Note that partial
401bf215546Sopenharmony_ci    * fast clears would not pose a problem with conditional rendering.
402bf215546Sopenharmony_ci    */
403bf215546Sopenharmony_ci   if (render_condition_enabled &&
404bf215546Sopenharmony_ci       ice->state.predicate == IRIS_PREDICATE_STATE_USE_BIT) {
405bf215546Sopenharmony_ci      return false;
406bf215546Sopenharmony_ci   }
407bf215546Sopenharmony_ci
408bf215546Sopenharmony_ci   if (!iris_resource_level_has_hiz(res, level))
409bf215546Sopenharmony_ci      return false;
410bf215546Sopenharmony_ci
411bf215546Sopenharmony_ci   if (!blorp_can_hiz_clear_depth(devinfo, &res->surf, res->aux.usage,
412bf215546Sopenharmony_ci                                  level, box->z, box->x, box->y,
413bf215546Sopenharmony_ci                                  box->x + box->width,
414bf215546Sopenharmony_ci                                  box->y + box->height)) {
415bf215546Sopenharmony_ci      return false;
416bf215546Sopenharmony_ci   }
417bf215546Sopenharmony_ci
418bf215546Sopenharmony_ci   return true;
419bf215546Sopenharmony_ci}
420bf215546Sopenharmony_ci
421bf215546Sopenharmony_cistatic void
422bf215546Sopenharmony_cifast_clear_depth(struct iris_context *ice,
423bf215546Sopenharmony_ci                 struct iris_resource *res,
424bf215546Sopenharmony_ci                 unsigned level,
425bf215546Sopenharmony_ci                 const struct pipe_box *box,
426bf215546Sopenharmony_ci                 float depth)
427bf215546Sopenharmony_ci{
428bf215546Sopenharmony_ci   struct iris_batch *batch = &ice->batches[IRIS_BATCH_RENDER];
429bf215546Sopenharmony_ci
430bf215546Sopenharmony_ci   bool update_clear_depth = false;
431bf215546Sopenharmony_ci
432bf215546Sopenharmony_ci   /* If we're clearing to a new clear value, then we need to resolve any clear
433bf215546Sopenharmony_ci    * flags out of the HiZ buffer into the real depth buffer.
434bf215546Sopenharmony_ci    */
435bf215546Sopenharmony_ci   if (res->aux.clear_color_unknown || res->aux.clear_color.f32[0] != depth) {
436bf215546Sopenharmony_ci      for (unsigned res_level = 0; res_level < res->surf.levels; res_level++) {
437bf215546Sopenharmony_ci         const unsigned level_layers =
438bf215546Sopenharmony_ci            iris_get_num_logical_layers(res, res_level);
439bf215546Sopenharmony_ci         for (unsigned layer = 0; layer < level_layers; layer++) {
440bf215546Sopenharmony_ci            if (res_level == level &&
441bf215546Sopenharmony_ci                layer >= box->z &&
442bf215546Sopenharmony_ci                layer < box->z + box->depth) {
443bf215546Sopenharmony_ci               /* We're going to clear this layer anyway.  Leave it alone. */
444bf215546Sopenharmony_ci               continue;
445bf215546Sopenharmony_ci            }
446bf215546Sopenharmony_ci
447bf215546Sopenharmony_ci            enum isl_aux_state aux_state =
448bf215546Sopenharmony_ci               iris_resource_get_aux_state(res, res_level, layer);
449bf215546Sopenharmony_ci
450bf215546Sopenharmony_ci            if (aux_state != ISL_AUX_STATE_CLEAR &&
451bf215546Sopenharmony_ci                aux_state != ISL_AUX_STATE_COMPRESSED_CLEAR) {
452bf215546Sopenharmony_ci               /* This slice doesn't have any fast-cleared bits. */
453bf215546Sopenharmony_ci               continue;
454bf215546Sopenharmony_ci            }
455bf215546Sopenharmony_ci
456bf215546Sopenharmony_ci            /* If we got here, then the level may have fast-clear bits that
457bf215546Sopenharmony_ci             * use the old clear value.  We need to do a depth resolve to get
458bf215546Sopenharmony_ci             * rid of their use of the clear value before we can change it.
459bf215546Sopenharmony_ci             * Fortunately, few applications ever change their depth clear
460bf215546Sopenharmony_ci             * value so this shouldn't happen often.
461bf215546Sopenharmony_ci             */
462bf215546Sopenharmony_ci            iris_hiz_exec(ice, batch, res, res_level, layer, 1,
463bf215546Sopenharmony_ci                          ISL_AUX_OP_FULL_RESOLVE, false);
464bf215546Sopenharmony_ci            iris_resource_set_aux_state(ice, res, res_level, layer, 1,
465bf215546Sopenharmony_ci                                        ISL_AUX_STATE_RESOLVED);
466bf215546Sopenharmony_ci         }
467bf215546Sopenharmony_ci      }
468bf215546Sopenharmony_ci      const union isl_color_value clear_value = { .f32 = {depth, } };
469bf215546Sopenharmony_ci      iris_resource_set_clear_color(ice, res, clear_value);
470bf215546Sopenharmony_ci      update_clear_depth = true;
471bf215546Sopenharmony_ci   }
472bf215546Sopenharmony_ci
473bf215546Sopenharmony_ci   if (res->aux.usage == ISL_AUX_USAGE_HIZ_CCS_WT) {
474bf215546Sopenharmony_ci      /* From Bspec 47010 (Depth Buffer Clear):
475bf215546Sopenharmony_ci       *
476bf215546Sopenharmony_ci       *    Since the fast clear cycles to CCS are not cached in TileCache,
477bf215546Sopenharmony_ci       *    any previous depth buffer writes to overlapping pixels must be
478bf215546Sopenharmony_ci       *    flushed out of TileCache before a succeeding Depth Buffer Clear.
479bf215546Sopenharmony_ci       *    This restriction only applies to Depth Buffer with write-thru
480bf215546Sopenharmony_ci       *    enabled, since fast clears to CCS only occur for write-thru mode.
481bf215546Sopenharmony_ci       *
482bf215546Sopenharmony_ci       * There may have been a write to this depth buffer. Flush it from the
483bf215546Sopenharmony_ci       * tile cache just in case.
484bf215546Sopenharmony_ci       */
485bf215546Sopenharmony_ci      iris_emit_pipe_control_flush(batch, "hiz_ccs_wt: before fast clear",
486bf215546Sopenharmony_ci                                   PIPE_CONTROL_DEPTH_CACHE_FLUSH |
487bf215546Sopenharmony_ci                                   PIPE_CONTROL_TILE_CACHE_FLUSH);
488bf215546Sopenharmony_ci   }
489bf215546Sopenharmony_ci
490bf215546Sopenharmony_ci   for (unsigned l = 0; l < box->depth; l++) {
491bf215546Sopenharmony_ci      enum isl_aux_state aux_state =
492bf215546Sopenharmony_ci         iris_resource_get_aux_state(res, level, box->z + l);
493bf215546Sopenharmony_ci      if (update_clear_depth || aux_state != ISL_AUX_STATE_CLEAR) {
494bf215546Sopenharmony_ci         if (aux_state == ISL_AUX_STATE_CLEAR) {
495bf215546Sopenharmony_ci            perf_debug(&ice->dbg, "Performing HiZ clear just to update the "
496bf215546Sopenharmony_ci                                  "depth clear value\n");
497bf215546Sopenharmony_ci         }
498bf215546Sopenharmony_ci         iris_hiz_exec(ice, batch, res, level,
499bf215546Sopenharmony_ci                       box->z + l, 1, ISL_AUX_OP_FAST_CLEAR,
500bf215546Sopenharmony_ci                       update_clear_depth);
501bf215546Sopenharmony_ci      }
502bf215546Sopenharmony_ci   }
503bf215546Sopenharmony_ci
504bf215546Sopenharmony_ci   iris_resource_set_aux_state(ice, res, level, box->z, box->depth,
505bf215546Sopenharmony_ci                               ISL_AUX_STATE_CLEAR);
506bf215546Sopenharmony_ci   ice->state.dirty |= IRIS_DIRTY_DEPTH_BUFFER;
507bf215546Sopenharmony_ci   ice->state.stage_dirty |= IRIS_ALL_STAGE_DIRTY_BINDINGS;
508bf215546Sopenharmony_ci}
509bf215546Sopenharmony_ci
510bf215546Sopenharmony_cistatic void
511bf215546Sopenharmony_ciclear_depth_stencil(struct iris_context *ice,
512bf215546Sopenharmony_ci                    struct pipe_resource *p_res,
513bf215546Sopenharmony_ci                    unsigned level,
514bf215546Sopenharmony_ci                    const struct pipe_box *box,
515bf215546Sopenharmony_ci                    bool render_condition_enabled,
516bf215546Sopenharmony_ci                    bool clear_depth,
517bf215546Sopenharmony_ci                    bool clear_stencil,
518bf215546Sopenharmony_ci                    float depth,
519bf215546Sopenharmony_ci                    uint8_t stencil)
520bf215546Sopenharmony_ci{
521bf215546Sopenharmony_ci   struct iris_resource *res = (void *) p_res;
522bf215546Sopenharmony_ci
523bf215546Sopenharmony_ci   struct iris_batch *batch = &ice->batches[IRIS_BATCH_RENDER];
524bf215546Sopenharmony_ci   enum blorp_batch_flags blorp_flags = 0;
525bf215546Sopenharmony_ci
526bf215546Sopenharmony_ci   if (render_condition_enabled) {
527bf215546Sopenharmony_ci      if (ice->state.predicate == IRIS_PREDICATE_STATE_DONT_RENDER)
528bf215546Sopenharmony_ci         return;
529bf215546Sopenharmony_ci
530bf215546Sopenharmony_ci      if (ice->state.predicate == IRIS_PREDICATE_STATE_USE_BIT)
531bf215546Sopenharmony_ci         blorp_flags |= BLORP_BATCH_PREDICATE_ENABLE;
532bf215546Sopenharmony_ci   }
533bf215546Sopenharmony_ci
534bf215546Sopenharmony_ci   iris_batch_maybe_flush(batch, 1500);
535bf215546Sopenharmony_ci
536bf215546Sopenharmony_ci   struct iris_resource *z_res;
537bf215546Sopenharmony_ci   struct iris_resource *stencil_res;
538bf215546Sopenharmony_ci   struct blorp_surf z_surf;
539bf215546Sopenharmony_ci   struct blorp_surf stencil_surf;
540bf215546Sopenharmony_ci
541bf215546Sopenharmony_ci   iris_get_depth_stencil_resources(p_res, &z_res, &stencil_res);
542bf215546Sopenharmony_ci   if (z_res && clear_depth &&
543bf215546Sopenharmony_ci       can_fast_clear_depth(ice, z_res, level, box, render_condition_enabled,
544bf215546Sopenharmony_ci                            depth)) {
545bf215546Sopenharmony_ci      fast_clear_depth(ice, z_res, level, box, depth);
546bf215546Sopenharmony_ci      iris_dirty_for_history(ice, res);
547bf215546Sopenharmony_ci      clear_depth = false;
548bf215546Sopenharmony_ci      z_res = false;
549bf215546Sopenharmony_ci   }
550bf215546Sopenharmony_ci
551bf215546Sopenharmony_ci   /* At this point, we might have fast cleared the depth buffer. So if there's
552bf215546Sopenharmony_ci    * no stencil clear pending, return early.
553bf215546Sopenharmony_ci    */
554bf215546Sopenharmony_ci   if (!(clear_depth || (clear_stencil && stencil_res))) {
555bf215546Sopenharmony_ci      return;
556bf215546Sopenharmony_ci   }
557bf215546Sopenharmony_ci
558bf215546Sopenharmony_ci   if (clear_depth && z_res) {
559bf215546Sopenharmony_ci      const enum isl_aux_usage aux_usage =
560bf215546Sopenharmony_ci         iris_resource_render_aux_usage(ice, z_res, level, z_res->surf.format,
561bf215546Sopenharmony_ci                                        false);
562bf215546Sopenharmony_ci      iris_resource_prepare_render(ice, z_res, level, box->z, box->depth,
563bf215546Sopenharmony_ci                                   aux_usage);
564bf215546Sopenharmony_ci      iris_emit_buffer_barrier_for(batch, z_res->bo, IRIS_DOMAIN_DEPTH_WRITE);
565bf215546Sopenharmony_ci      iris_blorp_surf_for_resource(&batch->screen->isl_dev, &z_surf,
566bf215546Sopenharmony_ci                                   &z_res->base.b, aux_usage, level, true);
567bf215546Sopenharmony_ci   }
568bf215546Sopenharmony_ci
569bf215546Sopenharmony_ci   uint8_t stencil_mask = clear_stencil && stencil_res ? 0xff : 0;
570bf215546Sopenharmony_ci   if (stencil_mask) {
571bf215546Sopenharmony_ci      iris_resource_prepare_access(ice, stencil_res, level, 1, box->z,
572bf215546Sopenharmony_ci                                   box->depth, stencil_res->aux.usage, false);
573bf215546Sopenharmony_ci      iris_emit_buffer_barrier_for(batch, stencil_res->bo,
574bf215546Sopenharmony_ci                                   IRIS_DOMAIN_DEPTH_WRITE);
575bf215546Sopenharmony_ci      iris_blorp_surf_for_resource(&batch->screen->isl_dev,
576bf215546Sopenharmony_ci                                   &stencil_surf, &stencil_res->base.b,
577bf215546Sopenharmony_ci                                   stencil_res->aux.usage, level, true);
578bf215546Sopenharmony_ci   }
579bf215546Sopenharmony_ci
580bf215546Sopenharmony_ci   iris_batch_sync_region_start(batch);
581bf215546Sopenharmony_ci
582bf215546Sopenharmony_ci   struct blorp_batch blorp_batch;
583bf215546Sopenharmony_ci   blorp_batch_init(&ice->blorp, &blorp_batch, batch, blorp_flags);
584bf215546Sopenharmony_ci
585bf215546Sopenharmony_ci   blorp_clear_depth_stencil(&blorp_batch, &z_surf, &stencil_surf,
586bf215546Sopenharmony_ci                             level, box->z, box->depth,
587bf215546Sopenharmony_ci                             box->x, box->y,
588bf215546Sopenharmony_ci                             box->x + box->width,
589bf215546Sopenharmony_ci                             box->y + box->height,
590bf215546Sopenharmony_ci                             clear_depth && z_res, depth,
591bf215546Sopenharmony_ci                             stencil_mask, stencil);
592bf215546Sopenharmony_ci
593bf215546Sopenharmony_ci   blorp_batch_finish(&blorp_batch);
594bf215546Sopenharmony_ci   iris_batch_sync_region_end(batch);
595bf215546Sopenharmony_ci
596bf215546Sopenharmony_ci   iris_dirty_for_history(ice, res);
597bf215546Sopenharmony_ci
598bf215546Sopenharmony_ci   if (clear_depth && z_res) {
599bf215546Sopenharmony_ci      iris_resource_finish_render(ice, z_res, level, box->z, box->depth,
600bf215546Sopenharmony_ci                                  z_surf.aux_usage);
601bf215546Sopenharmony_ci   }
602bf215546Sopenharmony_ci
603bf215546Sopenharmony_ci   if (stencil_mask) {
604bf215546Sopenharmony_ci      iris_resource_finish_write(ice, stencil_res, level, box->z, box->depth,
605bf215546Sopenharmony_ci                                 stencil_res->aux.usage);
606bf215546Sopenharmony_ci   }
607bf215546Sopenharmony_ci}
608bf215546Sopenharmony_ci
609bf215546Sopenharmony_ci/**
610bf215546Sopenharmony_ci * The pipe->clear() driver hook.
611bf215546Sopenharmony_ci *
612bf215546Sopenharmony_ci * This clears buffers attached to the current draw framebuffer.
613bf215546Sopenharmony_ci */
614bf215546Sopenharmony_cistatic void
615bf215546Sopenharmony_ciiris_clear(struct pipe_context *ctx,
616bf215546Sopenharmony_ci           unsigned buffers,
617bf215546Sopenharmony_ci           const struct pipe_scissor_state *scissor_state,
618bf215546Sopenharmony_ci           const union pipe_color_union *p_color,
619bf215546Sopenharmony_ci           double depth,
620bf215546Sopenharmony_ci           unsigned stencil)
621bf215546Sopenharmony_ci{
622bf215546Sopenharmony_ci   struct iris_context *ice = (void *) ctx;
623bf215546Sopenharmony_ci   struct pipe_framebuffer_state *cso_fb = &ice->state.framebuffer;
624bf215546Sopenharmony_ci
625bf215546Sopenharmony_ci   assert(buffers != 0);
626bf215546Sopenharmony_ci
627bf215546Sopenharmony_ci   struct pipe_box box = {
628bf215546Sopenharmony_ci      .width = cso_fb->width,
629bf215546Sopenharmony_ci      .height = cso_fb->height,
630bf215546Sopenharmony_ci   };
631bf215546Sopenharmony_ci
632bf215546Sopenharmony_ci   if (scissor_state) {
633bf215546Sopenharmony_ci      box.x = scissor_state->minx;
634bf215546Sopenharmony_ci      box.y = scissor_state->miny;
635bf215546Sopenharmony_ci      box.width = MIN2(box.width, scissor_state->maxx - scissor_state->minx);
636bf215546Sopenharmony_ci      box.height = MIN2(box.height, scissor_state->maxy - scissor_state->miny);
637bf215546Sopenharmony_ci   }
638bf215546Sopenharmony_ci
639bf215546Sopenharmony_ci   if (buffers & PIPE_CLEAR_DEPTHSTENCIL) {
640bf215546Sopenharmony_ci      struct pipe_surface *psurf = cso_fb->zsbuf;
641bf215546Sopenharmony_ci
642bf215546Sopenharmony_ci      box.depth = psurf->u.tex.last_layer - psurf->u.tex.first_layer + 1;
643bf215546Sopenharmony_ci      box.z = psurf->u.tex.first_layer,
644bf215546Sopenharmony_ci      clear_depth_stencil(ice, psurf->texture, psurf->u.tex.level, &box, true,
645bf215546Sopenharmony_ci                          buffers & PIPE_CLEAR_DEPTH,
646bf215546Sopenharmony_ci                          buffers & PIPE_CLEAR_STENCIL,
647bf215546Sopenharmony_ci                          depth, stencil);
648bf215546Sopenharmony_ci   }
649bf215546Sopenharmony_ci
650bf215546Sopenharmony_ci   if (buffers & PIPE_CLEAR_COLOR) {
651bf215546Sopenharmony_ci      for (unsigned i = 0; i < cso_fb->nr_cbufs; i++) {
652bf215546Sopenharmony_ci         if (buffers & (PIPE_CLEAR_COLOR0 << i)) {
653bf215546Sopenharmony_ci            struct pipe_surface *psurf = cso_fb->cbufs[i];
654bf215546Sopenharmony_ci            struct iris_surface *isurf = (void *) psurf;
655bf215546Sopenharmony_ci            box.depth = psurf->u.tex.last_layer - psurf->u.tex.first_layer + 1,
656bf215546Sopenharmony_ci            box.z = psurf->u.tex.first_layer,
657bf215546Sopenharmony_ci
658bf215546Sopenharmony_ci            clear_color(ice, psurf->texture, psurf->u.tex.level, &box,
659bf215546Sopenharmony_ci                        true, isurf->view.format, isurf->view.swizzle,
660bf215546Sopenharmony_ci                        convert_clear_color(psurf->format, p_color));
661bf215546Sopenharmony_ci         }
662bf215546Sopenharmony_ci      }
663bf215546Sopenharmony_ci   }
664bf215546Sopenharmony_ci}
665bf215546Sopenharmony_ci
666bf215546Sopenharmony_ci/**
667bf215546Sopenharmony_ci * The pipe->clear_texture() driver hook.
668bf215546Sopenharmony_ci *
669bf215546Sopenharmony_ci * This clears the given texture resource.
670bf215546Sopenharmony_ci */
671bf215546Sopenharmony_cistatic void
672bf215546Sopenharmony_ciiris_clear_texture(struct pipe_context *ctx,
673bf215546Sopenharmony_ci                   struct pipe_resource *p_res,
674bf215546Sopenharmony_ci                   unsigned level,
675bf215546Sopenharmony_ci                   const struct pipe_box *box,
676bf215546Sopenharmony_ci                   const void *data)
677bf215546Sopenharmony_ci{
678bf215546Sopenharmony_ci   struct iris_context *ice = (void *) ctx;
679bf215546Sopenharmony_ci   struct iris_screen *screen = (void *) ctx->screen;
680bf215546Sopenharmony_ci   const struct intel_device_info *devinfo = &screen->devinfo;
681bf215546Sopenharmony_ci
682bf215546Sopenharmony_ci   if (util_format_is_depth_or_stencil(p_res->format)) {
683bf215546Sopenharmony_ci      const struct util_format_unpack_description *unpack =
684bf215546Sopenharmony_ci         util_format_unpack_description(p_res->format);
685bf215546Sopenharmony_ci
686bf215546Sopenharmony_ci      float depth = 0.0;
687bf215546Sopenharmony_ci      uint8_t stencil = 0;
688bf215546Sopenharmony_ci
689bf215546Sopenharmony_ci      if (unpack->unpack_z_float)
690bf215546Sopenharmony_ci         util_format_unpack_z_float(p_res->format, &depth, data, 1);
691bf215546Sopenharmony_ci
692bf215546Sopenharmony_ci      if (unpack->unpack_s_8uint)
693bf215546Sopenharmony_ci         util_format_unpack_s_8uint(p_res->format, &stencil, data, 1);
694bf215546Sopenharmony_ci
695bf215546Sopenharmony_ci      clear_depth_stencil(ice, p_res, level, box, true, true, true,
696bf215546Sopenharmony_ci                          depth, stencil);
697bf215546Sopenharmony_ci   } else {
698bf215546Sopenharmony_ci      union isl_color_value color;
699bf215546Sopenharmony_ci      struct iris_resource *res = (void *) p_res;
700bf215546Sopenharmony_ci      enum isl_format format = res->surf.format;
701bf215546Sopenharmony_ci
702bf215546Sopenharmony_ci      if (!isl_format_supports_rendering(devinfo, format)) {
703bf215546Sopenharmony_ci         const struct isl_format_layout *fmtl = isl_format_get_layout(format);
704bf215546Sopenharmony_ci         // XXX: actually just get_copy_format_for_bpb from BLORP
705bf215546Sopenharmony_ci         // XXX: don't cut and paste this
706bf215546Sopenharmony_ci         switch (fmtl->bpb) {
707bf215546Sopenharmony_ci         case 8:   format = ISL_FORMAT_R8_UINT;           break;
708bf215546Sopenharmony_ci         case 16:  format = ISL_FORMAT_R8G8_UINT;         break;
709bf215546Sopenharmony_ci         case 24:  format = ISL_FORMAT_R8G8B8_UINT;       break;
710bf215546Sopenharmony_ci         case 32:  format = ISL_FORMAT_R8G8B8A8_UINT;     break;
711bf215546Sopenharmony_ci         case 48:  format = ISL_FORMAT_R16G16B16_UINT;    break;
712bf215546Sopenharmony_ci         case 64:  format = ISL_FORMAT_R16G16B16A16_UINT; break;
713bf215546Sopenharmony_ci         case 96:  format = ISL_FORMAT_R32G32B32_UINT;    break;
714bf215546Sopenharmony_ci         case 128: format = ISL_FORMAT_R32G32B32A32_UINT; break;
715bf215546Sopenharmony_ci         default:
716bf215546Sopenharmony_ci            unreachable("Unknown format bpb");
717bf215546Sopenharmony_ci         }
718bf215546Sopenharmony_ci
719bf215546Sopenharmony_ci         /* No aux surfaces for non-renderable surfaces */
720bf215546Sopenharmony_ci         assert(res->aux.usage == ISL_AUX_USAGE_NONE);
721bf215546Sopenharmony_ci      }
722bf215546Sopenharmony_ci
723bf215546Sopenharmony_ci      isl_color_value_unpack(&color, format, data);
724bf215546Sopenharmony_ci
725bf215546Sopenharmony_ci      clear_color(ice, p_res, level, box, true, format,
726bf215546Sopenharmony_ci                  ISL_SWIZZLE_IDENTITY, color);
727bf215546Sopenharmony_ci   }
728bf215546Sopenharmony_ci}
729bf215546Sopenharmony_ci
730bf215546Sopenharmony_ci/**
731bf215546Sopenharmony_ci * The pipe->clear_render_target() driver hook.
732bf215546Sopenharmony_ci *
733bf215546Sopenharmony_ci * This clears the given render target surface.
734bf215546Sopenharmony_ci */
735bf215546Sopenharmony_cistatic void
736bf215546Sopenharmony_ciiris_clear_render_target(struct pipe_context *ctx,
737bf215546Sopenharmony_ci                         struct pipe_surface *psurf,
738bf215546Sopenharmony_ci                         const union pipe_color_union *p_color,
739bf215546Sopenharmony_ci                         unsigned dst_x, unsigned dst_y,
740bf215546Sopenharmony_ci                         unsigned width, unsigned height,
741bf215546Sopenharmony_ci                         bool render_condition_enabled)
742bf215546Sopenharmony_ci{
743bf215546Sopenharmony_ci   struct iris_context *ice = (void *) ctx;
744bf215546Sopenharmony_ci   struct iris_surface *isurf = (void *) psurf;
745bf215546Sopenharmony_ci   struct pipe_box box = {
746bf215546Sopenharmony_ci      .x = dst_x,
747bf215546Sopenharmony_ci      .y = dst_y,
748bf215546Sopenharmony_ci      .z = psurf->u.tex.first_layer,
749bf215546Sopenharmony_ci      .width = width,
750bf215546Sopenharmony_ci      .height = height,
751bf215546Sopenharmony_ci      .depth = psurf->u.tex.last_layer - psurf->u.tex.first_layer + 1
752bf215546Sopenharmony_ci   };
753bf215546Sopenharmony_ci
754bf215546Sopenharmony_ci   clear_color(ice, psurf->texture, psurf->u.tex.level, &box,
755bf215546Sopenharmony_ci               render_condition_enabled,
756bf215546Sopenharmony_ci               isurf->view.format, isurf->view.swizzle,
757bf215546Sopenharmony_ci               convert_clear_color(psurf->format, p_color));
758bf215546Sopenharmony_ci}
759bf215546Sopenharmony_ci
760bf215546Sopenharmony_ci/**
761bf215546Sopenharmony_ci * The pipe->clear_depth_stencil() driver hook.
762bf215546Sopenharmony_ci *
763bf215546Sopenharmony_ci * This clears the given depth/stencil surface.
764bf215546Sopenharmony_ci */
765bf215546Sopenharmony_cistatic void
766bf215546Sopenharmony_ciiris_clear_depth_stencil(struct pipe_context *ctx,
767bf215546Sopenharmony_ci                         struct pipe_surface *psurf,
768bf215546Sopenharmony_ci                         unsigned flags,
769bf215546Sopenharmony_ci                         double depth,
770bf215546Sopenharmony_ci                         unsigned stencil,
771bf215546Sopenharmony_ci                         unsigned dst_x, unsigned dst_y,
772bf215546Sopenharmony_ci                         unsigned width, unsigned height,
773bf215546Sopenharmony_ci                         bool render_condition_enabled)
774bf215546Sopenharmony_ci{
775bf215546Sopenharmony_ci   struct iris_context *ice = (void *) ctx;
776bf215546Sopenharmony_ci   struct pipe_box box = {
777bf215546Sopenharmony_ci      .x = dst_x,
778bf215546Sopenharmony_ci      .y = dst_y,
779bf215546Sopenharmony_ci      .z = psurf->u.tex.first_layer,
780bf215546Sopenharmony_ci      .width = width,
781bf215546Sopenharmony_ci      .height = height,
782bf215546Sopenharmony_ci      .depth = psurf->u.tex.last_layer - psurf->u.tex.first_layer + 1
783bf215546Sopenharmony_ci   };
784bf215546Sopenharmony_ci
785bf215546Sopenharmony_ci   assert(util_format_is_depth_or_stencil(psurf->texture->format));
786bf215546Sopenharmony_ci
787bf215546Sopenharmony_ci   clear_depth_stencil(ice, psurf->texture, psurf->u.tex.level, &box,
788bf215546Sopenharmony_ci                       render_condition_enabled,
789bf215546Sopenharmony_ci                       flags & PIPE_CLEAR_DEPTH, flags & PIPE_CLEAR_STENCIL,
790bf215546Sopenharmony_ci                       depth, stencil);
791bf215546Sopenharmony_ci}
792bf215546Sopenharmony_ci
793bf215546Sopenharmony_civoid
794bf215546Sopenharmony_ciiris_init_clear_functions(struct pipe_context *ctx)
795bf215546Sopenharmony_ci{
796bf215546Sopenharmony_ci   ctx->clear = iris_clear;
797bf215546Sopenharmony_ci   ctx->clear_texture = iris_clear_texture;
798bf215546Sopenharmony_ci   ctx->clear_render_target = iris_clear_render_target;
799bf215546Sopenharmony_ci   ctx->clear_depth_stencil = iris_clear_depth_stencil;
800bf215546Sopenharmony_ci}
801