[Mesa-dev] [PATCH v2 26/32] intel/isl: Add support for computing offsets with miptails

Jason Ekstrand jason at jlekstrand.net
Fri Oct 12 18:46:56 UTC 2018


Unfortunately, there is no nice way to calculate miptail offsets in
closed form.  Instead, we just copy the tables from the PRM directly
verbatim.
---
 src/intel/isl/isl.c | 217 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 213 insertions(+), 4 deletions(-)

diff --git a/src/intel/isl/isl.c b/src/intel/isl/isl.c
index 3657b11ee00..c86390bf851 100644
--- a/src/intel/isl/isl.c
+++ b/src/intel/isl/isl.c
@@ -863,6 +863,169 @@ isl_calc_phys_level0_extent_sa(const struct isl_device *dev,
    }
 }
 
+static const uint16_t std_y_1d_miptail_offset_el[] = {
+/* 128 bpb */
+   2048,
+   1024,
+   512,
+   256,
+   128,
+   64,
+   48,
+   32,
+   28,
+   24,
+   20,
+   16,
+   12,
+   8,
+   4,
+   0,
+};
+
+static const uint8_t gen9_std_y_2d_miptail_offset_el[][5][2] = {
+/*   128 bpb    64 bpb    32 bpb    16 bpb      8 bpb     */
+   { {32,  0}, {64,  0}, {64,  0}, {128,  0}, {128,  0} },
+   { { 0, 32}, { 0, 32}, { 0, 64}, {  0, 64}, {  0,128} },
+   { {16,  0}, {32,  0}, {32,  0}, { 64,  0}, { 64,  0} },
+   { { 0, 16}, { 0, 16}, { 0, 32}, {  0, 32}, {  0, 64} },
+   { { 8,  0}, {16,  0}, {16,  0}, { 32,  0}, { 32,  0} },
+   { { 4,  8}, { 8,  8}, { 8, 16}, { 16, 16}, { 16, 32} },
+   { { 0, 12}, { 0, 12}, { 0, 24}, {  0, 24}, {  0, 48} },
+   { { 0,  8}, { 0,  8}, { 0, 16}, {  0, 16}, {  0, 32} },
+   { { 4,  4}, { 8,  4}, { 8,  8}, { 16,  8}, { 16, 16} },
+   { { 4,  0}, { 8,  0}, { 8,  0}, { 16,  0}, { 16,  0} },
+   { { 0,  4}, { 0,  4}, { 0,  8}, {  0,  8}, {  0, 16} },
+   { { 3,  0}, { 6,  0}, { 4,  4}, {  8,  4}, {  0, 12} },
+   { { 2,  0}, { 4,  0}, { 4,  0}, {  8,  0}, {  0,  8} },
+   { { 1,  0}, { 2,  0}, { 0,  4}, {  0,  4}, {  0,  4} },
+   { { 0,  0}, { 0,  0}, { 0,  0}, {  0,  0}, {  0,  0} },
+};
+
+static const uint8_t gen10_std_y_2d_miptail_offset_el[][5][2] = {
+/*   128 bpb    64 bpb    32 bpb    16 bpb      8 bpb     */
+   { {32,  0}, {64,  0}, {64,  0}, {128,  0}, {128,   0} },
+   { { 0, 32}, { 0, 32}, { 0, 64}, {  0, 64}, {  0, 128} },
+   { {16,  0}, {32,  0}, {32,  0}, { 64,  0}, { 64,   0} },
+   { { 0, 16}, { 0, 16}, { 0, 32}, {  0, 32}, {  0,  64} },
+   { { 8,  0}, {16,  0}, {16,  0}, { 32,  0}, { 32,   0} },
+   { { 4,  8}, { 8,  8}, { 8, 16}, { 16, 16}, { 16,  32} },
+   { { 0, 12}, { 0, 12}, { 0, 24}, {  0, 24}, {  0,  48} },
+   { { 0,  8}, { 0,  8}, { 0, 16}, {  0, 16}, {  0,  32} },
+   { { 4,  4}, { 8,  4}, { 8,  8}, { 16,  8}, { 16,  16} },
+   { { 4,  0}, { 8,  0}, { 8,  0}, { 16,  0}, { 16,   0} },
+   { { 0,  4}, { 0,  4}, { 0,  8}, {  0,  8}, {  0,  16} },
+   { { 0,  0}, { 0,  0}, { 0,  0}, {  0,  0}, {  0,   0} },
+   { { 1,  0}, { 2,  0}, { 0,  4}, {  0,  4}, {  0,   4} },
+   { { 2,  0}, { 4,  0}, { 4,  0}, {  8,  0}, {  0,   8} },
+   { { 3,  0}, { 6,  0}, { 4,  4}, {  8,  4}, {  0,  12} },
+};
+
+static const uint8_t gen9_std_y_3d_miptail_offset_el[][5][3] = {
+/*    128 bpb     64 bpb      32 bpb        16 bpb        8 bpb      */
+   { {8, 0, 0}, {16, 0, 0}, {16,  0, 0}, {16,  0,  0}, {32,  0,  0} },
+   { {0, 8, 0}, { 0, 8, 0}, { 0, 16, 0}, { 0, 16,  0}, { 0, 16,  0} },
+   { {0, 0, 8}, { 0, 0, 8}, { 0,  0, 8}, { 0,  0, 16}, { 0,  0, 16} },
+   { {4, 0, 0}, { 8, 0, 0}, { 8,  0, 0}, { 8,  0,  0}, {16,  0,  0} },
+   { {0, 4, 0}, { 0, 4, 0}, { 0,  8, 0}, { 0,  8,  0}, { 0,  8,  0} },
+   { {0, 0, 4}, { 0, 0, 4}, { 0,  0, 4}, { 0,  0,  8}, { 0,  0,  8} },
+   { {3, 0, 0}, { 6, 0, 0}, { 4,  4, 0}, { 0,  4,  4}, { 0,  4,  4} },
+   { {2, 0, 0}, { 4, 0, 0}, { 0,  4, 0}, { 0,  4,  0}, { 0,  4,  0} },
+   { {1, 0, 3}, { 2, 0, 3}, { 4,  0, 3}, { 0,  0,  7}, { 0,  0,  7} },
+   { {1, 0, 2}, { 2, 0, 2}, { 4,  0, 2}, { 0,  0,  6}, { 0,  0,  6} },
+   { {1, 0, 1}, { 2, 0, 1}, { 4,  0, 1}, { 0,  0,  5}, { 0,  0,  5} },
+   { {1, 0, 0}, { 2, 0, 0}, { 4,  0, 0}, { 0,  0,  4}, { 0,  0,  4} },
+   { {0, 0, 3}, { 0, 0, 3}, { 0,  0, 3}, { 0,  0,  3}, { 0,  0,  3} },
+   { {0, 0, 2}, { 0, 0, 2}, { 0,  0, 2}, { 0,  0,  2}, { 0,  0,  2} },
+   { {0, 0, 1}, { 0, 0, 1}, { 0,  0, 1}, { 0,  0,  1}, { 0,  0,  1} },
+   { {0, 0, 0}, { 0, 0, 0}, { 0,  0, 0}, { 0,  0,  0}, { 0,  0,  0} },
+};
+
+static const uint8_t gen10_std_y_3d_miptail_offset_el[][5][3] = {
+/*    128 bpb     64 bpb      32 bpb        16 bpb        8 bpb      */
+   { {8, 0, 0}, {16, 0, 0}, {16,  0, 0}, {16,  0,  0}, {32,  0,  0} },
+   { {0, 8, 0}, { 0, 8, 0}, { 0, 16, 0}, { 0, 16,  0}, { 0, 16,  0} },
+   { {0, 0, 8}, { 0, 0, 8}, { 0,  0, 8}, { 0,  0, 16}, { 0,  0, 16} },
+   { {4, 0, 0}, { 8, 0, 0}, { 8,  0, 0}, { 8,  0,  0}, {16,  0,  0} },
+   { {0, 4, 0}, { 0, 4, 0}, { 0,  8, 0}, { 0,  8,  0}, { 0,  8,  0} },
+   { {2, 0, 4}, { 4, 0, 4}, { 4,  0, 4}, { 4,  0,  8}, { 8,  0,  8} },
+   { {0, 2, 4}, { 0, 2, 4}, { 0,  4, 4}, { 0,  4,  8}, { 0,  4,  8} },
+   { {0, 0, 4}, { 0, 0, 4}, { 0,  0, 4}, { 0,  0,  8}, { 0,  0,  8} },
+   { {2, 2, 0}, { 4, 2, 0}, { 4,  4, 0}, { 4,  4,  0}, { 8,  4,  0} },
+   { {2, 0, 0}, { 4, 0, 0}, { 4,  0, 0}, { 4,  0,  0}, { 8,  0,  0} },
+   { {0, 2, 0}, { 0, 2, 0}, { 0,  4, 0}, { 0,  4,  0}, { 0,  4,  0} },
+   { {1, 0, 2}, { 2, 0, 2}, { 2,  0, 2}, { 2,  0,  4}, { 4,  0,  4} },
+   { {0, 0, 2}, { 0, 0, 2}, { 0,  0, 2}, { 0,  0,  4}, { 0,  0,  4} },
+   { {1, 0, 0}, { 2, 0, 0}, { 2,  0, 0}, { 2,  0,  0}, { 4,  0,  0} },
+   { {0, 0, 0}, { 0, 0, 0}, { 0,  0, 0}, { 0,  0,  0}, { 0,  0,  0} },
+
+};
+
+static void
+isl_get_miptail_level_offset_el(enum isl_tiling tiling,
+                                enum isl_surf_dim dim,
+                                uint32_t format_bpb,
+                                uint32_t samples,
+                                uint32_t level,
+                                uint32_t *x_offset_el,
+                                uint32_t *y_offset_el,
+                                uint32_t *z_offset_el)
+{
+   uint32_t row = level;
+   uint32_t col = 8 - ffs(format_bpb);
+
+   if (tiling == ISL_TILING_GEN9_Yf || tiling == ISL_TILING_GEN10_Yf)
+      row += 4;
+
+   switch (dim) {
+   case ISL_SURF_DIM_1D:
+      assert(samples == 1);
+      /* The 1D case is simple and doesn't need a table. */
+      *x_offset_el = std_y_1d_miptail_offset_el[row] << col;
+      *y_offset_el = 0;
+      *z_offset_el = 0;
+      break;
+
+   case ISL_SURF_DIM_2D:
+      assert(isl_is_pow2(samples) && samples <= 16);
+      if (tiling != ISL_TILING_GEN9_Yf)
+         row += ffs(samples) - 1;
+
+      if (tiling == ISL_TILING_GEN10_Yf || tiling == ISL_TILING_GEN10_Ys) {
+         assert(row < ARRAY_SIZE(gen10_std_y_2d_miptail_offset_el));
+         assert(col < ARRAY_SIZE(gen10_std_y_2d_miptail_offset_el[0]));
+         *x_offset_el = gen10_std_y_2d_miptail_offset_el[row][col][0];
+         *y_offset_el = gen10_std_y_2d_miptail_offset_el[row][col][1];
+      } else {
+         assert(tiling == ISL_TILING_GEN9_Yf || tiling == ISL_TILING_GEN9_Ys);
+         assert(row < ARRAY_SIZE(gen9_std_y_2d_miptail_offset_el));
+         assert(col < ARRAY_SIZE(gen9_std_y_2d_miptail_offset_el[0]));
+         *x_offset_el = gen9_std_y_2d_miptail_offset_el[row][col][0];
+         *y_offset_el = gen9_std_y_2d_miptail_offset_el[row][col][1];
+      }
+      *z_offset_el = 0;
+      break;
+
+   case ISL_SURF_DIM_3D:
+      assert(samples == 1);
+      if (tiling == ISL_TILING_GEN10_Yf || tiling == ISL_TILING_GEN10_Ys) {
+         assert(row < ARRAY_SIZE(gen10_std_y_3d_miptail_offset_el));
+         assert(col < ARRAY_SIZE(gen10_std_y_3d_miptail_offset_el[0]));
+         *x_offset_el = gen10_std_y_3d_miptail_offset_el[row][col][0];
+         *y_offset_el = gen10_std_y_3d_miptail_offset_el[row][col][1];
+         *z_offset_el = gen10_std_y_3d_miptail_offset_el[row][col][2];
+      } else {
+         assert(tiling == ISL_TILING_GEN9_Yf || tiling == ISL_TILING_GEN9_Ys);
+         assert(row < ARRAY_SIZE(gen9_std_y_3d_miptail_offset_el));
+         assert(col < ARRAY_SIZE(gen9_std_y_3d_miptail_offset_el[0]));
+         *x_offset_el = gen9_std_y_3d_miptail_offset_el[row][col][0];
+         *y_offset_el = gen9_std_y_3d_miptail_offset_el[row][col][1];
+         *z_offset_el = gen9_std_y_3d_miptail_offset_el[row][col][2];
+      }
+      break;
+   }
+}
+
 /**
  * Calculate the pitch between physical array slices, in units of rows of
  * surface elements.
@@ -2050,7 +2213,7 @@ get_image_offset_sa_gen4_2d(const struct isl_surf *surf,
       *array_offset = 0;
    }
 
-   for (uint32_t l = 0; l < level; ++l) {
+   for (uint32_t l = 0; l < MIN(level, surf->miptail_start_level); ++l) {
       if (l == 1) {
          uint32_t W = isl_minify(W0, l);
          x += isl_align_npot(W, image_align_sa.w);
@@ -2062,6 +2225,22 @@ get_image_offset_sa_gen4_2d(const struct isl_surf *surf,
 
    *x_offset_sa = x;
    *y_offset_sa = y;
+
+   if (level >= surf->miptail_start_level) {
+      const struct isl_format_layout *fmtl =
+         isl_format_get_layout(surf->format);
+
+      uint32_t tail_offset_x_el, tail_offset_y_el, tail_offset_z_el;
+      isl_get_miptail_level_offset_el(surf->tiling, surf->dim,
+                                      fmtl->bpb, surf->samples,
+                                      level - surf->miptail_start_level,
+                                      &tail_offset_x_el,
+                                      &tail_offset_y_el,
+                                      &tail_offset_z_el);
+      *x_offset_sa += tail_offset_x_el * fmtl->bw;
+      *y_offset_sa += tail_offset_y_el * fmtl->bh;
+      *z_offset_sa += tail_offset_z_el * fmtl->bd;
+   }
 }
 
 /**
@@ -2204,7 +2383,7 @@ get_image_offset_sa_gen9_1d(const struct isl_surf *surf,
 
    uint32_t x = 0;
 
-   for (uint32_t l = 0; l < level; ++l) {
+   for (uint32_t l = 0; l < MIN(level, surf->miptail_start_level); ++l) {
       uint32_t W = isl_minify(W0, l);
       uint32_t w = isl_align_npot(W, image_align_sa.w);
 
@@ -2221,6 +2400,21 @@ get_image_offset_sa_gen9_1d(const struct isl_surf *surf,
       *y_offset_sa = 0;
       *array_offset = layer;
    }
+
+   if (level >= surf->miptail_start_level) {
+      const struct isl_format_layout *fmtl =
+         isl_format_get_layout(surf->format);
+
+      uint32_t tail_offset_x_el, tail_offset_y_el, tail_offset_z_el;
+      isl_get_miptail_level_offset_el(surf->tiling, surf->dim,
+                                      fmtl->bpb, surf->samples,
+                                      level - surf->miptail_start_level,
+                                      &tail_offset_x_el,
+                                      &tail_offset_y_el,
+                                      &tail_offset_z_el);
+      assert(tail_offset_y_el == 0 && tail_offset_z_el == 0);
+      *x_offset_sa += tail_offset_x_el * fmtl->bw;
+   }
 }
 
 /**
@@ -2375,8 +2569,23 @@ isl_surf_get_image_offset_B_tile_el(const struct isl_surf *surf,
                                       y_offset_el,
                                       &z_offset_el,
                                       &array_offset);
-   assert(z_offset_el == 0);
-   assert(array_offset == 0);
+   if (level >= surf->miptail_start_level) {
+      /* We can do a byte offset to the first level of a miptail but we cannot
+       * offset into a miptail.
+       */
+      assert(level == surf->miptail_start_level);
+
+      /* The byte offset will get us to the miptail page.  The other offsets
+       * are to the actual level within the miptail.  It is assumed that the
+       * caller will set up a texture with a miptail and use the hardware to
+       * handle offseting inside the miptail.
+       */
+      *x_offset_el = 0;
+      *y_offset_el = 0;
+   } else {
+      assert(z_offset_el == 0);
+      assert(array_offset == 0);
+   }
 }
 
 void
-- 
2.19.1



More information about the mesa-dev mailing list