From patchwork Wed Apr 10 22:20:32 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jerome Glisse X-Patchwork-Id: 2423831 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by patchwork1.kernel.org (Postfix) with ESMTP id 6A3F93FD8C for ; Wed, 10 Apr 2013 22:24:57 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 177A0E6560 for ; Wed, 10 Apr 2013 15:24:57 -0700 (PDT) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-qc0-f176.google.com (mail-qc0-f176.google.com [209.85.216.176]) by gabe.freedesktop.org (Postfix) with ESMTP id 6C4ECE5DC1 for ; Wed, 10 Apr 2013 15:23:55 -0700 (PDT) Received: by mail-qc0-f176.google.com with SMTP id n41so431322qco.35 for ; Wed, 10 Apr 2013 15:23:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=x-received:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references; bh=DGJL3HpsmiWzxB51wuQ5hHhlzX+GH2AO1Qg13NeILDI=; b=eLnhp+gGGp6lPLyjx4KoiPlkh+5/juP9gOM9/73p7aJTdGPjx928ynfNAvVxY63xes Ja9pGbVfSw0TRGdmZ2oQkt53Si/8yb6L22edI1VluZtdTeGt8+iaqmD6iUOas7huuDTW yUYsTaSOfeTlfzgBK6bfL88KevfRjpvZ6yx+LOiuPpKYFuIQZb7u4hj0F3D83Qf+B9oZ jpr7jF4MKpZovt/v+RKrdEvXWQcnysVaKLuC0lA7Wjf+C9ag/KQWgp2Q7mBN3SGPLoz9 /AYDQqec12ksGmD2uFrTG3WjkhuZhgoo3STbIvuCdxeMKN03j8+MYhaFpTaJGXJ3FsWu UKtg== X-Received: by 10.224.79.18 with SMTP id n18mr4636716qak.85.1365632635094; Wed, 10 Apr 2013 15:23:55 -0700 (PDT) Received: from localhost.boston.devel.redhat.com ([66.187.233.206]) by mx.google.com with ESMTPS id j6sm2749829qek.8.2013.04.10.15.23.54 (version=TLSv1 cipher=RC4-SHA bits=128/128); Wed, 10 Apr 2013 15:23:54 -0700 (PDT) From: j.glisse@gmail.com To: dri-devel@lists.freedesktop.org Subject: [PATCH 2/2] radeon: add si tiling support v5 Date: Wed, 10 Apr 2013 18:20:32 -0400 Message-Id: <1365632432-5078-2-git-send-email-j.glisse@gmail.com> X-Mailer: git-send-email 1.7.11.7 In-Reply-To: <1365632432-5078-1-git-send-email-j.glisse@gmail.com> References: <1365632432-5078-1-git-send-email-j.glisse@gmail.com> Cc: Jerome Glisse X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org Errors-To: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org From: Jerome Glisse v2: Only writte tile index if flags for it is set v3: Remove useless allow2d scanout flags v4: Split radeon_drm.h update to its own patch v5: update against lastest next tree for radeon Signed-off-by: Jerome Glisse Reviewed-by: Michel Dänzer --- radeon/radeon_surface.c | 658 ++++++++++++++++++++++++++++++++++++++++++++---- radeon/radeon_surface.h | 31 +++ 2 files changed, 644 insertions(+), 45 deletions(-) diff --git a/radeon/radeon_surface.c b/radeon/radeon_surface.c index 5935c23..288b5e2 100644 --- a/radeon/radeon_surface.c +++ b/radeon/radeon_surface.c @@ -83,12 +83,14 @@ typedef int (*hw_best_surface_t)(struct radeon_surface_manager *surf_man, struct radeon_hw_info { /* apply to r6, eg */ - uint32_t group_bytes; - uint32_t num_banks; - uint32_t num_pipes; + uint32_t group_bytes; + uint32_t num_banks; + uint32_t num_pipes; /* apply to eg */ - uint32_t row_size; - unsigned allow_2d; + uint32_t row_size; + unsigned allow_2d; + /* apply to si */ + uint32_t tile_mode_array[32]; }; struct radeon_surface_manager { @@ -1000,12 +1002,403 @@ static int eg_surface_best(struct radeon_surface_manager *surf_man, /* =========================================================================== * Southern Islands family */ +#define SI__GB_TILE_MODE__PIPE_CONFIG(x) (((x) >> 6) & 0x1f) +#define SI__PIPE_CONFIG__ADDR_SURF_P2 0 +#define SI__PIPE_CONFIG__ADDR_SURF_P4_8x16 4 +#define SI__PIPE_CONFIG__ADDR_SURF_P4_16x16 5 +#define SI__PIPE_CONFIG__ADDR_SURF_P4_16x32 6 +#define SI__PIPE_CONFIG__ADDR_SURF_P4_32x32 7 +#define SI__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16 8 +#define SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16 9 +#define SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16 10 +#define SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16 11 +#define SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16 12 +#define SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32 13 +#define SI__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32 14 +#define SI__GB_TILE_MODE__TILE_SPLIT(x) (((x) >> 11) & 0x7) +#define SI__TILE_SPLIT__64B 0 +#define SI__TILE_SPLIT__128B 1 +#define SI__TILE_SPLIT__256B 2 +#define SI__TILE_SPLIT__512B 3 +#define SI__TILE_SPLIT__1024B 4 +#define SI__TILE_SPLIT__2048B 5 +#define SI__TILE_SPLIT__4096B 6 +#define SI__GB_TILE_MODE__BANK_WIDTH(x) (((x) >> 14) & 0x3) +#define SI__BANK_WIDTH__1 0 +#define SI__BANK_WIDTH__2 1 +#define SI__BANK_WIDTH__4 2 +#define SI__BANK_WIDTH__8 3 +#define SI__GB_TILE_MODE__BANK_HEIGHT(x) (((x) >> 16) & 0x3) +#define SI__BANK_HEIGHT__1 0 +#define SI__BANK_HEIGHT__2 1 +#define SI__BANK_HEIGHT__4 2 +#define SI__BANK_HEIGHT__8 3 +#define SI__GB_TILE_MODE__MACRO_TILE_ASPECT(x) (((x) >> 18) & 0x3) +#define SI__MACRO_TILE_ASPECT__1 0 +#define SI__MACRO_TILE_ASPECT__2 1 +#define SI__MACRO_TILE_ASPECT__4 2 +#define SI__MACRO_TILE_ASPECT__8 3 +#define SI__GB_TILE_MODE__NUM_BANKS(x) (((x) >> 20) & 0x3) +#define SI__NUM_BANKS__2_BANK 0 +#define SI__NUM_BANKS__4_BANK 1 +#define SI__NUM_BANKS__8_BANK 2 +#define SI__NUM_BANKS__16_BANK 3 + + +static void si_gb_tile_mode(uint32_t gb_tile_mode, + unsigned *num_pipes, + unsigned *num_banks, + uint32_t *macro_tile_aspect, + uint32_t *bank_w, + uint32_t *bank_h, + uint32_t *tile_split) +{ + if (num_pipes) { + switch (SI__GB_TILE_MODE__PIPE_CONFIG(gb_tile_mode)) { + case SI__PIPE_CONFIG__ADDR_SURF_P2: + default: + *num_pipes = 2; + break; + case SI__PIPE_CONFIG__ADDR_SURF_P4_8x16: + case SI__PIPE_CONFIG__ADDR_SURF_P4_16x16: + case SI__PIPE_CONFIG__ADDR_SURF_P4_16x32: + case SI__PIPE_CONFIG__ADDR_SURF_P4_32x32: + *num_pipes = 4; + break; + case SI__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16: + case SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16: + case SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16: + case SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16: + case SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16: + case SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32: + case SI__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32: + *num_pipes = 8; + break; + } + } + if (num_banks) { + switch (SI__GB_TILE_MODE__NUM_BANKS(gb_tile_mode)) { + default: + case SI__NUM_BANKS__2_BANK: + *num_banks = 2; + break; + case SI__NUM_BANKS__4_BANK: + *num_banks = 4; + break; + case SI__NUM_BANKS__8_BANK: + *num_banks = 8; + break; + case SI__NUM_BANKS__16_BANK: + *num_banks = 16; + break; + } + } + if (macro_tile_aspect) { + switch (SI__GB_TILE_MODE__MACRO_TILE_ASPECT(gb_tile_mode)) { + default: + case SI__MACRO_TILE_ASPECT__1: + *macro_tile_aspect = 1; + break; + case SI__MACRO_TILE_ASPECT__2: + *macro_tile_aspect = 2; + break; + case SI__MACRO_TILE_ASPECT__4: + *macro_tile_aspect = 4; + break; + case SI__MACRO_TILE_ASPECT__8: + *macro_tile_aspect = 8; + break; + } + } + if (bank_w) { + switch (SI__GB_TILE_MODE__BANK_WIDTH(gb_tile_mode)) { + default: + case SI__BANK_WIDTH__1: + *bank_w = 1; + break; + case SI__BANK_WIDTH__2: + *bank_w = 2; + break; + case SI__BANK_WIDTH__4: + *bank_w = 4; + break; + case SI__BANK_WIDTH__8: + *bank_w = 8; + break; + } + } + if (bank_h) { + switch (SI__GB_TILE_MODE__BANK_HEIGHT(gb_tile_mode)) { + default: + case SI__BANK_HEIGHT__1: + *bank_h = 1; + break; + case SI__BANK_HEIGHT__2: + *bank_h = 2; + break; + case SI__BANK_HEIGHT__4: + *bank_h = 4; + break; + case SI__BANK_HEIGHT__8: + *bank_h = 8; + break; + } + } + if (tile_split) { + switch (SI__GB_TILE_MODE__TILE_SPLIT(gb_tile_mode)) { + default: + case SI__TILE_SPLIT__64B: + *tile_split = 64; + break; + case SI__TILE_SPLIT__128B: + *tile_split = 128; + break; + case SI__TILE_SPLIT__256B: + *tile_split = 256; + break; + case SI__TILE_SPLIT__512B: + *tile_split = 512; + break; + case SI__TILE_SPLIT__1024B: + *tile_split = 1024; + break; + case SI__TILE_SPLIT__2048B: + *tile_split = 2048; + break; + case SI__TILE_SPLIT__4096B: + *tile_split = 4096; + break; + } + } +} + +static int si_init_hw_info(struct radeon_surface_manager *surf_man) +{ + uint32_t tiling_config; + drmVersionPtr version; + int r; + + r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG, + &tiling_config); + if (r) { + return r; + } + + surf_man->hw_info.allow_2d = 0; + version = drmGetVersion(surf_man->fd); + if (version && version->version_minor >= 33) { + if (!radeon_get_value(surf_man->fd, RADEON_INFO_SI_TILE_MODE_ARRAY, surf_man->hw_info.tile_mode_array)) { + surf_man->hw_info.allow_2d = 1; + } + } + drmFreeVersion(version); + + switch (tiling_config & 0xf) { + case 0: + surf_man->hw_info.num_pipes = 1; + break; + case 1: + surf_man->hw_info.num_pipes = 2; + break; + case 2: + surf_man->hw_info.num_pipes = 4; + break; + case 3: + surf_man->hw_info.num_pipes = 8; + break; + default: + surf_man->hw_info.num_pipes = 8; + surf_man->hw_info.allow_2d = 0; + break; + } + + switch ((tiling_config & 0xf0) >> 4) { + case 0: + surf_man->hw_info.num_banks = 4; + break; + case 1: + surf_man->hw_info.num_banks = 8; + break; + case 2: + surf_man->hw_info.num_banks = 16; + break; + default: + surf_man->hw_info.num_banks = 8; + surf_man->hw_info.allow_2d = 0; + break; + } + + switch ((tiling_config & 0xf00) >> 8) { + case 0: + surf_man->hw_info.group_bytes = 256; + break; + case 1: + surf_man->hw_info.group_bytes = 512; + break; + default: + surf_man->hw_info.group_bytes = 256; + surf_man->hw_info.allow_2d = 0; + break; + } + + switch ((tiling_config & 0xf000) >> 12) { + case 0: + surf_man->hw_info.row_size = 1024; + break; + case 1: + surf_man->hw_info.row_size = 2048; + break; + case 2: + surf_man->hw_info.row_size = 4096; + break; + default: + surf_man->hw_info.row_size = 4096; + surf_man->hw_info.allow_2d = 0; + break; + } + return 0; +} + +static int si_surface_sanity(struct radeon_surface_manager *surf_man, + struct radeon_surface *surf, + unsigned mode, unsigned *tile_mode, unsigned *stencil_tile_mode) +{ + uint32_t gb_tile_mode; + + /* check surface dimension */ + if (surf->npix_x > 16384 || surf->npix_y > 16384 || surf->npix_z > 16384) { + return -EINVAL; + } + + /* check mipmap last_level */ + if (surf->last_level > 15) { + return -EINVAL; + } + + /* force 1d on kernel that can't do 2d */ + if (mode > RADEON_SURF_MODE_1D && + (!surf_man->hw_info.allow_2d || !(surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX))) { + if (surf->nsamples > 1) { + fprintf(stderr, "radeon: Cannot use 1D tiling for an MSAA surface (%i).\n", __LINE__); + return -EFAULT; + } + mode = RADEON_SURF_MODE_1D; + surf->flags = RADEON_SURF_CLR(surf->flags, MODE); + surf->flags |= RADEON_SURF_SET(mode, MODE); + } + + if (surf->nsamples > 1 && mode != RADEON_SURF_MODE_2D) { + return -EINVAL; + } + + if (!surf->tile_split) { + /* default value */ + surf->mtilea = 1; + surf->bankw = 1; + surf->bankw = 1; + surf->tile_split = 64; + surf->stencil_tile_split = 64; + } + + switch (mode) { + case RADEON_SURF_MODE_2D: + if (surf->flags & RADEON_SURF_SBUFFER) { + switch (surf->nsamples) { + case 1: + *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D; + break; + case 2: + *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_2AA; + break; + case 4: + *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_4AA; + break; + case 8: + *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_8AA; + break; + default: + return -EINVAL; + } + /* retrieve tiling mode value */ + gb_tile_mode = surf_man->hw_info.tile_mode_array[*stencil_tile_mode]; + si_gb_tile_mode(gb_tile_mode, NULL, NULL, NULL, NULL, NULL, &surf->stencil_tile_split); + } + if (surf->flags & RADEON_SURF_ZBUFFER) { + switch (surf->nsamples) { + case 1: + *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D; + break; + case 2: + *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_2AA; + break; + case 4: + *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_4AA; + break; + case 8: + *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_8AA; + break; + default: + return -EINVAL; + } + } else if (surf->flags & RADEON_SURF_SCANOUT) { + switch (surf->bpe) { + case 2: + *tile_mode = SI_TILE_MODE_COLOR_2D_SCANOUT_16BPP; + break; + case 4: + *tile_mode = SI_TILE_MODE_COLOR_2D_SCANOUT_32BPP; + break; + default: + return -EINVAL; + } + } else { + switch (surf->bpe) { + case 1: + *tile_mode = SI_TILE_MODE_COLOR_2D_8BPP; + break; + case 2: + *tile_mode = SI_TILE_MODE_COLOR_2D_16BPP; + break; + case 4: + *tile_mode = SI_TILE_MODE_COLOR_2D_32BPP; + break; + case 8: + case 16: + *tile_mode = SI_TILE_MODE_COLOR_2D_64BPP; + break; + default: + return -EINVAL; + } + } + /* retrieve tiling mode value */ + gb_tile_mode = surf_man->hw_info.tile_mode_array[*tile_mode]; + si_gb_tile_mode(gb_tile_mode, NULL, NULL, &surf->mtilea, &surf->bankw, &surf->bankh, &surf->tile_split); + break; + case RADEON_SURF_MODE_1D: + if (surf->flags & RADEON_SURF_SBUFFER) { + *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D; + } + if (surf->flags & RADEON_SURF_ZBUFFER) { + *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D; + } else if (surf->flags & RADEON_SURF_SCANOUT) { + *tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT; + } else { + *tile_mode = SI_TILE_MODE_COLOR_1D; + } + break; + case RADEON_SURF_MODE_LINEAR_ALIGNED: + default: + *tile_mode = SI_TILE_MODE_COLOR_LINEAR_ALIGNED; + } + + return 0; +} static void si_surf_minify(struct radeon_surface *surf, - struct radeon_surface_level *surflevel, - unsigned bpe, unsigned level, - uint32_t xalign, uint32_t yalign, uint32_t zalign, uint32_t slice_align, - unsigned offset) + struct radeon_surface_level *surflevel, + unsigned bpe, unsigned level, + uint32_t xalign, uint32_t yalign, uint32_t zalign, + uint32_t slice_align, unsigned offset) { surflevel->npix_x = mip_minify(surf->npix_x, level); surflevel->npix_y = mip_minify(surf->npix_y, level); @@ -1043,8 +1436,52 @@ static void si_surf_minify(struct radeon_surface *surf, surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size; } +static void si_surf_minify_2d(struct radeon_surface *surf, + struct radeon_surface_level *surflevel, + unsigned bpe, unsigned level, unsigned slice_pt, + uint32_t xalign, uint32_t yalign, uint32_t zalign, + unsigned mtileb, unsigned offset) +{ + unsigned mtile_pr, mtile_ps; + + surflevel->npix_x = mip_minify(surf->npix_x, level); + surflevel->npix_y = mip_minify(surf->npix_y, level); + surflevel->npix_z = mip_minify(surf->npix_z, level); + + if (level == 0 && surf->last_level > 0) { + surflevel->nblk_x = (next_power_of_two(surflevel->npix_x) + surf->blk_w - 1) / surf->blk_w; + surflevel->nblk_y = (next_power_of_two(surflevel->npix_y) + surf->blk_h - 1) / surf->blk_h; + surflevel->nblk_z = (next_power_of_two(surflevel->npix_z) + surf->blk_d - 1) / surf->blk_d; + } else { + surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w; + surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h; + surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d; + } + + if (surf->nsamples == 1 && surflevel->mode == RADEON_SURF_MODE_2D) { + if (surflevel->nblk_x < xalign || surflevel->nblk_y < yalign) { + surflevel->mode = RADEON_SURF_MODE_1D; + return; + } + } + surflevel->nblk_x = ALIGN(surflevel->nblk_x, xalign); + surflevel->nblk_y = ALIGN(surflevel->nblk_y, yalign); + surflevel->nblk_z = ALIGN(surflevel->nblk_z, zalign); + + /* macro tile per row */ + mtile_pr = surflevel->nblk_x / xalign; + /* macro tile per slice */ + mtile_ps = (mtile_pr * surflevel->nblk_y) / yalign; + surflevel->offset = offset; + surflevel->pitch_bytes = surflevel->nblk_x * bpe * slice_pt; + surflevel->slice_size = mtile_ps * mtileb * slice_pt; + + surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size; +} + static int si_surface_init_linear_aligned(struct radeon_surface_manager *surf_man, struct radeon_surface *surf, + unsigned tile_mode, uint64_t offset, unsigned start_level) { uint32_t xalign, yalign, zalign, slice_align; @@ -1062,13 +1499,15 @@ static int si_surface_init_linear_aligned(struct radeon_surface_manager *surf_ma /* build mipmap tree */ for (i = start_level; i <= surf->last_level; i++) { surf->level[i].mode = RADEON_SURF_MODE_LINEAR_ALIGNED; - si_surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, - zalign, slice_align, offset); + si_surf_minify(surf, surf->level+i, surf->bpe, 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); } + if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) { + surf->tiling_index[i] = tile_mode; + } } return 0; } @@ -1076,7 +1515,7 @@ static int si_surface_init_linear_aligned(struct radeon_surface_manager *surf_ma static int si_surface_init_1d(struct radeon_surface_manager *surf_man, struct radeon_surface *surf, struct radeon_surface_level *level, - unsigned bpe, + unsigned bpe, unsigned tile_mode, uint64_t offset, unsigned start_level) { uint32_t xalign, yalign, zalign, slice_align; @@ -1092,11 +1531,10 @@ static int si_surface_init_1d(struct radeon_surface_manager *surf_man, } if (!start_level) { - unsigned alignment = MAX2(256, surf_man->hw_info.group_bytes); - surf->bo_alignment = MAX2(surf->bo_alignment, alignment); + surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes); if (offset) { - offset = ALIGN(offset, alignment); + offset = ALIGN(offset, surf->bo_alignment); } } @@ -1109,28 +1547,140 @@ static int si_surface_init_1d(struct radeon_surface_manager *surf_man, if ((i == 0)) { offset = ALIGN(offset, surf->bo_alignment); } + if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) { + if (surf->level == level) { + surf->tiling_index[i] = tile_mode; + /* it's ok because stencil is done after */ + surf->stencil_tiling_index[i] = tile_mode; + } else { + surf->stencil_tiling_index[i] = tile_mode; + } + } } return 0; } static int si_surface_init_1d_miptrees(struct radeon_surface_manager *surf_man, - struct radeon_surface *surf) + struct radeon_surface *surf, + unsigned tile_mode, unsigned stencil_tile_mode) { - unsigned zs_flags = RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER; - int r, is_depth_stencil = (surf->flags & zs_flags) == zs_flags; - /* Old libdrm headers didn't have stencil_level in it. This prevents crashes. */ - struct radeon_surface_level tmp[RADEON_SURF_MAX_LEVEL]; - struct radeon_surface_level *stencil_level = - (surf->flags & RADEON_SURF_HAS_SBUFFER_MIPTREE) ? surf->stencil_level : tmp; + int r; - r = si_surface_init_1d(surf_man, surf, surf->level, surf->bpe, 0, 0); - if (r) + r = si_surface_init_1d(surf_man, surf, surf->level, surf->bpe, tile_mode, 0, 0); + if (r) { return r; + } - if (is_depth_stencil) { - r = si_surface_init_1d(surf_man, surf, stencil_level, 1, - surf->bo_size, 0); - surf->stencil_offset = stencil_level[0].offset; + if (surf->flags & RADEON_SURF_SBUFFER) { + r = si_surface_init_1d(surf_man, surf, surf->stencil_level, 1, stencil_tile_mode, surf->bo_size, 0); + surf->stencil_offset = surf->stencil_level[0].offset; + } + return r; +} + +static int si_surface_init_2d(struct radeon_surface_manager *surf_man, + struct radeon_surface *surf, + struct radeon_surface_level *level, + unsigned bpe, unsigned tile_mode, + unsigned num_pipes, unsigned num_banks, + unsigned tile_split, + uint64_t offset, + unsigned start_level) +{ + unsigned tilew, tileh, tileb; + unsigned mtilew, mtileh, mtileb; + unsigned slice_pt; + unsigned i; + + /* compute tile values */ + tilew = 8; + tileh = 8; + tileb = tilew * tileh * bpe * surf->nsamples; + /* slices per tile */ + slice_pt = 1; + if (tileb > tile_split) { + slice_pt = tileb / tile_split; + } + tileb = tileb / slice_pt; + + /* macro tile width & height */ + mtilew = (tilew * surf->bankw * num_pipes) * surf->mtilea; + mtileh = (tileh * surf->bankh * num_banks) / surf->mtilea; + + /* macro tile bytes */ + mtileb = (mtilew / tilew) * (mtileh / tileh) * tileb; + + if (!start_level) { + unsigned alignment = MAX2(256, mtileb); + surf->bo_alignment = MAX2(surf->bo_alignment, alignment); + + if (offset) { + offset = ALIGN(offset, alignment); + } + } + + /* build mipmap tree */ + for (i = start_level; i <= surf->last_level; i++) { + level[i].mode = RADEON_SURF_MODE_2D; + si_surf_minify_2d(surf, level+i, bpe, i, slice_pt, mtilew, mtileh, 1, mtileb, offset); + if (level[i].mode == RADEON_SURF_MODE_1D) { + switch (tile_mode) { + case SI_TILE_MODE_COLOR_2D_8BPP: + case SI_TILE_MODE_COLOR_2D_16BPP: + case SI_TILE_MODE_COLOR_2D_32BPP: + case SI_TILE_MODE_COLOR_2D_64BPP: + tile_mode = SI_TILE_MODE_COLOR_1D; + break; + case SI_TILE_MODE_COLOR_2D_SCANOUT_16BPP: + case SI_TILE_MODE_COLOR_2D_SCANOUT_32BPP: + tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT; + break; + case SI_TILE_MODE_DEPTH_STENCIL_2D: + tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D; + break; + default: + return -EINVAL; + } + return si_surface_init_1d(surf_man, surf, level, bpe, tile_mode, offset, i); + } + /* level0 and first mipmap need to have alignment */ + offset = surf->bo_size; + if ((i == 0)) { + offset = ALIGN(offset, surf->bo_alignment); + } + if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) { + if (surf->level == level) { + surf->tiling_index[i] = tile_mode; + /* it's ok because stencil is done after */ + surf->stencil_tiling_index[i] = tile_mode; + } else { + surf->stencil_tiling_index[i] = tile_mode; + } + } + } + return 0; +} + +static int si_surface_init_2d_miptrees(struct radeon_surface_manager *surf_man, + struct radeon_surface *surf, + unsigned tile_mode, unsigned stencil_tile_mode) +{ + unsigned num_pipes, num_banks; + uint32_t gb_tile_mode; + int r; + + /* retrieve tiling mode value */ + gb_tile_mode = surf_man->hw_info.tile_mode_array[tile_mode]; + si_gb_tile_mode(gb_tile_mode, &num_pipes, &num_banks, NULL, NULL, NULL, NULL); + + r = si_surface_init_2d(surf_man, surf, surf->level, surf->bpe, tile_mode, num_pipes, num_banks, surf->tile_split, 0, 0); + if (r) { + return r; + } + + if (surf->flags & RADEON_SURF_SBUFFER) { + r = si_surface_init_2d(surf_man, surf, surf->stencil_level, 1, stencil_tile_mode, num_pipes, num_banks, surf->stencil_tile_split, surf->bo_size, 0); + surf->stencil_offset = surf->stencil_level[0].offset; } return r; } @@ -1138,7 +1688,7 @@ static int si_surface_init_1d_miptrees(struct radeon_surface_manager *surf_man, static int si_surface_init(struct radeon_surface_manager *surf_man, struct radeon_surface *surf) { - unsigned mode; + unsigned mode, tile_mode, stencil_tile_mode; int r; /* MSAA surfaces support the 2D mode only. */ @@ -1150,12 +1700,6 @@ static int si_surface_init(struct radeon_surface_manager *surf_man, /* tiling mode */ mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK; - /* those are already handled by the kernel tile mode array but we still - * need value that won't be rejected by kernel set tiling function - */ - surf->tile_split = 0; - surf->stencil_tile_split = 0; - if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) { /* zbuffer only support 1D or 2D tiled surface */ switch (mode) { @@ -1170,7 +1714,7 @@ static int si_surface_init(struct radeon_surface_manager *surf_man, } } - r = eg_surface_sanity(surf_man, surf, mode); + r = si_surface_sanity(surf_man, surf, mode, &tile_mode, &stencil_tile_mode); if (r) { return r; } @@ -1184,13 +1728,13 @@ static int si_surface_init(struct radeon_surface_manager *surf_man, 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); + r = si_surface_init_linear_aligned(surf_man, surf, tile_mode, 0, 0); break; case RADEON_SURF_MODE_1D: - r = si_surface_init_1d_miptrees(surf_man, surf); + r = si_surface_init_1d_miptrees(surf_man, surf, tile_mode, stencil_tile_mode); break; case RADEON_SURF_MODE_2D: - r = eg_surface_init_2d_miptrees(surf_man, surf); + r = si_surface_init_2d_miptrees(surf_man, surf, tile_mode, stencil_tile_mode); break; default: return -EINVAL; @@ -1198,6 +1742,28 @@ static int si_surface_init(struct radeon_surface_manager *surf_man, return r; } +/* + * depending on surface + */ +static int si_surface_best(struct radeon_surface_manager *surf_man, + struct radeon_surface *surf) +{ + unsigned mode, tile_mode, stencil_tile_mode; + + /* tiling mode */ + mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK; + + if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER) && + !(surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX)) { + /* depth/stencil force 1d tiling for old mesa */ + surf->flags = RADEON_SURF_CLR(surf->flags, MODE); + surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE); + } + + return si_surface_sanity(surf_man, surf, mode, &tile_mode, &stencil_tile_mode); +} + + /* =========================================================================== * public API */ @@ -1223,16 +1789,18 @@ struct radeon_surface_manager *radeon_surface_manager_new(int fd) } surf_man->surface_init = &r6_surface_init; surf_man->surface_best = &r6_surface_best; - } else { + } else if (surf_man->family <= CHIP_ARUBA) { if (eg_init_hw_info(surf_man)) { goto out_err; } - if (surf_man->family <= CHIP_ARUBA) { - surf_man->surface_init = &eg_surface_init; - } else { - surf_man->surface_init = &si_surface_init; - } + surf_man->surface_init = &eg_surface_init; surf_man->surface_best = &eg_surface_best; + } else { + if (si_init_hw_info(surf_man)) { + goto out_err; + } + surf_man->surface_init = &si_surface_init; + surf_man->surface_best = &si_surface_best; } return surf_man; diff --git a/radeon/radeon_surface.h b/radeon/radeon_surface.h index ed4b994..2babfd7 100644 --- a/radeon/radeon_surface.h +++ b/radeon/radeon_surface.h @@ -55,6 +55,7 @@ #define RADEON_SURF_ZBUFFER (1 << 17) #define RADEON_SURF_SBUFFER (1 << 18) #define RADEON_SURF_HAS_SBUFFER_MIPTREE (1 << 19) +#define RADEON_SURF_HAS_TILE_MODE_INDEX (1 << 20) #define RADEON_SURF_GET(v, field) (((v) >> RADEON_SURF_ ## field ## _SHIFT) & RADEON_SURF_ ## field ## _MASK) #define RADEON_SURF_SET(v, field) (((v) & RADEON_SURF_ ## field ## _MASK) << RADEON_SURF_ ## field ## _SHIFT) @@ -76,6 +77,34 @@ struct radeon_surface_level { uint32_t mode; }; +enum si_tiling_mode { + SI_TILING_AUTO = 0, + + SI_TILING_COLOR_1D, + SI_TILING_COLOR_1D_SCANOUT, + SI_TILING_COLOR_2D_8BPP, + SI_TILING_COLOR_2D_16BPP, + SI_TILING_COLOR_2D_32BPP, + SI_TILING_COLOR_2D_64BPP, + SI_TILING_COLOR_2D_SCANOUT_16BPP, + SI_TILING_COLOR_2D_SCANOUT_32BPP, + SI_TILING_COLOR_LINEAR, + + SI_TILING_STENCIL_1D, + SI_TILING_STENCIL_2D, + SI_TILING_STENCIL_2D_2AA, + SI_TILING_STENCIL_2D_4AA, + SI_TILING_STENCIL_2D_8AA, + + SI_TILING_DEPTH_1D, + SI_TILING_DEPTH_2D, + SI_TILING_DEPTH_2D_2AA, + SI_TILING_DEPTH_2D_4AA, + SI_TILING_DEPTH_2D_8AA, + + SI_TILING_LAST_MODE, +}; + struct radeon_surface { uint32_t npix_x; uint32_t npix_y; @@ -104,6 +133,8 @@ struct radeon_surface { uint64_t stencil_offset; struct radeon_surface_level level[RADEON_SURF_MAX_LEVEL]; struct radeon_surface_level stencil_level[RADEON_SURF_MAX_LEVEL]; + uint32_t tiling_index[RADEON_SURF_MAX_LEVEL]; + uint32_t stencil_tiling_index[RADEON_SURF_MAX_LEVEL]; }; struct radeon_surface_manager *radeon_surface_manager_new(int fd);