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 <alexander.deucher@amd.com>
This commit is contained in:
parent
61506257f6
commit
61c995bc47
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue