diff mbox

[libdrm,1/3] radeon: Fix layout of linear aligned mipmaps on SI.

Message ID 1346928819-5202-1-git-send-email-michel@daenzer.net (mailing list archive)
State New, archived
Headers show

Commit Message

Michel Dänzer Sept. 6, 2012, 10:53 a.m. UTC
From: Michel Dänzer <michel.daenzer@amd.com>

Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
---
 radeon/radeon_surface.c |  124 ++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 123 insertions(+), 1 deletion(-)

Comments

Christian König Sept. 6, 2012, 11:46 a.m. UTC | #1
On 06.09.2012 12:53, Michel Dänzer wrote:
> From: Michel Dänzer <michel.daenzer@amd.com>
>
> Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
Sounds good to me, but shouldn't we also increase the version number?

Anyway: Reviewed-by: Christian König <christian.koenig@amd.com>

> ---
>   radeon/radeon_surface.c |  124 ++++++++++++++++++++++++++++++++++++++++++++++-
>   1 file changed, 123 insertions(+), 1 deletion(-)
>
> diff --git a/radeon/radeon_surface.c b/radeon/radeon_surface.c
> index 4118a37..593c51c 100644
> --- a/radeon/radeon_surface.c
> +++ b/radeon/radeon_surface.c
> @@ -952,6 +952,124 @@ static int eg_surface_best(struct radeon_surface_manager *surf_man,
>   
>   
>   /* ===========================================================================
> + * Southern Islands family
> + */
> +
> +static void si_surf_minify_linear_aligned(struct radeon_surface *surf,
> +                                          unsigned level,
> +                                          uint32_t xalign, uint32_t yalign, uint32_t zalign, uint32_t slice_align,
> +                                          unsigned offset)
> +{
> +    surf->level[level].npix_x = mip_minify(surf->npix_x, level);
> +    surf->level[level].npix_y = mip_minify(surf->npix_y, level);
> +    surf->level[level].npix_z = mip_minify(surf->npix_z, level);
> +    surf->level[level].nblk_x = (surf->level[level].npix_x + surf->blk_w - 1) / surf->blk_w;
> +    surf->level[level].nblk_y = (surf->level[level].npix_y + surf->blk_h - 1) / surf->blk_h;
> +    surf->level[level].nblk_z = (surf->level[level].npix_z + surf->blk_d - 1) / surf->blk_d;
> +
> +    /* XXX: Second smallest level uses larger pitch, not sure of the real reason,
> +     * my best guess so far: rows evenly distributed across slice
> +     */
> +    xalign = MAX2(xalign, slice_align / surf->bpe / surf->level[level].npix_y);
> +
> +    surf->level[level].nblk_x  = ALIGN(surf->level[level].nblk_x, xalign);
> +    surf->level[level].nblk_y  = ALIGN(surf->level[level].nblk_y, yalign);
> +    surf->level[level].nblk_z  = ALIGN(surf->level[level].nblk_z, zalign);
> +
> +    surf->level[level].offset = offset;
> +    surf->level[level].pitch_bytes = surf->level[level].nblk_x * surf->bpe * surf->nsamples;
> +    surf->level[level].slice_size = ALIGN(surf->level[level].pitch_bytes * surf->level[level].nblk_y, slice_align);
> +
> +    surf->bo_size = offset + surf->level[level].slice_size * surf->level[level].nblk_z * surf->array_size;
> +}
> +
> +static int si_surface_init_linear_aligned(struct radeon_surface_manager *surf_man,
> +                                          struct radeon_surface *surf,
> +                                          uint64_t offset, unsigned start_level)
> +{
> +    uint32_t xalign, yalign, zalign, slice_align;
> +    unsigned i;
> +
> +    /* compute alignment */
> +    if (!start_level) {
> +        surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
> +    }
> +    xalign = MAX2(8, 64 / surf->bpe);
> +    yalign = 1;
> +    zalign = 1;
> +    slice_align = MAX2(64 * surf->bpe, surf_man->hw_info.group_bytes);
> +
> +    /* build mipmap tree */
> +    for (i = start_level; i <= surf->last_level; i++) {
> +        surf->level[i].mode = RADEON_SURF_MODE_LINEAR_ALIGNED;
> +        si_surf_minify_linear_aligned(surf, i, xalign, yalign, zalign, slice_align, offset);
> +        /* level0 and first mipmap need to have alignment */
> +        offset = surf->bo_size;
> +        if ((i == 0)) {
> +            offset = ALIGN(offset, surf->bo_alignment);
> +        }
> +    }
> +    return 0;
> +}
> +
> +static int si_surface_init(struct radeon_surface_manager *surf_man,
> +                           struct radeon_surface *surf)
> +{
> +    unsigned mode;
> +    int r;
> +
> +    /* MSAA surfaces support the 2D mode only. */
> +    if (surf->nsamples > 1) {
> +        surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
> +        surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
> +    }
> +
> +    /* tiling mode */
> +    mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
> +
> +    if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
> +        /* zbuffer only support 1D or 2D tiled surface */
> +        switch (mode) {
> +        case RADEON_SURF_MODE_1D:
> +        case RADEON_SURF_MODE_2D:
> +            break;
> +        default:
> +            mode = RADEON_SURF_MODE_1D;
> +            surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
> +            surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
> +            break;
> +        }
> +    }
> +
> +    r = eg_surface_sanity(surf_man, surf, mode);
> +    if (r) {
> +        return r;
> +    }
> +
> +    surf->stencil_offset = 0;
> +    surf->stencil_tile_split = 0;
> +
> +    /* check tiling mode */
> +    switch (mode) {
> +    case RADEON_SURF_MODE_LINEAR:
> +        r = r6_surface_init_linear(surf_man, surf, 0, 0);
> +        break;
> +    case RADEON_SURF_MODE_LINEAR_ALIGNED:
> +        r = si_surface_init_linear_aligned(surf_man, surf, 0, 0);
> +        break;
> +    case RADEON_SURF_MODE_1D:
> +        r = eg_surface_init_1d(surf_man, surf, 0, 0);
> +        break;
> +    case RADEON_SURF_MODE_2D:
> +        r = eg_surface_init_2d(surf_man, surf, 0, 0);
> +        break;
> +    default:
> +        return -EINVAL;
> +    }
> +    return r;
> +}
> +
> +/* ===========================================================================
>    * public API
>    */
>   struct radeon_surface_manager *radeon_surface_manager_new(int fd)
> @@ -980,7 +1098,11 @@ struct radeon_surface_manager *radeon_surface_manager_new(int fd)
>           if (eg_init_hw_info(surf_man)) {
>               goto out_err;
>           }
> -        surf_man->surface_init = &eg_surface_init;
> +        if (surf_man->family <= CHIP_ARUBA) {
> +            surf_man->surface_init = &eg_surface_init;
> +        } else {
> +            surf_man->surface_init = &si_surface_init;
> +        }
>           surf_man->surface_best = &eg_surface_best;
>       }
>
Michel Dänzer Sept. 6, 2012, 1:01 p.m. UTC | #2
On Don, 2012-09-06 at 13:46 +0200, Christian König wrote: 
> On 06.09.2012 12:53, Michel Dänzer wrote:
> > From: Michel Dänzer <michel.daenzer@amd.com>
> >
> > Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
> Sounds good to me, but shouldn't we also increase the version number?

