Mesa (master): ilo: construct depth/stencil command in create_surface()

Chia-I Wu olv at kemper.freedesktop.org
Tue Jun 18 08:26:17 UTC 2013


Module: Mesa
Branch: master
Commit: 443dc15cf77edcaa7804c4277f0cce5d7c1d6b25
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=443dc15cf77edcaa7804c4277f0cce5d7c1d6b25

Author: Chia-I Wu <olvaffe at gmail.com>
Date:   Tue Jun 18 12:33:15 2013 +0800

ilo: construct depth/stencil command in create_surface()

Add ilo_gpe_init_zs_surface() to construct

 3DSTATE_DEPTH_BUFFER
 3DSTATE_STENCIL_BUFFER
 3DSTATE_HIER_DEPTH_BUFFER

at surface creation time.  This allows fast state emission in draw_vbo().

---

 src/gallium/drivers/ilo/ilo_3d_pipeline_gen6.c |   15 +-
 src/gallium/drivers/ilo/ilo_3d_pipeline_gen7.c |   19 +-
 src/gallium/drivers/ilo/ilo_gpe.h              |   15 +
 src/gallium/drivers/ilo/ilo_gpe_gen6.c         |  575 +++++++++++++-----------
 src/gallium/drivers/ilo/ilo_gpe_gen6.h         |    6 +-
 src/gallium/drivers/ilo/ilo_state.c            |    9 +-
 6 files changed, 368 insertions(+), 271 deletions(-)

