ilo: add HiZ op support to the pipelines
authorChia-I Wu <olvaffe@gmail.com>
Sat, 28 Dec 2013 07:57:49 +0000 (15:57 +0800)
committerChia-I Wu <olvaffe@gmail.com>
Wed, 8 Jan 2014 10:11:35 +0000 (18:11 +0800)
Add blitter functions to perform Depth Buffer Clear, Depth Buffer Resolve, and
Hierarchical Depth Buffer Resolve.  Those functions set ilo_blitter up and
pass it to the pipelines to emit the commands.

src/gallium/drivers/ilo/Makefile.sources
src/gallium/drivers/ilo/ilo_3d.c
src/gallium/drivers/ilo/ilo_3d.h
src/gallium/drivers/ilo/ilo_3d_pipeline.c
src/gallium/drivers/ilo/ilo_3d_pipeline.h
src/gallium/drivers/ilo/ilo_3d_pipeline_gen6.c
src/gallium/drivers/ilo/ilo_3d_pipeline_gen6.h
src/gallium/drivers/ilo/ilo_3d_pipeline_gen7.c
src/gallium/drivers/ilo/ilo_blitter.c
src/gallium/drivers/ilo/ilo_blitter.h
src/gallium/drivers/ilo/ilo_blitter_rectlist.c [new file with mode: 0644]

index 1612a7745195c6fb9864611a218fe8ed2b8ad9d7..d109af0097c106bac1e26a1f7e2f108238f85538 100644 (file)
@@ -8,6 +8,7 @@ C_SOURCES := \
        ilo_blitter.c \
        ilo_blitter_blt.c \
        ilo_blitter_pipe.c \
+       ilo_blitter_rectlist.c \
        ilo_context.c \
        ilo_cp.c \
        ilo_format.c \
index c7e5014075a17d0ee1a9f0837202283de2a78434..5f0f2312f75d3ea898be9a722741ee0fc4f795f3 100644 (file)
@@ -156,7 +156,7 @@ ilo_3d_release_render_ring(struct ilo_cp *cp, void *data)
    ilo_3d_pause_queries(hw3d);
 }
 