Assuming you mean the libdrm package version, I don't think it's worth
doing that just for these fixes. At this point, one should always use
latest Git of mesa and libdrm for radeonsi. But of course, once a libdrm
release is out with these fixes, we can require that as the minimum
version for radeonsi.


> Anyway: Reviewed-by: Christian König <christian.koenig@amd.com>

Thanks, is that for the whole series?
Christian König Sept. 6, 2012, 1:15 p.m. UTC | #3
On 06.09.2012 15:01, Michel Dänzer wrote:
> On Don, 2012-09-06 at 13:46 +0200, Christian König wrote:
>> On 06.09.2012 12:53, Michel Dänzer wrote:
>>> From: Michel Dänzer <michel.daenzer@amd.com>
>>>
>>> Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
>> Sounds good to me, but shouldn't we also increase the version number?
> Assuming you mean the libdrm package version, I don't think it's worth
> doing that just for these fixes. At this point, one should always use
> latest Git of mesa and libdrm for radeonsi. But of course, once a libdrm
> release is out with these fixes, we can require that as the minimum
> version for radeonsi.
Ok, that makes sense.

>> Anyway: Reviewed-by: Christian König <christian.koenig@amd.com>
> Thanks, is that for the whole series?

Yes it is, and also for the four patches to radeonsi which depends on 
this change.

