ilo: support and prefer compact array spacing
authorChia-I Wu <olvaffe@gmail.com>
Tue, 30 Apr 2013 04:14:29 +0000 (12:14 +0800)
committerChia-I Wu <olvaffe@gmail.com>
Wed, 1 May 2013 03:31:15 +0000 (11:31 +0800)
There is no reason to waste the memory when the HW can support compact array
spacing (ARYSPC_LOD0).

src/gallium/drivers/ilo/ilo_gpe_gen6.c
src/gallium/drivers/ilo/ilo_gpe_gen7.c
src/gallium/drivers/ilo/ilo_resource.c
src/gallium/drivers/ilo/ilo_resource.h

index b3efe2a512ea138c7beba13884568edc27d61854..bbab416ca3b47145ab940505bcab7be3f9ff2cf1 100644 (file)
@@ -3740,6 +3740,9 @@ gen6_fill_normal_SURFACE_STATE(const struct ilo_dev_info *dev,
       break;
    }
 
+   /* non-full array spacing is supported only on GEN7+ */
+   assert(res->array_spacing_full);
+
    /*
     * Compute the offset to the layer manually.
     *
index 613933290a5ab643778a02fb551123788f209d64..44c4a77912c1142b3836e2f3c86a042f2485fe32 100644 (file)
@@ -1455,8 +1455,7 @@ gen7_fill_normal_SURFACE_STATE(const struct ilo_dev_info *dev,
 
    dw[0] = surface_type << BRW_SURFACE_TYPE_SHIFT |
            surface_format << BRW_SURFACE_FORMAT_SHIFT |
-           ilo_gpe_gen6_translate_winsys_tiling(res->tiling) << 13 |
-           GEN7_SURFACE_ARYSPC_FULL;
+           ilo_gpe_gen6_translate_winsys_tiling(res->tiling) << 13;
 
    if (surface_type != BRW_SURFACE_3D && depth > 1)
       dw[0] |= GEN7_SURFACE_IS_ARRAY;
@@ -1467,6 +1466,11 @@ gen7_fill_normal_SURFACE_STATE(const struct ilo_dev_info *dev,
    if (res->halign_8)
       dw[0] |= GEN7_SURFACE_HALIGN_8;
 
+   if (res->array_spacing_full)
+      dw[0] |= GEN7_SURFACE_ARYSPC_FULL;
+   else
+      dw[0] |= GEN7_SURFACE_ARYSPC_LOD0;
+
    if (render_cache_rw)
       dw[0] |= BRW_SURFACE_RC_READ_WRITE;
 
index fd6e858a258722c4a49f13c4c2cc971604e0c1a0..a1f414035dc8ded7b8477408c5a66d44e2a7a0b3 100644 (file)
@@ -441,6 +441,7 @@ struct layout_tex_info {
    bool compressed;
    int block_width, block_height;
    int align_i, align_j;
+   bool array_spacing_full;
    int qpitch;
 
    struct {
@@ -626,10 +627,45 @@ layout_tex_init(const struct ilo_resource *res, struct layout_tex_info *info)
    assert(util_is_power_of_two(info->block_width) &&
           util_is_power_of_two(info->block_height));
 
+   if (is->dev.gen >= ILO_GEN(7)) {
+      /*
+       * From the Ivy Bridge PRM, volume 1 part 1, page 111:
+       *
+       *     "note that the depth buffer and stencil buffer have an implied
+       *      value of ARYSPC_FULL"
+       *
+       * From the Ivy Bridge PRM, volume 4 part 1, page 66:
+       *
+       *     "If Multisampled Surface Storage Format is MSFMT_MSS and Number
+       *      of Multisamples is not MULTISAMPLECOUNT_1, this field (Surface
+       *      Array Spacing) must be set to ARYSPC_LOD0."
+       *
+       * We use ARYSPC_FULL only when needed, and as such, we never use
+       * ARYSPC_FULL for multisampled resources.
+       */
+      info->array_spacing_full = (templ->last_level > 0 ||
+            util_format_is_depth_or_stencil(templ->format));
+   }
+   else {
+      /*
+       * From the Sandy Bridge PRM, volume 1 part 1, page 115:
+       *
+       *     "The separate stencil buffer does not support mip mapping, thus
+       *      the storage for LODs other than LOD 0 is not needed. The
+       *      following QPitch equation applies only to the separate stencil
+       *      buffer:
+       *
+       *        QPitch = h_0"
+       *
+       * GEN6 does not support compact spacing otherwise.
+       */
+      info->array_spacing_full = (templ->format != PIPE_FORMAT_S8_UINT);
+   }
+
    last_level = templ->last_level;
