nvc0: fix layer stride state
authorChristoph Bumiller <e0425955@student.tuwien.ac.at>
Thu, 23 Dec 2010 14:21:36 +0000 (15:21 +0100)
committerChristoph Bumiller <e0425955@student.tuwien.ac.at>
Thu, 23 Dec 2010 14:21:36 +0000 (15:21 +0100)
src/gallium/drivers/nvc0/nvc0_miptree.c
src/gallium/drivers/nvc0/nvc0_resource.h
src/gallium/drivers/nvc0/nvc0_state_validate.c

index 70b10a0..7c7e134 100644 (file)
@@ -58,17 +58,18 @@ get_tile_dims(unsigned nx, unsigned ny, unsigned nz)
 }
 
 static INLINE unsigned
-get_zslice_offset(uint32_t tile_mode, unsigned z, unsigned pitch, unsigned nbh)
+calc_zslice_offset(uint32_t tile_mode, unsigned z, unsigned pitch, unsigned nbh)
 {
    unsigned tile_h = NVC0_TILE_HEIGHT(tile_mode);
-   unsigned tile_d = NVC0_TILE_DEPTH(tile_mode);
+   unsigned tile_d_shift = NVC0_TILE_DIM_SHIFT(tile_mode, 2);
+   unsigned tile_d = 1 << tile_d_shift;
 
-   /* pitch_2d == to next slice within this volume tile */
-   /* pitch_3d == size (in bytes) of a volume tile */
-   unsigned pitch_2d = tile_h * NVC0_TILE_PITCH(tile_mode);
-   unsigned pitch_3d = tile_d * align(nbh, tile_h) * pitch;
+   /* stride_2d == to next slice within this volume tile */
+   /* stride_3d == size (in bytes) of a volume tile */
+   unsigned stride_2d = tile_h * NVC0_TILE_PITCH(tile_mode);
+   unsigned stride_3d = tile_d * align(nbh, tile_h) * pitch;
 
-   return (z % tile_d) * pitch_2d + (z / tile_d) * pitch_3d;
+   return (z & (tile_d - 1)) * stride_2d + (z >> tile_d_shift) * stride_3d;
 }
 
 static void
@@ -298,10 +299,16 @@ nvc0_miptree_surface_new(struct pipe_context *pipe,
    ps->height = ns->height;
 
    if (mt->layout_3d) {
-      ns->offset += get_zslice_offset(lvl->tile_mode, ps->u.tex.first_layer,
-                                      lvl->pitch,
-                                      util_format_get_nblocksy(pt->format,
-                                                               ns->height));
+      unsigned zslice = ps->u.tex.first_layer;
+
+      /* TODO: re-layout the texture to use only depth 1 tiles in this case: */
+      if (ns->depth > 1 && (zslice & (NVC0_TILE_DEPTH(lvl->tile_mode) - 1)))
+         NOUVEAU_ERR("Creating unsupported 3D surface of slices [%u:%u].\n",
+                     zslice, ps->u.tex.last_layer);
+
+      ns->offset += calc_zslice_offset(lvl->tile_mode, zslice, lvl->pitch,
+                                       util_format_get_nblocksy(pt->format,
+                                                                ns->height));
    } else {
       ns->offset += mt->layer_stride * ps->u.tex.first_layer;
    }
index 0ff7a03..9384f19 100644 (file)
@@ -66,12 +66,17 @@ nvc0_resource_unmap(struct nvc0_resource *res)
       nouveau_bo_unmap(res->bo);
 }
 
-#define NVC0_TILE_PITCH(m)  (64 << ((m) & 0xf))
-#define NVC0_TILE_HEIGHT(m) (8 << (((m) >> 4) & 0xf))
-#define NVC0_TILE_DEPTH(m)  (1 << ((m) >> 8))
+#define NVC0_TILE_DIM_SHIFT(m, d) (((m) >> (d * 4)) & 0xf)
 
-#define NVC0_TILE_SIZE(m) \
-   (NVC0_TILE_PITCH(m) * NVC0_TILE_HEIGHT(m) * NVC0_TILE_DEPTH(m))
+#define NVC0_TILE_PITCH(m)  (64 << NVC0_TILE_DIM_SHIFT(m, 0))
+#define NVC0_TILE_HEIGHT(m) ( 8 << NVC0_TILE_DIM_SHIFT(m, 1))
+#define NVC0_TILE_DEPTH(m)  ( 1 << NVC0_TILE_DIM_SHIFT(m, 2))
+
+#define NVC0_TILE_SIZE_2D(m) (((64 * 8) <<                     \
+                               NVC0_TILE_DIM_SHIFT(m, 0)) <<   \
+                              NVC0_TILE_DIM_SHIFT(m, 1))
+
+#define NVC0_TILE_SIZE(m) (NVC0_TILE_SIZE_2D(m) << NVC0_TILE_DIM_SHIFT(m, 2))
 
 struct nvc0_miptree_level {
    uint32_t offset;
index f20e7e9..25aec02 100644 (file)
@@ -81,7 +81,7 @@ nvc0_validate_fb(struct nvc0_context *nvc0)
         OUT_RING  (chan, (mt->layout_3d << 16) |
                    mt->level[sf->base.u.tex.level].tile_mode);
         OUT_RING  (chan, sf->depth);
-        OUT_RING  (chan, mt->layer_stride);
+        OUT_RING  (chan, mt->layer_stride >> 2);
 
         nvc0_bufctx_add_resident(nvc0, NVC0_BUFCTX_FRAME, &mt->base,
                                  NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
@@ -99,7 +99,7 @@ nvc0_validate_fb(struct nvc0_context *nvc0)
         OUT_RELOCl(chan, bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
         OUT_RING  (chan, nvc0_format_table[fb->zsbuf->format].rt);
         OUT_RING  (chan, mt->level[sf->base.u.tex.level].tile_mode);
-        OUT_RING  (chan, 0);
+        OUT_RING  (chan, mt->layer_stride >> 2);
         BEGIN_RING(chan, RING_3D(ZETA_ENABLE), 1);
         OUT_RING  (chan, 1);
         BEGIN_RING(chan, RING_3D(ZETA_HORIZ), 3);