anv: Implement VK_KHX_external_memory
[mesa.git] / src / intel / vulkan / genX_cmd_buffer.c
index 39856b9af7c77c2580433df3a727c26bdb5094e4..ddb22c4539001191a429154483a1d0b544bb5fe8 100644 (file)
@@ -291,27 +291,21 @@ color_attachment_compute_aux_usage(struct anv_device *device,
       att_state->input_aux_usage = ISL_AUX_USAGE_CCS_E;
    } else if (att_state->fast_clear) {
       att_state->aux_usage = ISL_AUX_USAGE_CCS_D;
-      if (GEN_GEN >= 9 &&
-          !isl_format_supports_ccs_e(&device->info, iview->isl.format)) {
-         /* From the Sky Lake PRM, RENDER_SURFACE_STATE::AuxiliarySurfaceMode:
-          *
-          *    "If Number of Multisamples is MULTISAMPLECOUNT_1, AUX_CCS_D
-          *    setting is only allowed if Surface Format supported for Fast
-          *    Clear. In addition, if the surface is bound to the sampling
-          *    engine, Surface Format must be supported for Render Target
-          *    Compression for surfaces bound to the sampling engine."
-          *
-          * In other words, we can't sample from a fast-cleared image if it
-          * doesn't also support color compression.
-          */
-         att_state->input_aux_usage = ISL_AUX_USAGE_NONE;
-      } else if (GEN_GEN >= 8) {
-         /* Broadwell/Skylake can sample from fast-cleared images */
+      /* From the Sky Lake PRM, RENDER_SURFACE_STATE::AuxiliarySurfaceMode:
+       *
+       *    "If Number of Multisamples is MULTISAMPLECOUNT_1, AUX_CCS_D
+       *    setting is only allowed if Surface Format supported for Fast
+       *    Clear. In addition, if the surface is bound to the sampling
+       *    engine, Surface Format must be supported for Render Target
+       *    Compression for surfaces bound to the sampling engine."
+       *
+       * In other words, we can only sample from a fast-cleared image if it
+       * also supports color compression.
+       */
+      if (isl_format_supports_ccs_e(&device->info, iview->isl.format))
          att_state->input_aux_usage = ISL_AUX_USAGE_CCS_D;
-      } else {
-         /* Ivy Bridge and Haswell cannot */
+      else
          att_state->input_aux_usage = ISL_AUX_USAGE_NONE;
-      }
    } else {
       att_state->aux_usage = ISL_AUX_USAGE_NONE;
       att_state->input_aux_usage = ISL_AUX_USAGE_NONE;
@@ -411,23 +405,15 @@ genX(cmd_buffer_setup_attachments)(struct anv_cmd_buffer *cmd_buffer,
                                  VK_ERROR_OUT_OF_HOST_MEMORY);
    }
 
-   bool need_null_state = false;
-   unsigned num_states = 0;
+   /* Reserve one for the NULL state. */
+   unsigned num_states = 1;
    for (uint32_t i = 0; i < pass->attachment_count; ++i) {
-      if (vk_format_is_color(pass->attachments[i].format)) {
+      if (vk_format_is_color(pass->attachments[i].format))
          num_states++;
-      } else {
-         /* We need a null state for any depth-stencil-only subpasses.
-          * Importantly, this includes depth/stencil clears so we create one
-          * whenever we have depth or stencil
-          */
-         need_null_state = true;
-      }
 
       if (need_input_attachment_state(&pass->attachments[i]))
          num_states++;
    }
-   num_states += need_null_state;
 
    const uint32_t ss_stride = align_u32(isl_dev->ss.size, isl_dev->ss.align);
    state->render_pass_states =
