From 61c995bc47b838317a4a62fba2ff2031bcb0c23e Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Thu, 11 Apr 2013 14:54:40 +0200 Subject: [PATCH] r600g: rewrite FMASK allocation, fix FMASK texturing with 2 and 4 samples 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 --- configure.ac | 2 +- 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 ++++++++++++++++-------------- 8 files changed, 43 insertions(+), 37 deletions(-) diff --git a/configure.ac b/configure.ac index 5bc8c94..eef4327 100644 --- a/configure.ac +++ b/configure.ac @@ -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" 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 47cdb9e..efb4501 100644 --- a/src/gallium/drivers/r600/r600_pipe.c +++ b/src/gallium/drivers/r600/r600_pipe.c @@ -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; 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; -- 2.7.4