ilo: use UMS layout for render targets
authorChia-I Wu <olvaffe@gmail.com>
Tue, 30 Apr 2013 04:55:18 +0000 (12:55 +0800)
committerChia-I Wu <olvaffe@gmail.com>
Wed, 1 May 2013 03:56:43 +0000 (11:56 +0800)
As we do not advertise MSAA support, this change should not make any
difference yet.

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 bbab416ca3b47145ab940505bcab7be3f9ff2cf1..159a117272f9e4fcfd5403549056137adc8431d9 100644 (file)
@@ -3742,6 +3742,9 @@ gen6_fill_normal_SURFACE_STATE(const struct ilo_dev_info *dev,
 
    /* non-full array spacing is supported only on GEN7+ */
    assert(res->array_spacing_full);
+   /* non-interleaved samples are supported only on GEN7+ */
+   if (res->base.nr_samples > 1)
+      assert(res->interleaved);
 
    /*
     * Compute the offset to the layer manually.
index 44c4a77912c1142b3836e2f3c86a042f2485fe32..f6282b4fbec6299c7436a28639804c306b2e8192 100644 (file)
@@ -1488,6 +1488,19 @@ gen7_fill_normal_SURFACE_STATE(const struct ilo_dev_info *dev,
    dw[4] = first_layer << 18 |
            (depth - 1) << 7;
 
+   /*
+    * MSFMT_MSS means the samples are not interleaved and MSFMT_DEPTH_STENCIL
+    * means the samples are interleaved.  The layouts are the same when the
+    * number of samples is 1.
+    */
+   if (res->interleaved && res->base.nr_samples > 1) {
+      assert(!is_rt);
+      dw[4] |= GEN7_SURFACE_MSFMT_DEPTH_STENCIL;
+   }
+   else {
+      dw[4] |= GEN7_SURFACE_MSFMT_MSS;
+   }
+
    if (res->base.nr_samples > 4)
       dw[4] |= GEN7_SURFACE_MULTISAMPLECOUNT_8;
    else if (res->base.nr_samples > 2)
index a1f414035dc8ded7b8477408c5a66d44e2a7a0b3..b480601371a5ac087d0eb5e8567284fa1637eaf1 100644 (file)
@@ -442,6 +442,7 @@ struct layout_tex_info {
    int block_width, block_height;
    int align_i, align_j;
    bool array_spacing_full;
+   bool interleaved;
    int qpitch;
 
    struct {
@@ -629,24 +630,45 @@ layout_tex_init(const struct ilo_resource *res, struct layout_tex_info *info)
 
    if (is->dev.gen >= ILO_GEN(7)) {
       /*
-       * From the Ivy Bridge PRM, volume 1 part 1, page 111:
+       * It is not explicitly states, but render targets are expected to be
+       * UMS/CMS (samples non-interleaved) and depth/stencil buffers are
+       * expected to be IMS (samples interleaved).
        *
-       *     "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.
+       * See "Multisampled Surface Storage Format" field of SURFACE_STATE.
        */
-      info->array_spacing_full = (templ->last_level > 0 ||
-            util_format_is_depth_or_stencil(templ->format));
+      if (util_format_is_depth_or_stencil(templ->format)) {
+         info->interleaved = true;
+
+         /*
+          * 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"
+          */
+         info->array_spacing_full = true;
+      }
+      else {
+         info->interleaved = false;
+
+         /*
+          * 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."
+          *
+          * As multisampled resources are not mipmapped, we never use
+          * ARYSPC_FULL for them.
+          */
+         if (templ->nr_samples > 1)
+            assert(templ->last_level == 0);
+         info->array_spacing_full = (templ->last_level > 0);
+      }
    }
    else {
+      /* GEN6 supports only interleaved samples */
+      info->interleaved = true;
+
       /*
        * From the Sandy Bridge PRM, volume 1 part 1, page 115:
        *
@@ -695,10 +717,61 @@ layout_tex_init(const struct ilo_resource *res, struct layout_tex_info *info)
        *
        *        W_L = ceiling(W_L / 2) * 4
        *        H_L = ceiling(H_L / 2) * 4"
+       *
+       * From the Ivy Bridge PRM, volume 1 part 1, page 108:
+       *
+       *     "If the surface is multisampled and it is a depth or stencil
+       *      surface or Multisampled Surface StorageFormat in SURFACE_STATE
+       *      is MSFMT_DEPTH_STENCIL, W_L and H_L must be adjusted as follows
+       *      before proceeding:
+       *
+       *        #samples  W_L =                    H_L =
+       *        2         ceiling(W_L / 2) * 4     HL [no adjustment]
+       *        4         ceiling(W_L / 2) * 4     ceiling(H_L / 2) * 4
+       *        8         ceiling(W_L / 2) * 8     ceiling(H_L / 2) * 4
+       *        16        ceiling(W_L / 2) * 8     ceiling(H_L / 2) * 8"
+       *
+       * For interleaved samples (4x), where pixels
+       *
+       *   (x, y  ) (x+1, y  )
+       *   (x, y+1) (x+1, y+1)
+       *
+       * would be is occupied by
+       *
+       *   (x, y  , si0) (x+1, y  , si0) (x, y  , si1) (x+1, y  , si1)
+       *   (x, y+1, si0) (x+1, y+1, si0) (x, y+1, si1) (x+1, y+1, si1)
+       *   (x, y  , si2) (x+1, y  , si2) (x, y  , si3) (x+1, y  , si3)
+       *   (x, y+1, si2) (x+1, y+1, si2) (x, y+1, si3) (x+1, y+1, si3)
+       *
+       * Thus the need to
+       *
+       *   w = align(w, 2) * 2;
+       *   y = align(y, 2) * 2;
        */
-      if (templ->nr_samples > 1) {
-         w = align(w, 2) * 2;
-         h = align(h, 2) * 2;
+      if (info->interleaved) {
+         switch (templ->nr_samples) {
+         case 0:
+         case 1:
+            break;
+         case 2:
+            w = align(w, 2) * 2;
+            break;
+         case 4:
+            w = align(w, 2) * 2;
+            h = align(h, 2) * 2;
+            break;
+         case 8:
+            w = align(w, 2) * 4;
+            h = align(h, 2) * 2;
+            break;
+         case 16:
+            w = align(w, 2) * 4;
+            h = align(h, 2) * 4;
+            break;
+         default:
+            assert(!"unsupported sample count");
+            break;
+         }
       }
 
       info->sizes[lv].w = w;
@@ -767,7 +840,7 @@ static void
 layout_tex_2d(struct ilo_resource *res, const struct layout_tex_info *info)
 {
    const struct pipe_resource *templ = &res->base;
-   unsigned int level_x, level_y;
+   unsigned int level_x, level_y, num_slices;
    int lv;
 
    res->bo_width = 0;
@@ -799,8 +872,13 @@ layout_tex_2d(struct ilo_resource *res, const struct layout_tex_info *info)
          level_y += align(level_h, info->align_j);
    }
 
+   num_slices = templ->array_size;
+   /* samples of the same index are stored in a slice */
+   if (templ->nr_samples > 1 && !info->interleaved)
+      num_slices *= templ->nr_samples;
+
    /* we did not take slices into consideration in the computation above */
-   res->bo_height += info->qpitch * (templ->array_size - 1);
+   res->bo_height += info->qpitch * (num_slices - 1);
 }
 
 /**
@@ -987,6 +1065,7 @@ init_texture(struct ilo_resource *res)
    res->halign_8 = (info.align_i == 8);
    res->valign_4 = (info.align_j == 4);
    res->array_spacing_full = info.array_spacing_full;
+   res->interleaved = info.interleaved;
 
    switch (res->base.target) {
    case PIPE_TEXTURE_1D:
@@ -1030,6 +1109,7 @@ init_buffer(struct ilo_resource *res)
    res->halign_8 = false;
    res->valign_4 = false;
    res->array_spacing_full = false;
+   res->interleaved = false;
 }
 
 static struct pipe_resource *
index 964647249421f57f86e52cea38f85e744ae8a774..89ad8c20811a4e944482211c672b46c653be876e 100644 (file)
@@ -69,6 +69,8 @@ struct ilo_resource {
    bool halign_8, valign_4;
    /* true if space is reserved between layers */
    bool array_spacing_full;
+   /* true if samples are interleaved */
+   bool interleaved;
 
    /* 2D offsets into a layer/slice/face */
    struct {