[Mesa-dev] [PATCH 1/2] r600g: rewrite FMASK allocation, fix FMASK texturing with 2 and 4 samples

Alex Deucher alexdeucher at gmail.com
Thu May 9 16:14:26 PDT 2013


On Thu, May 9, 2013 at 5:33 PM, Marek Olšák <maraeo at gmail.com> wrote:
> This fixes and enables texturing with compressed MSAA colorbuffers
> on Evergreen and Cayman. For the first time, multisample textures work
> on Cayman.
>
> This requires the libdrm flag RADEON_SURF_FMASK.

Maybe bump the libdrm requirement when you commit?  Other than that:

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

> ---
>  src/gallium/drivers/r600/evergreen_state.c |   17 +++++++-----
>  src/gallium/drivers/r600/evergreend.h      |    3 +++
>  src/gallium/drivers/r600/r600_blit.c       |    6 +----
>  src/gallium/drivers/r600/r600_pipe.c       |    3 +--
>  src/gallium/drivers/r600/r600_resource.h   |    5 +++-
>  src/gallium/drivers/r600/r600_state.c      |    4 +--
>  src/gallium/drivers/r600/r600_texture.c    |   40 +++++++++++++++-------------
>  7 files changed, 42 insertions(+), 36 deletions(-)
>
> diff --git a/src/gallium/drivers/r600/evergreen_state.c b/src/gallium/drivers/r600/evergreen_state.c
> index 6797b22..4eb9768 100644
> --- a/src/gallium/drivers/r600/evergreen_state.c
> +++ b/src/gallium/drivers/r600/evergreen_state.c
> @@ -1101,7 +1101,7 @@ evergreen_create_sampler_view_custom(struct pipe_context *ctx,
>         uint32_t word4 = 0, yuv_format = 0, pitch = 0;
>         unsigned char swizzle[4], array_mode = 0, non_disp_tiling = 0;
>         unsigned height, depth, width;
> -       unsigned macro_aspect, tile_split, bankh, bankw, nbanks;
> +       unsigned macro_aspect, tile_split, bankh, bankw, nbanks, fmask_bankh;
>         enum pipe_format pipe_format = state->format;
>         struct radeon_surface_level *surflevel;
>
> @@ -1188,6 +1188,7 @@ evergreen_create_sampler_view_custom(struct pipe_context *ctx,
>         macro_aspect = eg_macro_tile_aspect(macro_aspect);
>         bankw = eg_bank_wh(bankw);
>         bankh = eg_bank_wh(bankh);
> +       fmask_bankh = eg_bank_wh(tmp->fmask_bank_height);
>
>         /* 128 bit formats require tile type = 1 */
>         if (rscreen->chip_class == CAYMAN) {
> @@ -1219,8 +1220,7 @@ evergreen_create_sampler_view_custom(struct pipe_context *ctx,
>
>         /* TEX_RESOURCE_WORD3.MIP_ADDRESS */
>         if (texture->nr_samples > 1 && rscreen->msaa_texture_support == MSAA_TEXTURE_COMPRESSED) {
> -               /* XXX the 2x and 4x cases are broken. */
> -               if (tmp->is_depth || tmp->resource.b.b.nr_samples != 8) {
> +               if (tmp->is_depth) {
>                         /* disable FMASK (0 = disabled) */
>                         view->tex_resource_words[3] = 0;
>                         view->skip_mip_address_reloc = true;
> @@ -1239,6 +1239,8 @@ evergreen_create_sampler_view_custom(struct pipe_context *ctx,
>                                        S_030010_ENDIAN_SWAP(endian));
>         view->tex_resource_words[5] = S_030014_BASE_ARRAY(state->u.tex.first_layer) |
>                                       S_030014_LAST_ARRAY(state->u.tex.last_layer);
> +       view->tex_resource_words[6] = S_030018_TILE_SPLIT(tile_split);
> +
>         if (texture->nr_samples > 1) {
>                 unsigned log_samples = util_logbase2(texture->nr_samples);
>                 if (rscreen->chip_class == CAYMAN) {
> @@ -1246,13 +1248,14 @@ evergreen_create_sampler_view_custom(struct pipe_context *ctx,
>                 }
>                 /* LAST_LEVEL holds log2(nr_samples) for multisample textures */
>                 view->tex_resource_words[5] |= S_030014_LAST_LEVEL(log_samples);
> +               view->tex_resource_words[6] |= S_030018_FMASK_BANK_HEIGHT(fmask_bankh);
>         } else {
>                 view->tex_resource_words[4] |= S_030010_BASE_LEVEL(state->u.tex.first_level);
>                 view->tex_resource_words[5] |= S_030014_LAST_LEVEL(state->u.tex.last_level);
> +               /* aniso max 16 samples */
> +               view->tex_resource_words[6] |= S_030018_MAX_ANISO(4);
>         }
> -       /* aniso max 16 samples */
> -       view->tex_resource_words[6] = (S_030018_MAX_ANISO(4)) |
> -                                     (S_030018_TILE_SPLIT(tile_split));
> +
>         view->tex_resource_words[7] = S_03001C_DATA_FORMAT(format) |
>                                       S_03001C_TYPE(V_03001C_SQ_TEX_VTX_VALID_TEXTURE) |
>                                       S_03001C_BANK_WIDTH(bankw) |
> @@ -1576,7 +1579,7 @@ void evergreen_init_color_surface(struct r600_context *rctx,
>                 surf->cb_color_fmask = surf->cb_color_base;
>                 surf->cb_color_cmask = surf->cb_color_base;
>         }
> -       surf->cb_color_fmask_slice = S_028C88_TILE_MAX(slice);
> +       surf->cb_color_fmask_slice = S_028C88_TILE_MAX(rtex->fmask_slice_tile_max);
>         surf->cb_color_cmask_slice = S_028C80_TILE_MAX(rtex->cmask_slice_tile_max);
>
>         surf->color_initialized = true;
> diff --git a/src/gallium/drivers/r600/evergreend.h b/src/gallium/drivers/r600/evergreend.h
> index 757c951..8990d6c 100644
> --- a/src/gallium/drivers/r600/evergreend.h
> +++ b/src/gallium/drivers/r600/evergreend.h
> @@ -1140,9 +1140,12 @@
>  #define   G_030014_LAST_ARRAY(x)                       (((x) >> 17) & 0x1FFF)
>  #define   C_030014_LAST_ARRAY                          0xC001FFFF
>  #define R_030018_SQ_TEX_RESOURCE_WORD6_0             0x030018
> +/* FMASK_BANK_HEIGHT and MAX_ANISO share the first two bits.
> + * The former is only used with MSAA textures. */
>  #define   S_030018_MAX_ANISO(x)                        (((x) & 0x7) << 0)
>  #define   G_030018_MAX_ANISO(x)                        (((x) >> 0) & 0x7)
>  #define   C_030018_MAX_ANISO                           0xFFFFFFF8
> +#define   S_030018_FMASK_BANK_HEIGHT(x)                (((x) & 0x3) << 0)
>  #define   S_030018_PERF_MODULATION(x)                  (((x) & 0x7) << 3)
>  #define   G_030018_PERF_MODULATION(x)                  (((x) >> 3) & 0x7)
>  #define   C_030018_PERF_MODULATION                     0xFFFFFFC7
> diff --git a/src/gallium/drivers/r600/r600_blit.c b/src/gallium/drivers/r600/r600_blit.c
> index afe4389..7d32eef 100644
> --- a/src/gallium/drivers/r600/r600_blit.c
> +++ b/src/gallium/drivers/r600/r600_blit.c
> @@ -300,11 +300,7 @@ static void r600_blit_decompress_color(struct pipe_context *ctx,
>                 blend_decompress = rctx->custom_blend_decompress;
>                 break;
>         case MSAA_TEXTURE_COMPRESSED:
> -               /* XXX the 2x and 4x cases are broken. */
> -               if (rtex->resource.b.b.nr_samples == 8)
> -                       blend_decompress = rctx->custom_blend_fmask_decompress;
> -               else
> -                       blend_decompress = rctx->custom_blend_decompress;
> +               blend_decompress = rctx->custom_blend_fmask_decompress;
>                 break;
>         case MSAA_TEXTURE_SAMPLE_ZERO:
>         default:
> diff --git a/src/gallium/drivers/r600/r600_pipe.c b/src/gallium/drivers/r600/r600_pipe.c
> index e7b5152..533e0c0 100644
> --- a/src/gallium/drivers/r600/r600_pipe.c
> +++ b/src/gallium/drivers/r600/r600_pipe.c
> @@ -1268,8 +1268,7 @@ struct pipe_screen *r600_screen_create(struct radeon_winsys *ws)
>                 break;
>         case CAYMAN:
>                 rscreen->has_msaa = rscreen->info.drm_minor >= 19;
> -               /* We should be able to read compressed MSAA textures, but it doesn't work. */
> -               rscreen->msaa_texture_support = MSAA_TEXTURE_SAMPLE_ZERO;
> +               rscreen->msaa_texture_support = MSAA_TEXTURE_COMPRESSED;
>                 break;
>         default:
>                 rscreen->has_msaa = FALSE;
> diff --git a/src/gallium/drivers/r600/r600_resource.h b/src/gallium/drivers/r600/r600_resource.h
> index e20e942..d5df633 100644
> --- a/src/gallium/drivers/r600/r600_resource.h
> +++ b/src/gallium/drivers/r600/r600_resource.h
> @@ -84,7 +84,9 @@ struct r600_texture {
>         /* FMASK and CMASK can only be used with MSAA textures for now.
>          * MSAA textures cannot have mipmaps. */
>         unsigned                        fmask_offset, fmask_size, fmask_bank_height;
> -       unsigned                        cmask_offset, cmask_size, cmask_slice_tile_max;
> +       unsigned                        fmask_slice_tile_max;
> +       unsigned                        cmask_offset, cmask_size;
> +       unsigned                        cmask_slice_tile_max;
>
>         struct r600_resource            *htile;
>         /* use htile only for first level */
> @@ -97,6 +99,7 @@ struct r600_fmask_info {
>         unsigned size;
>         unsigned alignment;
>         unsigned bank_height;
> +       unsigned slice_tile_max;
>  };
>
>  struct r600_cmask_info {
> diff --git a/src/gallium/drivers/r600/r600_state.c b/src/gallium/drivers/r600/r600_state.c
> index 4e0e4a6..f0e3675 100644
> --- a/src/gallium/drivers/r600/r600_state.c
> +++ b/src/gallium/drivers/r600/r600_state.c
> @@ -1404,7 +1404,7 @@ static void r600_init_color_surface(struct r600_context *rctx,
>                 if (rtex->fmask_size) {
>                         color_info |= S_0280A0_TILE_MODE(V_0280A0_FRAG_ENABLE);
>                         surf->cb_color_fmask = rtex->fmask_offset >> 8;
> -                       surf->cb_color_mask |= S_028100_FMASK_TILE_MAX(slice);
> +                       surf->cb_color_mask |= S_028100_FMASK_TILE_MAX(rtex->fmask_slice_tile_max);
>                 } else { /* cmask only */
>                         color_info |= S_0280A0_TILE_MODE(V_0280A0_CLEAR_ENABLE);
>                 }
> @@ -1455,7 +1455,7 @@ static void r600_init_color_surface(struct r600_context *rctx,
>                 surf->cb_color_cmask = 0;
>                 surf->cb_color_fmask = 0;
>                 surf->cb_color_mask = S_028100_CMASK_BLOCK_MAX(cmask.slice_tile_max) |
> -                                     S_028100_FMASK_TILE_MAX(slice);
> +                                     S_028100_FMASK_TILE_MAX(fmask.slice_tile_max);
>         }
>
>         surf->cb_color_info = color_info;
> diff --git a/src/gallium/drivers/r600/r600_texture.c b/src/gallium/drivers/r600/r600_texture.c
> index 3a1f2fe..19afd65 100644
> --- a/src/gallium/drivers/r600/r600_texture.c
> +++ b/src/gallium/drivers/r600/r600_texture.c
> @@ -284,50 +284,51 @@ void r600_texture_get_fmask_info(struct r600_screen *rscreen,
>                                  unsigned nr_samples,
>                                  struct r600_fmask_info *out)
>  {
> -       /* FMASK is allocated pretty much like an ordinary texture.
> -        * Here we use bpe in the units of bits, not bytes. */
> +       /* FMASK is allocated like an ordinary texture. */
>         struct radeon_surface fmask = rtex->surface;
>
> +       memset(out, 0, sizeof(*out));
> +
> +       fmask.bo_alignment = 0;
> +       fmask.bo_size = 0;
> +       fmask.nsamples = 1;
> +       fmask.flags |= RADEON_SURF_FMASK;
> +
>         switch (nr_samples) {
>         case 2:
> -               /* This should be 8,1, but we should set nsamples > 1
> -                * for the allocator to treat it as a multisample surface.
> -                * Let's set 4,2 then. */
>         case 4:
> -               fmask.bpe = 4;
> -               fmask.nsamples = 2;
> +               fmask.bpe = 1;
> +               fmask.bankh = 4;
>                 break;
>         case 8:
> -               fmask.bpe = 8;
> -               fmask.nsamples = 4;
> -               break;
> -       case 16:
> -               fmask.bpe = 16;
> -               fmask.nsamples = 4;
> +               fmask.bpe = 4;
>                 break;
>         default:
>                 R600_ERR("Invalid sample count for FMASK allocation.\n");
>                 return;
>         }
>
> -       /* R600-R700 errata? Anyway, this fixes colorbuffer corruption. */
> +       /* Overallocate FMASK on R600-R700 to fix colorbuffer corruption.
> +        * This can be fixed by writing a separate FMASK allocator specifically
> +        * for R600-R700 asics. */
>         if (rscreen->chip_class <= R700) {
>                 fmask.bpe *= 2;
>         }
>
> -       if (rscreen->chip_class >= EVERGREEN) {
> -               fmask.bankh = nr_samples <= 4 ? 4 : 1;
> -       }
> -
>         if (rscreen->ws->surface_init(rscreen->ws, &fmask)) {
>                 R600_ERR("Got error in surface_init while allocating FMASK.\n");
>                 return;
>         }
> +
>         assert(fmask.level[0].mode == RADEON_SURF_MODE_2D);
>
> +       out->slice_tile_max = (fmask.level[0].nblk_x * fmask.level[0].nblk_y) / 64;
> +       if (out->slice_tile_max)
> +               out->slice_tile_max -= 1;
> +
>         out->bank_height = fmask.bankh;
>         out->alignment = MAX2(256, fmask.bo_alignment);
> -       out->size = (fmask.bo_size + 7) / 8;
> +       out->size = fmask.bo_size;
>  }
>
>  static void r600_texture_allocate_fmask(struct r600_screen *rscreen,
> @@ -339,6 +340,7 @@ static void r600_texture_allocate_fmask(struct r600_screen *rscreen,
>                                     rtex->resource.b.b.nr_samples, &fmask);
>
>         rtex->fmask_bank_height = fmask.bank_height;
> +       rtex->fmask_slice_tile_max = fmask.slice_tile_max;
>         rtex->fmask_offset = align(rtex->size, fmask.alignment);
>         rtex->fmask_size = fmask.size;
>         rtex->size = rtex->fmask_offset + rtex->fmask_size;
> --
> 1.7.10.4
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev


More information about the mesa-dev mailing list