iris: Allocate buffer space for the fast clear color.
authorRafael Antognolli <rafael.antognolli@intel.com>
Fri, 15 Feb 2019 22:45:05 +0000 (14:45 -0800)
committerRafael Antognolli <rafael.antognolli@intel.com>
Wed, 20 Mar 2019 23:46:25 +0000 (16:46 -0700)
Also store clear color in the iris_resource.

Always allocate clear color state buffer.

v2:
 - Make clear_color_offset be 64 bits (Ken).
 - Simplify the logic to decide when to memset the aux buffer (Ken).

Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
src/gallium/drivers/iris/iris_resource.c
src/gallium/drivers/iris/iris_resource.h

index 8bb0b3faa719f7d06aea047ed89fe1d060d00a27..3e4b7e71c4aeebfe7f91faec65adf214ce2411f5 100644 (file)
@@ -200,14 +200,14 @@ void
 iris_resource_disable_aux(struct iris_resource *res)
 {
    iris_bo_unreference(res->aux.bo);
+   iris_bo_unreference(res->aux.clear_color_bo);
    free(res->aux.state);
 
-   // XXX: clear color BO
-
    res->aux.usage = ISL_AUX_USAGE_NONE;
    res->aux.possible_usages = 1 << ISL_AUX_USAGE_NONE;
    res->aux.surf.size_B = 0;
    res->aux.bo = NULL;
+   res->aux.clear_color_bo = NULL;
    res->aux.state = NULL;
 }
 
@@ -294,6 +294,11 @@ iris_resource_alloc_aux(struct iris_screen *screen, struct iris_resource *res)
    UNUSED bool ok = false;
    uint8_t memset_value = 0;
    uint32_t alloc_flags = 0;
+   const struct gen_device_info *devinfo = &screen->devinfo;
+   const unsigned clear_color_state_size = devinfo->gen >= 10 ?
+      screen->isl_dev.ss.clear_color_state_size :
+      screen->isl_dev.ss.clear_value_size;
+
 
    assert(!res->aux.bo);
 
@@ -353,32 +358,50 @@ iris_resource_alloc_aux(struct iris_screen *screen, struct iris_resource *res)
    if (!res->aux.state)
       return false;
 
+   uint64_t size = res->aux.surf.size_B;
+
+   /* Allocate space in the buffer for storing the clear color. On modern
+    * platforms (gen > 9), we can read it directly from such buffer.
+    *
+    * On gen <= 9, we are going to store the clear color on the buffer
+    * anyways, and copy it back to the surface state during state emission.
+    */
+   res->aux.clear_color_offset = size;
+   size += clear_color_state_size;
+
    /* Allocate the auxiliary buffer.  ISL has stricter set of alignment rules
     * the drm allocator.  Therefore, one can pass the ISL dimensions in terms
     * of bytes instead of trying to recalculate based on different format
     * block sizes.
     */
