[Mesa-dev,3/3] i965: fix the size of HiZ buffers

Submitted by Chia-I Wu on Feb. 18, 2014, 8:44 a.m.

Details

Message ID 1392713085-4173-3-git-send-email-olvaffe@gmail.com
State New
Headers show

Not browsing as part of any series.

Commit Message

Chia-I Wu Feb. 18, 2014, 8:44 a.m.
Use the formulas defined for HiZ to calculate the size needed.  This normally
results in a HiZ buffer that is one-fourth to one-eighth the size of the
corresponding depth buffer, which is a great save for many games.

For small HiZ buffers, the size may be greater than before because of the
paddings.  But it should be necessary, at least according to the PRM.

No piglit regression on Sandy Bridge and Haswell.

Signed-off-by: Chia-I Wu <olv@lunarg.com>
---
 src/mesa/drivers/dri/i965/intel_mipmap_tree.c | 59 ++++++++++++++++++++-------
 1 file changed, 44 insertions(+), 15 deletions(-)

Patch hide | download patch | download mbox

diff --git a/src/mesa/drivers/dri/i965/intel_mipmap_tree.c b/src/mesa/drivers/dri/i965/intel_mipmap_tree.c
index c40503a..94e063f 100644
--- a/src/mesa/drivers/dri/i965/intel_mipmap_tree.c
+++ b/src/mesa/drivers/dri/i965/intel_mipmap_tree.c
@@ -1348,26 +1348,55 @@  bool
 intel_miptree_alloc_hiz(struct brw_context *brw,
 			struct intel_mipmap_tree *mt)
 {
-   struct intel_mipmap_tree *tmp_hiz_mt;
+   const unsigned hiz_align_j = 8;
+   unsigned hiz_width, hiz_height;
 
    assert(mt->hiz_region == NULL);
 
-   tmp_hiz_mt = intel_miptree_create(brw,
-                                     mt->target,
-                                     mt->format,
-                                     mt->first_level,
-                                     mt->last_level,
-                                     mt->logical_width0,
-                                     mt->logical_height0,
-                                     mt->logical_depth0,
-                                     true,
-                                     mt->num_samples,
-                                     INTEL_MIPTREE_TILING_ANY);
-   if (tmp_hiz_mt) {
-      intel_region_reference(&mt->hiz_region, tmp_hiz_mt->region);
-      intel_miptree_release(&tmp_hiz_mt);
+   /*
+    * The formulas are described in the Sandy Bridge PRM, Vol2 Part1 7.5.3 and
+    * Ivy Bridge PRM, Vol2 Part1 11.5.3.
+    *
+    * Since the HiZ buffer is opaque, all we care about is to allocate a
+    * buffer that is large enough.  On GEN7, the formulas are pretty much
+    * followed.
+    *
+    * On GEN6, we use the formulas defined for GEN7.  This is because GEN6
+    * does not support mipmapped HiZ buffers directly, and the formulas
+    * defined for GEN7 are good enough (that is, large enough) on GEN6.  When
+    * rendering, we will play with Coordinate Offset X/Y and etc. to point to
+    * the destination slice directly.
+    */
+   hiz_width = ALIGN(mt->physical_width0, 16);
+
+   if (mt->target == GL_TEXTURE_3D) {
+      hiz_height = 0;
+
+      for (unsigned l = mt->first_level; l <= mt->last_level; l++) {
+         const unsigned h = ALIGN(minify(mt->physical_height0, l), hiz_align_j);
+         hiz_height += h * minify(mt->physical_depth0, l);
+      }
+
+      hiz_height /= 2;
+   } else {
+      /*
+       * We probably could simply set qpitch to h0 if the mt is non-mipmapped
+       * and non-array.
+       */
+      const unsigned h0 = ALIGN(mt->physical_height0, hiz_align_j);
+      const unsigned h1 = ALIGN(minify(mt->physical_height0, 1), hiz_align_j);
+      const unsigned qpitch = h0 + h1 +
+         (brw->gen >= 7 ? 12 : 11) * hiz_align_j;
+
+      hiz_height = ALIGN(qpitch * mt->physical_depth0 / 2, 8);
    }
 
+   mt->hiz_region = intel_region_alloc(brw->intelScreen,
+                                       I915_TILING_Y,
+                                       1,
+                                       hiz_width,
+                                       hiz_height,
+                                       true);
    if (!mt->hiz_region)
       return false;