-static void
+void
 ilo_3d_own_render_ring(struct ilo_3d *hw3d)
 {
    ilo_cp_set_ring(hw3d->cp, ILO_CP_RING_RENDER);
index f73b8177a4cf2542a29129a342267991ad863777..694820d953f81fce6047fd293a2e8c2e9f261dfc 100644 (file)
@@ -73,6 +73,9 @@ ilo_3d_destroy(struct ilo_3d *hw3d);
 void
 ilo_3d_cp_flushed(struct ilo_3d *hw3d);
 
+void
+ilo_3d_own_render_ring(struct ilo_3d *hw3d);
+
 void
 ilo_3d_begin_query(struct ilo_context *ilo, struct ilo_query *q);
 
index c4e133ec57bff840dd955d23ca0c699288718f3e..ca02b35137091e24b45cf754180273ad0d119808 100644 (file)
@@ -28,6 +28,7 @@
 #include "util/u_prim.h"
 #include "intel_winsys.h"
 
+#include "ilo_blitter.h"
 #include "ilo_context.h"
 #include "ilo_cp.h"
 #include "ilo_state.h"
@@ -258,6 +259,48 @@ ilo_3d_pipeline_emit_write_depth_count(struct ilo_3d_pipeline *p,
    p->emit_write_depth_count(p, bo, index);
 }
 
+void
+ilo_3d_pipeline_emit_rectlist(struct ilo_3d_pipeline *p,
+                              const struct ilo_blitter *blitter)
+{
+   const int max_len = ilo_3d_pipeline_estimate_size(p,
+         ILO_3D_PIPELINE_RECTLIST, blitter);
+
+   if (max_len > ilo_cp_space(p->cp))
+      ilo_cp_flush(p->cp, "out of space");
+
+   while (true) {
+      struct ilo_cp_jmp_buf jmp;
+      int err;
+
+      /* we will rewind if aperture check below fails */
+      ilo_cp_setjmp(p->cp, &jmp);
+
+      handle_invalid_batch_bo(p, false);
+
+      ilo_cp_assert_no_implicit_flush(p->cp, true);
+      p->emit_rectlist(p, blitter);
+      ilo_cp_assert_no_implicit_flush(p->cp, false);
+
+      err = intel_winsys_check_aperture_space(blitter->ilo->winsys,
+            &p->cp->bo, 1);
+      if (err) {
+         /* rewind */
+         ilo_cp_longjmp(p->cp, &jmp);
+
+         /* flush and try again */
+         if (!ilo_cp_empty(p->cp)) {
+            ilo_cp_flush(p->cp, "out of aperture");
+            continue;
+         }
+      }
+
+      break;
+   }
+
+   ilo_3d_pipeline_invalidate(p, ILO_3D_PIPELINE_INVALIDATE_HW);
+}
+
 void
 ilo_3d_pipeline_get_sample_position(struct ilo_3d_pipeline *p,
                                     unsigned sample_count,
index 5353ae99f81e793e77c69d7d30d965709cc76b43..0574d7479e6920f0cfcbf74c1a7940341ad18948 100644 (file)
@@ -32,6 +32,7 @@
 #include "ilo_gpe.h"
 
 struct intel_bo;
+struct ilo_blitter;
 struct ilo_cp;
 struct ilo_context;
 
@@ -49,6 +50,7 @@ enum ilo_3d_pipeline_action {
    ILO_3D_PIPELINE_FLUSH,
    ILO_3D_PIPELINE_WRITE_TIMESTAMP,
    ILO_3D_PIPELINE_WRITE_DEPTH_COUNT,
+   ILO_3D_PIPELINE_RECTLIST,
 };
 
 /**
@@ -81,6 +83,9 @@ struct ilo_3d_pipeline {
    void (*emit_write_depth_count)(struct ilo_3d_pipeline *pipeline,
                                   struct intel_bo *bo, int index);
 
+   void (*emit_rectlist)(struct ilo_3d_pipeline *pipeline,
+                         const struct ilo_blitter *blitter);
+
    /**
     * HW states.
     */
@@ -171,6 +176,10 @@ void
 ilo_3d_pipeline_emit_write_depth_count(struct ilo_3d_pipeline *p,
                                        struct intel_bo *bo, int index);
 
+void
+ilo_3d_pipeline_emit_rectlist(struct ilo_3d_pipeline *p,
+                              const struct ilo_blitter *blitter);
+
 void
 ilo_3d_pipeline_get_sample_position(struct ilo_3d_pipeline *p,
                                     unsigned sample_count,
index 3b6a3c41e952bf29d21c8ccd0f082cbacba83f03..ceab6fec8be5a398558e6bc862c90a2a25d49486 100644 (file)
@@ -29,6 +29,7 @@
 #include "util/u_prim.h"
 #include "intel_reg.h"
 
+#include "ilo_blitter.h"
 #include "ilo_3d.h"
 #include "ilo_context.h"
 #include "ilo_cp.h"
@@ -1518,6 +1519,178 @@ ilo_3d_pipeline_emit_write_depth_count_gen6(struct ilo_3d_pipeline *p,
          true, p->cp);
 }
 
+static void
+gen6_rectlist_vs_to_sf(struct ilo_3d_pipeline *p,
+                       const struct ilo_blitter *blitter,
+                       struct gen6_rectlist_session *session)
+{
+   gen6_emit_3DSTATE_CONSTANT_VS(p->dev, NULL, NULL, 0, p->cp);
+   gen6_emit_3DSTATE_VS(p->dev, NULL, 0, p->cp);
+
+   gen6_wa_pipe_control_vs_const_flush(p);
+
+   gen6_emit_3DSTATE_CONSTANT_GS(p->dev, NULL, NULL, 0, p->cp);
+   gen6_emit_3DSTATE_GS(p->dev, NULL, NULL, 0, p->cp);
+
+   gen6_emit_3DSTATE_CLIP(p->dev, NULL, NULL, false, 0, p->cp);
+   gen6_emit_3DSTATE_SF(p->dev, NULL, NULL, p->cp);
+}
+
+static void
+gen6_rectlist_wm(struct ilo_3d_pipeline *p,
+                 const struct ilo_blitter *blitter,
+                 struct gen6_rectlist_session *session)
+{
+   uint32_t hiz_op;
+
+   switch (blitter->op) {
+   case ILO_BLITTER_RECTLIST_CLEAR_ZS:
+      hiz_op = GEN6_WM_DEPTH_CLEAR;
+      break;
+   case ILO_BLITTER_RECTLIST_RESOLVE_Z:
+      hiz_op = GEN6_WM_DEPTH_RESOLVE;
+      break;
+   case ILO_BLITTER_RECTLIST_RESOLVE_HIZ:
+      hiz_op = GEN6_WM_HIERARCHICAL_DEPTH_RESOLVE;
+      break;
+   default:
+      hiz_op = 0;
+      break;
+   }
+
+   gen6_emit_3DSTATE_CONSTANT_PS(p->dev, NULL, NULL, 0, p->cp);
+
+   gen6_wa_pipe_control_wm_max_threads_stall(p);
+   gen6_emit_3DSTATE_WM(p->dev, NULL, 0, NULL, false, false, hiz_op, p->cp);
+}
+
+static void
+gen6_rectlist_wm_depth(struct ilo_3d_pipeline *p,
+                       const struct ilo_blitter *blitter,
+                       struct gen6_rectlist_session *session)
+{
+   gen6_wa_pipe_control_wm_depth_flush(p);
+
+   if (blitter->uses & ILO_BLITTER_USE_FB_DEPTH) {
+      gen6_emit_3DSTATE_DEPTH_BUFFER(p->dev,
+            &blitter->fb.dst.u.zs, p->cp);
+
+      gen6_emit_3DSTATE_HIER_DEPTH_BUFFER(p->dev,
+            &blitter->fb.dst.u.zs, p->cp);
+   }
+
+   if (blitter->uses & ILO_BLITTER_USE_FB_STENCIL) {
+      gen6_emit_3DSTATE_STENCIL_BUFFER(p->dev,
+            &blitter->fb.dst.u.zs, p->cp);
+   }
+
+   gen6_emit_3DSTATE_CLEAR_PARAMS(p->dev,
+         blitter->depth_clear_value, p->cp);
+}
+
+static void
+gen6_rectlist_wm_multisample(struct ilo_3d_pipeline *p,
+                             const struct ilo_blitter *blitter,
+                             struct gen6_rectlist_session *session)
+{
+   const uint32_t *packed_sample_pos = (blitter->fb.num_samples > 1) ?
+      &p->packed_sample_position_4x : &p->packed_sample_position_1x;
+
+   gen6_wa_pipe_control_wm_multisample_flush(p);
+
+   gen6_emit_3DSTATE_MULTISAMPLE(p->dev, blitter->fb.num_samples,
+         packed_sample_pos, true, p->cp);
+
+   gen6_emit_3DSTATE_SAMPLE_MASK(p->dev,
+         (1 << blitter->fb.num_samples) - 1, p->cp);
+}
+
+static void
+gen6_rectlist_commands(struct ilo_3d_pipeline *p,
+                       const struct ilo_blitter *blitter,
+                       struct gen6_rectlist_session *session)
+{
+   gen6_wa_pipe_control_post_sync(p, false);
+
+   gen6_rectlist_wm_multisample(p, blitter, session);
+
+   gen6_emit_STATE_BASE_ADDRESS(p->dev,
+         NULL,                /* General State Base */
+         p->cp->bo,           /* Surface State Base */
+         p->cp->bo,           /* Dynamic State Base */
+         NULL,                /* Indirect Object Base */
+         NULL,                /* Instruction Base */
+         0, 0, 0, 0, p->cp);
+
+   gen6_emit_3DSTATE_VERTEX_BUFFERS(p->dev,
+         &blitter->ve, &blitter->vb, p->cp);
+
+   gen6_emit_3DSTATE_VERTEX_ELEMENTS(p->dev,
+         &blitter->ve, false, false, p->cp);
+
+   gen6_emit_3DSTATE_URB(p->dev,
+         p->dev->urb_size, 0, blitter->ve.count * 4 * sizeof(float), 0, p->cp);
+   /* 3DSTATE_URB workaround */
+   if (p->state.gs.active) {
+      ilo_3d_pipeline_emit_flush_gen6(p);
+      p->state.gs.active = false;
+   }
+
+   if (blitter->uses &
+       (ILO_BLITTER_USE_DSA | ILO_BLITTER_USE_CC)) {
+      gen6_emit_3DSTATE_CC_STATE_POINTERS(p->dev, 0,
+            session->DEPTH_STENCIL_STATE, session->COLOR_CALC_STATE, p->cp);
+   }
+
+   gen6_rectlist_vs_to_sf(p, blitter, session);
+   gen6_rectlist_wm(p, blitter, session);
+
+   if (blitter->uses & ILO_BLITTER_USE_VIEWPORT) {
+      gen6_emit_3DSTATE_VIEWPORT_STATE_POINTERS(p->dev,
+            0, 0, session->CC_VIEWPORT, p->cp);
+   }
+
+   gen6_rectlist_wm_depth(p, blitter, session);
+
+   gen6_emit_3DSTATE_DRAWING_RECTANGLE(p->dev, 0, 0,
+         blitter->fb.width, blitter->fb.height, p->cp);
+
+   gen6_emit_3DPRIMITIVE(p->dev, &blitter->draw, NULL, true, p->cp);
+}
+
+static void
+gen6_rectlist_states(struct ilo_3d_pipeline *p,
+                     const struct ilo_blitter *blitter,
+                     struct gen6_rectlist_session *session)
+{
+   if (blitter->uses & ILO_BLITTER_USE_DSA) {
+      session->DEPTH_STENCIL_STATE =
+         gen6_emit_DEPTH_STENCIL_STATE(p->dev, &blitter->dsa, p->cp);
+   }
+
+   if (blitter->uses & ILO_BLITTER_USE_CC) {
+      session->COLOR_CALC_STATE =
+         gen6_emit_COLOR_CALC_STATE(p->dev, &blitter->cc.stencil_ref,
+               blitter->cc.alpha_ref, &blitter->cc.blend_color, p->cp);
+   }
+
+   if (blitter->uses & ILO_BLITTER_USE_VIEWPORT) {
+      session->CC_VIEWPORT =
+         gen6_emit_CC_VIEWPORT(p->dev, &blitter->viewport, 1, p->cp);
+   }
+}
+
+static void
+ilo_3d_pipeline_emit_rectlist_gen6(struct ilo_3d_pipeline *p,
+                                   const struct ilo_blitter *blitter)
+{
+   struct gen6_rectlist_session session;
+
+   memset(&session, 0, sizeof(session));
+   gen6_rectlist_states(p, blitter, &session);
+   gen6_rectlist_commands(p, blitter, &session);
+}
+
 static int
 gen6_pipeline_estimate_commands(const struct ilo_3d_pipeline *p,
                                 const struct ilo_context *ilo)
@@ -1702,6 +1875,9 @@ ilo_3d_pipeline_estimate_size_gen6(struct ilo_3d_pipeline *p,
       size = ilo_gpe_gen6_estimate_command_size(p->dev,
             ILO_GPE_GEN6_PIPE_CONTROL, 1) * 3;
       break;
+   case ILO_3D_PIPELINE_RECTLIST:
+      size = 64 + 256; /* states + commands */
+      break;
    default:
       assert(!"unknown 3D pipeline action");
       size = 0;
@@ -1719,4 +1895,5 @@ ilo_3d_pipeline_init_gen6(struct ilo_3d_pipeline *p)
    p->emit_flush = ilo_3d_pipeline_emit_flush_gen6;
    p->emit_write_timestamp = ilo_3d_pipeline_emit_write_timestamp_gen6;
    p->emit_write_depth_count = ilo_3d_pipeline_emit_write_depth_count_gen6;
+   p->emit_rectlist = ilo_3d_pipeline_emit_rectlist_gen6;
 }
index 36609f238f175ae5fb51fefede74c746530ab044..c6f48ebbe7c4fcb6e3bbe5b8613480e98e944684 100644 (file)
@@ -73,6 +73,12 @@ struct gen6_pipeline_session {
    int num_surfaces[PIPE_SHADER_TYPES];
 };
 
+struct gen6_rectlist_session {
+   uint32_t DEPTH_STENCIL_STATE;
+   uint32_t COLOR_CALC_STATE;
+   uint32_t CC_VIEWPORT;
+};
+
 void
 gen6_pipeline_prepare(const struct ilo_3d_pipeline *p,
                       const struct ilo_context *ilo,
index a63a77e03476d586bbeaed87e27a34fa180d6994..40687aeeed2b8e7114c5e60823c734f4cf8bb7ee 100644 (file)
@@ -28,7 +28,7 @@
 #include "util/u_dual_blend.h"
 #include "intel_reg.h"
 
-#include "ilo_common.h"
+#include "ilo_blitter.h"
 #include "ilo_context.h"
 #include "ilo_cp.h"
 #include "ilo_gpe_gen7.h"
@@ -650,6 +650,233 @@ ilo_3d_pipeline_emit_draw_gen7(struct ilo_3d_pipeline *p,
    gen6_pipeline_end(p, ilo, &session);
 }
 
+static void
+gen7_rectlist_pcb_alloc(struct ilo_3d_pipeline *p,
+                        const struct ilo_blitter *blitter,
+                        struct gen6_rectlist_session *session)
+{
+   /*
+    * Push constant buffers are only allowed to take up at most the first
+    * 16KB of the URB.  Split the space evenly for VS and FS.
+    */
+   const int max_size =
+      (p->dev->gen == ILO_GEN(7.5) && p->dev->gt == 3) ? 32768 : 16384;
+   const int size = max_size / 2;
+   int offset = 0;
+
+   gen7_emit_3DSTATE_PUSH_CONSTANT_ALLOC_VS(p->dev, offset, size, p->cp);
+   offset += size;
+
+   gen7_emit_3DSTATE_PUSH_CONSTANT_ALLOC_PS(p->dev, offset, size, p->cp);
+
+   gen7_wa_pipe_control_cs_stall(p, true, true);
+}
+
+static void
+gen7_rectlist_urb(struct ilo_3d_pipeline *p,
+                  const struct ilo_blitter *blitter,
+                  struct gen6_rectlist_session *session)
+{
+   /* the first 16KB are reserved for VS and PS PCBs */
+   const int offset =
+      (p->dev->gen == ILO_GEN(7.5) && p->dev->gt == 3) ? 32768 : 16384;
+
+   gen7_emit_3DSTATE_URB_VS(p->dev, offset, p->dev->urb_size - offset,
+         blitter->ve.count * 4 * sizeof(float), p->cp);
+
+   gen7_emit_3DSTATE_URB_GS(p->dev, offset, 0, 0, p->cp);
+   gen7_emit_3DSTATE_URB_HS(p->dev, offset, 0, 0, p->cp);
+   gen7_emit_3DSTATE_URB_DS(p->dev, offset, 0, 0, p->cp);
+}
+
+static void
+gen7_rectlist_vs_to_sf(struct ilo_3d_pipeline *p,
+                       const struct ilo_blitter *blitter,
+                       struct gen6_rectlist_session *session)
+{
+   gen7_emit_3DSTATE_CONSTANT_VS(p->dev, NULL, NULL, 0, p->cp);
+   gen6_emit_3DSTATE_VS(p->dev, NULL, 0, p->cp);
+
+   gen7_emit_3DSTATE_CONSTANT_HS(p->dev, NULL, NULL, 0, p->cp);
+   gen7_emit_3DSTATE_HS(p->dev, NULL, 0, p->cp);
+
+   gen7_emit_3DSTATE_TE(p->dev, p->cp);
+
+   gen7_emit_3DSTATE_CONSTANT_DS(p->dev, NULL, NULL, 0, p->cp);
+   gen7_emit_3DSTATE_DS(p->dev, NULL, 0, p->cp);
+
+   gen7_emit_3DSTATE_CONSTANT_GS(p->dev, NULL, NULL, 0, p->cp);
+   gen7_emit_3DSTATE_GS(p->dev, NULL, 0, p->cp);
+
+   gen7_emit_3DSTATE_STREAMOUT(p->dev, 0x0, 0, false, p->cp);
+
+   gen6_emit_3DSTATE_CLIP(p->dev, NULL, NULL, false, 0, p->cp);
+
+   gen7_wa_pipe_control_cs_stall(p, true, true);
+
+   gen7_emit_3DSTATE_SF(p->dev, NULL, blitter->fb.dst.base.format, p->cp);
+   gen7_emit_3DSTATE_SBE(p->dev, NULL, NULL, p->cp);
+}
+
+static void
+gen7_rectlist_wm(struct ilo_3d_pipeline *p,
+                 const struct ilo_blitter *blitter,
+                 struct gen6_rectlist_session *session)
+{
+   uint32_t hiz_op;
+
+   switch (blitter->op) {
+   case ILO_BLITTER_RECTLIST_CLEAR_ZS:
+      hiz_op = GEN7_WM_DEPTH_CLEAR;
+      break;
+   case ILO_BLITTER_RECTLIST_RESOLVE_Z:
+      hiz_op = GEN7_WM_DEPTH_RESOLVE;
+      break;
+   case ILO_BLITTER_RECTLIST_RESOLVE_HIZ:
+      hiz_op = GEN7_WM_HIERARCHICAL_DEPTH_RESOLVE;
+      break;
+   default:
+      hiz_op = 0;
+      break;
+   }
+
+   gen7_wa_pipe_control_wm_max_threads_stall(p);
+   gen7_emit_3DSTATE_WM(p->dev, NULL, NULL, false, hiz_op, p->cp);
+
+   gen7_emit_3DSTATE_CONSTANT_PS(p->dev, NULL, NULL, 0, p->cp);
+   gen7_emit_3DSTATE_PS(p->dev, NULL, 0, false, p->cp);
+}
+
+static void
+gen7_rectlist_wm_depth(struct ilo_3d_pipeline *p,
+                       const struct ilo_blitter *blitter,
+                       struct gen6_rectlist_session *session)
+{
+   gen7_wa_pipe_control_wm_depth_stall(p, true);
+
+   if (blitter->uses & ILO_BLITTER_USE_FB_DEPTH) {
+      gen6_emit_3DSTATE_DEPTH_BUFFER(p->dev,
+            &blitter->fb.dst.u.zs, p->cp);
+
+      gen6_emit_3DSTATE_HIER_DEPTH_BUFFER(p->dev,
+            &blitter->fb.dst.u.zs, p->cp);
+   }
+
+   if (blitter->uses & ILO_BLITTER_USE_FB_STENCIL) {
+      gen6_emit_3DSTATE_STENCIL_BUFFER(p->dev,
+            &blitter->fb.dst.u.zs, p->cp);
+   }
+
+   gen7_emit_3DSTATE_CLEAR_PARAMS(p->dev,
+         blitter->depth_clear_value, p->cp);
+}
+
+static void
+gen7_rectlist_wm_multisample(struct ilo_3d_pipeline *p,
+                             const struct ilo_blitter *blitter,
+                             struct gen6_rectlist_session *session)
+{
+   const uint32_t *packed_sample_pos =
+      (blitter->fb.num_samples > 4) ? p->packed_sample_position_8x :
+      (blitter->fb.num_samples > 1) ? &p->packed_sample_position_4x :
+      &p->packed_sample_position_1x;
+
+   gen7_wa_pipe_control_cs_stall(p, true, true);
+
+   gen6_emit_3DSTATE_MULTISAMPLE(p->dev, blitter->fb.num_samples,
+         packed_sample_pos, true, p->cp);
+
+   gen7_emit_3DSTATE_SAMPLE_MASK(p->dev,
+         (1 << blitter->fb.num_samples) - 1, blitter->fb.num_samples, p->cp);
+}
+
+static void
+gen7_rectlist_commands(struct ilo_3d_pipeline *p,
+                       const struct ilo_blitter *blitter,
+                       struct gen6_rectlist_session *session)
+{
+   gen7_rectlist_wm_multisample(p, blitter, session);
+
+   gen6_emit_STATE_BASE_ADDRESS(p->dev,
+         NULL,                /* General State Base */
+         p->cp->bo,           /* Surface State Base */
+         p->cp->bo,           /* Dynamic State Base */
+         NULL,                /* Indirect Object Base */
+         NULL,                /* Instruction Base */
+         0, 0, 0, 0, p->cp);
+
+   gen6_emit_3DSTATE_VERTEX_BUFFERS(p->dev,
+         &blitter->ve, &blitter->vb, p->cp);
+
+   gen6_emit_3DSTATE_VERTEX_ELEMENTS(p->dev,
+         &blitter->ve, false, false, p->cp);
+
+   gen7_rectlist_pcb_alloc(p, blitter, session);
+
+   /* needed for any VS-related commands */
+   gen7_wa_pipe_control_vs_depth_stall(p);
+
+   gen7_rectlist_urb(p, blitter, session);
+
+   if (blitter->uses & ILO_BLITTER_USE_DSA) {
+      gen7_emit_3DSTATE_DEPTH_STENCIL_STATE_POINTERS(p->dev,
+            session->DEPTH_STENCIL_STATE, p->cp);
+   }
+
+   if (blitter->uses & ILO_BLITTER_USE_CC) {
+      gen7_emit_3DSTATE_CC_STATE_POINTERS(p->dev,
+            session->COLOR_CALC_STATE, p->cp);
+   }
+
+   gen7_rectlist_vs_to_sf(p, blitter, session);
+   gen7_rectlist_wm(p, blitter, session);
+
+   if (blitter->uses & ILO_BLITTER_USE_VIEWPORT) {
+      gen7_emit_3DSTATE_VIEWPORT_STATE_POINTERS_CC(p->dev,
+            session->CC_VIEWPORT, p->cp);
+   }
+
+   gen7_rectlist_wm_depth(p, blitter, session);
+
+   gen6_emit_3DSTATE_DRAWING_RECTANGLE(p->dev, 0, 0,
+         blitter->fb.width, blitter->fb.height, p->cp);
+
+   gen7_emit_3DPRIMITIVE(p->dev, &blitter->draw, NULL, true, p->cp);
+}
+
+static void
+gen7_rectlist_states(struct ilo_3d_pipeline *p,
+                     const struct ilo_blitter *blitter,
+                     struct gen6_rectlist_session *session)
+{
+   if (blitter->uses & ILO_BLITTER_USE_DSA) {
+      session->DEPTH_STENCIL_STATE =
+         gen6_emit_DEPTH_STENCIL_STATE(p->dev, &blitter->dsa, p->cp);
+   }
+
+   if (blitter->uses & ILO_BLITTER_USE_CC) {
+      session->COLOR_CALC_STATE =
+         gen6_emit_COLOR_CALC_STATE(p->dev, &blitter->cc.stencil_ref,
+               blitter->cc.alpha_ref, &blitter->cc.blend_color, p->cp);
+   }
+
+   if (blitter->uses & ILO_BLITTER_USE_VIEWPORT) {
+      session->CC_VIEWPORT =
+         gen6_emit_CC_VIEWPORT(p->dev, &blitter->viewport, 1, p->cp);
+   }
+}
+
+static void
+ilo_3d_pipeline_emit_rectlist_gen7(struct ilo_3d_pipeline *p,
+                                   const struct ilo_blitter *blitter)
+{
+   struct gen6_rectlist_session session;
+
+   memset(&session, 0, sizeof(session));
+   gen7_rectlist_states(p, blitter, &session);
+   gen7_rectlist_commands(p, blitter, &session);
+}
+
 static int
 gen7_pipeline_estimate_commands(const struct ilo_3d_pipeline *p,
                                 const struct ilo_context *ilo)
@@ -809,6 +1036,9 @@ ilo_3d_pipeline_estimate_size_gen7(struct ilo_3d_pipeline *p,
       size = ilo_gpe_gen7_estimate_command_size(p->dev,
             ILO_GPE_GEN7_PIPE_CONTROL, 1);
       break;
+   case ILO_3D_PIPELINE_RECTLIST:
+      size = 64 + 256; /* states + commands */
+      break;
    default:
       assert(!"unknown 3D pipeline action");
       size = 0;
@@ -826,4 +1056,5 @@ ilo_3d_pipeline_init_gen7(struct ilo_3d_pipeline *p)
    p->emit_flush = ilo_3d_pipeline_emit_flush_gen6;
    p->emit_write_timestamp = ilo_3d_pipeline_emit_write_timestamp_gen6;
    p->emit_write_depth_count = ilo_3d_pipeline_emit_write_depth_count_gen6;
+   p->emit_rectlist = ilo_3d_pipeline_emit_rectlist_gen7;
 }
index 103359203642627041ff29499b96f6bc9cd44b6a..d08563da436fdbf40c54d942f16370dd5d22edf3 100644 (file)
@@ -70,5 +70,10 @@ ilo_blitter_destroy(struct ilo_blitter *blitter)
    if (blitter->pipe_blitter)
       util_blitter_destroy(blitter->pipe_blitter);
 
+   if (blitter->buffer.res) {
+      struct pipe_screen *screen = blitter->ilo->base.screen;
+      screen->resource_destroy(screen, blitter->buffer.res);
+   }
+
    FREE(blitter);
 }
index 6a2a0d7022ed7d8792ce2239b7fad4823eb70824..c2c86c04e90b2c542e11e6cec98c43c13e91a940 100644 (file)
 #define ILO_BLITTER_H
 
 #include "ilo_common.h"
+#include "ilo_context.h"
+#include "ilo_gpe.h"
+
+enum ilo_blitter_uses {
+   ILO_BLITTER_USE_DSA           = 1 << 0,
+   ILO_BLITTER_USE_CC            = 1 << 1,
+   ILO_BLITTER_USE_VIEWPORT      = 1 << 2,
+   ILO_BLITTER_USE_FB_DEPTH      = 1 << 3,
+   ILO_BLITTER_USE_FB_STENCIL    = 1 << 4,
+};
+
+enum ilo_blitter_rectlist_op {
+   ILO_BLITTER_RECTLIST_CLEAR_ZS,
+   ILO_BLITTER_RECTLIST_RESOLVE_Z,
+   ILO_BLITTER_RECTLIST_RESOLVE_HIZ,
+};
 
-struct ilo_context;
 struct blitter_context;
+struct pipe_resource;
+struct pipe_surface;
 
 struct ilo_blitter {
    struct ilo_context *ilo;
-
    struct blitter_context *pipe_blitter;
+
+   /*
+    * A minimal context with the goal to send RECTLISTs down the pipeline.
+    */
+   enum ilo_blitter_rectlist_op op;
+   uint32_t uses;
+
+   bool initialized;
+
+   struct {
+      struct pipe_resource *res;
+      unsigned offset, size;
+   } buffer;
+
+   struct ilo_ve_state ve;
+   struct ilo_vb_state vb;
+   struct pipe_draw_info draw;
+
+   struct ilo_viewport_cso viewport;
+   struct ilo_dsa_state dsa;
+
+   struct {
+      struct pipe_stencil_ref stencil_ref;
+      ubyte alpha_ref;
+      struct pipe_blend_color blend_color;
+   } cc;
+
+   uint32_t depth_clear_value;
+
+   struct {
+      struct ilo_surface_cso dst;
+      unsigned width, height;
+      unsigned num_samples;
+   } fb;
 };
 
 struct ilo_blitter *
@@ -99,4 +149,20 @@ ilo_blitter_blt_clear_zs(struct ilo_blitter *blitter,
                          unsigned x, unsigned y,
                          unsigned width, unsigned height);
 
+bool
+ilo_blitter_rectlist_clear_zs(struct ilo_blitter *blitter,
+                              struct pipe_surface *zs,
+                              unsigned clear_flags,
+                              double depth, unsigned stencil);
+
+void
+ilo_blitter_rectlist_resolve_z(struct ilo_blitter *blitter,
+                               struct pipe_resource *res,
+                               unsigned level, unsigned slice);
+
+void
+ilo_blitter_rectlist_resolve_hiz(struct ilo_blitter *blitter,
+                                 struct pipe_resource *res,
+                                 unsigned level, unsigned slice);
+
 #endif /* ILO_BLITTER_H */
diff --git a/src/gallium/drivers/ilo/ilo_blitter_rectlist.c b/src/gallium/drivers/ilo/ilo_blitter_rectlist.c
new file mode 100644 (file)
index 0000000..6314c35
--- /dev/null
@@ -0,0 +1,525 @@
+/*
+ * Mesa 3-D graphics library
+ *
+ * Copyright (C) 2014 LunarG, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Chia-I Wu <olv@lunarg.com>
+ */
+
+#include "util/u_draw.h"
+#include "util/u_pack_color.h"
+
+#include "ilo_blitter.h"
+#include "ilo_3d.h"
+#include "ilo_3d_pipeline.h"
+#include "ilo_gpe.h"
+#include "ilo_gpe_gen6.h" /* for ve_init_cso_with_components */
+
+/**
+ * Set the states that are invariant between all ops.
+ */
+static bool
+ilo_blitter_set_invariants(struct ilo_blitter *blitter)
+{
+   struct pipe_screen *screen = blitter->ilo->base.screen;
+   struct pipe_resource templ;
+   struct pipe_vertex_element velems[2];
+   struct pipe_viewport_state vp;
+
+   if (blitter->initialized)
+      return true;
+
+   blitter->buffer.size = 4096;
+
+   /* allocate the vertex buffer */
+   memset(&templ, 0, sizeof(templ));
+   templ.target = PIPE_BUFFER;
+   templ.width0 = blitter->buffer.size;
+   templ.usage = PIPE_USAGE_STREAM;
+   templ.bind = PIPE_BIND_VERTEX_BUFFER;
+   blitter->buffer.res = screen->resource_create(screen, &templ);
+   if (!blitter->buffer.res)
+      return false;
+
+   /* do not increase reference count */
+   blitter->vb.states[0].buffer = blitter->buffer.res;
+
+   /* only vertex X and Y */
+   blitter->vb.states[0].stride = 2 * sizeof(float);
+   blitter->vb.enabled_mask = 0x1;
+   memset(&velems, 0, sizeof(velems));
+   velems[1].src_format = PIPE_FORMAT_R32G32_FLOAT;
+   ilo_gpe_init_ve(blitter->ilo->dev, 2, velems, &blitter->ve);
+
+   /* override first VE to be VUE header */
+   ve_init_cso_with_components(blitter->ilo->dev,
+         BRW_VE1_COMPONENT_STORE_0, /* Reserved */
+         BRW_VE1_COMPONENT_STORE_0, /* Render Target Array Index */
+         BRW_VE1_COMPONENT_STORE_0, /* Viewport Index */
+         BRW_VE1_COMPONENT_STORE_0, /* Point Width */
+         &blitter->ve.cso[0]);
+
+   /* a rectangle has 3 vertices in a RECTLIST */
+   util_draw_init_info(&blitter->draw);
+   blitter->draw.count = 3;
+
+   /**
+    * From the Haswell PRM, volume 7, page 615:
+    *
+    *     "The clear value must be between the min and max depth values
+    *     (inclusive) defined in the CC_VIEWPORT."
+    *
+    * Even though clipping and viewport transformation will be disabled, we
+    * still need to set up the viewport states.
+    */
+   memset(&vp, 0, sizeof(vp));
+   vp.scale[0] = 1.0f;
+   vp.scale[1] = 1.0f;
+   vp.scale[2] = 1.0f;
+   vp.scale[3] = 1.0f;
+   ilo_gpe_set_viewport_cso(blitter->ilo->dev, &vp, &blitter->viewport);
+
+   blitter->initialized = true;
+
+   return true;
+}
+
+static void
+ilo_blitter_set_op(struct ilo_blitter *blitter,
+                   enum ilo_blitter_rectlist_op op)
+{
+   blitter->op = op;
+}
+
+/**
+ * Set the rectangle primitive.
+ */
+static void
+ilo_blitter_set_rectlist(struct ilo_blitter *blitter,
+                         unsigned x, unsigned y,
+                         unsigned width, unsigned height)
+{
+   unsigned usage = PIPE_TRANSFER_WRITE | PIPE_TRANSFER_UNSYNCHRONIZED;
+   float vertices[3][2];
+   struct pipe_box box;
+
+   /*
+    * From the Sandy Bridge PRM, volume 2 part 1, page 11:
+    *
+    *     "(RECTLIST) A list of independent rectangles, where only 3 vertices
+    *      are provided per rectangle object, with the fourth vertex implied
+    *      by the definition of a rectangle. V0=LowerRight, V1=LowerLeft,
+    *      V2=UpperLeft. Implied V3 = V0- V1+V2."
+    */
+   vertices[0][0] = (float) (x + width);
+   vertices[0][1] = (float) (y + height);
+   vertices[1][0] = (float) x;
+   vertices[1][1] = (float) (y + height);
+   vertices[2][0] = (float) x;
+   vertices[2][1] = (float) y;
+
+   /* buffer is full */
+   if (blitter->buffer.offset + sizeof(vertices) > blitter->buffer.size) {
+      if (!ilo_buffer_alloc_bo(ilo_buffer(blitter->buffer.res)))
+         usage &= ~PIPE_TRANSFER_UNSYNCHRONIZED;
+
+      blitter->buffer.offset = 0;
+   }
+
+   u_box_1d(blitter->buffer.offset, sizeof(vertices), &box);
+
+   blitter->ilo->base.transfer_inline_write(&blitter->ilo->base,
+         blitter->buffer.res, 0, usage, &box, vertices, 0, 0);
+
+   blitter->vb.states[0].buffer_offset = blitter->buffer.offset;
+   blitter->buffer.offset += sizeof(vertices);
+}
+
+static void
+ilo_blitter_set_clear_values(struct ilo_blitter *blitter,
+                             uint32_t depth, ubyte stencil)
+{
+   blitter->depth_clear_value = depth;
+   blitter->cc.stencil_ref.ref_value[0] = stencil;
+}
+
+static void
+ilo_blitter_set_dsa(struct ilo_blitter *blitter,
+                    const struct pipe_depth_stencil_alpha_state *state)
+{
+   ilo_gpe_init_dsa(blitter->ilo->dev, state, &blitter->dsa);
+}
+
+static void
+ilo_blitter_set_fb(struct ilo_blitter *blitter,
+                   const struct pipe_resource *res, unsigned level,
+                   const struct ilo_surface_cso *cso)
+{
+   blitter->fb.width = u_minify(res->width0, level);
+   blitter->fb.height = u_minify(res->height0, level);
+
+   blitter->fb.num_samples = res->nr_samples;
+   if (!blitter->fb.num_samples)
+      blitter->fb.num_samples = 1;
+
+   memcpy(&blitter->fb.dst, cso, sizeof(*cso));
+}
+
+static void
+ilo_blitter_set_fb_from_surface(struct ilo_blitter *blitter,
+                                struct pipe_surface *surf)
+{
+   ilo_blitter_set_fb(blitter, surf->texture, surf->u.tex.level,
+         (const struct ilo_surface_cso *) surf);
+}
+
+static void
+ilo_blitter_set_fb_from_resource(struct ilo_blitter *blitter,
+                                 struct pipe_resource *res,
+                                 enum pipe_format format,
+                                 unsigned level, unsigned slice)
+{
+   struct pipe_surface templ, *surf;
+
+   memset(&templ, 0, sizeof(templ));
+   templ.format = format;
+   templ.u.tex.level = level;
+   templ.u.tex.first_layer = slice;
+   templ.u.tex.last_layer = slice;
+
+   /* if we did not call create_surface(), it would never fail */
+   surf = blitter->ilo->base.create_surface(&blitter->ilo->base, res, &templ);
+   assert(surf);
+
+   ilo_blitter_set_fb(blitter, res, level,
+         (const struct ilo_surface_cso *) surf);
+
+   pipe_surface_reference(&surf, NULL);
+}
+
+static void
+ilo_blitter_set_uses(struct ilo_blitter *blitter, uint32_t uses)
+{
+   blitter->uses = uses;
+}
+
+static void
+hiz_emit_rectlist(struct ilo_blitter *blitter)
+{
+   struct ilo_3d *hw3d = blitter->ilo->hw3d;
+   struct ilo_3d_pipeline *p = hw3d->pipeline;
+
+   ilo_3d_own_render_ring(hw3d);
+
+   /*
+    * From the Sandy Bridge PRM, volume 2 part 1, page 313:
+    *
+    *     "If other rendering operations have preceded this clear, a
+    *      PIPE_CONTROL with write cache flush enabled and Z-inhibit
+    *      disabled must be issued before the rectangle primitive used for
+    *      the depth buffer clear operation."
+    *
+    * From the Sandy Bridge PRM, volume 2 part 1, page 314:
+    *
+    *     "Depth buffer clear pass must be followed by a PIPE_CONTROL
+    *      command with DEPTH_STALL bit set and Then followed by Depth
+    *      FLUSH"
+    *
+    * But the pipeline has to be flushed both before and after not only
+    * because of these workarounds.  We need them for reasons such as
+    *
+    *  - we may sample from a texture that was rendered to
+    *  - we may sample from the fb shortly after
+    */
+   if (!ilo_cp_empty(p->cp))
+      ilo_3d_pipeline_emit_flush(p);
+
+   ilo_3d_pipeline_emit_rectlist(p, blitter);
+
+   ilo_3d_pipeline_emit_flush(p);
+}
+
+/**
+ * This must be called after ilo_blitter_set_fb().
+ */
+static void
+hiz_set_rectlist(struct ilo_blitter *blitter, bool aligned)
+{
+   unsigned width = blitter->fb.width;
+   unsigned height = blitter->fb.height;
+
+   /*
+    * From the Sandy Bridge PRM, volume 2 part 1, page 313-314:
+    *
+    *     "A rectangle primitive representing the clear area is delivered. The
+    *      primitive must adhere to the following restrictions on size:
+    *
+    *      - If Number of Multisamples is NUMSAMPLES_1, the rectangle must be
+    *        aligned to an 8x4 pixel block relative to the upper left corner
+    *        of the depth buffer, and contain an integer number of these pixel
+    *        blocks, and all 8x4 pixels must be lit.
+    *
+    *      - If Number of Multisamples is NUMSAMPLES_4, the rectangle must be
+    *        aligned to a 4x2 pixel block (8x4 sample block) relative to the
+    *        upper left corner of the depth buffer, and contain an integer
+    *        number of these pixel blocks, and all samples of the 4x2 pixels
+    *        must be lit
+    *
+    *      - If Number of Multisamples is NUMSAMPLES_8, the rectangle must be
+    *        aligned to a 2x2 pixel block (8x4 sample block) relative to the
+    *        upper left corner of the depth buffer, and contain an integer
+    *        number of these pixel blocks, and all samples of the 2x2 pixels
+    *        must be list."
+    *
+    *     "The following is required when performing a depth buffer resolve:
+    *
+    *      - A rectangle primitive of the same size as the previous depth
+    *        buffer clear operation must be delivered, and depth buffer state
+    *        cannot have changed since the previous depth buffer clear
+    *        operation."
+    *
+    * Making the RECTLIST aligned to 8x4 is easy.  But how about
+    * 3DSTATE_DRAWING_RECTANGLE and 3DSTATE_DEPTH_BUFFER?  Since we use
+    * HALIGN_8 and VALIGN_4 for depth buffers, we can safely align the drawing
+    * rectangle, except that the PRM requires the drawing rectangle to be
+    * clampped to the render target boundary.  For 3DSTATE_DEPTH_BUFFER, we
+    * cannot align the Width and Height fields if level or slice is greater
+    * than zero.
+    */
+   if (aligned) {
+      switch (blitter->fb.num_samples) {
+      case 1:
+         width = align(width, 8);
+         height = align(height, 4);
+         break;
+      case 2:
+         width = align(width, 4);
+         height = align(height, 4);
+         break;
+      case 4:
+         width = align(width, 4);
+         height = align(height, 2);
+         break;
+      case 8:
+      default:
+         width = align(width, 2);
+         height = align(height, 2);
+         break;
+      }
+   }
+
+   ilo_blitter_set_rectlist(blitter, 0, 0, width, height);
+}
+
+static bool
+hiz_can_clear_zs(const struct ilo_blitter *blitter,
+                 const struct ilo_texture *tex)
+{
+   if (blitter->ilo->dev->gen > ILO_GEN(6))
+      return true;
+
+   /*
+    * From the Sandy Bridge PRM, volume 2 part 1, page 314:
+    *
+    *      Several cases exist where Depth Buffer Clear cannot be enabled (the
+    *      legacy method of clearing must be performed):
+    *
+    *      - If the depth buffer format is D32_FLOAT_S8X24_UINT or
+    *        D24_UNORM_S8_UINT.
+    *
+    *      - If stencil test is enabled but the separate stencil buffer is
+    *        disabled.
+    *
+    *      - [DevSNB-A{W/A}]: ...
+    *
+    *      - [DevSNB{W/A}]: When depth buffer format is D16_UNORM and the
+    *        width of the map (LOD0) is not multiple of 16, fast clear
+    *        optimization must be disabled.
+    */
+   switch (tex->bo_format) {
+   case PIPE_FORMAT_Z16_UNORM:
+      if (tex->base.width0 % 16)
+         return false;
+      break;
+   case PIPE_FORMAT_Z24_UNORM_S8_UINT:
+   case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
+      assert(!"HiZ with combined depth/stencil");
+      return false;
+      break;
+   default:
+      break;
+   }
+
+   return true;
+}
+
+bool
+ilo_blitter_rectlist_clear_zs(struct ilo_blitter *blitter,
+                              struct pipe_surface *zs,
+                              unsigned clear_flags,
+                              double depth, unsigned stencil)
+{
+   struct ilo_texture *tex = ilo_texture(zs->texture);
+   struct pipe_depth_stencil_alpha_state dsa_state;
+   uint32_t uses;
+
+   if (!tex->hiz.bo)
+      return false;
+
+   if (!hiz_can_clear_zs(blitter, tex))
+      return false;
+
+   /*
+    * From the Sandy Bridge PRM, volume 2 part 1, page 313-314:
+    *
+    *     "- Depth Test Enable must be disabled and Depth Buffer Write Enable
+    *        must be enabled (if depth is being cleared).
+    *
+    *      - Stencil buffer clear can be performed at the same time by
+    *        enabling Stencil Buffer Write Enable.  Stencil Test Enable must
+    *        be enabled and Stencil Pass Depth Pass Op set to REPLACE, and the
+    *        clear value that is placed in the stencil buffer is the Stencil
+    *        Reference Value from COLOR_CALC_STATE.
+    *
+    *      - Note also that stencil buffer clear can be performed without
+    *        depth buffer clear. For stencil only clear, Depth Test Enable and
+    *        Depth Buffer Write Enable must be disabled.
+    *
+    *      - [DevSNB] errata: For stencil buffer only clear, the previous
+    *        depth clear value must be delivered during the clear."
+    */
+   memset(&dsa_state, 0, sizeof(dsa_state));
+
+   if (clear_flags & PIPE_CLEAR_DEPTH)
+      dsa_state.depth.writemask = true;
+
+   if (clear_flags & PIPE_CLEAR_STENCIL) {
+      dsa_state.stencil[0].enabled = true;
+      dsa_state.stencil[0].func = PIPE_FUNC_ALWAYS;
+      dsa_state.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
+      dsa_state.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
+      dsa_state.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
+
+      /*
+       * From the Ivy Bridge PRM, volume 2 part 1, page 277:
+       *
+       *     "Additionally the following must be set to the correct values.
+       *
+       *      - DEPTH_STENCIL_STATE::Stencil Write Mask must be 0xFF
+       *      - DEPTH_STENCIL_STATE::Stencil Test Mask must be 0xFF
+       *      - DEPTH_STENCIL_STATE::Back Face Stencil Write Mask must be 0xFF
+       *      - DEPTH_STENCIL_STATE::Back Face Stencil Test Mask must be 0xFF"
+       */
+      dsa_state.stencil[0].valuemask = 0xff;
+      dsa_state.stencil[0].writemask = 0xff;
+      dsa_state.stencil[1].valuemask = 0xff;
+      dsa_state.stencil[1].writemask = 0xff;
+   }
+
+   ilo_blitter_set_invariants(blitter);
+   ilo_blitter_set_op(blitter, ILO_BLITTER_RECTLIST_CLEAR_ZS);
+
+   ilo_blitter_set_dsa(blitter, &dsa_state);
+   ilo_blitter_set_clear_values(blitter,
+         util_pack_z(zs->format, depth), (ubyte) stencil);
+   ilo_blitter_set_fb_from_surface(blitter, zs);
+
+   uses = ILO_BLITTER_USE_DSA;
+   if (clear_flags & PIPE_CLEAR_DEPTH)
+      uses |= ILO_BLITTER_USE_VIEWPORT | ILO_BLITTER_USE_FB_DEPTH;
+   if (clear_flags & PIPE_CLEAR_STENCIL)
+      uses |= ILO_BLITTER_USE_CC | ILO_BLITTER_USE_FB_STENCIL;
+   ilo_blitter_set_uses(blitter, uses);
+
+   hiz_set_rectlist(blitter, true);
+   hiz_emit_rectlist(blitter);
+
+   return true;
+}
+
+void
+ilo_blitter_rectlist_resolve_z(struct ilo_blitter *blitter,
+                               struct pipe_resource *res,
+                               unsigned level, unsigned slice)
+{
+   struct ilo_texture *tex = ilo_texture(res);
+   struct pipe_depth_stencil_alpha_state dsa_state;
+
+   if (!tex->hiz.bo)
+      return;
+
+   /*
+    * From the Sandy Bridge PRM, volume 2 part 1, page 314:
+    *
+    *     "Depth Test Enable must be enabled with the Depth Test Function set
+    *      to NEVER. Depth Buffer Write Enable must be enabled. Stencil Test
+    *      Enable and Stencil Buffer Write Enable must be disabled."
+    */
+   memset(&dsa_state, 0, sizeof(dsa_state));
+   dsa_state.depth.writemask = true;
+   dsa_state.depth.enabled = true;
+   dsa_state.depth.func = PIPE_FUNC_NEVER;
+
+   ilo_blitter_set_invariants(blitter);
+   ilo_blitter_set_op(blitter, ILO_BLITTER_RECTLIST_RESOLVE_Z);
+
+   ilo_blitter_set_dsa(blitter, &dsa_state);
+   ilo_blitter_set_fb_from_resource(blitter, res, res->format, level, slice);
+   ilo_blitter_set_uses(blitter,
+         ILO_BLITTER_USE_DSA | ILO_BLITTER_USE_FB_DEPTH);
+
+   hiz_set_rectlist(blitter, true);
+   hiz_emit_rectlist(blitter);
+}
+
+void
+ilo_blitter_rectlist_resolve_hiz(struct ilo_blitter *blitter,
+                                 struct pipe_resource *res,
+                                 unsigned level, unsigned slice)
+{
+   struct ilo_texture *tex = ilo_texture(res);
+   struct pipe_depth_stencil_alpha_state dsa_state;
+
+   if (!tex->hiz.bo)
+      return;
+
+   /*
+    * From the Sandy Bridge PRM, volume 2 part 1, page 315:
+    *
+    *     "(Hierarchical Depth Buffer Resolve) Depth Test Enable must be
+    *      disabled. Depth Buffer Write Enable must be enabled. Stencil Test
+    *      Enable and Stencil Buffer Write Enable must be disabled."
+    */
+   memset(&dsa_state, 0, sizeof(dsa_state));
+   dsa_state.depth.writemask = true;
+
+   ilo_blitter_set_invariants(blitter);
+   ilo_blitter_set_op(blitter, ILO_BLITTER_RECTLIST_RESOLVE_HIZ);
+
+   ilo_blitter_set_dsa(blitter, &dsa_state);
+   ilo_blitter_set_fb_from_resource(blitter, res, res->format, level, slice);
+   ilo_blitter_set_uses(blitter,
+         ILO_BLITTER_USE_DSA | ILO_BLITTER_USE_FB_DEPTH);
+
+   hiz_set_rectlist(blitter, false);
+   hiz_emit_rectlist(blitter);
+}