diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/amd/common/ac_surface.c | 430 | ||||
-rw-r--r-- | src/amd/common/ac_surface.h | 24 | ||||
-rw-r--r-- | src/gallium/winsys/amdgpu/drm/amdgpu_surface.c | 427 |
3 files changed, 470 insertions, 411 deletions
diff --git a/src/amd/common/ac_surface.c b/src/amd/common/ac_surface.c index 6cfa99625e8..cf741049db8 100644 --- a/src/amd/common/ac_surface.c +++ b/src/amd/common/ac_surface.c @@ -33,6 +33,7 @@ #include <stdio.h> #include <stdlib.h> #include <amdgpu.h> +#include <amdgpu_drm.h> #include "addrlib/addrinterface.h" @@ -200,3 +201,432 @@ ADDR_HANDLE amdgpu_addr_create(enum radeon_family family, return addrCreateOutput.hLib; } + +static int gfx6_compute_level(ADDR_HANDLE addrlib, + const struct ac_surf_config *config, + struct radeon_surf *surf, bool is_stencil, + unsigned level, bool compressed, + ADDR_COMPUTE_SURFACE_INFO_INPUT *AddrSurfInfoIn, + ADDR_COMPUTE_SURFACE_INFO_OUTPUT *AddrSurfInfoOut, + ADDR_COMPUTE_DCCINFO_INPUT *AddrDccIn, + ADDR_COMPUTE_DCCINFO_OUTPUT *AddrDccOut, + ADDR_COMPUTE_HTILE_INFO_INPUT *AddrHtileIn, + ADDR_COMPUTE_HTILE_INFO_OUTPUT *AddrHtileOut) +{ + struct legacy_surf_level *surf_level; + ADDR_E_RETURNCODE ret; + + AddrSurfInfoIn->mipLevel = level; + AddrSurfInfoIn->width = u_minify(config->info.width, level); + AddrSurfInfoIn->height = u_minify(config->info.height, level); + + if (config->is_3d) + AddrSurfInfoIn->numSlices = u_minify(config->info.depth, level); + else if (config->is_cube) + AddrSurfInfoIn->numSlices = 6; + else + AddrSurfInfoIn->numSlices = config->info.array_size; + + if (level > 0) { + /* Set the base level pitch. This is needed for calculation + * of non-zero levels. */ + if (is_stencil) + AddrSurfInfoIn->basePitch = surf->u.legacy.stencil_level[0].nblk_x; + else + AddrSurfInfoIn->basePitch = surf->u.legacy.level[0].nblk_x; + + /* Convert blocks to pixels for compressed formats. */ + if (compressed) + AddrSurfInfoIn->basePitch *= surf->blk_w; + } + + ret = AddrComputeSurfaceInfo(addrlib, + AddrSurfInfoIn, + AddrSurfInfoOut); + if (ret != ADDR_OK) { + return ret; + } + + surf_level = is_stencil ? &surf->u.legacy.stencil_level[level] : &surf->u.legacy.level[level]; + surf_level->offset = align64(surf->surf_size, AddrSurfInfoOut->baseAlign); + surf_level->slice_size = AddrSurfInfoOut->sliceSize; + surf_level->nblk_x = AddrSurfInfoOut->pitch; + surf_level->nblk_y = AddrSurfInfoOut->height; + + switch (AddrSurfInfoOut->tileMode) { + case ADDR_TM_LINEAR_ALIGNED: + surf_level->mode = RADEON_SURF_MODE_LINEAR_ALIGNED; + break; + case ADDR_TM_1D_TILED_THIN1: + surf_level->mode = RADEON_SURF_MODE_1D; + break; + case ADDR_TM_2D_TILED_THIN1: + surf_level->mode = RADEON_SURF_MODE_2D; + break; + default: + assert(0); + } + + if (is_stencil) + surf->u.legacy.stencil_tiling_index[level] = AddrSurfInfoOut->tileIndex; + else + surf->u.legacy.tiling_index[level] = AddrSurfInfoOut->tileIndex; + + surf->surf_size = surf_level->offset + AddrSurfInfoOut->surfSize; + + /* Clear DCC fields at the beginning. */ + surf_level->dcc_offset = 0; + + /* The previous level's flag tells us if we can use DCC for this level. */ + if (AddrSurfInfoIn->flags.dccCompatible && + (level == 0 || AddrDccOut->subLvlCompressible)) { + AddrDccIn->colorSurfSize = AddrSurfInfoOut->surfSize; + AddrDccIn->tileMode = AddrSurfInfoOut->tileMode; + AddrDccIn->tileInfo = *AddrSurfInfoOut->pTileInfo; + AddrDccIn->tileIndex = AddrSurfInfoOut->tileIndex; + AddrDccIn->macroModeIndex = AddrSurfInfoOut->macroModeIndex; + + ret = AddrComputeDccInfo(addrlib, + AddrDccIn, + AddrDccOut); + + if (ret == ADDR_OK) { + surf_level->dcc_offset = surf->dcc_size; + surf_level->dcc_fast_clear_size = AddrDccOut->dccFastClearSize; + surf->num_dcc_levels = level + 1; + surf->dcc_size = surf_level->dcc_offset + AddrDccOut->dccRamSize; + surf->dcc_alignment = MAX2(surf->dcc_alignment, AddrDccOut->dccRamBaseAlign); + } + } + + /* TC-compatible HTILE. */ + if (!is_stencil && + AddrSurfInfoIn->flags.depth && + AddrSurfInfoIn->flags.tcCompatible && + surf_level->mode == RADEON_SURF_MODE_2D && + level == 0) { + AddrHtileIn->flags.tcCompatible = 1; + AddrHtileIn->pitch = AddrSurfInfoOut->pitch; + AddrHtileIn->height = AddrSurfInfoOut->height; + AddrHtileIn->numSlices = AddrSurfInfoOut->depth; + AddrHtileIn->blockWidth = ADDR_HTILE_BLOCKSIZE_8; + AddrHtileIn->blockHeight = ADDR_HTILE_BLOCKSIZE_8; + AddrHtileIn->pTileInfo = AddrSurfInfoOut->pTileInfo; + AddrHtileIn->tileIndex = AddrSurfInfoOut->tileIndex; + AddrHtileIn->macroModeIndex = AddrSurfInfoOut->macroModeIndex; + + ret = AddrComputeHtileInfo(addrlib, + AddrHtileIn, + AddrHtileOut); + + if (ret == ADDR_OK) { + surf->htile_size = AddrHtileOut->htileBytes; + surf->htile_alignment = AddrHtileOut->baseAlign; + } + } + + return 0; +} + +#define G_009910_MICRO_TILE_MODE(x) (((x) >> 0) & 0x03) +#define G_009910_MICRO_TILE_MODE_NEW(x) (((x) >> 22) & 0x07) + +static void gfx6_set_micro_tile_mode(struct radeon_surf *surf, + const struct amdgpu_gpu_info *amdinfo) +{ + uint32_t tile_mode = amdinfo->gb_tile_mode[surf->u.legacy.tiling_index[0]]; + + if (amdinfo->family_id >= AMDGPU_FAMILY_CI) + surf->micro_tile_mode = G_009910_MICRO_TILE_MODE_NEW(tile_mode); + else + surf->micro_tile_mode = G_009910_MICRO_TILE_MODE(tile_mode); +} + +static unsigned cik_get_macro_tile_index(struct radeon_surf *surf) +{ + unsigned index, tileb; + + tileb = 8 * 8 * surf->bpe; + tileb = MIN2(surf->u.legacy.tile_split, tileb); + + for (index = 0; tileb > 64; index++) + tileb >>= 1; + + assert(index < 16); + return index; +} + +/** + * Fill in the tiling information in \p surf based on the given surface config. + * + * The following fields of \p surf must be initialized by the caller: + * blk_w, blk_h, bpe, flags. + */ +int gfx6_compute_surface(ADDR_HANDLE addrlib, + const struct ac_surf_config *config, + enum radeon_surf_mode mode, + struct radeon_surf *surf) +{ + unsigned level; + bool compressed; + ADDR_COMPUTE_SURFACE_INFO_INPUT AddrSurfInfoIn = {0}; + ADDR_COMPUTE_SURFACE_INFO_OUTPUT AddrSurfInfoOut = {0}; + ADDR_COMPUTE_DCCINFO_INPUT AddrDccIn = {0}; + ADDR_COMPUTE_DCCINFO_OUTPUT AddrDccOut = {0}; + ADDR_COMPUTE_HTILE_INFO_INPUT AddrHtileIn = {0}; + ADDR_COMPUTE_HTILE_INFO_OUTPUT AddrHtileOut = {0}; + ADDR_TILEINFO AddrTileInfoIn = {0}; + ADDR_TILEINFO AddrTileInfoOut = {0}; + int r; + + AddrSurfInfoIn.size = sizeof(ADDR_COMPUTE_SURFACE_INFO_INPUT); + AddrSurfInfoOut.size = sizeof(ADDR_COMPUTE_SURFACE_INFO_OUTPUT); + AddrDccIn.size = sizeof(ADDR_COMPUTE_DCCINFO_INPUT); + AddrDccOut.size = sizeof(ADDR_COMPUTE_DCCINFO_OUTPUT); + AddrHtileIn.size = sizeof(ADDR_COMPUTE_HTILE_INFO_INPUT); + AddrHtileOut.size = sizeof(ADDR_COMPUTE_HTILE_INFO_OUTPUT); + AddrSurfInfoOut.pTileInfo = &AddrTileInfoOut; + + compressed = surf->blk_w == 4 && surf->blk_h == 4; + + /* MSAA and FMASK require 2D tiling. */ + if (config->info.samples > 1 || + (surf->flags & RADEON_SURF_FMASK)) + mode = RADEON_SURF_MODE_2D; + + /* DB doesn't support linear layouts. */ + if (surf->flags & (RADEON_SURF_Z_OR_SBUFFER) && + mode < RADEON_SURF_MODE_1D) + mode = RADEON_SURF_MODE_1D; + + /* Set the requested tiling mode. */ + switch (mode) { + case RADEON_SURF_MODE_LINEAR_ALIGNED: + AddrSurfInfoIn.tileMode = ADDR_TM_LINEAR_ALIGNED; + break; + case RADEON_SURF_MODE_1D: + AddrSurfInfoIn.tileMode = ADDR_TM_1D_TILED_THIN1; + break; + case RADEON_SURF_MODE_2D: + AddrSurfInfoIn.tileMode = ADDR_TM_2D_TILED_THIN1; + break; + default: + assert(0); + } + + /* The format must be set correctly for the allocation of compressed + * textures to work. In other cases, setting the bpp is sufficient. + */ + if (compressed) { + switch (surf->bpe) { + case 8: + AddrSurfInfoIn.format = ADDR_FMT_BC1; + break; + case 16: + AddrSurfInfoIn.format = ADDR_FMT_BC3; + break; + default: + assert(0); + } + } + else { + AddrDccIn.bpp = AddrSurfInfoIn.bpp = surf->bpe * 8; + } + + AddrDccIn.numSamples = AddrSurfInfoIn.numSamples = + config->info.samples ? config->info.samples : 1; + AddrSurfInfoIn.tileIndex = -1; + + /* Set the micro tile type. */ + if (surf->flags & RADEON_SURF_SCANOUT) + AddrSurfInfoIn.tileType = ADDR_DISPLAYABLE; + else if (surf->flags & (RADEON_SURF_Z_OR_SBUFFER | RADEON_SURF_FMASK)) + AddrSurfInfoIn.tileType = ADDR_DEPTH_SAMPLE_ORDER; + else + AddrSurfInfoIn.tileType = ADDR_NON_DISPLAYABLE; + + AddrSurfInfoIn.flags.color = !(surf->flags & RADEON_SURF_Z_OR_SBUFFER); + AddrSurfInfoIn.flags.depth = (surf->flags & RADEON_SURF_ZBUFFER) != 0; + AddrSurfInfoIn.flags.cube = config->is_cube; + AddrSurfInfoIn.flags.fmask = (surf->flags & RADEON_SURF_FMASK) != 0; + AddrSurfInfoIn.flags.display = (surf->flags & RADEON_SURF_SCANOUT) != 0; + AddrSurfInfoIn.flags.pow2Pad = config->info.levels > 1; + AddrSurfInfoIn.flags.tcCompatible = (surf->flags & RADEON_SURF_TC_COMPATIBLE_HTILE) != 0; + + /* Only degrade the tile mode for space if TC-compatible HTILE hasn't been + * requested, because TC-compatible HTILE requires 2D tiling. + */ + AddrSurfInfoIn.flags.opt4Space = !AddrSurfInfoIn.flags.tcCompatible && + !AddrSurfInfoIn.flags.fmask && + config->info.samples <= 1 && + (surf->flags & RADEON_SURF_OPTIMIZE_FOR_SPACE); + + /* DCC notes: + * - If we add MSAA support, keep in mind that CB can't decompress 8bpp + * with samples >= 4. + * - Mipmapped array textures have low performance (discovered by a closed + * driver team). + */ + AddrSurfInfoIn.flags.dccCompatible = + config->chip_class >= VI && + !(surf->flags & RADEON_SURF_Z_OR_SBUFFER) && + !(surf->flags & RADEON_SURF_DISABLE_DCC) && + !compressed && AddrDccIn.numSamples <= 1 && + ((config->info.array_size == 1 && config->info.depth == 1) || + config->info.levels == 1); + + AddrSurfInfoIn.flags.noStencil = (surf->flags & RADEON_SURF_SBUFFER) == 0; + AddrSurfInfoIn.flags.compressZ = AddrSurfInfoIn.flags.depth; + + /* noStencil = 0 can result in a depth part that is incompatible with + * mipmapped texturing. So set noStencil = 1 when mipmaps are requested (in + * this case, we may end up setting stencil_adjusted). + * + * TODO: update addrlib to a newer version, remove this, and + * use flags.matchStencilTileCfg = 1 as an alternative fix. + */ + if (config->info.levels > 1) + AddrSurfInfoIn.flags.noStencil = 1; + + /* Set preferred macrotile parameters. This is usually required + * for shared resources. This is for 2D tiling only. */ + if (AddrSurfInfoIn.tileMode >= ADDR_TM_2D_TILED_THIN1 && + surf->u.legacy.bankw && surf->u.legacy.bankh && + surf->u.legacy.mtilea && surf->u.legacy.tile_split) { + assert(!(surf->flags & RADEON_SURF_FMASK)); + + /* If any of these parameters are incorrect, the calculation + * will fail. */ + AddrTileInfoIn.banks = surf->u.legacy.num_banks; + AddrTileInfoIn.bankWidth = surf->u.legacy.bankw; + AddrTileInfoIn.bankHeight = surf->u.legacy.bankh; + AddrTileInfoIn.macroAspectRatio = surf->u.legacy.mtilea; + AddrTileInfoIn.tileSplitBytes = surf->u.legacy.tile_split; + AddrTileInfoIn.pipeConfig = surf->u.legacy.pipe_config + 1; /* +1 compared to GB_TILE_MODE */ + AddrSurfInfoIn.flags.opt4Space = 0; + AddrSurfInfoIn.pTileInfo = &AddrTileInfoIn; + + /* If AddrSurfInfoIn.pTileInfo is set, Addrlib doesn't set + * the tile index, because we are expected to know it if + * we know the other parameters. + * + * This is something that can easily be fixed in Addrlib. + * For now, just figure it out here. + * Note that only 2D_TILE_THIN1 is handled here. + */ + assert(!(surf->flags & RADEON_SURF_Z_OR_SBUFFER)); + assert(AddrSurfInfoIn.tileMode == ADDR_TM_2D_TILED_THIN1); + + if (config->chip_class == SI) { + if (AddrSurfInfoIn.tileType == ADDR_DISPLAYABLE) { + if (surf->bpe == 2) + AddrSurfInfoIn.tileIndex = 11; /* 16bpp */ + else + AddrSurfInfoIn.tileIndex = 12; /* 32bpp */ + } else { + if (surf->bpe == 1) + AddrSurfInfoIn.tileIndex = 14; /* 8bpp */ + else if (surf->bpe == 2) + AddrSurfInfoIn.tileIndex = 15; /* 16bpp */ + else if (surf->bpe == 4) + AddrSurfInfoIn.tileIndex = 16; /* 32bpp */ + else + AddrSurfInfoIn.tileIndex = 17; /* 64bpp (and 128bpp) */ + } + } else { + /* CIK - VI */ + if (AddrSurfInfoIn.tileType == ADDR_DISPLAYABLE) + AddrSurfInfoIn.tileIndex = 10; /* 2D displayable */ + else + AddrSurfInfoIn.tileIndex = 14; /* 2D non-displayable */ + + /* Addrlib doesn't set this if tileIndex is forced like above. */ + AddrSurfInfoOut.macroModeIndex = cik_get_macro_tile_index(surf); + } + } + + surf->num_dcc_levels = 0; + surf->surf_size = 0; + surf->dcc_size = 0; + surf->dcc_alignment = 1; + surf->htile_size = 0; + surf->htile_alignment = 1; + + /* Calculate texture layout information. */ + for (level = 0; level < config->info.levels; level++) { + r = gfx6_compute_level(addrlib, config, surf, false, level, compressed, + &AddrSurfInfoIn, &AddrSurfInfoOut, + &AddrDccIn, &AddrDccOut, &AddrHtileIn, &AddrHtileOut); + if (r) + return r; + + if (level == 0) { + surf->surf_alignment = AddrSurfInfoOut.baseAlign; + surf->u.legacy.pipe_config = AddrSurfInfoOut.pTileInfo->pipeConfig - 1; + gfx6_set_micro_tile_mode(surf, config->amdinfo); + + /* For 2D modes only. */ + if (AddrSurfInfoOut.tileMode >= ADDR_TM_2D_TILED_THIN1) { + surf->u.legacy.bankw = AddrSurfInfoOut.pTileInfo->bankWidth; + surf->u.legacy.bankh = AddrSurfInfoOut.pTileInfo->bankHeight; + surf->u.legacy.mtilea = AddrSurfInfoOut.pTileInfo->macroAspectRatio; + surf->u.legacy.tile_split = AddrSurfInfoOut.pTileInfo->tileSplitBytes; + surf->u.legacy.num_banks = AddrSurfInfoOut.pTileInfo->banks; + surf->u.legacy.macro_tile_index = AddrSurfInfoOut.macroModeIndex; + } else { + surf->u.legacy.macro_tile_index = 0; + } + } + } + + /* Calculate texture layout information for stencil. */ + if (surf->flags & RADEON_SURF_SBUFFER) { + AddrSurfInfoIn.bpp = 8; + AddrSurfInfoIn.flags.depth = 0; + AddrSurfInfoIn.flags.stencil = 1; + AddrSurfInfoIn.flags.tcCompatible = 0; + /* This will be ignored if AddrSurfInfoIn.pTileInfo is NULL. */ + AddrTileInfoIn.tileSplitBytes = surf->u.legacy.stencil_tile_split; + + for (level = 0; level < config->info.levels; level++) { + r = gfx6_compute_level(addrlib, config, surf, true, level, compressed, + &AddrSurfInfoIn, &AddrSurfInfoOut, + &AddrDccIn, &AddrDccOut, + NULL, NULL); + if (r) + return r; + + /* DB uses the depth pitch for both stencil and depth. */ + if (surf->u.legacy.stencil_level[level].nblk_x != + surf->u.legacy.level[level].nblk_x) + surf->u.legacy.stencil_adjusted = true; + + if (level == 0) { + /* For 2D modes only. */ + if (AddrSurfInfoOut.tileMode >= ADDR_TM_2D_TILED_THIN1) { + surf->u.legacy.stencil_tile_split = + AddrSurfInfoOut.pTileInfo->tileSplitBytes; + } + } + } + } + + /* Recalculate the whole DCC miptree size including disabled levels. + * This is what addrlib does, but calling addrlib would be a lot more + * complicated. + */ + if (surf->dcc_size && config->info.levels > 1) { + surf->dcc_size = align64(surf->surf_size >> 8, + config->pipe_interleave_bytes * + config->num_tile_pipes); + } + + /* Make sure HTILE covers the whole miptree, because the shader reads + * TC-compatible HTILE even for levels where it's disabled by DB. + */ + if (surf->htile_size && config->info.levels > 1) + surf->htile_size *= 2; + + surf->is_linear = surf->u.legacy.level[0].mode == RADEON_SURF_MODE_LINEAR_ALIGNED; + return 0; +} diff --git a/src/amd/common/ac_surface.h b/src/amd/common/ac_surface.h index d648e88ae20..5e4cb81630b 100644 --- a/src/amd/common/ac_surface.h +++ b/src/amd/common/ac_surface.h @@ -182,7 +182,31 @@ struct radeon_surf { } u; }; +struct ac_surf_info { + uint32_t width; + uint32_t height; + uint32_t depth; + uint8_t samples; + uint8_t levels; + uint16_t array_size; +}; + +struct ac_surf_config { + struct ac_surf_info info; + unsigned is_3d : 1; + unsigned is_cube : 1; + enum chip_class chip_class : 4; + unsigned num_tile_pipes; + unsigned pipe_interleave_bytes; + const struct amdgpu_gpu_info *amdinfo; +}; + ADDR_HANDLE amdgpu_addr_create(enum radeon_family family, const struct amdgpu_gpu_info *info); +int gfx6_compute_surface(ADDR_HANDLE addrlib, + const struct ac_surf_config *config, + enum radeon_surf_mode mode, + struct radeon_surf *surf); + #endif /* AC_SURFACE_H */ diff --git a/src/gallium/winsys/amdgpu/drm/amdgpu_surface.c b/src/gallium/winsys/amdgpu/drm/amdgpu_surface.c index 7480a432af6..fc062a6427a 100644 --- a/src/gallium/winsys/amdgpu/drm/amdgpu_surface.c +++ b/src/gallium/winsys/amdgpu/drm/amdgpu_surface.c @@ -80,160 +80,6 @@ static int amdgpu_surface_sanity(const struct pipe_resource *tex) return 0; } -static int gfx6_compute_level(struct amdgpu_winsys *ws, - const struct pipe_resource *tex, - struct radeon_surf *surf, bool is_stencil, - unsigned level, bool compressed, - ADDR_COMPUTE_SURFACE_INFO_INPUT *AddrSurfInfoIn, - ADDR_COMPUTE_SURFACE_INFO_OUTPUT *AddrSurfInfoOut, - ADDR_COMPUTE_DCCINFO_INPUT *AddrDccIn, - ADDR_COMPUTE_DCCINFO_OUTPUT *AddrDccOut, - ADDR_COMPUTE_HTILE_INFO_INPUT *AddrHtileIn, - ADDR_COMPUTE_HTILE_INFO_OUTPUT *AddrHtileOut) -{ - struct legacy_surf_level *surf_level; - ADDR_E_RETURNCODE ret; - - AddrSurfInfoIn->mipLevel = level; - AddrSurfInfoIn->width = u_minify(tex->width0, level); - AddrSurfInfoIn->height = u_minify(tex->height0, level); - - if (tex->target == PIPE_TEXTURE_3D) - AddrSurfInfoIn->numSlices = u_minify(tex->depth0, level); - else if (tex->target == PIPE_TEXTURE_CUBE) - AddrSurfInfoIn->numSlices = 6; - else - AddrSurfInfoIn->numSlices = tex->array_size; - - if (level > 0) { - /* Set the base level pitch. This is needed for calculation - * of non-zero levels. */ - if (is_stencil) - AddrSurfInfoIn->basePitch = surf->u.legacy.stencil_level[0].nblk_x; - else - AddrSurfInfoIn->basePitch = surf->u.legacy.level[0].nblk_x; - - /* Convert blocks to pixels for compressed formats. */ - if (compressed) - AddrSurfInfoIn->basePitch *= surf->blk_w; - } - - ret = AddrComputeSurfaceInfo(ws->addrlib, - AddrSurfInfoIn, - AddrSurfInfoOut); - if (ret != ADDR_OK) { - return ret; - } - - surf_level = is_stencil ? &surf->u.legacy.stencil_level[level] : &surf->u.legacy.level[level]; - surf_level->offset = align64(surf->surf_size, AddrSurfInfoOut->baseAlign); - surf_level->slice_size = AddrSurfInfoOut->sliceSize; - surf_level->nblk_x = AddrSurfInfoOut->pitch; - surf_level->nblk_y = AddrSurfInfoOut->height; - - switch (AddrSurfInfoOut->tileMode) { - case ADDR_TM_LINEAR_ALIGNED: - surf_level->mode = RADEON_SURF_MODE_LINEAR_ALIGNED; - break; - case ADDR_TM_1D_TILED_THIN1: - surf_level->mode = RADEON_SURF_MODE_1D; - break; - case ADDR_TM_2D_TILED_THIN1: - surf_level->mode = RADEON_SURF_MODE_2D; - break; - default: - assert(0); - } - - if (is_stencil) - surf->u.legacy.stencil_tiling_index[level] = AddrSurfInfoOut->tileIndex; - else - surf->u.legacy.tiling_index[level] = AddrSurfInfoOut->tileIndex; - - surf->surf_size = surf_level->offset + AddrSurfInfoOut->surfSize; - - /* Clear DCC fields at the beginning. */ - surf_level->dcc_offset = 0; - - /* The previous level's flag tells us if we can use DCC for this level. */ - if (AddrSurfInfoIn->flags.dccCompatible && - (level == 0 || AddrDccOut->subLvlCompressible)) { - AddrDccIn->colorSurfSize = AddrSurfInfoOut->surfSize; - AddrDccIn->tileMode = AddrSurfInfoOut->tileMode; - AddrDccIn->tileInfo = *AddrSurfInfoOut->pTileInfo; - AddrDccIn->tileIndex = AddrSurfInfoOut->tileIndex; - AddrDccIn->macroModeIndex = AddrSurfInfoOut->macroModeIndex; - - ret = AddrComputeDccInfo(ws->addrlib, - AddrDccIn, - AddrDccOut); - - if (ret == ADDR_OK) { - surf_level->dcc_offset = surf->dcc_size; - surf_level->dcc_fast_clear_size = AddrDccOut->dccFastClearSize; - surf->num_dcc_levels = level + 1; - surf->dcc_size = surf_level->dcc_offset + AddrDccOut->dccRamSize; - surf->dcc_alignment = MAX2(surf->dcc_alignment, AddrDccOut->dccRamBaseAlign); - } - } - - /* TC-compatible HTILE. */ - if (!is_stencil && - AddrSurfInfoIn->flags.depth && - AddrSurfInfoIn->flags.tcCompatible && - surf_level->mode == RADEON_SURF_MODE_2D && - level == 0) { - AddrHtileIn->flags.tcCompatible = 1; - AddrHtileIn->pitch = AddrSurfInfoOut->pitch; - AddrHtileIn->height = AddrSurfInfoOut->height; - AddrHtileIn->numSlices = AddrSurfInfoOut->depth; - AddrHtileIn->blockWidth = ADDR_HTILE_BLOCKSIZE_8; - AddrHtileIn->blockHeight = ADDR_HTILE_BLOCKSIZE_8; - AddrHtileIn->pTileInfo = AddrSurfInfoOut->pTileInfo; - AddrHtileIn->tileIndex = AddrSurfInfoOut->tileIndex; - AddrHtileIn->macroModeIndex = AddrSurfInfoOut->macroModeIndex; - - ret = AddrComputeHtileInfo(ws->addrlib, - AddrHtileIn, - AddrHtileOut); - - if (ret == ADDR_OK) { - surf->htile_size = AddrHtileOut->htileBytes; - surf->htile_alignment = AddrHtileOut->baseAlign; - } - } - - return 0; -} - -#define G_009910_MICRO_TILE_MODE(x) (((x) >> 0) & 0x03) -#define G_009910_MICRO_TILE_MODE_NEW(x) (((x) >> 22) & 0x07) - -static void gfx6_set_micro_tile_mode(struct radeon_surf *surf, - struct radeon_info *info) -{ - uint32_t tile_mode = info->si_tile_mode_array[surf->u.legacy.tiling_index[0]]; - - if (info->chip_class >= CIK) - surf->micro_tile_mode = G_009910_MICRO_TILE_MODE_NEW(tile_mode); - else - surf->micro_tile_mode = G_009910_MICRO_TILE_MODE(tile_mode); -} - -static unsigned cik_get_macro_tile_index(struct radeon_surf *surf) -{ - unsigned index, tileb; - - tileb = 8 * 8 * surf->bpe; - tileb = MIN2(surf->u.legacy.tile_split, tileb); - - for (index = 0; tileb > 64; index++) - tileb >>= 1; - - assert(index < 16); - return index; -} - static int gfx6_surface_init(struct radeon_winsys *rws, const struct pipe_resource *tex, unsigned flags, unsigned bpe, @@ -241,274 +87,33 @@ static int gfx6_surface_init(struct radeon_winsys *rws, struct radeon_surf *surf) { struct amdgpu_winsys *ws = (struct amdgpu_winsys*)rws; - unsigned level; - bool compressed; - ADDR_COMPUTE_SURFACE_INFO_INPUT AddrSurfInfoIn = {0}; - ADDR_COMPUTE_SURFACE_INFO_OUTPUT AddrSurfInfoOut = {0}; - ADDR_COMPUTE_DCCINFO_INPUT AddrDccIn = {0}; - ADDR_COMPUTE_DCCINFO_OUTPUT AddrDccOut = {0}; - ADDR_COMPUTE_HTILE_INFO_INPUT AddrHtileIn = {0}; - ADDR_COMPUTE_HTILE_INFO_OUTPUT AddrHtileOut = {0}; - ADDR_TILEINFO AddrTileInfoIn = {0}; - ADDR_TILEINFO AddrTileInfoOut = {0}; int r; r = amdgpu_surface_sanity(tex); if (r) return r; - AddrSurfInfoIn.size = sizeof(ADDR_COMPUTE_SURFACE_INFO_INPUT); - AddrSurfInfoOut.size = sizeof(ADDR_COMPUTE_SURFACE_INFO_OUTPUT); - AddrDccIn.size = sizeof(ADDR_COMPUTE_DCCINFO_INPUT); - AddrDccOut.size = sizeof(ADDR_COMPUTE_DCCINFO_OUTPUT); - AddrHtileIn.size = sizeof(ADDR_COMPUTE_HTILE_INFO_INPUT); - AddrHtileOut.size = sizeof(ADDR_COMPUTE_HTILE_INFO_OUTPUT); - AddrSurfInfoOut.pTileInfo = &AddrTileInfoOut; - surf->blk_w = util_format_get_blockwidth(tex->format); surf->blk_h = util_format_get_blockheight(tex->format); surf->bpe = bpe; surf->flags = flags; - compressed = surf->blk_w == 4 && surf->blk_h == 4; - - /* MSAA and FMASK require 2D tiling. */ - if (tex->nr_samples > 1 || - (flags & RADEON_SURF_FMASK)) - mode = RADEON_SURF_MODE_2D; - - /* DB doesn't support linear layouts. */ - if (flags & (RADEON_SURF_Z_OR_SBUFFER) && - mode < RADEON_SURF_MODE_1D) - mode = RADEON_SURF_MODE_1D; - - /* Set the requested tiling mode. */ - switch (mode) { - case RADEON_SURF_MODE_LINEAR_ALIGNED: - AddrSurfInfoIn.tileMode = ADDR_TM_LINEAR_ALIGNED; - break; - case RADEON_SURF_MODE_1D: - AddrSurfInfoIn.tileMode = ADDR_TM_1D_TILED_THIN1; - break; - case RADEON_SURF_MODE_2D: - AddrSurfInfoIn.tileMode = ADDR_TM_2D_TILED_THIN1; - break; - default: - assert(0); - } - - /* The format must be set correctly for the allocation of compressed - * textures to work. In other cases, setting the bpp is sufficient. */ - if (compressed) { - switch (bpe) { - case 8: - AddrSurfInfoIn.format = ADDR_FMT_BC1; - break; - case 16: - AddrSurfInfoIn.format = ADDR_FMT_BC3; - break; - default: - assert(0); - } - } - else { - AddrDccIn.bpp = AddrSurfInfoIn.bpp = bpe * 8; - } - - AddrDccIn.numSamples = AddrSurfInfoIn.numSamples = - tex->nr_samples ? tex->nr_samples : 1; - AddrSurfInfoIn.tileIndex = -1; - - /* Set the micro tile type. */ - if (flags & RADEON_SURF_SCANOUT) - AddrSurfInfoIn.tileType = ADDR_DISPLAYABLE; - else if (flags & (RADEON_SURF_Z_OR_SBUFFER | RADEON_SURF_FMASK)) - AddrSurfInfoIn.tileType = ADDR_DEPTH_SAMPLE_ORDER; - else - AddrSurfInfoIn.tileType = ADDR_NON_DISPLAYABLE; - - AddrSurfInfoIn.flags.color = !(flags & RADEON_SURF_Z_OR_SBUFFER); - AddrSurfInfoIn.flags.depth = (flags & RADEON_SURF_ZBUFFER) != 0; - AddrSurfInfoIn.flags.cube = tex->target == PIPE_TEXTURE_CUBE; - AddrSurfInfoIn.flags.fmask = (flags & RADEON_SURF_FMASK) != 0; - AddrSurfInfoIn.flags.display = (flags & RADEON_SURF_SCANOUT) != 0; - AddrSurfInfoIn.flags.pow2Pad = tex->last_level > 0; - AddrSurfInfoIn.flags.tcCompatible = (flags & RADEON_SURF_TC_COMPATIBLE_HTILE) != 0; - - /* Only degrade the tile mode for space if TC-compatible HTILE hasn't been - * requested, because TC-compatible HTILE requires 2D tiling. - */ - AddrSurfInfoIn.flags.opt4Space = !AddrSurfInfoIn.flags.tcCompatible && - !AddrSurfInfoIn.flags.fmask && - tex->nr_samples <= 1 && - (flags & RADEON_SURF_OPTIMIZE_FOR_SPACE); - - /* DCC notes: - * - If we add MSAA support, keep in mind that CB can't decompress 8bpp - * with samples >= 4. - * - Mipmapped array textures have low performance (discovered by a closed - * driver team). - */ - AddrSurfInfoIn.flags.dccCompatible = ws->info.chip_class >= VI && - !(flags & RADEON_SURF_Z_OR_SBUFFER) && - !(flags & RADEON_SURF_DISABLE_DCC) && - !compressed && AddrDccIn.numSamples <= 1 && - ((tex->array_size == 1 && tex->depth0 == 1) || - tex->last_level == 0); - - AddrSurfInfoIn.flags.noStencil = (flags & RADEON_SURF_SBUFFER) == 0; - AddrSurfInfoIn.flags.compressZ = AddrSurfInfoIn.flags.depth; - - /* noStencil = 0 can result in a depth part that is incompatible with - * mipmapped texturing. So set noStencil = 1 when mipmaps are requested (in - * this case, we may end up setting stencil_adjusted). - * - * TODO: update addrlib to a newer version, remove this, and - * use flags.matchStencilTileCfg = 1 as an alternative fix. - */ - if (tex->last_level > 0) - AddrSurfInfoIn.flags.noStencil = 1; - - /* Set preferred macrotile parameters. This is usually required - * for shared resources. This is for 2D tiling only. */ - if (AddrSurfInfoIn.tileMode >= ADDR_TM_2D_TILED_THIN1 && - surf->u.legacy.bankw && surf->u.legacy.bankh && - surf->u.legacy.mtilea && surf->u.legacy.tile_split) { - assert(!(flags & RADEON_SURF_FMASK)); - - /* If any of these parameters are incorrect, the calculation - * will fail. */ - AddrTileInfoIn.banks = surf->u.legacy.num_banks; - AddrTileInfoIn.bankWidth = surf->u.legacy.bankw; - AddrTileInfoIn.bankHeight = surf->u.legacy.bankh; - AddrTileInfoIn.macroAspectRatio = surf->u.legacy.mtilea; - AddrTileInfoIn.tileSplitBytes = surf->u.legacy.tile_split; - AddrTileInfoIn.pipeConfig = surf->u.legacy.pipe_config + 1; /* +1 compared to GB_TILE_MODE */ - AddrSurfInfoIn.flags.opt4Space = 0; - AddrSurfInfoIn.pTileInfo = &AddrTileInfoIn; - - /* If AddrSurfInfoIn.pTileInfo is set, Addrlib doesn't set - * the tile index, because we are expected to know it if - * we know the other parameters. - * - * This is something that can easily be fixed in Addrlib. - * For now, just figure it out here. - * Note that only 2D_TILE_THIN1 is handled here. - */ - assert(!(flags & RADEON_SURF_Z_OR_SBUFFER)); - assert(AddrSurfInfoIn.tileMode == ADDR_TM_2D_TILED_THIN1); - - if (ws->info.chip_class == SI) { - if (AddrSurfInfoIn.tileType == ADDR_DISPLAYABLE) { - if (bpe == 2) - AddrSurfInfoIn.tileIndex = 11; /* 16bpp */ - else - AddrSurfInfoIn.tileIndex = 12; /* 32bpp */ - } else { - if (bpe == 1) - AddrSurfInfoIn.tileIndex = 14; /* 8bpp */ - else if (bpe == 2) - AddrSurfInfoIn.tileIndex = 15; /* 16bpp */ - else if (bpe == 4) - AddrSurfInfoIn.tileIndex = 16; /* 32bpp */ - else - AddrSurfInfoIn.tileIndex = 17; /* 64bpp (and 128bpp) */ - } - } else { - /* CIK - VI */ - if (AddrSurfInfoIn.tileType == ADDR_DISPLAYABLE) - AddrSurfInfoIn.tileIndex = 10; /* 2D displayable */ - else - AddrSurfInfoIn.tileIndex = 14; /* 2D non-displayable */ - - /* Addrlib doesn't set this if tileIndex is forced like above. */ - AddrSurfInfoOut.macroModeIndex = cik_get_macro_tile_index(surf); - } - } - - surf->num_dcc_levels = 0; - surf->surf_size = 0; - surf->dcc_size = 0; - surf->dcc_alignment = 1; - surf->htile_size = 0; - surf->htile_alignment = 1; - - /* Calculate texture layout information. */ - for (level = 0; level <= tex->last_level; level++) { - r = gfx6_compute_level(ws, tex, surf, false, level, compressed, - &AddrSurfInfoIn, &AddrSurfInfoOut, - &AddrDccIn, &AddrDccOut, &AddrHtileIn, &AddrHtileOut); - if (r) - return r; - - if (level == 0) { - surf->surf_alignment = AddrSurfInfoOut.baseAlign; - surf->u.legacy.pipe_config = AddrSurfInfoOut.pTileInfo->pipeConfig - 1; - gfx6_set_micro_tile_mode(surf, &ws->info); - - /* For 2D modes only. */ - if (AddrSurfInfoOut.tileMode >= ADDR_TM_2D_TILED_THIN1) { - surf->u.legacy.bankw = AddrSurfInfoOut.pTileInfo->bankWidth; - surf->u.legacy.bankh = AddrSurfInfoOut.pTileInfo->bankHeight; - surf->u.legacy.mtilea = AddrSurfInfoOut.pTileInfo->macroAspectRatio; - surf->u.legacy.tile_split = AddrSurfInfoOut.pTileInfo->tileSplitBytes; - surf->u.legacy.num_banks = AddrSurfInfoOut.pTileInfo->banks; - surf->u.legacy.macro_tile_index = AddrSurfInfoOut.macroModeIndex; - } else { - surf->u.legacy.macro_tile_index = 0; - } - } - } - - /* Calculate texture layout information for stencil. */ - if (flags & RADEON_SURF_SBUFFER) { - AddrSurfInfoIn.bpp = 8; - AddrSurfInfoIn.flags.depth = 0; - AddrSurfInfoIn.flags.stencil = 1; - AddrSurfInfoIn.flags.tcCompatible = 0; - /* This will be ignored if AddrSurfInfoIn.pTileInfo is NULL. */ - AddrTileInfoIn.tileSplitBytes = surf->u.legacy.stencil_tile_split; - - for (level = 0; level <= tex->last_level; level++) { - r = gfx6_compute_level(ws, tex, surf, true, level, compressed, - &AddrSurfInfoIn, &AddrSurfInfoOut, - &AddrDccIn, &AddrDccOut, - NULL, NULL); - if (r) - return r; - - /* DB uses the depth pitch for both stencil and depth. */ - if (surf->u.legacy.stencil_level[level].nblk_x != surf->u.legacy.level[level].nblk_x) - surf->u.legacy.stencil_adjusted = true; - - if (level == 0) { - /* For 2D modes only. */ - if (AddrSurfInfoOut.tileMode >= ADDR_TM_2D_TILED_THIN1) { - surf->u.legacy.stencil_tile_split = - AddrSurfInfoOut.pTileInfo->tileSplitBytes; - } - } - } - } - - /* Recalculate the whole DCC miptree size including disabled levels. - * This is what addrlib does, but calling addrlib would be a lot more - * complicated. - */ - if (surf->dcc_size && tex->last_level > 0) { - surf->dcc_size = align64(surf->surf_size >> 8, - ws->info.pipe_interleave_bytes * - ws->info.num_tile_pipes); - } - - /* Make sure HTILE covers the whole miptree, because the shader reads - * TC-compatible HTILE even for levels where it's disabled by DB. - */ - if (surf->htile_size && tex->last_level) - surf->htile_size *= 2; - - surf->is_linear = surf->u.legacy.level[0].mode == RADEON_SURF_MODE_LINEAR_ALIGNED; - return 0; + struct ac_surf_config config; + + config.info.width = tex->width0; + config.info.height = tex->height0; + config.info.depth = tex->depth0; + config.info.array_size = tex->array_size; + config.info.samples = tex->nr_samples; + config.info.levels = tex->last_level + 1; + config.is_3d = !!(tex->target == PIPE_TEXTURE_3D); + config.is_cube = !!(tex->target == PIPE_TEXTURE_CUBE); + config.chip_class = ws->info.chip_class; + config.num_tile_pipes = ws->info.num_tile_pipes; + config.pipe_interleave_bytes = ws->info.pipe_interleave_bytes; + config.amdinfo = &ws->amdinfo; + + return gfx6_compute_surface(ws->addrlib, &config, mode, surf); } /* This is only called when expecting a tiled layout. */ |