1b8e80941Smrg/*
2b8e80941Smrg * Copyright © 2017 Intel Corporation
3b8e80941Smrg *
4b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a
5b8e80941Smrg * copy of this software and associated documentation files (the "Software"),
6b8e80941Smrg * to deal in the Software without restriction, including without limitation
7b8e80941Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8b8e80941Smrg * and/or sell copies of the Software, and to permit persons to whom the
9b8e80941Smrg * Software is furnished to do so, subject to the following conditions:
10b8e80941Smrg *
11b8e80941Smrg * The above copyright notice and this permission notice shall be included
12b8e80941Smrg * in all copies or substantial portions of the Software.
13b8e80941Smrg *
14b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15b8e80941Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17b8e80941Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18b8e80941Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19b8e80941Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20b8e80941Smrg * DEALINGS IN THE SOFTWARE.
21b8e80941Smrg */
22b8e80941Smrg
23b8e80941Smrg#include <stdio.h>
24b8e80941Smrg#include <errno.h>
25b8e80941Smrg#include "pipe/p_defines.h"
26b8e80941Smrg#include "pipe/p_state.h"
27b8e80941Smrg#include "pipe/p_context.h"
28b8e80941Smrg#include "pipe/p_screen.h"
29b8e80941Smrg#include "util/u_inlines.h"
30b8e80941Smrg#include "util/u_format.h"
31b8e80941Smrg#include "util/u_upload_mgr.h"
32b8e80941Smrg#include "util/ralloc.h"
33b8e80941Smrg#include "iris_context.h"
34b8e80941Smrg#include "iris_resource.h"
35b8e80941Smrg#include "iris_screen.h"
36b8e80941Smrg#include "intel/compiler/brw_compiler.h"
37b8e80941Smrg#include "util/format_srgb.h"
38b8e80941Smrg
39b8e80941Smrgstatic bool
40b8e80941Smrgiris_is_color_fast_clear_compatible(struct iris_context *ice,
41b8e80941Smrg                                    enum isl_format format,
42b8e80941Smrg                                    const union isl_color_value color)
43b8e80941Smrg{
44b8e80941Smrg   struct iris_batch *batch = &ice->batches[IRIS_BATCH_RENDER];
45b8e80941Smrg   const struct gen_device_info *devinfo = &batch->screen->devinfo;
46b8e80941Smrg
47b8e80941Smrg   if (isl_format_has_int_channel(format)) {
48b8e80941Smrg      perf_debug(&ice->dbg, "Integer fast clear not enabled for %s",
49b8e80941Smrg                 isl_format_get_name(format));
50b8e80941Smrg      return false;
51b8e80941Smrg   }
52b8e80941Smrg
53b8e80941Smrg   for (int i = 0; i < 4; i++) {
54b8e80941Smrg      if (!isl_format_has_color_component(format, i)) {
55b8e80941Smrg         continue;
56b8e80941Smrg      }
57b8e80941Smrg
58b8e80941Smrg      if (devinfo->gen < 9 &&
59b8e80941Smrg          color.f32[i] != 0.0f && color.f32[i] != 1.0f) {
60b8e80941Smrg         return false;
61b8e80941Smrg      }
62b8e80941Smrg   }
63b8e80941Smrg
64b8e80941Smrg   return true;
65b8e80941Smrg}
66b8e80941Smrg
67b8e80941Smrgstatic bool
68b8e80941Smrgcan_fast_clear_color(struct iris_context *ice,
69b8e80941Smrg                     struct pipe_resource *p_res,
70b8e80941Smrg                     unsigned level,
71b8e80941Smrg                     const struct pipe_box *box,
72b8e80941Smrg                     enum isl_format format,
73b8e80941Smrg                     enum isl_format render_format,
74b8e80941Smrg                     union isl_color_value color)
75b8e80941Smrg{
76b8e80941Smrg   struct iris_resource *res = (void *) p_res;
77b8e80941Smrg
78b8e80941Smrg   struct iris_batch *batch = &ice->batches[IRIS_BATCH_RENDER];
79b8e80941Smrg   const struct gen_device_info *devinfo = &batch->screen->devinfo;
80b8e80941Smrg
81b8e80941Smrg   if (res->aux.usage == ISL_AUX_USAGE_NONE)
82b8e80941Smrg      return false;
83b8e80941Smrg
84b8e80941Smrg   /* Surface state can only record one fast clear color value. Therefore
85b8e80941Smrg    * unless different levels/layers agree on the color it can be used to
86b8e80941Smrg    * represent only single level/layer. Here it will be reserved for the
87b8e80941Smrg    * first slice (level 0, layer 0).
88b8e80941Smrg    */
89b8e80941Smrg   if (level > 0 || box->z > 0 || box->depth > 1)
90b8e80941Smrg      return false;
91b8e80941Smrg
92b8e80941Smrg   /* Check for partial clear */
93b8e80941Smrg   if (box->x > 0 || box->y > 0 ||
94b8e80941Smrg       box->width < p_res->width0 ||
95b8e80941Smrg       box->height < p_res->height0) {
96b8e80941Smrg      return false;
97b8e80941Smrg   }
98b8e80941Smrg
99b8e80941Smrg   /* We store clear colors as floats or uints as needed.  If there are
100b8e80941Smrg    * texture views in play, the formats will not properly be respected
101b8e80941Smrg    * during resolves because the resolve operations only know about the
102b8e80941Smrg    * resource and not the renderbuffer.
103b8e80941Smrg    */
104b8e80941Smrg   if (isl_format_srgb_to_linear(render_format) !=
105b8e80941Smrg       isl_format_srgb_to_linear(format)) {
106b8e80941Smrg      return false;
107b8e80941Smrg   }
108b8e80941Smrg
109b8e80941Smrg   /* XXX: if (irb->mt->supports_fast_clear)
110b8e80941Smrg    * see intel_miptree_create_for_dri_image()
111b8e80941Smrg    */
112b8e80941Smrg
113b8e80941Smrg   if (!iris_is_color_fast_clear_compatible(ice, format, color))
114b8e80941Smrg      return false;
115b8e80941Smrg
116b8e80941Smrg   return true;
117b8e80941Smrg}
118b8e80941Smrg
119b8e80941Smrgstatic union isl_color_value
120b8e80941Smrgconvert_fast_clear_color(struct iris_context *ice,
121b8e80941Smrg                         struct iris_resource *res,
122b8e80941Smrg                         enum isl_format render_format,
123b8e80941Smrg                         const union isl_color_value color)
124b8e80941Smrg{
125b8e80941Smrg   union isl_color_value override_color = color;
126b8e80941Smrg   struct pipe_resource *p_res = (void *) res;
127b8e80941Smrg
128b8e80941Smrg   const enum pipe_format format = p_res->format;
129b8e80941Smrg   const struct util_format_description *desc =
130b8e80941Smrg      util_format_description(format);
131b8e80941Smrg   unsigned colormask = util_format_colormask(desc);
132b8e80941Smrg
133b8e80941Smrg   if (util_format_is_intensity(format) ||
134b8e80941Smrg       util_format_is_luminance(format) ||
135b8e80941Smrg       util_format_is_luminance_alpha(format)) {
136b8e80941Smrg      override_color.u32[1] = override_color.u32[0];
137b8e80941Smrg      override_color.u32[2] = override_color.u32[0];
138b8e80941Smrg      if (util_format_is_intensity(format))
139b8e80941Smrg         override_color.u32[3] = override_color.u32[0];
140b8e80941Smrg   } else {
141b8e80941Smrg      for (int chan = 0; chan < 3; chan++) {
142b8e80941Smrg         if (!(colormask & (1 << chan)))
143b8e80941Smrg            override_color.u32[chan] = 0;
144b8e80941Smrg      }
145b8e80941Smrg   }
146b8e80941Smrg
147b8e80941Smrg   if (util_format_is_unorm(format)) {
148b8e80941Smrg      for (int i = 0; i < 4; i++)
149b8e80941Smrg         override_color.f32[i] = CLAMP(override_color.f32[i], 0.0f, 1.0f);
150b8e80941Smrg   } else if (util_format_is_snorm(format)) {
151b8e80941Smrg      for (int i = 0; i < 4; i++)
152b8e80941Smrg         override_color.f32[i] = CLAMP(override_color.f32[i], -1.0f, 1.0f);
153b8e80941Smrg   } else if (util_format_is_pure_uint(format)) {
154b8e80941Smrg      for (int i = 0; i < 4; i++) {
155b8e80941Smrg         unsigned bits = util_format_get_component_bits(
156b8e80941Smrg            format, UTIL_FORMAT_COLORSPACE_RGB, i);
157b8e80941Smrg         if (bits < 32) {
158b8e80941Smrg            uint32_t max = (1u << bits) - 1;
159b8e80941Smrg            override_color.u32[i] = MIN2(override_color.u32[i], max);
160b8e80941Smrg         }
161b8e80941Smrg      }
162b8e80941Smrg   } else if (util_format_is_pure_sint(format)) {
163b8e80941Smrg      for (int i = 0; i < 4; i++) {
164b8e80941Smrg         unsigned bits = util_format_get_component_bits(
165b8e80941Smrg            format, UTIL_FORMAT_COLORSPACE_RGB, i);
166b8e80941Smrg         if (bits < 32) {
167b8e80941Smrg            int32_t max = (1 << (bits - 1)) - 1;
168b8e80941Smrg            int32_t min = -(1 << (bits - 1));
169b8e80941Smrg            override_color.i32[i] = CLAMP(override_color.i32[i], min, max);
170b8e80941Smrg         }
171b8e80941Smrg      }
172b8e80941Smrg   } else if (format == PIPE_FORMAT_R11G11B10_FLOAT ||
173b8e80941Smrg              format == PIPE_FORMAT_R9G9B9E5_FLOAT) {
174b8e80941Smrg      /* these packed float formats only store unsigned values */
175b8e80941Smrg      for (int i = 0; i < 4; i++)
176b8e80941Smrg         override_color.f32[i] = MAX2(override_color.f32[i], 0.0f);
177b8e80941Smrg   }
178b8e80941Smrg
179b8e80941Smrg   if (!(colormask & 1 << 3)) {
180b8e80941Smrg      if (util_format_is_pure_integer(format))
181b8e80941Smrg         override_color.u32[3] = 1;
182b8e80941Smrg      else
183b8e80941Smrg         override_color.f32[3] = 1.0f;
184b8e80941Smrg   }
185b8e80941Smrg
186b8e80941Smrg   /* Handle linear to SRGB conversion */
187b8e80941Smrg   if (isl_format_is_srgb(render_format)) {
188b8e80941Smrg      for (int i = 0; i < 3; i++) {
189b8e80941Smrg         override_color.f32[i] =
190b8e80941Smrg            util_format_linear_to_srgb_float(override_color.f32[i]);
191b8e80941Smrg      }
192b8e80941Smrg   }
193b8e80941Smrg
194b8e80941Smrg   return override_color;
195b8e80941Smrg}
196b8e80941Smrg
197b8e80941Smrgstatic void
198b8e80941Smrgfast_clear_color(struct iris_context *ice,
199b8e80941Smrg                 struct iris_resource *res,
200b8e80941Smrg                 unsigned level,
201b8e80941Smrg                 const struct pipe_box *box,
202b8e80941Smrg                 enum isl_format format,
203b8e80941Smrg                 union isl_color_value color,
204b8e80941Smrg                 enum blorp_batch_flags blorp_flags)
205b8e80941Smrg{
206b8e80941Smrg   struct iris_batch *batch = &ice->batches[IRIS_BATCH_RENDER];
207b8e80941Smrg   struct pipe_resource *p_res = (void *) res;
208b8e80941Smrg   const enum isl_aux_state aux_state =
209b8e80941Smrg      iris_resource_get_aux_state(res, level, box->z);
210b8e80941Smrg
211b8e80941Smrg   color = convert_fast_clear_color(ice, res, format, color);
212b8e80941Smrg
213b8e80941Smrg   bool color_changed = !!memcmp(&res->aux.clear_color, &color,
214b8e80941Smrg                                 sizeof(color));
215b8e80941Smrg
216b8e80941Smrg   if (color_changed) {
217b8e80941Smrg      /* We decided that we are going to fast clear, and the color is
218b8e80941Smrg       * changing. But if we have a predicate bit set, the predication
219b8e80941Smrg       * affects whether we should clear or not, and if we shouldn't, we
220b8e80941Smrg       * also shouldn't update the clear color.
221b8e80941Smrg       *
222b8e80941Smrg       * However, we can't simply predicate-update the clear color (the
223b8e80941Smrg       * commands don't support that). And we would lose track of the
224b8e80941Smrg       * color, preventing us from doing some optimizations later.
225b8e80941Smrg       *
226b8e80941Smrg       * Since changing the clear color when the predication bit is enabled
227b8e80941Smrg       * is not something that should happen often, we stall on the CPU here
228b8e80941Smrg       * to resolve the predication, and then proceed.
229b8e80941Smrg       */
230b8e80941Smrg      iris_resolve_conditional_render(ice);
231b8e80941Smrg      if (ice->state.predicate == IRIS_PREDICATE_STATE_DONT_RENDER)
232b8e80941Smrg         return;
233b8e80941Smrg   }
234b8e80941Smrg
235b8e80941Smrg   iris_resource_set_clear_color(ice, res, color);
236b8e80941Smrg
237b8e80941Smrg   /* If the buffer is already in ISL_AUX_STATE_CLEAR, and the color hasn't
238b8e80941Smrg    * changed, the clear is redundant and can be skipped.
239b8e80941Smrg    */
240b8e80941Smrg   if (!color_changed && aux_state == ISL_AUX_STATE_CLEAR)
241b8e80941Smrg      return;
242b8e80941Smrg
243b8e80941Smrg   /* Ivybrigde PRM Vol 2, Part 1, "11.7 MCS Buffer for Render Target(s)":
244b8e80941Smrg    *
245b8e80941Smrg    *    "Any transition from any value in {Clear, Render, Resolve} to a
246b8e80941Smrg    *    different value in {Clear, Render, Resolve} requires end of pipe
247b8e80941Smrg    *    synchronization."
248b8e80941Smrg    *
249b8e80941Smrg    * In other words, fast clear ops are not properly synchronized with
250b8e80941Smrg    * other drawing.  We need to use a PIPE_CONTROL to ensure that the
251b8e80941Smrg    * contents of the previous draw hit the render target before we resolve
252b8e80941Smrg    * and again afterwards to ensure that the resolve is complete before we
253b8e80941Smrg    * do any more regular drawing.
254b8e80941Smrg    */
255b8e80941Smrg   iris_emit_end_of_pipe_sync(batch, PIPE_CONTROL_RENDER_TARGET_FLUSH);
256b8e80941Smrg
257b8e80941Smrg   /* If we reach this point, we need to fast clear to change the state to
258b8e80941Smrg    * ISL_AUX_STATE_CLEAR, or to update the fast clear color (or both).
259b8e80941Smrg    */
260b8e80941Smrg   blorp_flags |= color_changed ? 0 : BLORP_BATCH_NO_UPDATE_CLEAR_COLOR;
261b8e80941Smrg
262b8e80941Smrg   struct blorp_batch blorp_batch;
263b8e80941Smrg   blorp_batch_init(&ice->blorp, &blorp_batch, batch, blorp_flags);
264b8e80941Smrg
265b8e80941Smrg   struct blorp_surf surf;
266b8e80941Smrg   iris_blorp_surf_for_resource(&ice->vtbl, &surf, p_res, res->aux.usage,
267b8e80941Smrg                                level, true);
268b8e80941Smrg
269b8e80941Smrg   /* In newer gens (> 9), the hardware will do a linear -> sRGB conversion of
270b8e80941Smrg    * the clear color during the fast clear, if the surface format is of sRGB
271b8e80941Smrg    * type. We use the linear version of the surface format here to prevent
272b8e80941Smrg    * that from happening, since we already do our own linear -> sRGB
273b8e80941Smrg    * conversion in convert_fast_clear_color().
274b8e80941Smrg    */
275b8e80941Smrg   blorp_fast_clear(&blorp_batch, &surf, isl_format_srgb_to_linear(format),
276b8e80941Smrg                    level, box->z, box->depth,
277b8e80941Smrg                    box->x, box->y, box->x + box->width,
278b8e80941Smrg                    box->y + box->height);
279b8e80941Smrg   blorp_batch_finish(&blorp_batch);
280b8e80941Smrg   iris_emit_end_of_pipe_sync(batch, PIPE_CONTROL_RENDER_TARGET_FLUSH);
281b8e80941Smrg
282b8e80941Smrg   iris_resource_set_aux_state(ice, res, level, box->z,
283b8e80941Smrg                               box->depth, ISL_AUX_STATE_CLEAR);
284b8e80941Smrg   ice->state.dirty |= IRIS_ALL_DIRTY_BINDINGS;
285b8e80941Smrg   return;
286b8e80941Smrg}
287b8e80941Smrg
288b8e80941Smrgstatic void
289b8e80941Smrgclear_color(struct iris_context *ice,
290b8e80941Smrg            struct pipe_resource *p_res,
291b8e80941Smrg            unsigned level,
292b8e80941Smrg            const struct pipe_box *box,
293b8e80941Smrg            bool render_condition_enabled,
294b8e80941Smrg            enum isl_format format,
295b8e80941Smrg            struct isl_swizzle swizzle,
296b8e80941Smrg            union isl_color_value color)
297b8e80941Smrg{
298b8e80941Smrg   struct iris_resource *res = (void *) p_res;
299b8e80941Smrg
300b8e80941Smrg   struct iris_batch *batch = &ice->batches[IRIS_BATCH_RENDER];
301b8e80941Smrg   const struct gen_device_info *devinfo = &batch->screen->devinfo;
302b8e80941Smrg   enum blorp_batch_flags blorp_flags = 0;
303b8e80941Smrg
304b8e80941Smrg   if (render_condition_enabled) {
305b8e80941Smrg      if (ice->state.predicate == IRIS_PREDICATE_STATE_DONT_RENDER)
306b8e80941Smrg         return;
307b8e80941Smrg
308b8e80941Smrg      if (ice->state.predicate == IRIS_PREDICATE_STATE_USE_BIT)
309b8e80941Smrg         blorp_flags |= BLORP_BATCH_PREDICATE_ENABLE;
310b8e80941Smrg   }
311b8e80941Smrg
312b8e80941Smrg   if (p_res->target == PIPE_BUFFER)
313b8e80941Smrg      util_range_add(&res->valid_buffer_range, box->x, box->x + box->width);
314b8e80941Smrg
315b8e80941Smrg   iris_batch_maybe_flush(batch, 1500);
316b8e80941Smrg
317b8e80941Smrg   bool can_fast_clear = can_fast_clear_color(ice, p_res, level, box,
318b8e80941Smrg                                              res->surf.format, format, color);
319b8e80941Smrg   if (can_fast_clear) {
320b8e80941Smrg      fast_clear_color(ice, res, level, box, format, color,
321b8e80941Smrg                       blorp_flags);
322b8e80941Smrg      return;
323b8e80941Smrg   }
324b8e80941Smrg
325b8e80941Smrg   bool color_write_disable[4] = { false, false, false, false };
326b8e80941Smrg   enum isl_aux_usage aux_usage =
327b8e80941Smrg      iris_resource_render_aux_usage(ice, res, format,
328b8e80941Smrg                                     false, false);
329b8e80941Smrg
330b8e80941Smrg   iris_resource_prepare_render(ice, batch, res, level,
331b8e80941Smrg                                box->z, box->depth, aux_usage);
332b8e80941Smrg
333b8e80941Smrg   struct blorp_surf surf;
334b8e80941Smrg   iris_blorp_surf_for_resource(&ice->vtbl, &surf, p_res, aux_usage, level,
335b8e80941Smrg                                true);
336b8e80941Smrg
337b8e80941Smrg   struct blorp_batch blorp_batch;
338b8e80941Smrg   blorp_batch_init(&ice->blorp, &blorp_batch, batch, blorp_flags);
339b8e80941Smrg
340b8e80941Smrg   if (!isl_format_supports_rendering(devinfo, format) &&
341b8e80941Smrg       isl_format_is_rgbx(format))
342b8e80941Smrg      format = isl_format_rgbx_to_rgba(format);
343b8e80941Smrg
344b8e80941Smrg   blorp_clear(&blorp_batch, &surf, format, swizzle,
345b8e80941Smrg               level, box->z, box->depth, box->x, box->y,
346b8e80941Smrg               box->x + box->width, box->y + box->height,
347b8e80941Smrg               color, color_write_disable);
348b8e80941Smrg
349b8e80941Smrg   blorp_batch_finish(&blorp_batch);
350b8e80941Smrg   iris_flush_and_dirty_for_history(ice, batch, res);
351b8e80941Smrg
352b8e80941Smrg   iris_resource_finish_render(ice, res, level,
353b8e80941Smrg                               box->z, box->depth, aux_usage);
354b8e80941Smrg}
355b8e80941Smrg
356b8e80941Smrgstatic bool
357b8e80941Smrgcan_fast_clear_depth(struct iris_context *ice,
358b8e80941Smrg                     struct iris_resource *res,
359b8e80941Smrg                     unsigned level,
360b8e80941Smrg                     const struct pipe_box *box,
361b8e80941Smrg                     float depth)
362b8e80941Smrg{
363b8e80941Smrg   struct pipe_resource *p_res = (void *) res;
364b8e80941Smrg
365b8e80941Smrg   /* Check for partial clears */
366b8e80941Smrg   if (box->x > 0 || box->y > 0 ||
367b8e80941Smrg       box->width < u_minify(p_res->width0, level) ||
368b8e80941Smrg       box->height < u_minify(p_res->height0, level)) {
369b8e80941Smrg      return false;
370b8e80941Smrg   }
371b8e80941Smrg
372b8e80941Smrg   if (!(res->aux.has_hiz & (1 << level)))
373b8e80941Smrg      return false;
374b8e80941Smrg
375b8e80941Smrg   return true;
376b8e80941Smrg}
377b8e80941Smrg
378b8e80941Smrgstatic void
379b8e80941Smrgfast_clear_depth(struct iris_context *ice,
380b8e80941Smrg                 struct iris_resource *res,
381b8e80941Smrg                 unsigned level,
382b8e80941Smrg                 const struct pipe_box *box,
383b8e80941Smrg                 float depth)
384b8e80941Smrg{
385b8e80941Smrg   struct pipe_resource *p_res = (void *) res;
386b8e80941Smrg   struct iris_batch *batch = &ice->batches[IRIS_BATCH_RENDER];
387b8e80941Smrg
388b8e80941Smrg   /* Quantize the clear value to what can be stored in the actual depth
389b8e80941Smrg    * buffer.  This makes the following check more accurate because it now
390b8e80941Smrg    * checks if the actual depth bits will match.  It also prevents us from
391b8e80941Smrg    * getting a too-accurate depth value during depth testing or when sampling
392b8e80941Smrg    * with HiZ enabled.
393b8e80941Smrg    */
394b8e80941Smrg   const unsigned nbits = p_res->format == PIPE_FORMAT_Z16_UNORM ? 16 : 24;
395b8e80941Smrg   const uint32_t depth_max = (1 << nbits) - 1;
396b8e80941Smrg   depth = p_res->format == PIPE_FORMAT_Z32_FLOAT ? depth :
397b8e80941Smrg      (unsigned)(depth * depth_max) / (float)depth_max;
398b8e80941Smrg
399b8e80941Smrg   bool update_clear_depth = false;
400b8e80941Smrg
401b8e80941Smrg   /* If we're clearing to a new clear value, then we need to resolve any clear
402b8e80941Smrg    * flags out of the HiZ buffer into the real depth buffer.
403b8e80941Smrg    */
404b8e80941Smrg   if (res->aux.clear_color.f32[0] != depth) {
405b8e80941Smrg      /* We decided that we are going to fast clear, and the color is
406b8e80941Smrg       * changing. But if we have a predicate bit set, the predication
407b8e80941Smrg       * affects whether we should clear or not, and if we shouldn't, we
408b8e80941Smrg       * also shouldn't update the clear color.
409b8e80941Smrg       *
410b8e80941Smrg       * However, we can't simply predicate-update the clear color (the
411b8e80941Smrg       * commands don't support that). And we would lose track of the
412b8e80941Smrg       * color, preventing us from doing some optimizations later.
413b8e80941Smrg       *
414b8e80941Smrg       * For depth clears, things are even more complicated, because here we
415b8e80941Smrg       * resolve the other levels/layers if they have a different color than
416b8e80941Smrg       * the current one. That resolve can be predicated, but we also set those
417b8e80941Smrg       * layers as ISL_AUX_STATE_RESOLVED, and this can't be predicated.
418b8e80941Smrg       * Keeping track of the aux state when predication is involved is just
419b8e80941Smrg       * even more complex, so the easiest thing to do when the fast clear
420b8e80941Smrg       * depth is changing is to stall on the CPU and resolve the predication.
421b8e80941Smrg       */
422b8e80941Smrg      iris_resolve_conditional_render(ice);
423b8e80941Smrg      if (ice->state.predicate == IRIS_PREDICATE_STATE_DONT_RENDER)
424b8e80941Smrg         return;
425b8e80941Smrg
426b8e80941Smrg      for (unsigned res_level = 0; res_level < res->surf.levels; res_level++) {
427b8e80941Smrg         if (!(res->aux.has_hiz & (1 << res_level)))
428b8e80941Smrg            continue;
429b8e80941Smrg
430b8e80941Smrg         const unsigned level_layers =
431b8e80941Smrg            iris_get_num_logical_layers(res, res_level);
432b8e80941Smrg         for (unsigned layer = 0; layer < level_layers; layer++) {
433b8e80941Smrg            if (res_level == level &&
434b8e80941Smrg                layer >= box->z &&
435b8e80941Smrg                layer < box->z + box->depth) {
436b8e80941Smrg               /* We're going to clear this layer anyway.  Leave it alone. */
437b8e80941Smrg               continue;
438b8e80941Smrg            }
439b8e80941Smrg
440b8e80941Smrg            enum isl_aux_state aux_state =
441b8e80941Smrg               iris_resource_get_aux_state(res, res_level, layer);
442b8e80941Smrg
443b8e80941Smrg            if (aux_state != ISL_AUX_STATE_CLEAR &&
444b8e80941Smrg                aux_state != ISL_AUX_STATE_COMPRESSED_CLEAR) {
445b8e80941Smrg               /* This slice doesn't have any fast-cleared bits. */
446b8e80941Smrg               continue;
447b8e80941Smrg            }
448b8e80941Smrg
449b8e80941Smrg            /* If we got here, then the level may have fast-clear bits that
450b8e80941Smrg             * use the old clear value.  We need to do a depth resolve to get
451b8e80941Smrg             * rid of their use of the clear value before we can change it.
452b8e80941Smrg             * Fortunately, few applications ever change their depth clear
453b8e80941Smrg             * value so this shouldn't happen often.
454b8e80941Smrg             */
455b8e80941Smrg            iris_hiz_exec(ice, batch, res, res_level, layer, 1,
456b8e80941Smrg                          ISL_AUX_OP_FULL_RESOLVE, false);
457b8e80941Smrg            iris_resource_set_aux_state(ice, res, res_level, layer, 1,
458b8e80941Smrg                                        ISL_AUX_STATE_RESOLVED);
459b8e80941Smrg         }
460b8e80941Smrg      }
461b8e80941Smrg      const union isl_color_value clear_value = { .f32 = {depth, } };
462b8e80941Smrg      iris_resource_set_clear_color(ice, res, clear_value);
463b8e80941Smrg      update_clear_depth = true;
464b8e80941Smrg   }
465b8e80941Smrg
466b8e80941Smrg   for (unsigned l = 0; l < box->depth; l++) {
467b8e80941Smrg      enum isl_aux_state aux_state =
468b8e80941Smrg         iris_resource_get_aux_state(res, level, box->z + l);
469b8e80941Smrg      if (aux_state != ISL_AUX_STATE_CLEAR) {
470b8e80941Smrg         iris_hiz_exec(ice, batch, res, level,
471b8e80941Smrg                       box->z + l, 1, ISL_AUX_OP_FAST_CLEAR,
472b8e80941Smrg                       update_clear_depth);
473b8e80941Smrg      }
474b8e80941Smrg   }
475b8e80941Smrg
476b8e80941Smrg   iris_resource_set_aux_state(ice, res, level, box->z, box->depth,
477b8e80941Smrg                               ISL_AUX_STATE_CLEAR);
478b8e80941Smrg   ice->state.dirty |= IRIS_DIRTY_DEPTH_BUFFER;
479b8e80941Smrg}
480b8e80941Smrg
481b8e80941Smrgstatic void
482b8e80941Smrgclear_depth_stencil(struct iris_context *ice,
483b8e80941Smrg                    struct pipe_resource *p_res,
484b8e80941Smrg                    unsigned level,
485b8e80941Smrg                    const struct pipe_box *box,
486b8e80941Smrg                    bool render_condition_enabled,
487b8e80941Smrg                    bool clear_depth,
488b8e80941Smrg                    bool clear_stencil,
489b8e80941Smrg                    float depth,
490b8e80941Smrg                    uint8_t stencil)
491b8e80941Smrg{
492b8e80941Smrg   struct iris_resource *res = (void *) p_res;
493b8e80941Smrg
494b8e80941Smrg   struct iris_batch *batch = &ice->batches[IRIS_BATCH_RENDER];
495b8e80941Smrg   enum blorp_batch_flags blorp_flags = 0;
496b8e80941Smrg
497b8e80941Smrg   if (render_condition_enabled) {
498b8e80941Smrg      if (ice->state.predicate == IRIS_PREDICATE_STATE_DONT_RENDER)
499b8e80941Smrg         return;
500b8e80941Smrg
501b8e80941Smrg      if (ice->state.predicate == IRIS_PREDICATE_STATE_USE_BIT)
502b8e80941Smrg         blorp_flags |= BLORP_BATCH_PREDICATE_ENABLE;
503b8e80941Smrg   }
504b8e80941Smrg
505b8e80941Smrg   iris_batch_maybe_flush(batch, 1500);
506b8e80941Smrg
507b8e80941Smrg   struct iris_resource *z_res;
508b8e80941Smrg   struct iris_resource *stencil_res;
509b8e80941Smrg   struct blorp_surf z_surf;
510b8e80941Smrg   struct blorp_surf stencil_surf;
511b8e80941Smrg
512b8e80941Smrg   iris_get_depth_stencil_resources(p_res, &z_res, &stencil_res);
513b8e80941Smrg   if (z_res && clear_depth &&
514b8e80941Smrg       can_fast_clear_depth(ice, z_res, level, box, depth)) {
515b8e80941Smrg      fast_clear_depth(ice, z_res, level, box, depth);
516b8e80941Smrg      iris_flush_and_dirty_for_history(ice, batch, res);
517b8e80941Smrg      clear_depth = false;
518b8e80941Smrg      z_res = false;
519b8e80941Smrg   }
520b8e80941Smrg
521b8e80941Smrg   /* At this point, we might have fast cleared the depth buffer. So if there's
522b8e80941Smrg    * no stencil clear pending, return early.
523b8e80941Smrg    */
524b8e80941Smrg   if (!(clear_depth || clear_stencil)) {
525b8e80941Smrg      return;
526b8e80941Smrg   }
527b8e80941Smrg
528b8e80941Smrg   if (z_res) {
529b8e80941Smrg      iris_resource_prepare_depth(ice, batch, z_res, level, box->z, box->depth);
530b8e80941Smrg      iris_blorp_surf_for_resource(&ice->vtbl, &z_surf, &z_res->base,
531b8e80941Smrg                                   z_res->aux.usage, level, true);
532b8e80941Smrg   }
533b8e80941Smrg
534b8e80941Smrg   struct blorp_batch blorp_batch;
535b8e80941Smrg   blorp_batch_init(&ice->blorp, &blorp_batch, batch, blorp_flags);
536b8e80941Smrg
537b8e80941Smrg   if (stencil_res) {
538b8e80941Smrg      iris_blorp_surf_for_resource(&ice->vtbl, &stencil_surf,
539b8e80941Smrg                                   &stencil_res->base, stencil_res->aux.usage,
540b8e80941Smrg                                   level, true);
541b8e80941Smrg   }
542b8e80941Smrg
543b8e80941Smrg   blorp_clear_depth_stencil(&blorp_batch, &z_surf, &stencil_surf,
544b8e80941Smrg                             level, box->z, box->depth,
545b8e80941Smrg                             box->x, box->y,
546b8e80941Smrg                             box->x + box->width,
547b8e80941Smrg                             box->y + box->height,
548b8e80941Smrg                             clear_depth && z_res, depth,
549b8e80941Smrg                             clear_stencil && stencil_res ? 0xff : 0, stencil);
550b8e80941Smrg
551b8e80941Smrg   blorp_batch_finish(&blorp_batch);
552b8e80941Smrg   iris_flush_and_dirty_for_history(ice, batch, res);
553b8e80941Smrg
554b8e80941Smrg   if (z_res) {
555b8e80941Smrg      iris_resource_finish_depth(ice, z_res, level,
556b8e80941Smrg                                 box->z, box->depth, true);
557b8e80941Smrg   }
558b8e80941Smrg}
559b8e80941Smrg
560b8e80941Smrg/**
561b8e80941Smrg * The pipe->clear() driver hook.
562b8e80941Smrg *
563b8e80941Smrg * This clears buffers attached to the current draw framebuffer.
564b8e80941Smrg */
565b8e80941Smrgstatic void
566b8e80941Smrgiris_clear(struct pipe_context *ctx,
567b8e80941Smrg           unsigned buffers,
568b8e80941Smrg           const union pipe_color_union *p_color,
569b8e80941Smrg           double depth,
570b8e80941Smrg           unsigned stencil)
571b8e80941Smrg{
572b8e80941Smrg   struct iris_context *ice = (void *) ctx;
573b8e80941Smrg   struct pipe_framebuffer_state *cso_fb = &ice->state.framebuffer;
574b8e80941Smrg
575b8e80941Smrg   assert(buffers != 0);
576b8e80941Smrg
577b8e80941Smrg   if (buffers & PIPE_CLEAR_DEPTHSTENCIL) {
578b8e80941Smrg      struct pipe_surface *psurf = cso_fb->zsbuf;
579b8e80941Smrg      struct pipe_box box = {
580b8e80941Smrg         .width = cso_fb->width,
581b8e80941Smrg         .height = cso_fb->height,
582b8e80941Smrg         .depth = psurf->u.tex.last_layer - psurf->u.tex.first_layer + 1,
583b8e80941Smrg         .z = psurf->u.tex.first_layer,
584b8e80941Smrg      };
585b8e80941Smrg
586b8e80941Smrg      clear_depth_stencil(ice, psurf->texture, psurf->u.tex.level, &box, true,
587b8e80941Smrg                          buffers & PIPE_CLEAR_DEPTH,
588b8e80941Smrg                          buffers & PIPE_CLEAR_STENCIL,
589b8e80941Smrg                          depth, stencil);
590b8e80941Smrg   }
591b8e80941Smrg
592b8e80941Smrg   if (buffers & PIPE_CLEAR_COLOR) {
593b8e80941Smrg      /* pipe_color_union and isl_color_value are interchangeable */
594b8e80941Smrg      union isl_color_value *color = (void *) p_color;
595b8e80941Smrg
596b8e80941Smrg      for (unsigned i = 0; i < cso_fb->nr_cbufs; i++) {
597b8e80941Smrg         if (buffers & (PIPE_CLEAR_COLOR0 << i)) {
598b8e80941Smrg            struct pipe_surface *psurf = cso_fb->cbufs[i];
599b8e80941Smrg            struct iris_surface *isurf = (void *) psurf;
600b8e80941Smrg            struct pipe_box box = {
601b8e80941Smrg               .width = cso_fb->width,
602b8e80941Smrg               .height = cso_fb->height,
603b8e80941Smrg               .depth = psurf->u.tex.last_layer - psurf->u.tex.first_layer + 1,
604b8e80941Smrg               .z = psurf->u.tex.first_layer,
605b8e80941Smrg            };
606b8e80941Smrg
607b8e80941Smrg            clear_color(ice, psurf->texture, psurf->u.tex.level, &box,
608b8e80941Smrg                        true, isurf->view.format, isurf->view.swizzle,
609b8e80941Smrg                        *color);
610b8e80941Smrg         }
611b8e80941Smrg      }
612b8e80941Smrg   }
613b8e80941Smrg}
614b8e80941Smrg
615b8e80941Smrg/**
616b8e80941Smrg * The pipe->clear_texture() driver hook.
617b8e80941Smrg *
618b8e80941Smrg * This clears the given texture resource.
619b8e80941Smrg */
620b8e80941Smrgstatic void
621b8e80941Smrgiris_clear_texture(struct pipe_context *ctx,
622b8e80941Smrg                   struct pipe_resource *p_res,
623b8e80941Smrg                   unsigned level,
624b8e80941Smrg                   const struct pipe_box *box,
625b8e80941Smrg                   const void *data)
626b8e80941Smrg{
627b8e80941Smrg   struct iris_context *ice = (void *) ctx;
628b8e80941Smrg   struct iris_screen *screen = (void *) ctx->screen;
629b8e80941Smrg   const struct gen_device_info *devinfo = &screen->devinfo;
630b8e80941Smrg
631b8e80941Smrg   if (util_format_is_depth_or_stencil(p_res->format)) {
632b8e80941Smrg      const struct util_format_description *fmt_desc =
633b8e80941Smrg         util_format_description(p_res->format);
634b8e80941Smrg
635b8e80941Smrg      float depth = 0.0;
636b8e80941Smrg      uint8_t stencil = 0;
637b8e80941Smrg
638b8e80941Smrg      if (fmt_desc->unpack_z_float)
639b8e80941Smrg         fmt_desc->unpack_z_float(&depth, 0, data, 0, 1, 1);
640b8e80941Smrg
641b8e80941Smrg      if (fmt_desc->unpack_s_8uint)
642b8e80941Smrg         fmt_desc->unpack_s_8uint(&stencil, 0, data, 0, 1, 1);
643b8e80941Smrg
644b8e80941Smrg      clear_depth_stencil(ice, p_res, level, box, true, true, true,
645b8e80941Smrg                          depth, stencil);
646b8e80941Smrg   } else {
647b8e80941Smrg      union isl_color_value color;
648b8e80941Smrg      struct iris_resource *res = (void *) p_res;
649b8e80941Smrg      enum isl_format format = res->surf.format;
650b8e80941Smrg
651b8e80941Smrg      if (!isl_format_supports_rendering(devinfo, format)) {
652b8e80941Smrg         const struct isl_format_layout *fmtl = isl_format_get_layout(format);
653b8e80941Smrg         // XXX: actually just get_copy_format_for_bpb from BLORP
654b8e80941Smrg         // XXX: don't cut and paste this
655b8e80941Smrg         switch (fmtl->bpb) {
656b8e80941Smrg         case 8:   format = ISL_FORMAT_R8_UINT;           break;
657b8e80941Smrg         case 16:  format = ISL_FORMAT_R8G8_UINT;         break;
658b8e80941Smrg         case 24:  format = ISL_FORMAT_R8G8B8_UINT;       break;
659b8e80941Smrg         case 32:  format = ISL_FORMAT_R8G8B8A8_UINT;     break;
660b8e80941Smrg         case 48:  format = ISL_FORMAT_R16G16B16_UINT;    break;
661b8e80941Smrg         case 64:  format = ISL_FORMAT_R16G16B16A16_UINT; break;
662b8e80941Smrg         case 96:  format = ISL_FORMAT_R32G32B32_UINT;    break;
663b8e80941Smrg         case 128: format = ISL_FORMAT_R32G32B32A32_UINT; break;
664b8e80941Smrg         default:
665b8e80941Smrg            unreachable("Unknown format bpb");
666b8e80941Smrg         }
667b8e80941Smrg
668b8e80941Smrg         /* No aux surfaces for non-renderable surfaces */
669b8e80941Smrg         assert(res->aux.usage == ISL_AUX_USAGE_NONE);
670b8e80941Smrg      }
671b8e80941Smrg
672b8e80941Smrg      isl_color_value_unpack(&color, format, data);
673b8e80941Smrg
674b8e80941Smrg      clear_color(ice, p_res, level, box, true, format,
675b8e80941Smrg                  ISL_SWIZZLE_IDENTITY, color);
676b8e80941Smrg   }
677b8e80941Smrg}
678b8e80941Smrg
679b8e80941Smrg/**
680b8e80941Smrg * The pipe->clear_render_target() driver hook.
681b8e80941Smrg *
682b8e80941Smrg * This clears the given render target surface.
683b8e80941Smrg */
684b8e80941Smrgstatic void
685b8e80941Smrgiris_clear_render_target(struct pipe_context *ctx,
686b8e80941Smrg                         struct pipe_surface *psurf,
687b8e80941Smrg                         const union pipe_color_union *p_color,
688b8e80941Smrg                         unsigned dst_x, unsigned dst_y,
689b8e80941Smrg                         unsigned width, unsigned height,
690b8e80941Smrg                         bool render_condition_enabled)
691b8e80941Smrg{
692b8e80941Smrg   struct iris_context *ice = (void *) ctx;
693b8e80941Smrg   struct iris_surface *isurf = (void *) psurf;
694b8e80941Smrg   struct pipe_box box = {
695b8e80941Smrg      .x = dst_x,
696b8e80941Smrg      .y = dst_y,
697b8e80941Smrg      .z = psurf->u.tex.first_layer,
698b8e80941Smrg      .width = width,
699b8e80941Smrg      .height = height,
700b8e80941Smrg      .depth = psurf->u.tex.last_layer - psurf->u.tex.first_layer + 1
701b8e80941Smrg   };
702b8e80941Smrg
703b8e80941Smrg   /* pipe_color_union and isl_color_value are interchangeable */
704b8e80941Smrg   union isl_color_value *color = (void *) p_color;
705b8e80941Smrg
706b8e80941Smrg   clear_color(ice, psurf->texture, psurf->u.tex.level, &box,
707b8e80941Smrg               render_condition_enabled,
708b8e80941Smrg               isurf->view.format, isurf->view.swizzle, *color);
709b8e80941Smrg}
710b8e80941Smrg
711b8e80941Smrg/**
712b8e80941Smrg * The pipe->clear_depth_stencil() driver hook.
713b8e80941Smrg *
714b8e80941Smrg * This clears the given depth/stencil surface.
715b8e80941Smrg */
716b8e80941Smrgstatic void
717b8e80941Smrgiris_clear_depth_stencil(struct pipe_context *ctx,
718b8e80941Smrg                         struct pipe_surface *psurf,
719b8e80941Smrg                         unsigned flags,
720b8e80941Smrg                         double depth,
721b8e80941Smrg                         unsigned stencil,
722b8e80941Smrg                         unsigned dst_x, unsigned dst_y,
723b8e80941Smrg                         unsigned width, unsigned height,
724b8e80941Smrg                         bool render_condition_enabled)
725b8e80941Smrg{
726b8e80941Smrg   struct iris_context *ice = (void *) ctx;
727b8e80941Smrg   struct pipe_box box = {
728b8e80941Smrg      .x = dst_x,
729b8e80941Smrg      .y = dst_y,
730b8e80941Smrg      .z = psurf->u.tex.first_layer,
731b8e80941Smrg      .width = width,
732b8e80941Smrg      .height = height,
733b8e80941Smrg      .depth = psurf->u.tex.last_layer - psurf->u.tex.first_layer + 1
734b8e80941Smrg   };
735b8e80941Smrg
736b8e80941Smrg   assert(util_format_is_depth_or_stencil(psurf->texture->format));
737b8e80941Smrg
738b8e80941Smrg   clear_depth_stencil(ice, psurf->texture, psurf->u.tex.level, &box,
739b8e80941Smrg                       render_condition_enabled,
740b8e80941Smrg                       flags & PIPE_CLEAR_DEPTH, flags & PIPE_CLEAR_STENCIL,
741b8e80941Smrg                       depth, stencil);
742b8e80941Smrg}
743b8e80941Smrg
744b8e80941Smrgvoid
745b8e80941Smrgiris_init_clear_functions(struct pipe_context *ctx)
746b8e80941Smrg{
747b8e80941Smrg   ctx->clear = iris_clear;
748b8e80941Smrg   ctx->clear_texture = iris_clear_texture;
749b8e80941Smrg   ctx->clear_render_target = iris_clear_render_target;
750b8e80941Smrg   ctx->clear_depth_stencil = iris_clear_depth_stencil;
751b8e80941Smrg}
752