Mesa (master): llvmpipe: always allocate whole miptrees not individual levels

Roland Scheidegger sroland at kemper.freedesktop.org
Mon Nov 12 20:03:36 UTC 2012


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

Author: Roland Scheidegger <sroland at vmware.com>
Date:   Mon Nov 12 20:08:19 2012 +0100

llvmpipe: always allocate whole miptrees not individual levels

This is preparation work for using mip level offsets + base_ptr for texture
sampling instead of per-mip pointers.

Reviewed-by: Brian Paul <brianp at vmware.com>
Reviewed-by: José Fonseca <jfonseca at vmware.com>

---

 src/gallium/drivers/llvmpipe/lp_texture.c |  134 ++++++++++++++++-------------
 src/gallium/drivers/llvmpipe/lp_texture.h |    7 +-
 2 files changed, 81 insertions(+), 60 deletions(-)

diff --git a/src/gallium/drivers/llvmpipe/lp_texture.c b/src/gallium/drivers/llvmpipe/lp_texture.c
index b4ea94c..f61e378 100644
--- a/src/gallium/drivers/llvmpipe/lp_texture.c
+++ b/src/gallium/drivers/llvmpipe/lp_texture.c
@@ -332,7 +332,7 @@ llvmpipe_resource_create(struct pipe_screen *_screen,
 
 static void
 llvmpipe_resource_destroy(struct pipe_screen *pscreen,
-			  struct pipe_resource *pt)
+                          struct pipe_resource *pt)
 {
    struct llvmpipe_screen *screen = llvmpipe_screen(pscreen);
    struct llvmpipe_resource *lpr = llvmpipe_resource(pt);
@@ -342,9 +342,9 @@ llvmpipe_resource_destroy(struct pipe_screen *pscreen,
       struct sw_winsys *winsys = screen->winsys;
       winsys->displaytarget_destroy(winsys, lpr->dt);
 
-      if (lpr->tiled[0].data) {
-         align_free(lpr->tiled[0].data);
-         lpr->tiled[0].data = NULL;
+      if (lpr->tiled_img.data) {
+         align_free(lpr->tiled_img.data);
+         lpr->tiled_img.data = NULL;
       }
 
       FREE(lpr->layout[0]);
@@ -354,23 +354,19 @@ llvmpipe_resource_destroy(struct pipe_screen *pscreen,
       uint level;
 
       /* free linear image data */
-      for (level = 0; level < Elements(lpr->linear); level++) {
-         if (lpr->linear[level].data) {
-            align_free(lpr->linear[level].data);
-            lpr->linear[level].data = NULL;
-         }
+      if (lpr->linear_img.data) {
+         align_free(lpr->linear_img.data);
+         lpr->linear_img.data = NULL;
       }
 
       /* free tiled image data */
-      for (level = 0; level < Elements(lpr->tiled); level++) {
-         if (lpr->tiled[level].data) {
-            align_free(lpr->tiled[level].data);
-            lpr->tiled[level].data = NULL;
-         }
+      if (lpr->tiled_img.data) {
+         align_free(lpr->tiled_img.data);
+         lpr->tiled_img.data = NULL;
       }
 
       /* free layout flag arrays */
-      for (level = 0; level < Elements(lpr->tiled); level++) {
+      for (level = 0; level < Elements(lpr->layout); level++) {
          FREE(lpr->layout[level]);
          lpr->layout[level] = NULL;
       }
@@ -434,7 +430,7 @@ llvmpipe_resource_map(struct pipe_resource *resource,
       map = winsys->displaytarget_map(winsys, lpr->dt, dt_usage);
 
       /* install this linear image in texture data structure */
-      lpr->linear[level].data = map;
+      lpr->linear_img.data = map;
 
       /* make sure tiled data gets converted to linear data */
       map2 = llvmpipe_get_texture_image(lpr, 0, 0, tex_usage, layout);
@@ -496,8 +492,8 @@ llvmpipe_resource_data(struct pipe_resource *resource)
 
 static struct pipe_resource *
 llvmpipe_resource_from_handle(struct pipe_screen *screen,
-			      const struct pipe_resource *template,
-			      struct winsys_handle *whandle)
+                              const struct pipe_resource *template,
+                              struct winsys_handle *whandle)
 {
    struct sw_winsys *winsys = llvmpipe_screen(screen)->winsys;
    struct llvmpipe_resource *lpr;
@@ -911,17 +907,17 @@ llvmpipe_get_texture_image_address(struct llvmpipe_resource *lpr,
    unsigned offset;
 
    if (layout == LP_TEX_LAYOUT_LINEAR) {
-      img = &lpr->linear[level];
+      img = &lpr->linear_img;
+      offset = lpr->linear_mip_offsets[level];
    }
    else {
       assert (layout == LP_TEX_LAYOUT_TILED);
-      img = &lpr->tiled[level];
+      img = &lpr->tiled_img;
+      offset = lpr->tiled_mip_offsets[level];
    }
 
    if (face_slice > 0)
-      offset = face_slice * tex_image_face_size(lpr, level, layout);
-   else
-      offset = 0;
+      offset += face_slice * tex_image_face_size(lpr, level, layout);
 
    return (ubyte *) img->data + offset;
 }
@@ -976,23 +972,29 @@ llvmpipe_set_texture_image_layout(struct llvmpipe_resource *lpr,
 
 /**
  * Allocate storage for a linear or tile texture image (all cube
- * faces and all 3D slices.
+ * faces and all 3D slices, all levels).
  */
 static void
-alloc_image_data(struct llvmpipe_resource *lpr, unsigned level,
+alloc_image_data(struct llvmpipe_resource *lpr,
                  enum lp_texture_layout layout)
 {
    uint alignment = MAX2(16, util_cpu_caps.cacheline);
+   uint level;
+   uint offset = 0;
 
    if (lpr->dt)
-      assert(level == 0);
+      assert(lpr->base.last_level == 0);
 
    if (layout == LP_TEX_LAYOUT_TILED) {
       /* tiled data is stored in regular memory */
-      uint buffer_size = tex_image_size(lpr, level, layout);
-      lpr->tiled[level].data = align_malloc(buffer_size, alignment);
-      if (lpr->tiled[level].data) {
-         memset(lpr->tiled[level].data, 0, buffer_size);
+      for (level = 0; level <= lpr->base.last_level; level++) {
+         uint buffer_size = tex_image_size(lpr, level, layout);
+         lpr->tiled_mip_offsets[level] = offset;
+         offset += align(buffer_size, alignment);
+      }
+      lpr->tiled_img.data = align_malloc(offset, alignment);
+      if (lpr->tiled_img.data) {
+         memset(lpr->tiled_img.data, 0, offset);
       }
    }
    else {
@@ -1004,16 +1006,24 @@ alloc_image_data(struct llvmpipe_resource *lpr, unsigned level,
          struct llvmpipe_screen *screen = llvmpipe_screen(lpr->base.screen);
          struct sw_winsys *winsys = screen->winsys;
 
-         lpr->linear[0].data =
+         lpr->linear_img.data =
             winsys->displaytarget_map(winsys, lpr->dt,
                                       PIPE_TRANSFER_READ_WRITE);
       }
       else {
          /* not a display target - allocate regular memory */
-         uint buffer_size = tex_image_size(lpr, level, LP_TEX_LAYOUT_LINEAR);
-         lpr->linear[level].data = align_malloc(buffer_size, alignment);
-         if (lpr->linear[level].data) {
-            memset(lpr->linear[level].data, 0, buffer_size);
+         /*
+          * Offset calculation for start of a specific mip/layer is always
+          * offset = lpr->linear_mip_offsets[level] + lpr->img_stride[level] * layer
+          */
+         for (level = 0; level <= lpr->base.last_level; level++) {
+            uint buffer_size = tex_image_size(lpr, level, LP_TEX_LAYOUT_LINEAR);
+            lpr->linear_mip_offsets[level] = offset;
+            offset += align(buffer_size, alignment);
+         }
+         lpr->linear_img.data = align_malloc(offset, alignment);
+         if (lpr->linear_img.data) {
+            memset(lpr->linear_img.data, 0, offset);
          }
       }
    }
@@ -1049,6 +1059,8 @@ llvmpipe_get_texture_image(struct llvmpipe_resource *lpr,
    const unsigned height = u_minify(lpr->base.height0, level);
    const unsigned width_t = align(width, TILE_SIZE) / TILE_SIZE;
    const unsigned height_t = align(height, TILE_SIZE) / TILE_SIZE;
+   unsigned target_offset, other_offset;
+   unsigned *target_off_ptr, *other_off_ptr;
    enum lp_texture_layout other_layout;
    boolean only_allocate;
 
@@ -1070,18 +1082,22 @@ llvmpipe_get_texture_image(struct llvmpipe_resource *lpr,
    }
 
    if (lpr->dt) {
-      assert(lpr->linear[level].data);
+      assert(lpr->linear_img.data);
    }
 
    /* which is target?  which is other? */
    if (layout == LP_TEX_LAYOUT_LINEAR) {
-      target_img = &lpr->linear[level];
-      other_img = &lpr->tiled[level];
+      target_img = &lpr->linear_img;
+      target_off_ptr = lpr->linear_mip_offsets;
+      other_img = &lpr->tiled_img;
+      other_off_ptr = lpr->tiled_mip_offsets;
       other_layout = LP_TEX_LAYOUT_TILED;
    }
    else {
-      target_img = &lpr->tiled[level];
-      other_img = &lpr->linear[level];
+      target_img = &lpr->tiled_img;
+      target_off_ptr = lpr->tiled_mip_offsets;
+      other_img = &lpr->linear_img;
+      other_off_ptr = lpr->linear_mip_offsets;
       other_layout = LP_TEX_LAYOUT_LINEAR;
    }
 
@@ -1090,21 +1106,23 @@ llvmpipe_get_texture_image(struct llvmpipe_resource *lpr,
 
    if (!target_data) {
       /* allocate memory for the target image now */
-      alloc_image_data(lpr, level, layout);
+      alloc_image_data(lpr, layout);
       target_data = target_img->data;
    }
 
+   target_offset = target_off_ptr[level];
+   other_offset = other_off_ptr[level];
+
    if (face_slice > 0) {
-      unsigned target_offset, other_offset;
+      target_offset += face_slice * tex_image_face_size(lpr, level, layout);
+      other_offset += face_slice * tex_image_face_size(lpr, level, other_layout);
+   }
 
-      target_offset = face_slice * tex_image_face_size(lpr, level, layout);
-      other_offset = face_slice * tex_image_face_size(lpr, level, other_layout);
-      if (target_data) {
-         target_data = (uint8_t *) target_data + target_offset;
-      }
-      if (other_data) {
-         other_data = (uint8_t *) other_data + other_offset;
-      }
+   if (target_data) {
+      target_data = (uint8_t *) target_data + target_offset;
+   }
+   if (other_data) {
+      other_data = (uint8_t *) other_data + other_offset;
    }
 
    if (only_allocate) {
@@ -1202,7 +1220,7 @@ llvmpipe_get_texture_tile_linear(struct llvmpipe_resource *lpr,
                                  enum lp_texture_usage usage,
                                  unsigned x, unsigned y)
 {
-   struct llvmpipe_texture_image *linear_img = &lpr->linear[level];
+   struct llvmpipe_texture_image *linear_img = &lpr->linear_img;
    enum lp_texture_layout cur_layout, new_layout;
    const unsigned tx = x / TILE_SIZE, ty = y / TILE_SIZE;
    boolean convert;
@@ -1214,7 +1232,7 @@ llvmpipe_get_texture_tile_linear(struct llvmpipe_resource *lpr,
 
    if (!linear_img->data) {
       /* allocate memory for the linear image now */
-      alloc_image_data(lpr, level, LP_TEX_LAYOUT_LINEAR);
+      alloc_image_data(lpr, LP_TEX_LAYOUT_LINEAR);
    }
 
    /* compute address of the slice/face of the image that contains the tile */
@@ -1253,7 +1271,7 @@ llvmpipe_get_texture_tile(struct llvmpipe_resource *lpr,
                           enum lp_texture_usage usage,
                           unsigned x, unsigned y)
 {
-   struct llvmpipe_texture_image *tiled_img = &lpr->tiled[level];
+   struct llvmpipe_texture_image *tiled_img = &lpr->tiled_img;
    enum lp_texture_layout cur_layout, new_layout;
    const unsigned tx = x / TILE_SIZE, ty = y / TILE_SIZE;
    boolean convert;
@@ -1265,7 +1283,7 @@ llvmpipe_get_texture_tile(struct llvmpipe_resource *lpr,
 
    if (!tiled_img->data) {
       /* allocate memory for the tiled image now */
-      alloc_image_data(lpr, level, LP_TEX_LAYOUT_TILED);
+      alloc_image_data(lpr, LP_TEX_LAYOUT_TILED);
    }
 
    /* compute address of the slice/face of the image that contains the tile */
@@ -1309,7 +1327,7 @@ llvmpipe_unswizzle_cbuf_tile(struct llvmpipe_resource *lpr,
                              unsigned x, unsigned y,
                              uint8_t *tile)
 {
-   struct llvmpipe_texture_image *linear_img = &lpr->linear[level];
+   struct llvmpipe_texture_image *linear_img = &lpr->linear_img;
    const unsigned tx = x / TILE_SIZE, ty = y / TILE_SIZE;
    uint8_t *linear_image;
 
@@ -1318,7 +1336,7 @@ llvmpipe_unswizzle_cbuf_tile(struct llvmpipe_resource *lpr,
 
    if (!linear_img->data) {
       /* allocate memory for the linear image now */
-      alloc_image_data(lpr, level, LP_TEX_LAYOUT_LINEAR);
+      alloc_image_data(lpr, LP_TEX_LAYOUT_LINEAR);
    }
 
    /* compute address of the slice/face of the image that contains the tile */
@@ -1397,10 +1415,10 @@ llvmpipe_resource_size(const struct pipe_resource *resource)
    unsigned lvl, size = 0;
 
    for (lvl = 0; lvl <= lpr->base.last_level; lvl++) {
-      if (lpr->linear[lvl].data)
+      if (lpr->linear_img.data)
          size += tex_image_size(lpr, lvl, LP_TEX_LAYOUT_LINEAR);
 
-      if (lpr->tiled[lvl].data)
+      if (lpr->tiled_img.data)
          size += tex_image_size(lpr, lvl, LP_TEX_LAYOUT_TILED);
    }
 
diff --git a/src/gallium/drivers/llvmpipe/lp_texture.h b/src/gallium/drivers/llvmpipe/lp_texture.h
index b4a0dfd..73eaddc 100644
--- a/src/gallium/drivers/llvmpipe/lp_texture.h
+++ b/src/gallium/drivers/llvmpipe/lp_texture.h
@@ -94,6 +94,9 @@ struct llvmpipe_resource
    unsigned tiles_per_image[LP_MAX_TEXTURE_LEVELS];
    /** Number of 3D slices or cube faces per level */
    unsigned num_slices_faces[LP_MAX_TEXTURE_LEVELS];
+   /** Offset to start of mipmap level, in bytes */
+   unsigned tiled_mip_offsets[LP_MAX_TEXTURE_LEVELS];
+   unsigned linear_mip_offsets[LP_MAX_TEXTURE_LEVELS];
 
    /**
     * Display target, for textures with the PIPE_BIND_DISPLAY_TARGET
@@ -104,8 +107,8 @@ struct llvmpipe_resource
    /**
     * Malloc'ed data for regular textures, or a mapping to dt above.
     */
-   struct llvmpipe_texture_image tiled[LP_MAX_TEXTURE_LEVELS];
-   struct llvmpipe_texture_image linear[LP_MAX_TEXTURE_LEVELS];
+   struct llvmpipe_texture_image tiled_img;
+   struct llvmpipe_texture_image linear_img;
 
    /**
     * Data for non-texture resources.




More information about the mesa-commit mailing list