util: Split the pack/unpack functions out of the format desc.
[mesa.git] / src / gallium / drivers / iris / iris_clear.c
index 163783a8504b45990ed64f83b8edb32c4d574c02..3d60c6bfbe3a3b06606eb2b889c27f8ce8f8dfc5 100644 (file)
@@ -34,7 +34,6 @@
 #include "iris_resource.h"
 #include "iris_screen.h"
 #include "intel/compiler/brw_compiler.h"
-#include "util/format_srgb.h"
 
 static bool
 iris_is_color_fast_clear_compatible(struct iris_context *ice,
@@ -69,7 +68,6 @@ can_fast_clear_color(struct iris_context *ice,
                      struct pipe_resource *p_res,
                      unsigned level,
                      const struct pipe_box *box,
-                     enum isl_format format,
                      enum isl_format render_format,
                      union isl_color_value color)
 {
@@ -88,13 +86,24 @@ can_fast_clear_color(struct iris_context *ice,
       return false;
    }
 
+   /* Disable sRGB fast-clears for non-0/1 color values. For texturing and
+    * draw calls, HW expects the clear color to be in two different color
+    * spaces after sRGB fast-clears - sRGB in the former and linear in the
+    * latter. By limiting the allowable values to 0/1, both color space
+    * requirements are satisfied.
+    */
+   if (isl_format_is_srgb(render_format) &&
+       !isl_color_value_is_zero_one(color, render_format)) {
+      return false;
+   }
+
    /* We store clear colors as floats or uints as needed.  If there are
     * texture views in play, the formats will not properly be respected
     * during resolves because the resolve operations only know about the
     * resource and not the renderbuffer.
     */
-   if (isl_format_srgb_to_linear(render_format) !=
-       isl_format_srgb_to_linear(format)) {
+   if (!iris_render_formats_color_compatible(render_format, res->surf.format,
+                                             color)) {
       return false;
    }
 
@@ -102,7 +111,7 @@ can_fast_clear_color(struct iris_context *ice,
     * see intel_miptree_create_for_dri_image()
     */
 
-   if (!iris_is_color_fast_clear_compatible(ice, format, color))
+   if (!iris_is_color_fast_clear_compatible(ice, res->surf.format, color))
       return false;
 
    return true;
@@ -111,7 +120,6 @@ can_fast_clear_color(struct iris_context *ice,
 static union isl_color_value
 convert_fast_clear_color(struct iris_context *ice,
                          struct iris_resource *res,
-                         enum isl_format render_format,
                          const union isl_color_value color)
 {
    union isl_color_value override_color = color;
@@ -138,7 +146,7 @@ convert_fast_clear_color(struct iris_context *ice,
 
    if (util_format_is_unorm(format)) {
       for (int i = 0; i < 4; i++)
-         override_color.f32[i] = CLAMP(override_color.f32[i], 0.0f, 1.0f);
+         override_color.f32[i] = SATURATE(override_color.f32[i]);
    } else if (util_format_is_snorm(format)) {
       for (int i = 0; i < 4; i++)
          override_color.f32[i] = CLAMP(override_color.f32[i], -1.0f, 1.0f);
@@ -175,14 +183,6 @@ convert_fast_clear_color(struct iris_context *ice,
          override_color.f32[3] = 1.0f;
    }
 
-   /* Handle linear to SRGB conversion */
-   if (isl_format_is_srgb(render_format)) {
-      for (int i = 0; i < 3; i++) {
-         override_color.f32[i] =
-            util_format_linear_to_srgb_float(override_color.f32[i]);
-      }
-   }
-
    return override_color;
 }
 
@@ -200,7 +200,7 @@ fast_clear_color(struct iris_context *ice,
    const enum isl_aux_state aux_state =
       iris_resource_get_aux_state(res, level, box->z);
 
-   color = convert_fast_clear_color(ice, res, format, color);
+   color = convert_fast_clear_color(ice, res, color);
 
    bool color_changed = !!memcmp(&res->aux.clear_color, &color,
                                  sizeof(color));
@@ -254,7 +254,7 @@ fast_clear_color(struct iris_context *ice,
              * Fortunately, few applications ever change their clear color at
              * different levels/layers, so this shouldn't happen often.
              */
-            iris_resource_prepare_access(ice, batch, res,
+            iris_resource_prepare_access(ice, res,
                                          res_lvl, 1, layer, 1,
                                          res->aux.usage,
                                          false);
@@ -296,6 +296,8 @@ fast_clear_color(struct iris_context *ice,
                               "fast clear: pre-flush",
                               PIPE_CONTROL_RENDER_TARGET_FLUSH);
 
+   iris_batch_sync_region_start(batch);
+
    /* If we reach this point, we need to fast clear to change the state to
     * ISL_AUX_STATE_CLEAR, or to update the fast clear color (or both).
     */
@@ -308,14 +310,7 @@ fast_clear_color(struct iris_context *ice,
    iris_blorp_surf_for_resource(&batch->screen->isl_dev, &surf,
                                 p_res, res->aux.usage, level, true);
 
-   /* In newer gens (> 9), the hardware will do a linear -> sRGB conversion of
-    * the clear color during the fast clear, if the surface format is of sRGB
-    * type. We use the linear version of the surface format here to prevent
-    * that from happening, since we already do our own linear -> sRGB
-    * conversion in convert_fast_clear_color().
-    */
-   blorp_fast_clear(&blorp_batch, &surf, isl_format_srgb_to_linear(format),
-                    ISL_SWIZZLE_IDENTITY,
+   blorp_fast_clear(&blorp_batch, &surf, format, ISL_SWIZZLE_IDENTITY,
                     level, box->z, box->depth,
                     box->x, box->y, box->x + box->width,
                     box->y + box->height);
@@ -323,10 +318,12 @@ fast_clear_color(struct iris_context *ice,
    iris_emit_end_of_pipe_sync(batch,
                               "fast clear: post flush",
                               PIPE_CONTROL_RENDER_TARGET_FLUSH);
+   iris_batch_sync_region_end(batch);
 
    iris_resource_set_aux_state(ice, res, level, box->z,
                                box->depth, ISL_AUX_STATE_CLEAR);
-   ice->state.dirty |= IRIS_ALL_DIRTY_BINDINGS;
+   ice->state.dirty |= IRIS_DIRTY_RENDER_BUFFER;
+   ice->state.stage_dirty |= IRIS_ALL_STAGE_DIRTY_BINDINGS;
    return;
 }
 
@@ -360,7 +357,7 @@ clear_color(struct iris_context *ice,
    iris_batch_maybe_flush(batch, 1500);
 
    bool can_fast_clear = can_fast_clear_color(ice, p_res, level, box,
-                                              res->surf.format, format, color);
+                                              format, color);
    if (can_fast_clear) {
       fast_clear_color(ice, res, level, box, format, color,
                        blorp_flags);
@@ -369,16 +366,18 @@ clear_color(struct iris_context *ice,
 
    bool color_write_disable[4] = { false, false, false, false };
    enum isl_aux_usage aux_usage =
-      iris_resource_render_aux_usage(ice, res, format,
-                                     false, false);
+      iris_resource_render_aux_usage(ice, res, format, false);
 
    iris_resource_prepare_render(ice, batch, res, level,
                                 box->z, box->depth, aux_usage);
+   iris_emit_buffer_barrier_for(batch, res->bo, IRIS_DOMAIN_RENDER_WRITE);
 
    struct blorp_surf surf;
    iris_blorp_surf_for_resource(&batch->screen->isl_dev, &surf,
                                 p_res, aux_usage, level, true);
 
+   iris_batch_sync_region_start(batch);
+
    struct blorp_batch blorp_batch;
    blorp_batch_init(&ice->blorp, &blorp_batch, batch, blorp_flags);
 
@@ -392,6 +391,8 @@ clear_color(struct iris_context *ice,
                color, color_write_disable);
 
    blorp_batch_finish(&blorp_batch);
+   iris_batch_sync_region_end(batch);
+
    iris_flush_and_dirty_for_history(ice, batch, res,
                                     PIPE_CONTROL_RENDER_TARGET_FLUSH,
                                     "cache history: post color clear");
@@ -582,29 +583,34 @@ clear_depth_stencil(struct iris_context *ice,
    /* At this point, we might have fast cleared the depth buffer. So if there's
     * no stencil clear pending, return early.
     */
-   if (!(clear_depth || clear_stencil)) {
+   if (!(clear_depth || (clear_stencil && stencil_res))) {
       return;
    }
 
    if (clear_depth && z_res) {
       iris_resource_prepare_depth(ice, batch, z_res, level, box->z, box->depth);
+      iris_emit_buffer_barrier_for(batch, z_res->bo, IRIS_DOMAIN_DEPTH_WRITE);
       iris_blorp_surf_for_resource(&batch->screen->isl_dev,
                                    &z_surf, &z_res->base, z_res->aux.usage,
                                    level, true);
    }
 
-   struct blorp_batch blorp_batch;
-   blorp_batch_init(&ice->blorp, &blorp_batch, batch, blorp_flags);
-
    uint8_t stencil_mask = clear_stencil && stencil_res ? 0xff : 0;
    if (stencil_mask) {
-      iris_resource_prepare_access(ice, batch, stencil_res, level, 1, box->z,
+      iris_resource_prepare_access(ice, stencil_res, level, 1, box->z,
                                    box->depth, stencil_res->aux.usage, false);
+      iris_emit_buffer_barrier_for(batch, stencil_res->bo,
+                                   IRIS_DOMAIN_DEPTH_WRITE);
       iris_blorp_surf_for_resource(&batch->screen->isl_dev,
                                    &stencil_surf, &stencil_res->base,
                                    stencil_res->aux.usage, level, true);
    }
 
+   iris_batch_sync_region_start(batch);
+
+   struct blorp_batch blorp_batch;
+   blorp_batch_init(&ice->blorp, &blorp_batch, batch, blorp_flags);
+
    blorp_clear_depth_stencil(&blorp_batch, &z_surf, &stencil_surf,
                              level, box->z, box->depth,
                              box->x, box->y,
@@ -614,6 +620,8 @@ clear_depth_stencil(struct iris_context *ice,
                              stencil_mask, stencil);
 
    blorp_batch_finish(&blorp_batch);
+   iris_batch_sync_region_end(batch);
+
    iris_flush_and_dirty_for_history(ice, batch, res, 0,
                                     "cache history: post slow ZS clear");
 
@@ -636,6 +644,7 @@ clear_depth_stencil(struct iris_context *ice,
 static void
 iris_clear(struct pipe_context *ctx,
            unsigned buffers,
+           const struct pipe_scissor_state *scissor_state,
            const union pipe_color_union *p_color,
            double depth,
            unsigned stencil)
@@ -645,15 +654,23 @@ iris_clear(struct pipe_context *ctx,
 
    assert(buffers != 0);
 
+   struct pipe_box box = {
+      .width = cso_fb->width,
+      .height = cso_fb->height,
+   };
+
+   if (scissor_state) {
+      box.x = scissor_state->minx;
+      box.y = scissor_state->miny;
+      box.width = MIN2(box.width, scissor_state->maxx - scissor_state->minx);
+      box.height = MIN2(box.height, scissor_state->maxy - scissor_state->miny);
+   }
+
    if (buffers & PIPE_CLEAR_DEPTHSTENCIL) {
       struct pipe_surface *psurf = cso_fb->zsbuf;
-      struct pipe_box box = {
-         .width = cso_fb->width,
-         .height = cso_fb->height,
-         .depth = psurf->u.tex.last_layer - psurf->u.tex.first_layer + 1,
-         .z = psurf->u.tex.first_layer,
-      };
 
+      box.depth = psurf->u.tex.last_layer - psurf->u.tex.first_layer + 1;
+      box.z = psurf->u.tex.first_layer,
       clear_depth_stencil(ice, psurf->texture, psurf->u.tex.level, &box, true,
                           buffers & PIPE_CLEAR_DEPTH,
                           buffers & PIPE_CLEAR_STENCIL,
@@ -668,12 +685,8 @@ iris_clear(struct pipe_context *ctx,
          if (buffers & (PIPE_CLEAR_COLOR0 << i)) {
             struct pipe_surface *psurf = cso_fb->cbufs[i];
             struct iris_surface *isurf = (void *) psurf;
-            struct pipe_box box = {
-               .width = cso_fb->width,
-               .height = cso_fb->height,
-               .depth = psurf->u.tex.last_layer - psurf->u.tex.first_layer + 1,
-               .z = psurf->u.tex.first_layer,
-            };
+            box.depth = psurf->u.tex.last_layer - psurf->u.tex.first_layer + 1,
+            box.z = psurf->u.tex.first_layer,
 
             clear_color(ice, psurf->texture, psurf->u.tex.level, &box,
                         true, isurf->view.format, isurf->view.swizzle,
@@ -697,19 +710,23 @@ iris_clear_texture(struct pipe_context *ctx,
 {
    struct iris_context *ice = (void *) ctx;
    struct iris_screen *screen = (void *) ctx->screen;
+   struct iris_resource *res = (void *) p_res;
    const struct gen_device_info *devinfo = &screen->devinfo;
 
+   if (iris_resource_unfinished_aux_import(res))
+      iris_resource_finish_aux_import(ctx->screen, res);
+
    if (util_format_is_depth_or_stencil(p_res->format)) {
-      const struct util_format_description *fmt_desc =
-         util_format_description(p_res->format);
+      const struct util_format_unpack_description *unpack =
+         util_format_unpack_description(p_res->format);
 
       float depth = 0.0;
       uint8_t stencil = 0;
 
-      if (fmt_desc->unpack_z_float)
+      if (unpack->unpack_z_float)
          util_format_unpack_z_float(p_res->format, &depth, data, 1);
 
-      if (fmt_desc->unpack_s_8uint)
+      if (unpack->unpack_s_8uint)
          util_format_unpack_s_8uint(p_res->format, &stencil, data, 1);
 
       clear_depth_stencil(ice, p_res, level, box, true, true, true,