Christian.
Alex Deucher Sept. 6, 2012, 2:22 p.m. UTC | #4
On Thu, Sep 6, 2012 at 6:53 AM, Michel Dänzer <michel@daenzer.net> wrote:
> From: Michel Dänzer <michel.daenzer@amd.com>
>
> Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>

for the series:

Reviewed-by: Alex Deucher <alexander.deucher@amd.com>

> ---
>  radeon/radeon_surface.c |  124 ++++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 123 insertions(+), 1 deletion(-)
>
> diff --git a/radeon/radeon_surface.c b/radeon/radeon_surface.c
> index 4118a37..593c51c 100644
> --- a/radeon/radeon_surface.c
> +++ b/radeon/radeon_surface.c
> @@ -952,6 +952,124 @@ static int eg_surface_best(struct radeon_surface_manager *surf_man,
>
>
>  /* ===========================================================================
> + * Southern Islands family
> + */
> +
> +static void si_surf_minify_linear_aligned(struct radeon_surface *surf,
> +                                          unsigned level,
> +                                          uint32_t xalign, uint32_t yalign, uint32_t zalign, uint32_t slice_align,
> +                                          unsigned offset)
> +{
> +    surf->level[level].npix_x = mip_minify(surf->npix_x, level);
> +    surf->level[level].npix_y = mip_minify(surf->npix_y, level);
> +    surf->level[level].npix_z = mip_minify(surf->npix_z, level);
> +    surf->level[level].nblk_x = (surf->level[level].npix_x + surf->blk_w - 1) / surf->blk_w;
> +    surf->level[level].nblk_y = (surf->level[level].npix_y + surf->blk_h - 1) / surf->blk_h;
> +    surf->level[level].nblk_z = (surf->level[level].npix_z + surf->blk_d - 1) / surf->blk_d;
> +
> +    /* XXX: Second smallest level uses larger pitch, not sure of the real reason,
> +     * my best guess so far: rows evenly distributed across slice
> +     */
> +    xalign = MAX2(xalign, slice_align / surf->bpe / surf->level[level].npix_y);
> +
> +    surf->level[level].nblk_x  = ALIGN(surf->level[level].nblk_x, xalign);
> +    surf->level[level].nblk_y  = ALIGN(surf->level[level].nblk_y, yalign);
> +    surf->level[level].nblk_z  = ALIGN(surf->level[level].nblk_z, zalign);
> +
> +    surf->level[level].offset = offset;
> +    surf->level[level].pitch_bytes = surf->level[level].nblk_x * surf->bpe * surf->nsamples;
> +    surf->level[level].slice_size = ALIGN(surf->level[level].pitch_bytes * surf->level[level].nblk_y, slice_align);
> +
> +    surf->bo_size = offset + surf->level[level].slice_size * surf->level[level].nblk_z * surf->array_size;
> +}
> +
> +static int si_surface_init_linear_aligned(struct radeon_surface_manager *surf_man,
> +                                          struct radeon_surface *surf,
> +                                          uint64_t offset, unsigned start_level)
> +{
> +    uint32_t xalign, yalign, zalign, slice_align;
> +    unsigned i;
> +
> +    /* compute alignment */
> +    if (!start_level) {
> +        surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
> +    }
> +    xalign = MAX2(8, 64 / surf->bpe);
> +    yalign = 1;
> +    zalign = 1;
> +    slice_align = MAX2(64 * surf->bpe, surf_man->hw_info.group_bytes);
> +
> +    /* build mipmap tree */
> +    for (i = start_level; i <= surf->last_level; i++) {
> +        surf->level[i].mode = RADEON_SURF_MODE_LINEAR_ALIGNED;
> +        si_surf_minify_linear_aligned(surf, i, xalign, yalign, zalign, slice_align, offset);
> +        /* level0 and first mipmap need to have alignment */
> +        offset = surf->bo_size;
> +        if ((i == 0)) {
> +            offset = ALIGN(offset, surf->bo_alignment);
> +        }
> +    }
> +    return 0;
> +}
> +
> +static int si_surface_init(struct radeon_surface_manager *surf_man,
> +                           struct radeon_surface *surf)
> +{
> +    unsigned mode;
> +    int r;
> +
> +    /* MSAA surfaces support the 2D mode only. */
> +    if (surf->nsamples > 1) {
> +        surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
> +        surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
> +    }
> +
> +    /* tiling mode */
> +    mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
> +
> +    if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
> +        /* zbuffer only support 1D or 2D tiled surface */
> +        switch (mode) {
> +        case RADEON_SURF_MODE_1D:
> +        case RADEON_SURF_MODE_2D:
> +            break;
> +        default:
> +            mode = RADEON_SURF_MODE_1D;
> +            surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
> +            surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
> +            break;
> +        }
> +    }
> +
> +    r = eg_surface_sanity(surf_man, surf, mode);
> +    if (r) {
> +        return r;
> +    }
> +
> +    surf->stencil_offset = 0;
> +    surf->stencil_tile_split = 0;
> +
> +    /* check tiling mode */
> +    switch (mode) {
> +    case RADEON_SURF_MODE_LINEAR:
> +        r = r6_surface_init_linear(surf_man, surf, 0, 0);
> +        break;
> +    case RADEON_SURF_MODE_LINEAR_ALIGNED:
> +        r = si_surface_init_linear_aligned(surf_man, surf, 0, 0);
> +        break;
> +    case RADEON_SURF_MODE_1D:
> +        r = eg_surface_init_1d(surf_man, surf, 0, 0);
> +        break;
> +    case RADEON_SURF_MODE_2D:
> +        r = eg_surface_init_2d(surf_man, surf, 0, 0);
> +        break;
> +    default:
> +        return -EINVAL;
> +    }
> +    return r;
> +}
> +
> +/* ===========================================================================
>   * public API
>   */
>  struct radeon_surface_manager *radeon_surface_manager_new(int fd)
> @@ -980,7 +1098,11 @@ struct radeon_surface_manager *radeon_surface_manager_new(int fd)
>          if (eg_init_hw_info(surf_man)) {
>              goto out_err;
>          }
> -        surf_man->surface_init = &eg_surface_init;
> +        if (surf_man->family <= CHIP_ARUBA) {
> +            surf_man->surface_init = &eg_surface_init;
> +        } else {
> +            surf_man->surface_init = &si_surface_init;
> +        }
>          surf_man->surface_best = &eg_surface_best;
>      }
>
> --
> 1.7.10.4
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
diff mbox