-   res->aux.bo = iris_bo_alloc_tiled(screen->bufmgr, "aux buffer",
-                                     res->aux.surf.size_B,
+   res->aux.bo = iris_bo_alloc_tiled(screen->bufmgr, "aux buffer", size,
                                      IRIS_MEMZONE_OTHER, I915_TILING_Y,
                                      res->aux.surf.row_pitch_B, alloc_flags);
    if (!res->aux.bo) {
-      iris_resource_disable_aux(res);
       return false;
    }
 
-   /* Optionally, initialize the auxiliary data to the desired value. */
-   if (memset_value != 0) {
+   if (!(alloc_flags & BO_ALLOC_ZEROED)) {
       void *map = iris_bo_map(NULL, res->aux.bo, MAP_WRITE | MAP_RAW);
+
       if (!map) {
          iris_resource_disable_aux(res);
          return false;
       }
 
-      memset(map, memset_value, res->aux.surf.size_B);
+      if (memset_value != 0)
+         memset(map, memset_value, res->aux.surf.size_B);
+
+      /* Zero the indirect clear color to match ::fast_clear_color. */
+      memset((char *)map + res->aux.clear_color_offset, 0,
+             clear_color_state_size);
+
       iris_bo_unmap(res->aux.bo);
    }
 
+   res->aux.clear_color_bo = res->aux.bo;
+   iris_bo_reference(res->aux.clear_color_bo);
+
    if (res->aux.usage == ISL_AUX_USAGE_HIZ) {
       for (unsigned level = 0; level < res->surf.levels; ++level) {
          uint32_t width = u_minify(res->surf.phys_level0_sa.width, level);
@@ -1371,6 +1394,56 @@ iris_flush_and_dirty_for_history(struct iris_context *ice,
    ice->state.dirty |= dirty;
 }
 
+bool
+iris_resource_set_clear_color(struct iris_context *ice,
+                              struct iris_resource *res,
+                              union isl_color_value color)
+{
+   if (memcmp(&res->aux.clear_color, &color, sizeof(color)) != 0) {
+      res->aux.clear_color = color;
+      struct iris_batch *batch = &ice->batches[IRIS_BATCH_RENDER];
+      /* We can't update the clear color while the hardware is still using
+       * the previous one for a resolve or sampling from it. Make sure that
+       * there are no pending commands at this point.
+       */
+      /* TODO: Make these pipe controls gen-specific?
+       *
+       * We don't really need them on gen <= 9 where we are reading the
+       * clear color from the surface state and clear_params, so they
+       * shouldn't be needed. On gen11, the clear color is read from this
+       * buffer, but the clear depth is still read from CLEAR_PARAMS, so we
+       * could probably skip it in the HiZ case as well.
+       *
+       * Need to also check that for i965.
+       */
+      iris_emit_pipe_control_flush(batch, PIPE_CONTROL_CS_STALL);
+      for (int i = 0; i < 4; i++) {
+         ice->vtbl.store_data_imm32(batch, res->aux.clear_color_bo,
+                                    res->aux.clear_color_offset + i * 4,
+                                    color.u32[i]);
+      }
+      iris_emit_pipe_control_flush(batch,
+                                   PIPE_CONTROL_STATE_CACHE_INVALIDATE);
+      return true;
+   }
+
+   return false;
+}
+
+union isl_color_value
+iris_resource_get_clear_color(const struct iris_resource *res,
+                              struct iris_bo **clear_color_bo,
+                              uint64_t *clear_color_offset)
+{
+   assert(res->aux.bo);
+
+   if (clear_color_bo)
+      *clear_color_bo = res->aux.clear_color_bo;
+   if (clear_color_offset)
+      *clear_color_offset = res->aux.clear_color_offset;
+   return res->aux.clear_color;
+}
+
 static enum pipe_format
 iris_resource_get_internal_format(struct pipe_resource *p_res)
 {
index d6bef37d898a778f173cb1c4337f8767387d3e7e..3349d3eafc0678f1c472571ec50fc97cb01c7744 100644 (file)
@@ -86,6 +86,18 @@ struct iris_resource {
       /** Offset into 'bo' where the auxiliary surface starts. */
       uint32_t offset;
 
+      /**
+       * Fast clear color for this surface.  For depth surfaces, the clear
+       * value is stored as a float32 in the red component.
+       */
+      union isl_color_value clear_color;
+
+      /** Buffer object containing the indirect clear color.  */
+      struct iris_bo *clear_color_bo;
+
+      /** Offset into bo where the clear color can be found.  */
+      uint64_t clear_color_offset;
+
       /**
        * \brief The type of auxiliary compression used by this resource.
        *
@@ -207,6 +219,13 @@ struct pipe_resource *iris_resource_get_separate_stencil(struct pipe_resource *)
 void iris_get_depth_stencil_resources(struct pipe_resource *res,
                                       struct iris_resource **out_z,
                                       struct iris_resource **out_s);
+bool iris_resource_set_clear_color(struct iris_context *ice,
+                                   struct iris_resource *res,
+                                   union isl_color_value color);
+union isl_color_value
+iris_resource_get_clear_color(const struct iris_resource *res,
+                              struct iris_bo **clear_color_bo,
+                              uint64_t *clear_color_offset);
 
 void iris_init_screen_resource_functions(struct pipe_screen *pscreen);