-   /* need at least 2 levels to compute qpitch below */
-   if (templ->array_size > 1 && last_level == 0 &&
-       templ->format != PIPE_FORMAT_S8_UINT)
+
+   /* need at least 2 levels to compute full qpitch */
+   if (last_level == 0 && templ->array_size > 1 && info->array_spacing_full)
       last_level++;
 
    /* compute mip level sizes */
@@ -673,10 +709,7 @@ layout_tex_init(const struct ilo_resource *res, struct layout_tex_info *info)
    if (templ->array_size > 1) {
       const int h0 = align(info->sizes[0].h, info->align_j);
 
-      if (templ->format == PIPE_FORMAT_S8_UINT) {
-         info->qpitch = h0;
-      }
-      else {
+      if (info->array_spacing_full) {
          const int h1 = align(info->sizes[1].h, info->align_j);
 
          /*
@@ -696,6 +729,17 @@ layout_tex_init(const struct ilo_resource *res, struct layout_tex_info *info)
           *      the value calculated in the equation above, for every other
           *      odd Surface Height starting from 1 i.e. 1,5,9,13"
           *
+          * From the Ivy Bridge PRM, volume 1 part 1, page 111-112:
+          *
+          *     "If Surface Array Spacing is set to ARYSPC_FULL (note that the
+          *      depth buffer and stencil buffer have an implied value of
+          *      ARYSPC_FULL):
+          *
+          *        QPitch = (h0 + h1 + 12j)
+          *        QPitch = (h0 + h1 + 12j) / 4 (compressed)
+          *
+          *      (There are many typos or missing words here...)"
+          *
           * To access the N-th slice, an offset of (Stride * QPitch * N) is
           * added to the base address.  The PRM divides QPitch by 4 for
           * compressed formats because the block height for those formats are
@@ -710,6 +754,9 @@ layout_tex_init(const struct ilo_resource *res, struct layout_tex_info *info)
                templ->height0 % 4 == 1)
             info->qpitch += 4;
       }
+      else {
+         info->qpitch = h0;
+      }
    }
 }
 
@@ -936,8 +983,10 @@ init_texture(struct ilo_resource *res)
    res->compressed = info.compressed;
    res->block_width = info.block_width;
    res->block_height = info.block_height;
+
    res->halign_8 = (info.align_i == 8);
    res->valign_4 = (info.align_j == 4);
+   res->array_spacing_full = info.array_spacing_full;
 
    switch (res->base.target) {
    case PIPE_TEXTURE_1D:
@@ -968,17 +1017,19 @@ init_texture(struct ilo_resource *res)
 static void
 init_buffer(struct ilo_resource *res)
 {
-   res->compressed = false;
-   res->block_width = 1;
-   res->block_height = 1;
-   res->halign_8 = false;
-   res->valign_4 = false;
-
    res->bo_width = res->base.width0;
    res->bo_height = 1;
    res->bo_cpp = 1;
    res->bo_stride = 0;
    res->tiling = INTEL_TILING_NONE;
+
+   res->compressed = false;
+   res->block_width = 1;
+   res->block_height = 1;
+
+   res->halign_8 = false;
+   res->valign_4 = false;
+   res->array_spacing_full = false;
 }
 
 static struct pipe_resource *
index 2d706ce007dd92999505210e889f841079edafc3..964647249421f57f86e52cea38f85e744ae8a774 100644 (file)
@@ -64,7 +64,11 @@ struct ilo_resource {
    bool compressed;
    unsigned block_width;
    unsigned block_height;
+
+   /* true if the mip level alignments are stricter */
    bool halign_8, valign_4;
+   /* true if space is reserved between layers */
+   bool array_spacing_full;
 
    /* 2D offsets into a layer/slice/face */
    struct {