@@ -437,11 +423,9 @@ genX(cmd_buffer_setup_attachments)(struct anv_cmd_buffer *cmd_buffer,
    struct anv_state next_state = state->render_pass_states;
    next_state.alloc_size = isl_dev->ss.size;
 
-   if (need_null_state) {
-      state->null_surface_state = next_state;
-      next_state.offset += ss_stride;
-      next_state.map += ss_stride;
-   }
+   state->null_surface_state = next_state;
+   next_state.offset += ss_stride;
+   next_state.map += ss_stride;
 
    for (uint32_t i = 0; i < pass->attachment_count; ++i) {
       if (vk_format_is_color(pass->attachments[i].format)) {
@@ -463,24 +447,22 @@ genX(cmd_buffer_setup_attachments)(struct anv_cmd_buffer *cmd_buffer,
       ANV_FROM_HANDLE(anv_framebuffer, framebuffer, begin->framebuffer);
       assert(pass->attachment_count == framebuffer->attachment_count);
 
-      if (need_null_state) {
-         struct GENX(RENDER_SURFACE_STATE) null_ss = {
-            .SurfaceType = SURFTYPE_NULL,
-            .SurfaceArray = framebuffer->layers > 0,
-            .SurfaceFormat = ISL_FORMAT_R8G8B8A8_UNORM,
+      struct GENX(RENDER_SURFACE_STATE) null_ss = {
+         .SurfaceType = SURFTYPE_NULL,
+         .SurfaceArray = framebuffer->layers > 0,
+         .SurfaceFormat = ISL_FORMAT_R8G8B8A8_UNORM,
 #if GEN_GEN >= 8
-            .TileMode = YMAJOR,
+         .TileMode = YMAJOR,
 #else
-            .TiledSurface = true,
+         .TiledSurface = true,
 #endif
-            .Width = framebuffer->width - 1,
-            .Height = framebuffer->height - 1,
-            .Depth = framebuffer->layers - 1,
-            .RenderTargetViewExtent = framebuffer->layers - 1,
-         };
-         GENX(RENDER_SURFACE_STATE_pack)(NULL, state->null_surface_state.map,
-                                         &null_ss);
-      }
+         .Width = framebuffer->width - 1,
+         .Height = framebuffer->height - 1,
+         .Depth = framebuffer->layers - 1,
+         .RenderTargetViewExtent = framebuffer->layers - 1,
+      };
+      GENX(RENDER_SURFACE_STATE_pack)(NULL, state->null_surface_state.map,
+                                      &null_ss);
 
       for (uint32_t i = 0; i < pass->attachment_count; ++i) {
          struct anv_render_pass_attachment *att = &pass->attachments[i];
@@ -597,6 +579,18 @@ genX(BeginCommandBuffer)(
 
    genX(cmd_buffer_emit_state_base_address)(cmd_buffer);
 
+   /* We sometimes store vertex data in the dynamic state buffer for blorp
+    * operations and our dynamic state stream may re-use data from previous
+    * command buffers.  In order to prevent stale cache data, we flush the VF
+    * cache.  We could do this on every blorp call but that's not really
+    * needed as all of the data will get written by the CPU prior to the GPU
+    * executing anything.  The chances are fairly high that they will use
+    * blorp at least once per primary command buffer so it shouldn't be
+    * wasted.
+    */
+   if (cmd_buffer->level == VK_COMMAND_BUFFER_LEVEL_PRIMARY)
+      cmd_buffer->state.pending_pipe_bits |= ANV_PIPE_VF_CACHE_INVALIDATE_BIT;
+
    VkResult result = VK_SUCCESS;
    if (cmd_buffer->usage_flags &
        VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT) {
@@ -654,6 +648,11 @@ genX(CmdExecuteCommands)(
     */
    genX(cmd_buffer_enable_pma_fix)(primary, false);
 
+   /* The secondary command buffer doesn't know which textures etc. have been
+    * flushed prior to their execution.  Apply those flushes now.
+    */
+   genX(cmd_buffer_apply_pipe_flushes)(primary);
+
    for (uint32_t i = 0; i < commandBufferCount; i++) {
       ANV_FROM_HANDLE(anv_cmd_buffer, secondary, pCmdBuffers[i]);
 
@@ -936,7 +935,6 @@ void genX(CmdPipelineBarrier)(
     const VkImageMemoryBarrier*                 pImageMemoryBarriers)
 {
    ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
-   uint32_t b;
 
    /* XXX: Right now, we're really dumb and just flush whatever categories
     * the app asks for.  One of these days we may make this a bit better
@@ -967,50 +965,9 @@ void genX(CmdPipelineBarrier)(
       }
    }
 
-   enum anv_pipe_bits pipe_bits = 0;
-
-   for_each_bit(b, src_flags) {
-      switch ((VkAccessFlagBits)(1 << b)) {
-      case VK_ACCESS_SHADER_WRITE_BIT:
-         pipe_bits |= ANV_PIPE_DATA_CACHE_FLUSH_BIT;
-         break;
-      case VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT:
-         pipe_bits |= ANV_PIPE_RENDER_TARGET_CACHE_FLUSH_BIT;
-         break;
-      case VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT:
-         pipe_bits |= ANV_PIPE_DEPTH_CACHE_FLUSH_BIT;
-         break;
-      case VK_ACCESS_TRANSFER_WRITE_BIT:
-         pipe_bits |= ANV_PIPE_RENDER_TARGET_CACHE_FLUSH_BIT;
-         pipe_bits |= ANV_PIPE_DEPTH_CACHE_FLUSH_BIT;
-         break;
-      default:
-         break; /* Nothing to do */
-      }
-   }
-
-   for_each_bit(b, dst_flags) {
-      switch ((VkAccessFlagBits)(1 << b)) {
-      case VK_ACCESS_INDIRECT_COMMAND_READ_BIT:
-      case VK_ACCESS_INDEX_READ_BIT:
-      case VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT:
-         pipe_bits |= ANV_PIPE_VF_CACHE_INVALIDATE_BIT;
-         break;
-      case VK_ACCESS_UNIFORM_READ_BIT:
-         pipe_bits |= ANV_PIPE_CONSTANT_CACHE_INVALIDATE_BIT;
-         pipe_bits |= ANV_PIPE_TEXTURE_CACHE_INVALIDATE_BIT;
-         break;
-      case VK_ACCESS_SHADER_READ_BIT:
-      case VK_ACCESS_INPUT_ATTACHMENT_READ_BIT:
-      case VK_ACCESS_TRANSFER_READ_BIT:
-         pipe_bits |= ANV_PIPE_TEXTURE_CACHE_INVALIDATE_BIT;
-         break;
-      default:
-         break; /* Nothing to do */
-      }
-   }
-
-   cmd_buffer->state.pending_pipe_bits |= pipe_bits;
+   cmd_buffer->state.pending_pipe_bits |=
+      anv_pipe_flush_bits_for_access_flags(src_flags) |
+      anv_pipe_invalidate_bits_for_access_flags(dst_flags);
 }
 
 static void
@@ -1159,8 +1116,20 @@ emit_binding_table(struct anv_cmd_buffer *cmd_buffer,
          assert(stage == MESA_SHADER_FRAGMENT);
          assert(binding->binding == 0);
          if (binding->index < subpass->color_count) {
-            const unsigned att = subpass->color_attachments[binding->index].attachment;
-            surface_state = cmd_buffer->state.attachments[att].color_rt_state;
+            const unsigned att =
+               subpass->color_attachments[binding->index].attachment;
+
+            /* From the Vulkan 1.0.46 spec:
+             *
+             *    "If any color or depth/stencil attachments are
+             *    VK_ATTACHMENT_UNUSED, then no writes occur for those
+             *    attachments."
+             */
+            if (att == VK_ATTACHMENT_UNUSED) {
+               surface_state = cmd_buffer->state.null_surface_state;
+            } else {
+               surface_state = cmd_buffer->state.attachments[att].color_rt_state;
+            }
          } else {
             surface_state = cmd_buffer->state.null_surface_state;
          }
@@ -2113,9 +2082,12 @@ void genX(CmdDispatchIndirect)(
 }
 
 static void
-flush_pipeline_before_pipeline_select(struct anv_cmd_buffer *cmd_buffer,
-                                      uint32_t pipeline)
+genX(flush_pipeline_select)(struct anv_cmd_buffer *cmd_buffer,
+                            uint32_t pipeline)
 {
+   if (cmd_buffer->state.current_pipeline == pipeline)
+      return;
+
 #if GEN_GEN >= 8 && GEN_GEN < 10
    /* From the Broadwell PRM, Volume 2a: Instructions, PIPELINE_SELECT:
     *
@@ -2128,67 +2100,54 @@ flush_pipeline_before_pipeline_select(struct anv_cmd_buffer *cmd_buffer,
     */
    if (pipeline == GPGPU)
       anv_batch_emit(&cmd_buffer->batch, GENX(3DSTATE_CC_STATE_POINTERS), t);
-#elif GEN_GEN <= 7
-      /* From "BXML » GT » MI » vol1a GPU Overview » [Instruction]
-       * PIPELINE_SELECT [DevBWR+]":
-       *
-       *   Project: DEVSNB+
-       *
-       *   Software must ensure all the write caches are flushed through a
-       *   stalling PIPE_CONTROL command followed by another PIPE_CONTROL
-       *   command to invalidate read only caches prior to programming
-       *   MI_PIPELINE_SELECT command to change the Pipeline Select Mode.
-       */
-      anv_batch_emit(&cmd_buffer->batch, GENX(PIPE_CONTROL), pc) {
-         pc.RenderTargetCacheFlushEnable  = true;
-         pc.DepthCacheFlushEnable         = true;
-         pc.DCFlushEnable                 = true;
-         pc.PostSyncOperation             = NoWrite;
-         pc.CommandStreamerStallEnable    = true;
-      }
+#endif
 
-      anv_batch_emit(&cmd_buffer->batch, GENX(PIPE_CONTROL), pc) {
-         pc.TextureCacheInvalidationEnable   = true;
-         pc.ConstantCacheInvalidationEnable  = true;
-         pc.StateCacheInvalidationEnable     = true;
-         pc.InstructionCacheInvalidateEnable = true;
-         pc.PostSyncOperation                = NoWrite;
-      }
+   /* From "BXML » GT » MI » vol1a GPU Overview » [Instruction]
+    * PIPELINE_SELECT [DevBWR+]":
+    *
+    *   Project: DEVSNB+
+    *
+    *   Software must ensure all the write caches are flushed through a
+    *   stalling PIPE_CONTROL command followed by another PIPE_CONTROL
+    *   command to invalidate read only caches prior to programming
+    *   MI_PIPELINE_SELECT command to change the Pipeline Select Mode.
+    */
+   anv_batch_emit(&cmd_buffer->batch, GENX(PIPE_CONTROL), pc) {
+      pc.RenderTargetCacheFlushEnable  = true;
+      pc.DepthCacheFlushEnable         = true;
+      pc.DCFlushEnable                 = true;
+      pc.PostSyncOperation             = NoWrite;
+      pc.CommandStreamerStallEnable    = true;
+   }
+
+   anv_batch_emit(&cmd_buffer->batch, GENX(PIPE_CONTROL), pc) {
+      pc.TextureCacheInvalidationEnable   = true;
+      pc.ConstantCacheInvalidationEnable  = true;
+      pc.StateCacheInvalidationEnable     = true;
+      pc.InstructionCacheInvalidateEnable = true;
+      pc.PostSyncOperation                = NoWrite;
+   }
+
+   anv_batch_emit(&cmd_buffer->batch, GENX(PIPELINE_SELECT), ps) {
+#if GEN_GEN >= 9
+      ps.MaskBits = 3;
 #endif
+      ps.PipelineSelection = pipeline;
+   }
+
+   cmd_buffer->state.current_pipeline = pipeline;
 }
 
 void
 genX(flush_pipeline_select_3d)(struct anv_cmd_buffer *cmd_buffer)
 {
-   if (cmd_buffer->state.current_pipeline != _3D) {
-      flush_pipeline_before_pipeline_select(cmd_buffer, _3D);
-
-      anv_batch_emit(&cmd_buffer->batch, GENX(PIPELINE_SELECT), ps) {
-#if GEN_GEN >= 9
-         ps.MaskBits = 3;
-#endif
-         ps.PipelineSelection = _3D;
-      }
-
-      cmd_buffer->state.current_pipeline = _3D;
-   }
+   genX(flush_pipeline_select)(cmd_buffer, _3D);
 }
 
 void
 genX(flush_pipeline_select_gpgpu)(struct anv_cmd_buffer *cmd_buffer)
 {
-   if (cmd_buffer->state.current_pipeline != GPGPU) {
-      flush_pipeline_before_pipeline_select(cmd_buffer, GPGPU);
-
-      anv_batch_emit(&cmd_buffer->batch, GENX(PIPELINE_SELECT), ps) {
-#if GEN_GEN >= 9
-         ps.MaskBits = 3;
-#endif
-         ps.PipelineSelection = GPGPU;
-      }
-
-      cmd_buffer->state.current_pipeline = GPGPU;
-   }
+   genX(flush_pipeline_select)(cmd_buffer, GPGPU);
 }
 
 void
@@ -2220,208 +2179,68 @@ genX(cmd_buffer_emit_gen7_depth_flush)(struct anv_cmd_buffer *cmd_buffer)
    }
 }
 
-static uint32_t
-depth_stencil_surface_type(enum isl_surf_dim dim)
-{
-   switch (dim) {
-   case ISL_SURF_DIM_1D:
-      if (GEN_GEN >= 9) {
-         /* From the Sky Lake PRM, 3DSTATAE_DEPTH_BUFFER::SurfaceType
-          *
-          *    Programming Notes:
-          *    The Surface Type of the depth buffer must be the same as the
-          *    Surface Type of the render target(s) (defined in
-          *    SURFACE_STATE), unless either the depth buffer or render
-          *    targets are SURFTYPE_NULL (see exception below for SKL).  1D
-          *    surface type not allowed for depth surface and stencil surface.
-          *
-          *    Workaround:
-          *    If depth/stencil is enabled with 1D render target,
-          *    depth/stencil surface type needs to be set to 2D surface type
-          *    and height set to 1. Depth will use (legacy) TileY and stencil
-          *    will use TileW. For this case only, the Surface Type of the
-          *    depth buffer can be 2D while the Surface Type of the render
-          *    target(s) are 1D, representing an exception to a programming
-          *    note above.
-          */
-         return SURFTYPE_2D;
-      } else {
-         return SURFTYPE_1D;
-      }
-   case ISL_SURF_DIM_2D:
-      return SURFTYPE_2D;
-   case ISL_SURF_DIM_3D:
-      if (GEN_GEN >= 9) {
-         /* The Sky Lake docs list the value for 3D as "Reserved".  However,
-          * they have the exact same layout as 2D arrays on gen9+, so we can
-          * just use 2D here.
-          */
-         return SURFTYPE_2D;
-      } else {
-         return SURFTYPE_3D;
-      }
-   default:
-      unreachable("Invalid surface dimension");
-   }
-}
-
 static void
 cmd_buffer_emit_depth_stencil(struct anv_cmd_buffer *cmd_buffer)
 {
    struct anv_device *device = cmd_buffer->device;
-   const struct anv_framebuffer *fb = cmd_buffer->state.framebuffer;
    const struct anv_image_view *iview =
       anv_cmd_buffer_get_depth_stencil_view(cmd_buffer);
    const struct anv_image *image = iview ? iview->image : NULL;
-   const bool has_depth = image && (image->aspects & VK_IMAGE_ASPECT_DEPTH_BIT);
-   const uint32_t ds = cmd_buffer->state.subpass->depth_stencil_attachment.attachment;
-   const bool has_hiz = image != NULL &&
-      cmd_buffer->state.attachments[ds].aux_usage == ISL_AUX_USAGE_HIZ;
-   const bool has_stencil =
-      image && (image->aspects & VK_IMAGE_ASPECT_STENCIL_BIT);
-
-   cmd_buffer->state.hiz_enabled = has_hiz;
 
    /* FIXME: Width and Height are wrong */
 
    genX(cmd_buffer_emit_gen7_depth_flush)(cmd_buffer);
 
-   /* Emit 3DSTATE_DEPTH_BUFFER */
-   if (has_depth) {
-      anv_batch_emit(&cmd_buffer->batch, GENX(3DSTATE_DEPTH_BUFFER), db) {
-         db.SurfaceType                   =
-            depth_stencil_surface_type(image->depth_surface.isl.dim);
-         db.DepthWriteEnable              = true;
-         db.StencilWriteEnable            = has_stencil;
-         db.HierarchicalDepthBufferEnable = has_hiz;
-
-         db.SurfaceFormat = isl_surf_get_depth_format(&device->isl_dev,
-                                                      &image->depth_surface.isl);
-
-         db.SurfaceBaseAddress = (struct anv_address) {
-            .bo = image->bo,
-            .offset = image->offset + image->depth_surface.offset,
-         };
-         db.DepthBufferObjectControlState = GENX(MOCS);
+   uint32_t *dw = anv_batch_emit_dwords(&cmd_buffer->batch,
+                                        device->isl_dev.ds.size / 4);
+   if (dw == NULL)
+      return;
 
-         db.SurfacePitch         = image->depth_surface.isl.row_pitch - 1;
-         db.Height               = image->extent.height - 1;
-         db.Width                = image->extent.width - 1;
-         db.LOD                  = iview->isl.base_level;
-         db.MinimumArrayElement  = iview->isl.base_array_layer;
+   struct isl_depth_stencil_hiz_emit_info info = {
+      .mocs = device->default_mocs,
+   };
 
-         assert(image->depth_surface.isl.dim != ISL_SURF_DIM_3D);
-         db.Depth =
-         db.RenderTargetViewExtent = iview->isl.array_len - 1;
+   if (iview)
+      info.view = &iview->isl;
 
-#if GEN_GEN >= 8
-         db.SurfaceQPitch =
-            isl_surf_get_array_pitch_el_rows(&image->depth_surface.isl) >> 2;
-#endif
-      }
-   } else {
-      /* Even when no depth buffer is present, the hardware requires that
-       * 3DSTATE_DEPTH_BUFFER be programmed correctly. The Broadwell PRM says:
-       *
-       *    If a null depth buffer is bound, the driver must instead bind depth as:
-       *       3DSTATE_DEPTH.SurfaceType = SURFTYPE_2D
-       *       3DSTATE_DEPTH.Width = 1
-       *       3DSTATE_DEPTH.Height = 1
-       *       3DSTATE_DEPTH.SuraceFormat = D16_UNORM
-       *       3DSTATE_DEPTH.SurfaceBaseAddress = 0
-       *       3DSTATE_DEPTH.HierarchicalDepthBufferEnable = 0
-       *       3DSTATE_WM_DEPTH_STENCIL.DepthTestEnable = 0
-       *       3DSTATE_WM_DEPTH_STENCIL.DepthBufferWriteEnable = 0
-       *
-       * The PRM is wrong, though. The width and height must be programmed to
-       * actual framebuffer's width and height, even when neither depth buffer
-       * nor stencil buffer is present.  Also, D16_UNORM is not allowed to
-       * be combined with a stencil buffer so we use D32_FLOAT instead.
-       */
-      anv_batch_emit(&cmd_buffer->batch, GENX(3DSTATE_DEPTH_BUFFER), db) {
-         if (has_stencil) {
-            db.SurfaceType       =
-               depth_stencil_surface_type(image->stencil_surface.isl.dim);
-         } else {
-            db.SurfaceType       = SURFTYPE_2D;
-         }
-         db.SurfaceFormat        = D32_FLOAT;
-         db.Width                = MAX2(fb->width, 1) - 1;
-         db.Height               = MAX2(fb->height, 1) - 1;
-         db.StencilWriteEnable   = has_stencil;
-      }
-   }
+   if (image && (image->aspects & VK_IMAGE_ASPECT_DEPTH_BIT)) {
+      info.depth_surf = &image->depth_surface.isl;
 
-   if (has_hiz) {
-      anv_batch_emit(&cmd_buffer->batch, GENX(3DSTATE_HIER_DEPTH_BUFFER), hdb) {
-         hdb.HierarchicalDepthBufferObjectControlState = GENX(MOCS);
-         hdb.SurfacePitch = image->aux_surface.isl.row_pitch - 1;
-         hdb.SurfaceBaseAddress = (struct anv_address) {
-            .bo = image->bo,
-            .offset = image->offset + image->aux_surface.offset,
-         };
-#if GEN_GEN >= 8
-         /* From the SKL PRM Vol2a:
-          *
-          *    The interpretation of this field is dependent on Surface Type
-          *    as follows:
-          *    - SURFTYPE_1D: distance in pixels between array slices
-          *    - SURFTYPE_2D/CUBE: distance in rows between array slices
-          *    - SURFTYPE_3D: distance in rows between R - slices
-          *
-          * Unfortunately, the docs aren't 100% accurate here.  They fail to
-          * mention that the 1-D rule only applies to linear 1-D images.
-          * Since depth and HiZ buffers are always tiled, they are treated as
-          * 2-D images.  Prior to Sky Lake, this field is always in rows.
-          */
-         hdb.SurfaceQPitch =
-            isl_surf_get_array_pitch_sa_rows(&image->aux_surface.isl) >> 2;
-#endif
-      }
-   } else {
-      anv_batch_emit(&cmd_buffer->batch, GENX(3DSTATE_HIER_DEPTH_BUFFER), hdb);
-   }
+      info.depth_address =
+         anv_batch_emit_reloc(&cmd_buffer->batch,
+                              dw + device->isl_dev.ds.depth_offset / 4,
+                              image->bo,
+                              image->offset + image->depth_surface.offset);
 
-   /* Emit 3DSTATE_STENCIL_BUFFER */
-   if (has_stencil) {
-      anv_batch_emit(&cmd_buffer->batch, GENX(3DSTATE_STENCIL_BUFFER), sb) {
-#if GEN_GEN >= 8 || GEN_IS_HASWELL
-         sb.StencilBufferEnable = true;
-#endif
-         sb.StencilBufferObjectControlState = GENX(MOCS);
+      const uint32_t ds =
+         cmd_buffer->state.subpass->depth_stencil_attachment.attachment;
+      info.hiz_usage = cmd_buffer->state.attachments[ds].aux_usage;
+      if (info.hiz_usage == ISL_AUX_USAGE_HIZ) {
+         info.hiz_surf = &image->aux_surface.isl;
 
-         sb.SurfacePitch = image->stencil_surface.isl.row_pitch - 1;
+         info.hiz_address =
+            anv_batch_emit_reloc(&cmd_buffer->batch,
+                                 dw + device->isl_dev.ds.hiz_offset / 4,
+                                 image->bo,
+                                 image->offset + image->aux_surface.offset);
 
-#if GEN_GEN >= 8
-         sb.SurfaceQPitch = isl_surf_get_array_pitch_el_rows(&image->stencil_surface.isl) >> 2;
-#endif
-         sb.SurfaceBaseAddress = (struct anv_address) {
-            .bo = image->bo,
-            .offset = image->offset + image->stencil_surface.offset,
-         };
+         info.depth_clear_value = ANV_HZ_FC_VAL;
       }
-   } else {
-      anv_batch_emit(&cmd_buffer->batch, GENX(3DSTATE_STENCIL_BUFFER), sb);
    }
 
-   /* From the IVB PRM Vol2P1, 11.5.5.4 3DSTATE_CLEAR_PARAMS:
-    *
-    *    3DSTATE_CLEAR_PARAMS must always be programmed in the along with
-    *    the other Depth/Stencil state commands(i.e. 3DSTATE_DEPTH_BUFFER,
-    *    3DSTATE_STENCIL_BUFFER, or 3DSTATE_HIER_DEPTH_BUFFER)
-    *
-    * Testing also shows that some variant of this restriction may exist HSW+.
-    * On BDW+, it is not possible to emit 2 of these packets consecutively when
-    * both have DepthClearValueValid set. An analysis of such state programming
-    * on SKL showed that the GPU doesn't register the latter packet's clear
-    * value.
-    */
-   anv_batch_emit(&cmd_buffer->batch, GENX(3DSTATE_CLEAR_PARAMS), cp) {
-      if (has_hiz) {
-         cp.DepthClearValueValid = true;
-         cp.DepthClearValue = ANV_HZ_FC_VAL;
-      }
+   if (image && (image->aspects & VK_IMAGE_ASPECT_STENCIL_BIT)) {
+      info.stencil_surf = &image->stencil_surface.isl;
+
+      info.stencil_address =
+         anv_batch_emit_reloc(&cmd_buffer->batch,
+                              dw + device->isl_dev.ds.stencil_offset / 4,
+                              image->bo,
+                              image->offset + image->stencil_surface.offset);
    }
+
+   isl_emit_depth_stencil_hiz_s(&device->isl_dev, dw, &info);
+
+   cmd_buffer->state.hiz_enabled = info.hiz_usage == ISL_AUX_USAGE_HIZ;
 }
 
 
@@ -2551,6 +2370,9 @@ void genX(CmdBeginRenderPass)(
    genX(flush_pipeline_select_3d)(cmd_buffer);
 
    genX(cmd_buffer_set_subpass)(cmd_buffer, pass->subpasses);
+
+   cmd_buffer->state.pending_pipe_bits |=
+      cmd_buffer->state.pass->subpass_flushes[0];
 }
 
 void genX(CmdNextSubpass)(
@@ -2571,6 +2393,10 @@ void genX(CmdNextSubpass)(
    cmd_buffer_subpass_transition_layouts(cmd_buffer, true);
 
    genX(cmd_buffer_set_subpass)(cmd_buffer, cmd_buffer->state.subpass + 1);
+
+   uint32_t subpass_id = anv_get_subpass_id(&cmd_buffer->state);
+   cmd_buffer->state.pending_pipe_bits |=
+      cmd_buffer->state.pass->subpass_flushes[subpass_id];
 }
 
 void genX(CmdEndRenderPass)(
@@ -2587,6 +2413,9 @@ void genX(CmdEndRenderPass)(
     */
    cmd_buffer_subpass_transition_layouts(cmd_buffer, true);
 
+   cmd_buffer->state.pending_pipe_bits |=
+      cmd_buffer->state.pass->subpass_flushes[cmd_buffer->state.pass->subpass_count];
+
    cmd_buffer->state.hiz_enabled = false;
 
 #ifndef NDEBUG