r600g: rewrite FMASK allocation, fix FMASK texturing with 2 and 4 samples
authorMarek Olšák <maraeo@gmail.com>
Thu, 11 Apr 2013 12:54:40 +0000 (14:54 +0200)
committerMarek Olšák <maraeo@gmail.com>
Wed, 15 May 2013 18:19:45 +0000 (20:19 +0200)
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.

v2: require libdrm_radeon 2.4.45

Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
configure.ac
src/gallium/drivers/r600/evergreen_state.c
src/gallium/drivers/r600/evergreend.h
src/gallium/drivers/r600/r600_blit.c
src/gallium/drivers/r600/r600_pipe.c
src/gallium/drivers/r600/r600_resource.h
src/gallium/drivers/r600/r600_state.c
src/gallium/drivers/r600/r600_texture.c

index 5bc8c94a2ecc127b1418daad5a46a4f457ddd406..eef4327804c3992a850e2a727513dc8e1c6452ca 100644 (file)
@@ -31,7 +31,7 @@ AC_SUBST([OSMESA_VERSION])
 
 dnl Versions for external dependencies
 LIBDRM_REQUIRED=2.4.24
-LIBDRM_RADEON_REQUIRED=2.4.44
+LIBDRM_RADEON_REQUIRED=2.4.45
 LIBDRM_INTEL_REQUIRED=2.4.38
 LIBDRM_NVVIEUX_REQUIRED=2.4.33
 LIBDRM_NOUVEAU_REQUIRED="2.4.33 libdrm >= 2.4.41"
index 6797b22374211a4056e374ab71a001bef470c8d6..4eb976849c5b909cdcf8bd92c2aa08a3f9a84f49 100644 (file)
@@ -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;
index 757c9512e5f3b3c1556e7bf5424d1cb8c3c010f9..8990d6c3fadae1c09a9c43e6aa8d355609fe20d4 100644 (file)
 #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
index afe43896568c46cbb57946cc3bd2da3e2874d348..7d32eef89eea4e64765d70706b57526aa5a40824 100644 (file)
@@ -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:
index 47cdb9e49265c34aad73cc111b892eb6ad63c975..efb45010a191dbd0b74a7ec48959e143282e8abe 100644 (file)
@@ -1271,8 +1271,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;
index e20e94212059bb0adbfc3683c0773ce47f240d78..d5df63396ccd8a2bea544024aaedfa7e030df1e6 100644 (file)
@@ -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 {
index 4e0e4a6de6996ff9e2e60eeae7a4c10edcf98a42..f0e36753d2b6f090165f41baf2ac8fb2d695a29c 100644 (file)
@@ -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;
index 3a1f2fea831c65f07b059cc820d5901d3e7769d6..19afd65e2c8fbcd5ea74c37971e36427a4bf5482 100644 (file)
@@ -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;