Patch

diff --git a/radeon/radeon_surface.c b/radeon/radeon_surface.c
index 4118a37..593c51c 100644
--- a/radeon/radeon_surface.c
+++ b/radeon/radeon_surface.c
@@ -952,6 +952,124 @@  static int eg_surface_best(struct radeon_surface_manager *surf_man,
 
 
 /* ===========================================================================
+ * Southern Islands family
+ */
+
+static void si_surf_minify_linear_aligned(struct radeon_surface *surf,
+                                          unsigned level,
+                                          uint32_t xalign, uint32_t yalign, uint32_t zalign, uint32_t slice_align,
+                                          unsigned offset)
+{
+    surf->level[level].npix_x = mip_minify(surf->npix_x, level);
+    surf->level[level].npix_y = mip_minify(surf->npix_y, level);
+    surf->level[level].npix_z = mip_minify(surf->npix_z, level);
+    surf->level[level].nblk_x = (surf->level[level].npix_x + surf->blk_w - 1) / surf->blk_w;
+    surf->level[level].nblk_y = (surf->level[level].npix_y + surf->blk_h - 1) / surf->blk_h;
+    surf->level[level].nblk_z = (surf->level[level].npix_z + surf->blk_d - 1) / surf->blk_d;
+
+    /* XXX: Second smallest level uses larger pitch, not sure of the real reason,
+     * my best guess so far: rows evenly distributed across slice
+     */
+    xalign = MAX2(xalign, slice_align / surf->bpe / surf->level[level].npix_y);
+
+    surf->level[level].nblk_x  = ALIGN(surf->level[level].nblk_x, xalign);
+    surf->level[level].nblk_y  = ALIGN(surf->level[level].nblk_y, yalign);
+    surf->level[level].nblk_z  = ALIGN(surf->level[level].nblk_z, zalign);
+
+    surf->level[level].offset = offset;
+    surf->level[level].pitch_bytes = surf->level[level].nblk_x * surf->bpe * surf->nsamples;
+    surf->level[level].slice_size = ALIGN(surf->level[level].pitch_bytes * surf->level[level].nblk_y, slice_align);
+
+    surf->bo_size = offset + surf->level[level].slice_size * surf->level[level].nblk_z * surf->array_size;
+}
+
+static int si_surface_init_linear_aligned(struct radeon_surface_manager *surf_man,
+                                          struct radeon_surface *surf,
+                                          uint64_t offset, unsigned start_level)
+{
+    uint32_t xalign, yalign, zalign, slice_align;
+    unsigned i;
+
+    /* compute alignment */
+    if (!start_level) {
+        surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
+    }
+    xalign = MAX2(8, 64 / surf->bpe);
+    yalign = 1;
+    zalign = 1;
+    slice_align = MAX2(64 * surf->bpe, surf_man->hw_info.group_bytes);
+
+    /* build mipmap tree */
+    for (i = start_level; i <= surf->last_level; i++) {
+        surf->level[i].mode = RADEON_SURF_MODE_LINEAR_ALIGNED;
+        si_surf_minify_linear_aligned(surf, i, xalign, yalign, zalign, slice_align, offset);
+        /* level0 and first mipmap need to have alignment */
+        offset = surf->bo_size;
+        if ((i == 0)) {
+            offset = ALIGN(offset, surf->bo_alignment);
+        }
+    }
+    return 0;
+}
+
+static int si_surface_init(struct radeon_surface_manager *surf_man,
+                           struct radeon_surface *surf)
+{
+    unsigned mode;
+    int r;
+
+    /* MSAA surfaces support the 2D mode only. */
+    if (surf->nsamples > 1) {
+        surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
+        surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
+    }
+
+    /* tiling mode */
+    mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
+
+    if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
+        /* zbuffer only support 1D or 2D tiled surface */
+        switch (mode) {
+        case RADEON_SURF_MODE_1D:
+        case RADEON_SURF_MODE_2D:
+            break;
+        default:
+            mode = RADEON_SURF_MODE_1D;
+            surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
+            surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
+            break;
+        }
+    }
+
+    r = eg_surface_sanity(surf_man, surf, mode);
+    if (r) {
+        return r;
+    }
+
+    surf->stencil_offset = 0;
+    surf->stencil_tile_split = 0;
+
+    /* check tiling mode */
+    switch (mode) {
+    case RADEON_SURF_MODE_LINEAR:
+        r = r6_surface_init_linear(surf_man, surf, 0, 0);
+        break;
+    case RADEON_SURF_MODE_LINEAR_ALIGNED:
+        r = si_surface_init_linear_aligned(surf_man, surf, 0, 0);
+        break;
+    case RADEON_SURF_MODE_1D:
+        r = eg_surface_init_1d(surf_man, surf, 0, 0);
+        break;
+    case RADEON_SURF_MODE_2D:
+        r = eg_surface_init_2d(surf_man, surf, 0, 0);
+        break;
+    default:
+        return -EINVAL;
+    }
+    return r;
+}
+
+/* ===========================================================================
  * public API
  */
 struct radeon_surface_manager *radeon_surface_manager_new(int fd)
@@ -980,7 +1098,11 @@  struct radeon_surface_manager *radeon_surface_manager_new(int fd)
         if (eg_init_hw_info(surf_man)) {
             goto out_err;
         }
-        surf_man->surface_init = &eg_surface_init;
+        if (surf_man->family <= CHIP_ARUBA) {
+            surf_man->surface_init = &eg_surface_init;
+        } else {
+            surf_man->surface_init = &si_surface_init;
+        }
         surf_man->surface_best = &eg_surface_best;
     }