anv: Only fast clear single-slice images
authorJason Ekstrand <jason.ekstrand@intel.com>
Thu, 18 Jan 2018 05:31:09 +0000 (21:31 -0800)
committerJason Ekstrand <jason.ekstrand@intel.com>
Fri, 9 Feb 2018 00:35:31 +0000 (16:35 -0800)
The current strategy we use for managing resolves has an issues where we
track clear colors and the need for resolves per-LOD but we still allow
resolves of only a subset of the slices in any given LOD and doing so
sets the "needs resolve" flag for that LOD to false while leaving the
remaining layers unresolved.  This patch is only the first step and does
not, by itself fix anything.  However, it's fairly self-contained and
splitting it out means any performance regressions should bisect to this
nice obvious commit rather than to the giant "rework aux tracking"
commit.

Nanley and I did some testing and none of the applications we tested
even tried to fast-clear anything other than the first slice of an
image.  The test was done by adding a printf right before we call
blorp_fast_clear if we were every going to touch any slice other than
the first with a fast-clear.  Due to the way the original code was
structured, this would not have included applications which only cleared
a subset of layers.  The applications tested were:

 * All Sascha Willems demos
 * Aztec Ruins
 * Dota 2
 * The Talos Principle
 * Mad Max
 * Warhammer 40,000: Dawn of War III
 * Serious Sam Fusion 2017: BFE

While not the full list of shipping applications, it's a pretty good
spread and covers most of the engines we've seen running on our driver.
If this is ever shown to be a performance problem in the future, we can
reconsider our strategy.

Reviewed-by: Nanley Chery <nanley.g.chery@intel.com>
src/intel/vulkan/genX_cmd_buffer.c

index ebb102c0f88095ea95be5b412309dffaac163d87..fee1876ce413e1ce3f39fa0e4f5d31c346f66df1 100644 (file)
@@ -309,23 +309,6 @@ color_attachment_compute_aux_usage(struct anv_device * device,
       if (GEN_GEN <= 8 && !att_state->clear_color_is_zero_one)
          att_state->fast_clear = false;
 
-      /* We allow fast clears when all aux layers of the miplevel are targeted.
-       * See add_fast_clear_state_buffer() for more information. Also, because
-       * we only either do a fast clear or a normal clear and not both, this
-       * complies with the gen7 restriction of not fast-clearing multiple
-       * layers.
-       */
-      if (cmd_state->framebuffer->layers !=
-          anv_image_aux_layers(iview->image, VK_IMAGE_ASPECT_COLOR_BIT,
-                               iview->planes[0].isl.base_level)) {
-         att_state->fast_clear = false;
-         if (GEN_GEN == 7) {
-            anv_perf_warn(device->instance, iview->image,
-                          "Not fast-clearing the first layer in "
-                          "a multi-layer fast clear.");
-         }
-      }
-
       /* We only allow fast clears in the GENERAL layout if the auxiliary
        * buffer is always enabled and the fast-clear value is all 0's. See
        * add_fast_clear_state_buffer() for more information.
@@ -337,6 +320,23 @@ color_attachment_compute_aux_usage(struct anv_device * device,
          att_state->fast_clear = false;
       }
 
+      /* We only allow fast clears to the first slice of an image (level 0,
+       * layer 0) and only for the entire slice.  This guarantees us that, at
+       * any given time, there is only one clear color on any given image at
+       * any given time.  At the time of our testing (Jan 17, 2018), there
+       * were no known applications which would benefit from fast-clearing
+       * more than just the first slice.
+       */
+      if (att_state->fast_clear &&
+          (iview->planes[0].isl.base_level > 0 ||
+           iview->image->extent.depth > 0 ||
+           iview->image->array_size > 0)) {
+         anv_perf_warn(device->instance, iview->image,
+                       "Rendering to a multi-LOD or multi-layer framebuffer "
+                       "with LOAD_OP_CLEAR.  Not fast-clearing");
+         att_state->fast_clear = false;
+      }
+
       if (att_state->fast_clear) {
          memcpy(fast_clear_color->u32, att_state->clear_value.color.uint32,
                 sizeof(fast_clear_color->u32));