diff --git a/src/gallium/drivers/ilo/ilo_3d_pipeline_gen6.c b/src/gallium/drivers/ilo/ilo_3d_pipeline_gen6.c
index c60fc01..e5c9db1 100644
--- a/src/gallium/drivers/ilo/ilo_3d_pipeline_gen6.c
+++ b/src/gallium/drivers/ilo/ilo_3d_pipeline_gen6.c
@@ -717,12 +717,25 @@ gen6_pipeline_wm_depth(struct ilo_3d_pipeline *p,
 {
    /* 3DSTATE_DEPTH_BUFFER and 3DSTATE_CLEAR_PARAMS */
    if (DIRTY(FRAMEBUFFER) || session->batch_bo_changed) {
+      const struct ilo_zs_surface *zs;
+
+      if (ilo->fb.state.zsbuf) {
+         const struct ilo_surface_cso *surface =
+            (const struct ilo_surface_cso *) ilo->fb.state.zsbuf;
+
+         assert(!surface->is_rt);
+         zs = &surface->u.zs;
+      }
+      else {
+         zs = &ilo->fb.null_zs;
+      }
+
       if (p->dev->gen == ILO_GEN(6)) {
          gen6_wa_pipe_control_post_sync(p, false);
          gen6_wa_pipe_control_wm_depth_flush(p);
       }
 
-      p->gen6_3DSTATE_DEPTH_BUFFER(p->dev, ilo->fb.state.zsbuf, p->cp);
+      p->gen6_3DSTATE_DEPTH_BUFFER(p->dev, zs, p->cp);
 
       /* TODO */
       p->gen6_3DSTATE_CLEAR_PARAMS(p->dev, 0, p->cp);
diff --git a/src/gallium/drivers/ilo/ilo_3d_pipeline_gen7.c b/src/gallium/drivers/ilo/ilo_3d_pipeline_gen7.c
index 96e2e18..878f6d0 100644
--- a/src/gallium/drivers/ilo/ilo_3d_pipeline_gen7.c
+++ b/src/gallium/drivers/ilo/ilo_3d_pipeline_gen7.c
@@ -532,9 +532,22 @@ gen7_pipeline_wm(struct ilo_3d_pipeline *p,
 
    /* 3DSTATE_DEPTH_BUFFER and 3DSTATE_CLEAR_PARAMS */
    if (DIRTY(FRAMEBUFFER) || session->batch_bo_changed) {
-      p->gen7_3DSTATE_DEPTH_BUFFER(p->dev, ilo->fb.state.zsbuf, p->cp);
-      p->gen6_3DSTATE_HIER_DEPTH_BUFFER(p->dev, ilo->fb.state.zsbuf, p->cp);
-      p->gen6_3DSTATE_STENCIL_BUFFER(p->dev, ilo->fb.state.zsbuf, p->cp);
+      const struct ilo_zs_surface *zs;
+
+      if (ilo->fb.state.zsbuf) {
+         const struct ilo_surface_cso *surface =
+            (const struct ilo_surface_cso *) ilo->fb.state.zsbuf;
+
+         assert(!surface->is_rt);
+         zs = &surface->u.zs;
+      }
+      else {
+         zs = &ilo->fb.null_zs;
+      }
+
+      p->gen7_3DSTATE_DEPTH_BUFFER(p->dev, zs, p->cp);
+      p->gen6_3DSTATE_HIER_DEPTH_BUFFER(p->dev, zs, p->cp);
+      p->gen6_3DSTATE_STENCIL_BUFFER(p->dev, zs, p->cp);
 
       /* TODO */
       p->gen6_3DSTATE_CLEAR_PARAMS(p->dev, 0, p->cp);
diff --git a/src/gallium/drivers/ilo/ilo_gpe.h b/src/gallium/drivers/ilo/ilo_gpe.h
index 3a3b355..fcbd5b8 100644
--- a/src/gallium/drivers/ilo/ilo_gpe.h
+++ b/src/gallium/drivers/ilo/ilo_gpe.h
@@ -216,12 +216,19 @@ struct ilo_surface_cso {
    bool is_rt;
    union {
       struct ilo_view_surface rt;
+      struct ilo_zs_surface {
+         uint32_t payload[10];
+         struct intel_bo *bo;
+         struct intel_bo *hiz_bo;
+         struct intel_bo *separate_s8_bo;
+      } zs;
    } u;
 };
 
 struct ilo_fb_state {
    struct pipe_framebuffer_state state;
 
+   struct ilo_zs_surface null_zs;
    unsigned num_samples;
 };
 
@@ -413,4 +420,12 @@ ilo_gpe_init_view_surface_for_texture(const struct ilo_dev_info *dev,
    }
 }
 
+void
+ilo_gpe_init_zs_surface(const struct ilo_dev_info *dev,
+                        const struct ilo_texture *tex,
+                        enum pipe_format format,
+                        unsigned level,
+                        unsigned first_layer, unsigned num_layers,
+                        struct ilo_zs_surface *zs);
+
 #endif /* ILO_GPE_H */
diff --git a/src/gallium/drivers/ilo/ilo_gpe_gen6.c b/src/gallium/drivers/ilo/ilo_gpe_gen6.c
index 89566b7..56db7da 100644
--- a/src/gallium/drivers/ilo/ilo_gpe_gen6.c
+++ b/src/gallium/drivers/ilo/ilo_gpe_gen6.c
@@ -2334,20 +2334,86 @@ gen6_emit_3DSTATE_DRAWING_RECTANGLE(const struct ilo_dev_info *dev,
    ilo_cp_end(cp);
 }
 
-static int
-gen6_get_depth_buffer_format(const struct ilo_dev_info *dev,
-                             enum pipe_format format,
-                             bool hiz,
-                             bool separate_stencil,
-                             bool *has_depth,
-                             bool *has_stencil)
+struct ilo_zs_surface_info {
+   int surface_type;
+   int format;
+
+   struct {
+      struct intel_bo *bo;
+      unsigned stride;
+      enum intel_tiling_mode tiling;
+      uint32_t offset;
+   } zs, stencil, hiz;
+
+   unsigned width, height, depth;
+   unsigned lod, first_layer, num_layers;
+   uint32_t x_offset, y_offset;
+};
+
+static void
+zs_init_info_null(const struct ilo_dev_info *dev,
+                  struct ilo_zs_surface_info *info)
+{
+   ILO_GPE_VALID_GEN(dev, 6, 7);
+
+   memset(info, 0, sizeof(*info));
+
+   info->surface_type = BRW_SURFACE_NULL;
+   info->format = BRW_DEPTHFORMAT_D32_FLOAT;
+   info->width = 1;
+   info->height = 1;
+   info->depth = 1;
+   info->num_layers = 1;
+}
+
+static void
+zs_init_info(const struct ilo_dev_info *dev,
+             const struct ilo_texture *tex,
+             enum pipe_format format,
+             unsigned level,
+             unsigned first_layer, unsigned num_layers,
+             struct ilo_zs_surface_info *info)
 {
-   int depth_format;
+   const bool rebase_layer = true;
+   struct intel_bo * const hiz_bo = NULL;
+   bool separate_stencil;
+   uint32_t x_offset[3], y_offset[3];
 
    ILO_GPE_VALID_GEN(dev, 6, 7);
 
-   *has_depth = true;
-   *has_stencil = false;
+   memset(info, 0, sizeof(*info));
+
+   info->surface_type = ilo_gpe_gen6_translate_texture(tex->base.target);
+
+   if (info->surface_type == BRW_SURFACE_CUBE) {
+      /*
+       * From the Sandy Bridge PRM, volume 2 part 1, page 325-326:
+       *
+       *     "For Other Surfaces (Cube Surfaces):
+       *      This field (Minimum Array Element) is ignored."
+       *
+       *     "For Other Surfaces (Cube Surfaces):
+       *      This field (Render Target View Extent) is ignored."
+       *
+       * As such, we cannot set first_layer and num_layers on cube surfaces.
+       * To work around that, treat it as a 2D surface.
+       */
+      info->surface_type = BRW_SURFACE_2D;
+   }
+
+   if (dev->gen >= ILO_GEN(7)) {
+      separate_stencil = true;
+   }
+   else {
+      /*
+       * From the Sandy Bridge PRM, volume 2 part 1, page 317:
+       *
+       *     "This field (Separate Stencil Buffer Enable) must be set to the
+       *      same value (enabled or disabled) as Hierarchical Depth Buffer
+       *      Enable."
+       */
+      separate_stencil = (hiz_bo != NULL);
+   }
 
    /*
     * From the Sandy Bridge PRM, volume 2 part 1, page 317:
@@ -2366,156 +2432,130 @@ gen6_get_depth_buffer_format(const struct ilo_dev_info *dev,
     * is indeed used, the depth values output by the fragment shaders will
     * be different when read back.
     *
-    * As for GEN7+, separate_stencil_buffer is always true.
+    * As for GEN7+, separate_stencil is always true.
     */
    switch (format) {
    case PIPE_FORMAT_Z16_UNORM:
-      depth_format = BRW_DEPTHFORMAT_D16_UNORM;
+      info->format = BRW_DEPTHFORMAT_D16_UNORM;
       break;
    case PIPE_FORMAT_Z32_FLOAT:
-      depth_format = BRW_DEPTHFORMAT_D32_FLOAT;
+      info->format = BRW_DEPTHFORMAT_D32_FLOAT;
       break;
    case PIPE_FORMAT_Z24X8_UNORM:
-      depth_format = (separate_stencil) ?
-         BRW_DEPTHFORMAT_D24_UNORM_X8_UINT :
-         BRW_DEPTHFORMAT_D24_UNORM_S8_UINT;
-      break;
    case PIPE_FORMAT_Z24_UNORM_S8_UINT:
-      depth_format = (separate_stencil) ?
+      info->format = (separate_stencil) ?
          BRW_DEPTHFORMAT_D24_UNORM_X8_UINT :
          BRW_DEPTHFORMAT_D24_UNORM_S8_UINT;
-      *has_stencil = true;
       break;
    case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
-      depth_format = (separate_stencil) ?
+      info->format = (separate_stencil) ?
          BRW_DEPTHFORMAT_D32_FLOAT :
          BRW_DEPTHFORMAT_D32_FLOAT_S8X24_UINT;
-      *has_stencil = true;
       break;
    case PIPE_FORMAT_S8_UINT:
       if (separate_stencil) {
-         depth_format = BRW_DEPTHFORMAT_D32_FLOAT;
-         *has_depth = false;
-         *has_stencil = true;
+         info->format = BRW_DEPTHFORMAT_D32_FLOAT;
          break;
       }
       /* fall through */
    default:
       assert(!"unsupported depth/stencil format");
-      depth_format = BRW_DEPTHFORMAT_D32_FLOAT;
-      *has_depth = false;
-      *has_stencil = false;
+      zs_init_info_null(dev, info);
+      return;
       break;
    }
 
-   return depth_format;
-}
+   if (format != PIPE_FORMAT_S8_UINT) {
+      info->zs.bo = tex->bo;
+      info->zs.stride = tex->bo_stride;
+      info->zs.tiling = tex->tiling;
 
-static void
-gen6_emit_3DSTATE_DEPTH_BUFFER(const struct ilo_dev_info *dev,
-                               const struct pipe_surface *surface,
-                               struct ilo_cp *cp)
-{
-   const uint32_t cmd = (dev->gen >= ILO_GEN(7)) ?
-      ILO_GPE_CMD(0x3, 0x0, 0x05) : ILO_GPE_CMD(0x3, 0x1, 0x05);
-   const uint8_t cmd_len = 7;
-   const int max_2d_size = (dev->gen >= ILO_GEN(7)) ? 16384 : 8192;
-   const int max_array_size = (dev->gen >= ILO_GEN(7)) ? 2048 : 512;
-   const bool hiz = false;
-   struct ilo_texture *tex;
-   uint32_t dw1, dw3, dw4, dw6;
-   uint32_t slice_offset, x_offset, y_offset;
-   int surface_type, depth_format;
-   unsigned lod, first_layer, num_layers;
-   unsigned width, height, depth;
-   bool separate_stencil, has_depth, has_stencil;
+      if (rebase_layer) {
+         info->zs.offset = ilo_texture_get_slice_offset(tex,
+               level, first_layer, &x_offset[0], &y_offset[0]);
+      }
+   }
 
-   ILO_GPE_VALID_GEN(dev, 6, 7);
+   if (tex->separate_s8 || format == PIPE_FORMAT_S8_UINT) {
+      const struct ilo_texture *s8_tex =
+         (tex->separate_s8) ? tex->separate_s8 : tex;
+
+      info->stencil.bo = s8_tex->bo;
 
-   if (dev->gen >= ILO_GEN(7)) {
-      separate_stencil = true;
-   }
-   else {
       /*
-       * From the Sandy Bridge PRM, volume 2 part 1, page 317:
+       * From the Sandy Bridge PRM, volume 2 part 1, page 329:
        *
-       *     "This field (Separate Stencil Buffer Enable) must be set to the
-       *      same value (enabled or disabled) as Hierarchical Depth Buffer
-       *      Enable."
+       *     "The pitch must be set to 2x the value computed based on width,
+       *       as the stencil buffer is stored with two rows interleaved."
+       *
+       * According to the classic driver, we need to do the same for GEN7+
+       * even though the Ivy Bridge PRM does not say anything about it.
        */
-      separate_stencil = hiz;
-   }
-
-   if (surface) {
-      depth_format = gen6_get_depth_buffer_format(dev,
-            surface->format, hiz, separate_stencil, &has_depth, &has_stencil);
-   }
-   else {
-      has_depth = false;
-      has_stencil = false;
-   }
+      info->stencil.stride = s8_tex->bo_stride * 2;
 
-   if (!has_depth && !has_stencil) {
-      dw1 = BRW_SURFACE_NULL << 29 |
-            BRW_DEPTHFORMAT_D32_FLOAT << 18;
+      info->stencil.tiling = s8_tex->tiling;
 
-      /* Y-tiled */
-      if (dev->gen == ILO_GEN(6)) {
-         dw1 |= 1 << 27 |
-                1 << 26;
+      if (rebase_layer) {
+         info->stencil.offset = ilo_texture_get_slice_offset(s8_tex,
+               level, first_layer, &x_offset[1], &y_offset[1]);
       }
-
-      ilo_cp_begin(cp, cmd_len);
-      ilo_cp_write(cp, cmd | (cmd_len - 2));
-      ilo_cp_write(cp, dw1);
-      ilo_cp_write(cp, 0);
-      ilo_cp_write(cp, 0);
-      ilo_cp_write(cp, 0);
-      ilo_cp_write(cp, 0);
-      ilo_cp_write(cp, 0);
-      ilo_cp_end(cp);
-
-      return;
    }
 
-   tex = ilo_texture(surface->texture);
-
-   surface_type = ilo_gpe_gen6_translate_texture(tex->base.target);
-   lod = surface->u.tex.level;
-   first_layer = surface->u.tex.first_layer;
-   num_layers = surface->u.tex.last_layer - first_layer + 1;
+   if (hiz_bo) {
+      info->hiz.bo = hiz_bo;
+      info->hiz.stride = 0;
+      info->hiz.tiling = 0;
+      info->hiz.offset = 0;
+      x_offset[2] = 0;
+      y_offset[2] = 0;
+   }
 
-   width = tex->base.width0;
-   height = tex->base.height0;
-   depth = (tex->base.target == PIPE_TEXTURE_3D) ?
+   info->width = tex->base.width0;
+   info->height = tex->base.height0;
+   info->depth = (tex->base.target == PIPE_TEXTURE_3D) ?
       tex->base.depth0 : num_layers;
 
-   if (surface_type == BRW_SURFACE_CUBE) {
-      /*
-       * From the Sandy Bridge PRM, volume 2 part 1, page 325-326:
-       *
-       *     "For Other Surfaces (Cube Surfaces):
-       *      This field (Minimum Array Element) is ignored."
-       *
-       *     "For Other Surfaces (Cube Surfaces):
-       *      This field (Render Target View Extent) is ignored."
-       *
-       * As such, we cannot set first_layer and num_layers on cube surfaces.
-       * To work around that, treat it as a 2D surface.
-       */
-      surface_type = BRW_SURFACE_2D;
-   }
+   info->lod = level;
+   info->first_layer = first_layer;
+   info->num_layers = num_layers;
+
+   if (rebase_layer) {
+      /* the size of the layer */
+      info->width = u_minify(info->width, level);
+      info->height = u_minify(info->height, level);
+      if (info->surface_type == BRW_SURFACE_3D)
+         info->depth = u_minify(info->depth, level);
+      else
+         info->depth = 1;
 
-   /*
-    * we always treat the resource as non-mipmapped and set the slice/x/y
-    * offsets manually
-    */
-   if (true) {
       /* no layered rendering */
       assert(num_layers == 1);
 
-      slice_offset = ilo_texture_get_slice_offset(tex,
-            lod, first_layer, &x_offset, &y_offset);
+      info->lod = 0;
+      info->first_layer = 0;
+      info->num_layers = 1;
+
+      /* all three share the same X/Y offsets */
+      if (info->zs.bo) {
+         if (info->stencil.bo) {
+            assert(x_offset[0] == x_offset[1]);
+            assert(y_offset[0] == y_offset[1]);
+         }
+
+         info->x_offset = x_offset[0];
+         info->y_offset = y_offset[0];
+      }
+      else {
+         assert(info->stencil.bo);
+
+         info->x_offset = x_offset[1];
+         info->y_offset = y_offset[1];
+      }
+
+      if (info->hiz.bo) {
+         assert(info->x_offset == x_offset[2]);
+         assert(info->y_offset == y_offset[2]);
+      }
 
       /*
        * From the Sandy Bridge PRM, volume 2 part 1, page 326:
@@ -2527,137 +2567,205 @@ gen6_emit_3DSTATE_DEPTH_BUFFER(const struct ilo_dev_info *dev,
        * sure that does not happen eventually.
        */
       if (dev->gen >= ILO_GEN(7)) {
-         assert((x_offset & 7) == 0 && (y_offset & 7) == 0);
-         x_offset &= ~7;
-         y_offset &= ~7;
+         assert((info->x_offset & 7) == 0 && (info->y_offset & 7) == 0);
+         info->x_offset &= ~7;
+         info->y_offset &= ~7;
       }
 
-      /* the size of the layer */
-      width = u_minify(width, lod);
-      height = u_minify(height, lod);
-      if (surface_type == BRW_SURFACE_3D)
-         depth = u_minify(depth, lod);
-      else
-         depth = 1;
-
-      lod = 0;
-      first_layer = 0;
-
-      width += x_offset;
-      height += y_offset;
+      info->width += info->x_offset;
+      info->height += info->y_offset;
 
       /* we have to treat them as 2D surfaces */
-      if (surface_type == BRW_SURFACE_CUBE) {
+      if (info->surface_type == BRW_SURFACE_CUBE) {
          assert(tex->base.width0 == tex->base.height0);
          /* we will set slice_offset to point to the single face */
-         surface_type = BRW_SURFACE_2D;
+         info->surface_type = BRW_SURFACE_2D;
       }
-      else if (surface_type == BRW_SURFACE_1D && height > 1) {
+      else if (info->surface_type == BRW_SURFACE_1D && info->height > 1) {
          assert(tex->base.height0 == 1);
-         surface_type = BRW_SURFACE_2D;
+         info->surface_type = BRW_SURFACE_2D;
       }
    }
-   else {
-      slice_offset = 0;
-      x_offset = 0;
-      y_offset = 0;
-   }
+}
 
-   /* required for GEN6+ */
-   assert(tex->tiling == INTEL_TILING_Y);
-   assert(tex->bo_stride > 0 && tex->bo_stride < 128 * 1024 &&
-         tex->bo_stride % 128 == 0);
-   assert(width <= tex->bo_stride);
+void
+ilo_gpe_init_zs_surface(const struct ilo_dev_info *dev,
+                        const struct ilo_texture *tex,
+                        enum pipe_format format,
+                        unsigned level,
+                        unsigned first_layer, unsigned num_layers,
+                        struct ilo_zs_surface *zs)
+{
+   const int max_2d_size = (dev->gen >= ILO_GEN(7)) ? 16384 : 8192;
+   const int max_array_size = (dev->gen >= ILO_GEN(7)) ? 2048 : 512;
+   struct ilo_zs_surface_info info;
+   uint32_t dw1, dw2, dw3, dw4, dw5, dw6;
 
-   switch (surface_type) {
+   ILO_GPE_VALID_GEN(dev, 6, 7);
+
+   if (tex)
+      zs_init_info(dev, tex, format, level, first_layer, num_layers, &info);
+   else
+      zs_init_info_null(dev, &info);
+
+   switch (info.surface_type) {
+   case BRW_SURFACE_NULL:
+      break;
    case BRW_SURFACE_1D:
-      assert(width <= max_2d_size && height == 1 &&
-             depth <= max_array_size);
-      assert(first_layer < max_array_size - 1 &&
-             num_layers <= max_array_size);
+      assert(info.width <= max_2d_size && info.height == 1 &&
+             info.depth <= max_array_size);
+      assert(info.first_layer < max_array_size - 1 &&
+             info.num_layers <= max_array_size);
       break;
    case BRW_SURFACE_2D:
-      assert(width <= max_2d_size && height <= max_2d_size &&
-             depth <= max_array_size);
-      assert(first_layer < max_array_size - 1 &&
-             num_layers <= max_array_size);
+      assert(info.width <= max_2d_size && info.height <= max_2d_size &&
+             info.depth <= max_array_size);
+      assert(info.first_layer < max_array_size - 1 &&
+             info.num_layers <= max_array_size);
       break;
    case BRW_SURFACE_3D:
-      assert(width <= 2048 && height <= 2048 && depth <= 2048);
-      assert(first_layer < 2048 && num_layers <= max_array_size);
-      assert(x_offset == 0 && y_offset == 0);
+      assert(info.width <= 2048 && info.height <= 2048 && info.depth <= 2048);
+      assert(info.first_layer < 2048 && info.num_layers <= max_array_size);
+      assert(info.x_offset == 0 && info.y_offset == 0);
       break;
    case BRW_SURFACE_CUBE:
-      assert(width <= max_2d_size && height <= max_2d_size && depth == 1);
-      assert(first_layer == 0 && num_layers == 1);
-      assert(width == height);
-      assert(x_offset == 0 && y_offset == 0);
+      assert(info.width <= max_2d_size && info.height <= max_2d_size &&
+             info.depth == 1);
+      assert(info.first_layer == 0 && info.num_layers == 1);
+      assert(info.width == info.height);
+      assert(info.x_offset == 0 && info.y_offset == 0);
       break;
    default:
       assert(!"unexpected depth surface type");
       break;
    }
 
-   dw1 = surface_type << 29 |
-         depth_format << 18 |
-         (tex->bo_stride - 1);
+   dw1 = info.surface_type << 29 |
+         info.format << 18;
+
+   if (info.zs.bo) {
+      /* required for GEN6+ */
+      assert(info.zs.tiling == INTEL_TILING_Y);
+      assert(info.zs.stride > 0 && info.zs.stride < 128 * 1024 &&
+            info.zs.stride % 128 == 0);
+      assert(info.width <= info.zs.stride);
+
+      dw1 |= (info.zs.stride - 1);
+      dw2 = info.zs.offset;
+   }
+   else {
+      dw2 = 0;
+   }
 
    if (dev->gen >= ILO_GEN(7)) {
-      if (has_depth)
+      if (info.zs.bo)
          dw1 |= 1 << 28;
 
-      if (has_stencil)
+      if (info.stencil.bo)
          dw1 |= 1 << 27;
 
-      if (hiz)
+      if (info.hiz.bo)
          dw1 |= 1 << 22;
 
-      dw3 = (height - 1) << 18 |
-            (width - 1) << 4 |
-            lod;
+      dw3 = (info.height - 1) << 18 |
+            (info.width - 1) << 4 |
+            info.lod;
+
+      dw4 = (info.depth - 1) << 21 |
+            info.first_layer << 10;
 
-      dw4 = (depth - 1) << 21 |
-            first_layer << 10;
+      dw5 = info.y_offset << 16 | info.x_offset;
 
-      dw6 = (num_layers - 1) << 21;
+      dw6 = (info.num_layers - 1) << 21;
    }
    else {
-      dw1 |= (tex->tiling != INTEL_TILING_NONE) << 27 |
-             (tex->tiling == INTEL_TILING_Y) << 26;
+      /* always Y-tiled */
+      dw1 |= 1 << 27 |
+             1 << 26;
 
-      if (hiz) {
+      if (info.hiz.bo) {
          dw1 |= 1 << 22 |
                 1 << 21;
       }
 
-      dw3 = (height - 1) << 19 |
-            (width - 1) << 6 |
-            lod << 2 |
+      dw3 = (info.height - 1) << 19 |
+            (info.width - 1) << 6 |
+            info.lod << 2 |
             BRW_SURFACE_MIPMAPLAYOUT_BELOW << 1;
 
-      dw4 = (depth - 1) << 21 |
-            first_layer << 10 |
-            (num_layers - 1) << 1;
+      dw4 = (info.depth - 1) << 21 |
+            info.first_layer << 10 |
+            (info.num_layers - 1) << 1;
+
+      dw5 = info.y_offset << 16 | info.x_offset;
 
       dw6 = 0;
    }
 
-   ilo_cp_begin(cp, cmd_len);
-   ilo_cp_write(cp, cmd | (cmd_len - 2));
-   ilo_cp_write(cp, dw1);
+   STATIC_ASSERT(Elements(zs->payload) >= 10);
+
+   zs->payload[0] = dw1;
+   zs->payload[1] = dw2;
+   zs->payload[2] = dw3;
+   zs->payload[3] = dw4;
+   zs->payload[4] = dw5;
+   zs->payload[5] = dw6;
 
-   if (has_depth) {
-      ilo_cp_write_bo(cp, slice_offset, tex->bo,
-            INTEL_DOMAIN_RENDER, INTEL_DOMAIN_RENDER);
+   /* do not increment reference count */
+   zs->bo = info.zs.bo;
+
+   /* separate stencil */
+   if (info.stencil.bo) {
+      assert(info.stencil.stride > 0 && info.stencil.stride < 128 * 1024 &&
+             info.stencil.stride % 128 == 0);
+
+      zs->payload[6] = info.stencil.stride - 1;
+      zs->payload[7] = info.stencil.offset;
+
+      /* do not increment reference count */
+      zs->separate_s8_bo = info.stencil.bo;
    }
    else {
-      ilo_cp_write(cp, 0);
+      zs->payload[6] = 0;
+      zs->payload[7] = 0;
+      zs->separate_s8_bo = NULL;
    }
 
-   ilo_cp_write(cp, dw3);
-   ilo_cp_write(cp, dw4);
-   ilo_cp_write(cp, y_offset << 16 | x_offset);
-   ilo_cp_write(cp, dw6);
+   /* hiz */
+   if (info.hiz.bo) {
+      zs->payload[8] = info.hiz.stride - 1;
+      zs->payload[9] = info.hiz.offset;
+
+      /* do not increment reference count */
+      zs->hiz_bo = info.hiz.bo;
+   }
+   else {
+      zs->payload[8] = 0;
+      zs->payload[9] = 0;
+      zs->hiz_bo = NULL;
+   }
+}
+
+static void
+gen6_emit_3DSTATE_DEPTH_BUFFER(const struct ilo_dev_info *dev,
+                               const struct ilo_zs_surface *zs,
+                               struct ilo_cp *cp)
+{
+   const uint32_t cmd = (dev->gen >= ILO_GEN(7)) ?
+      ILO_GPE_CMD(0x3, 0x0, 0x05) : ILO_GPE_CMD(0x3, 0x1, 0x05);
+   const uint8_t cmd_len = 7;
+
+   ILO_GPE_VALID_GEN(dev, 6, 7);
+
+   ilo_cp_begin(cp, cmd_len);
+   ilo_cp_write(cp, cmd | (cmd_len - 2));
+   ilo_cp_write(cp, zs->payload[0]);
+   ilo_cp_write_bo(cp, zs->payload[1], zs->bo,
+         INTEL_DOMAIN_RENDER, INTEL_DOMAIN_RENDER);
+   ilo_cp_write(cp, zs->payload[2]);
+   ilo_cp_write(cp, zs->payload[3]);
+   ilo_cp_write(cp, zs->payload[4]);
+   ilo_cp_write(cp, zs->payload[5]);
    ilo_cp_end(cp);
 }
 
@@ -2824,102 +2932,42 @@ gen6_emit_3DSTATE_MULTISAMPLE(const struct ilo_dev_info *dev,
 
 static void
 gen6_emit_3DSTATE_STENCIL_BUFFER(const struct ilo_dev_info *dev,
-                                 const struct pipe_surface *surface,
+                                 const struct ilo_zs_surface *zs,
                                  struct ilo_cp *cp)
 {
    const uint32_t cmd = (dev->gen >= ILO_GEN(7)) ?
       ILO_GPE_CMD(0x3, 0x0, 0x06) :
       ILO_GPE_CMD(0x3, 0x1, 0x0e);
    const uint8_t cmd_len = 3;
-   struct ilo_texture *tex;
-   uint32_t slice_offset, x_offset, y_offset;
-   int pitch;
 
    ILO_GPE_VALID_GEN(dev, 6, 7);
 
-   tex = (surface) ? ilo_texture(surface->texture) : NULL;
-   if (tex && surface->format != PIPE_FORMAT_S8_UINT)
-      tex = tex->separate_s8;
-
-   if (!tex) {
-      ilo_cp_begin(cp, cmd_len);
-      ilo_cp_write(cp, cmd | (cmd_len - 2));
-      ilo_cp_write(cp, 0);
-      ilo_cp_write(cp, 0);
-      ilo_cp_end(cp);
-
-      return;
-   }
-
-   if (true) {
-      slice_offset = ilo_texture_get_slice_offset(tex,
-            surface->u.tex.level, surface->u.tex.first_layer,
-            &x_offset, &y_offset);
-      /* XXX X/Y offsets inherit from 3DSTATE_DEPTH_BUFFER */
-   }
-   else {
-      slice_offset = 0;
-      x_offset = 0;
-      y_offset = 0;
-   }
-
-   /*
-    * From the Sandy Bridge PRM, volume 2 part 1, page 329:
-    *
-    *     "The pitch must be set to 2x the value computed based on width, as
-    *      the stencil buffer is stored with two rows interleaved."
-    *
-    * According to the classic driver, we need to do the same for GEN7+ even
-    * though the Ivy Bridge PRM does not say anything about it.
-    */
-   pitch = 2 * tex->bo_stride;
-   assert(pitch > 0 && pitch < 128 * 1024 && pitch % 128 == 0);
-
    ilo_cp_begin(cp, cmd_len);
    ilo_cp_write(cp, cmd | (cmd_len - 2));
-   ilo_cp_write(cp, pitch - 1);
-   ilo_cp_write_bo(cp, slice_offset, tex->bo,
+   /* see ilo_gpe_init_zs_surface() */
+   ilo_cp_write(cp, zs->payload[6]);
+   ilo_cp_write_bo(cp, zs->payload[7], zs->separate_s8_bo,
          INTEL_DOMAIN_RENDER, INTEL_DOMAIN_RENDER);
    ilo_cp_end(cp);
 }
 
 static void
 gen6_emit_3DSTATE_HIER_DEPTH_BUFFER(const struct ilo_dev_info *dev,
-                                    const struct pipe_surface *surface,
+                                    const struct ilo_zs_surface *zs,
                                     struct ilo_cp *cp)
 {
    const uint32_t cmd = (dev->gen >= ILO_GEN(7)) ?
       ILO_GPE_CMD(0x3, 0x0, 0x07) :
       ILO_GPE_CMD(0x3, 0x1, 0x0f);
    const uint8_t cmd_len = 3;
-   const bool hiz = false;
-   struct ilo_texture *tex;
-   uint32_t slice_offset;
 
    ILO_GPE_VALID_GEN(dev, 6, 7);
 
-   if (!surface || !hiz) {
-      ilo_cp_begin(cp, cmd_len);
-      ilo_cp_write(cp, cmd | (cmd_len - 2));
-      ilo_cp_write(cp, 0);
-      ilo_cp_write(cp, 0);
-      ilo_cp_end(cp);
-
-      return;
-   }
-
-   tex = ilo_texture(surface->texture);
-
-   /* TODO */
-   slice_offset = 0;
-
-   assert(tex->bo_stride > 0 && tex->bo_stride < 128 * 1024 &&
-          tex->bo_stride % 128 == 0);
-
    ilo_cp_begin(cp, cmd_len);
    ilo_cp_write(cp, cmd | (cmd_len - 2));
-   ilo_cp_write(cp, tex->bo_stride - 1);
-   ilo_cp_write_bo(cp, slice_offset, tex->bo,
+   /* see ilo_gpe_init_zs_surface() */
+   ilo_cp_write(cp, zs->payload[8]);
+   ilo_cp_write_bo(cp, zs->payload[9], zs->hiz_bo,
          INTEL_DOMAIN_RENDER, INTEL_DOMAIN_RENDER);
    ilo_cp_end(cp);
 }
@@ -4754,6 +4802,7 @@ gen6_emit_SAMPLER_BORDER_COLOR_STATE(const struct ilo_dev_info *dev,
    dw = ilo_cp_steal_ptr(cp, "SAMPLER_BORDER_COLOR_STATE",
          state_len, state_align, &state_offset);
 
+   /* see ilo_gpe_init_sampler_cso() */
    memcpy(dw, &sampler->payload[3], state_len * 4);
 
    return state_offset;
diff --git a/src/gallium/drivers/ilo/ilo_gpe_gen6.h b/src/gallium/drivers/ilo/ilo_gpe_gen6.h
index bc71b45..6e27364 100644
--- a/src/gallium/drivers/ilo/ilo_gpe_gen6.h
+++ b/src/gallium/drivers/ilo/ilo_gpe_gen6.h
@@ -299,7 +299,7 @@ typedef void
 
 typedef void
 (*ilo_gpe_gen6_3DSTATE_DEPTH_BUFFER)(const struct ilo_dev_info *dev,
-                                     const struct pipe_surface *surface,
+                                     const struct ilo_zs_surface *zs,
                                      struct ilo_cp *cp);
 
 typedef void
@@ -338,12 +338,12 @@ typedef void
 
 typedef void
 (*ilo_gpe_gen6_3DSTATE_STENCIL_BUFFER)(const struct ilo_dev_info *dev,
-                                       const struct pipe_surface *surface,
+                                       const struct ilo_zs_surface *zs,
                                        struct ilo_cp *cp);
 
 typedef void
 (*ilo_gpe_gen6_3DSTATE_HIER_DEPTH_BUFFER)(const struct ilo_dev_info *dev,
-                                          const struct pipe_surface *surface,
+                                          const struct ilo_zs_surface *zs,
                                           struct ilo_cp *cp);
 
 typedef void
diff --git a/src/gallium/drivers/ilo/ilo_state.c b/src/gallium/drivers/ilo/ilo_state.c
index 3210bb4..ba0efdd 100644
--- a/src/gallium/drivers/ilo/ilo_state.c
+++ b/src/gallium/drivers/ilo/ilo_state.c
@@ -952,7 +952,11 @@ ilo_create_surface(struct pipe_context *pipe,
    else {
       assert(res->target != PIPE_BUFFER);
 
-      /* will construct dynamically */
+      ilo_gpe_init_zs_surface(ilo->dev, ilo_texture(res),
+            templ->format, templ->u.tex.level,
+            templ->u.tex.first_layer,
+            templ->u.tex.last_layer - templ->u.tex.first_layer + 1,
+            &surf->u.zs);
    }
 
    return &surf->base;
@@ -1133,6 +1137,9 @@ ilo_init_states(struct ilo_context *ilo)
 {
    ilo_gpe_set_scissor_null(ilo->dev, &ilo->scissor);
 
+   ilo_gpe_init_zs_surface(ilo->dev, NULL,
+         PIPE_FORMAT_NONE, 0, 0, 1, &ilo->fb.null_zs);
+
    ilo->dirty = ILO_DIRTY_ALL;
 }
 




More information about the mesa-commit mailing list