diff options
author | Dave Airlie <[email protected]> | 2016-09-05 09:54:07 +1000 |
---|---|---|
committer | Dave Airlie <[email protected]> | 2016-09-06 10:06:33 +1000 |
commit | 69fca64259495d7a31135876e818e1ac2a36d190 (patch) | |
tree | 3462cfa208d32e2939a07681c0ab2ed56ff648da /src/amd/addrlib/r800 | |
parent | 1add3562e33f0234da50e54dda8cfa6dac613125 (diff) |
amd/addrlib: move addrlib from amdgpu winsys to common code
Acked-by: Marek Olšák <[email protected]>
Reviewed-by: Nicolai Hähnle <[email protected]>
Diffstat (limited to 'src/amd/addrlib/r800')
-rw-r--r-- | src/amd/addrlib/r800/chip/si_ci_vi_merged_enum.h | 40 | ||||
-rw-r--r-- | src/amd/addrlib/r800/ciaddrlib.cpp | 1831 | ||||
-rw-r--r-- | src/amd/addrlib/r800/ciaddrlib.h | 202 | ||||
-rw-r--r-- | src/amd/addrlib/r800/egbaddrlib.cpp | 4577 | ||||
-rw-r--r-- | src/amd/addrlib/r800/egbaddrlib.h | 412 | ||||
-rw-r--r-- | src/amd/addrlib/r800/siaddrlib.cpp | 2818 | ||||
-rw-r--r-- | src/amd/addrlib/r800/siaddrlib.h | 262 |
7 files changed, 10142 insertions, 0 deletions
diff --git a/src/amd/addrlib/r800/chip/si_ci_vi_merged_enum.h b/src/amd/addrlib/r800/chip/si_ci_vi_merged_enum.h new file mode 100644 index 00000000000..5ed81add264 --- /dev/null +++ b/src/amd/addrlib/r800/chip/si_ci_vi_merged_enum.h @@ -0,0 +1,40 @@ +/* + * Copyright © 2014 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS + * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + */ +#if !defined (SI_CI_VI_MERGED_ENUM_HEADER) +#define SI_CI_VI_MERGED_ENUM_HEADER + +typedef enum PipeInterleaveSize { +ADDR_CONFIG_PIPE_INTERLEAVE_256B = 0x00000000, +ADDR_CONFIG_PIPE_INTERLEAVE_512B = 0x00000001, +} PipeInterleaveSize; + +typedef enum RowSize { +ADDR_CONFIG_1KB_ROW = 0x00000000, +ADDR_CONFIG_2KB_ROW = 0x00000001, +ADDR_CONFIG_4KB_ROW = 0x00000002, +} RowSize; + +#endif diff --git a/src/amd/addrlib/r800/ciaddrlib.cpp b/src/amd/addrlib/r800/ciaddrlib.cpp new file mode 100644 index 00000000000..7c5d29a2166 --- /dev/null +++ b/src/amd/addrlib/r800/ciaddrlib.cpp @@ -0,0 +1,1831 @@ +/* + * Copyright © 2014 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS + * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + */ + +/** +*************************************************************************************************** +* @file ciaddrlib.cpp +* @brief Contains the implementation for the CIAddrLib class. +*************************************************************************************************** +*/ + +#include "ciaddrlib.h" + +#include "si_gb_reg.h" + +#include "si_ci_vi_merged_enum.h" + +#if BRAHMA_BUILD +#include "amdgpu_id.h" +#else +#include "ci_id.h" +#include "kv_id.h" +#include "vi_id.h" +#endif + +/////////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////////// + +/** +*************************************************************************************************** +* AddrMask +* +* @brief +* Gets a mask of "width" +* @return +* Bit mask +*************************************************************************************************** +*/ +static UINT_64 AddrMask( + UINT_32 width) ///< Width of bits +{ + UINT_64 ret; + + if (width >= sizeof(UINT_64)*8) + { + ret = ~((UINT_64) 0); + } + else + { + return (((UINT_64) 1) << width) - 1; + } + return ret; +} + +/** +*************************************************************************************************** +* AddrGetBits +* +* @brief +* Gets bits within a range of [msb, lsb] +* @return +* Bits of this range +*************************************************************************************************** +*/ +static UINT_64 AddrGetBits( + UINT_64 bits, ///< Source bits + UINT_32 msb, ///< Most signicant bit + UINT_32 lsb) ///< Least signicant bit +{ + UINT_64 ret = 0; + + if (msb >= lsb) + { + ret = (bits >> lsb) & (AddrMask(1 + msb - lsb)); + } + return ret; +} + +/** +*************************************************************************************************** +* AddrRemoveBits +* +* @brief +* Removes bits within the range of [msb, lsb] +* @return +* Modified bits +*************************************************************************************************** +*/ +static UINT_64 AddrRemoveBits( + UINT_64 bits, ///< Source bits + UINT_32 msb, ///< Most signicant bit + UINT_32 lsb) ///< Least signicant bit +{ + UINT_64 ret = bits; + + if (msb >= lsb) + { + ret = AddrGetBits(bits, lsb - 1, 0) // low bits + | (AddrGetBits(bits, 8 * sizeof(bits) - 1, msb + 1) << lsb); //high bits + } + return ret; +} + +/** +*************************************************************************************************** +* AddrInsertBits +* +* @brief +* Inserts new bits into the range of [msb, lsb] +* @return +* Modified bits +*************************************************************************************************** +*/ +static UINT_64 AddrInsertBits( + UINT_64 bits, ///< Source bits + UINT_64 newBits, ///< New bits to be inserted + UINT_32 msb, ///< Most signicant bit + UINT_32 lsb) ///< Least signicant bit +{ + UINT_64 ret = bits; + + if (msb >= lsb) + { + ret = AddrGetBits(bits, lsb - 1, 0) // old low bitss + | (AddrGetBits(newBits, msb - lsb, 0) << lsb) //new bits + | (AddrGetBits(bits, 8 * sizeof(bits) - 1, lsb) << (msb + 1)); //old high bits + } + return ret; +} + + +/** +*************************************************************************************************** +* AddrCIHwlInit +* +* @brief +* Creates an CIAddrLib object. +* +* @return +* Returns an CIAddrLib object pointer. +*************************************************************************************************** +*/ +AddrLib* AddrCIHwlInit(const AddrClient* pClient) +{ + return CIAddrLib::CreateObj(pClient); +} + +/** +*************************************************************************************************** +* CIAddrLib::CIAddrLib +* +* @brief +* Constructor +* +*************************************************************************************************** +*/ +CIAddrLib::CIAddrLib(const AddrClient* pClient) : + SIAddrLib(pClient), + m_noOfMacroEntries(0), + m_allowNonDispThickModes(FALSE) +{ + m_class = CI_ADDRLIB; + memset(&m_settings, 0, sizeof(m_settings)); +} + +/** +*************************************************************************************************** +* CIAddrLib::~CIAddrLib +* +* @brief +* Destructor +*************************************************************************************************** +*/ +CIAddrLib::~CIAddrLib() +{ +} + +/** +*************************************************************************************************** +* CIAddrLib::HwlComputeDccInfo +* +* @brief +* Compute DCC key size, base alignment +* @return +* ADDR_E_RETURNCODE +*************************************************************************************************** +*/ +ADDR_E_RETURNCODE CIAddrLib::HwlComputeDccInfo( + const ADDR_COMPUTE_DCCINFO_INPUT* pIn, + ADDR_COMPUTE_DCCINFO_OUTPUT* pOut) const +{ + ADDR_E_RETURNCODE returnCode = ADDR_OK; + + if (m_settings.isVolcanicIslands && IsMacroTiled(pIn->tileMode)) + { + UINT_64 dccFastClearSize = pIn->colorSurfSize >> 8; + + ADDR_ASSERT(0 == (pIn->colorSurfSize & 0xff)); + + if (pIn->numSamples > 1) + { + UINT_32 tileSizePerSample = BITS_TO_BYTES(pIn->bpp * MicroTileWidth * MicroTileHeight); + UINT_32 samplesPerSplit = pIn->tileInfo.tileSplitBytes / tileSizePerSample; + + if (samplesPerSplit < pIn->numSamples) + { + UINT_32 numSplits = pIn->numSamples / samplesPerSplit; + UINT_32 fastClearBaseAlign = HwlGetPipes(&pIn->tileInfo) * m_pipeInterleaveBytes; + + ADDR_ASSERT(IsPow2(fastClearBaseAlign)); + + dccFastClearSize /= numSplits; + + if (0 != (dccFastClearSize & (fastClearBaseAlign - 1))) + { + // Disable dcc fast clear + // if key size of fisrt sample split is not pipe*interleave aligned + dccFastClearSize = 0; + } + } + } + + pOut->dccRamSize = pIn->colorSurfSize >> 8; + pOut->dccRamBaseAlign = pIn->tileInfo.banks * + HwlGetPipes(&pIn->tileInfo) * + m_pipeInterleaveBytes; + pOut->dccFastClearSize = dccFastClearSize; + + ADDR_ASSERT(IsPow2(pOut->dccRamBaseAlign)); + + if (0 == (pOut->dccRamSize & (pOut->dccRamBaseAlign - 1))) + { + pOut->subLvlCompressible = TRUE; + } + else + { + UINT_64 dccRamSizeAlign = HwlGetPipes(&pIn->tileInfo) * m_pipeInterleaveBytes; + + if (pOut->dccRamSize == pOut->dccFastClearSize) + { + pOut->dccFastClearSize = PowTwoAlign(pOut->dccRamSize, dccRamSizeAlign); + } + pOut->dccRamSize = PowTwoAlign(pOut->dccRamSize, dccRamSizeAlign); + pOut->subLvlCompressible = FALSE; + } + } + else + { + returnCode = ADDR_NOTSUPPORTED; + } + + return returnCode; +} + +/** +*************************************************************************************************** +* CIAddrLib::HwlComputeCmaskAddrFromCoord +* +* @brief +* Compute tc compatible Cmask address from fmask ram address +* +* @return +* ADDR_E_RETURNCODE +*************************************************************************************************** +*/ +ADDR_E_RETURNCODE CIAddrLib::HwlComputeCmaskAddrFromCoord( + const ADDR_COMPUTE_CMASK_ADDRFROMCOORD_INPUT* pIn, ///< [in] fmask addr/bpp/tile input + ADDR_COMPUTE_CMASK_ADDRFROMCOORD_OUTPUT* pOut ///< [out] cmask address + ) const +{ + ADDR_E_RETURNCODE returnCode = ADDR_NOTSUPPORTED; + + if ((m_settings.isVolcanicIslands == TRUE) && + (pIn->flags.tcCompatible == TRUE)) + { + UINT_32 numOfPipes = HwlGetPipes(pIn->pTileInfo); + UINT_32 numOfBanks = pIn->pTileInfo->banks; + UINT_64 fmaskAddress = pIn->fmaskAddr; + UINT_32 elemBits = pIn->bpp; + UINT_32 blockByte = 64 * elemBits / 8; + UINT_64 metaNibbleAddress = HwlComputeMetadataNibbleAddress(fmaskAddress, + 0, + 0, + 4, + elemBits, + blockByte, + m_pipeInterleaveBytes, + numOfPipes, + numOfBanks, + 1); + pOut->addr = (metaNibbleAddress >> 1); + pOut->bitPosition = (metaNibbleAddress % 2) ? 4 : 0; + returnCode = ADDR_OK; + } + + return returnCode; +} +/** +*************************************************************************************************** +* CIAddrLib::HwlConvertChipFamily +* +* @brief +* Convert familyID defined in atiid.h to AddrChipFamily and set m_chipFamily/m_chipRevision +* @return +* AddrChipFamily +*************************************************************************************************** +*/ +AddrChipFamily CIAddrLib::HwlConvertChipFamily( + UINT_32 uChipFamily, ///< [in] chip family defined in atiih.h + UINT_32 uChipRevision) ///< [in] chip revision defined in "asic_family"_id.h +{ + AddrChipFamily family = ADDR_CHIP_FAMILY_CI; + + switch (uChipFamily) + { + case FAMILY_CI: + m_settings.isSeaIsland = 1; + m_settings.isBonaire = ASICREV_IS_BONAIRE_M(uChipRevision); + m_settings.isHawaii = ASICREV_IS_HAWAII_P(uChipRevision); + break; + case FAMILY_KV: + m_settings.isKaveri = 1; + m_settings.isSpectre = ASICREV_IS_SPECTRE(uChipRevision); + m_settings.isSpooky = ASICREV_IS_SPOOKY(uChipRevision); + m_settings.isKalindi = ASICREV_IS_KALINDI(uChipRevision); + break; + case FAMILY_VI: + m_settings.isVolcanicIslands = 1; + m_settings.isIceland = ASICREV_IS_ICELAND_M(uChipRevision); + m_settings.isTonga = ASICREV_IS_TONGA_P(uChipRevision); + m_settings.isFiji = ASICREV_IS_FIJI_P(uChipRevision); + m_settings.isPolaris10 = ASICREV_IS_POLARIS10_P(uChipRevision); + m_settings.isPolaris11 = ASICREV_IS_POLARIS11_M(uChipRevision); + break; + case FAMILY_CZ: + m_settings.isCarrizo = 1; + m_settings.isVolcanicIslands = 1; + break; + default: + ADDR_ASSERT(!"This should be a unexpected Fusion"); + break; + } + + return family; +} + +/** +*************************************************************************************************** +* CIAddrLib::HwlInitGlobalParams +* +* @brief +* Initializes global parameters +* +* @return +* TRUE if all settings are valid +* +*************************************************************************************************** +*/ +BOOL_32 CIAddrLib::HwlInitGlobalParams( + const ADDR_CREATE_INPUT* pCreateIn) ///< [in] create input +{ + BOOL_32 valid = TRUE; + + const ADDR_REGISTER_VALUE* pRegValue = &pCreateIn->regValue; + + valid = DecodeGbRegs(pRegValue); + + // The following assignments for m_pipes is only for fail-safe, InitTileSettingTable should + // read the correct pipes from tile mode table + if (m_settings.isHawaii) + { + // Hawaii has 16-pipe, see GFXIP_Config_Summary.xls + m_pipes = 16; + } + else if (m_settings.isBonaire || m_settings.isSpectre) + { + m_pipes = 4; + } + else // Treat other KV asics to be 2-pipe + { + m_pipes = 2; + } + + // @todo: VI + // Move this to VI code path once created + if (m_settings.isTonga || m_settings.isPolaris10) + { + m_pipes = 8; + } + else if (m_settings.isIceland) + { + m_pipes = 2; + } + else if (m_settings.isFiji) + { + m_pipes = 16; + } + else if (m_settings.isPolaris11) + { + m_pipes = 4; + } + + if (valid) + { + valid = InitTileSettingTable(pRegValue->pTileConfig, pRegValue->noOfEntries); + } + if (valid) + { + valid = InitMacroTileCfgTable(pRegValue->pMacroTileConfig, pRegValue->noOfMacroEntries); + } + + return valid; +} + +/** +*************************************************************************************************** +* CIAddrLib::HwlPostCheckTileIndex +* +* @brief +* Map a tile setting to index if curIndex is invalid, otherwise check if curIndex matches +* tile mode/type/info and change the index if needed +* @return +* Tile index. +*************************************************************************************************** +*/ +INT_32 CIAddrLib::HwlPostCheckTileIndex( + const ADDR_TILEINFO* pInfo, ///< [in] Tile Info + AddrTileMode mode, ///< [in] Tile mode + AddrTileType type, ///< [in] Tile type + INT curIndex ///< [in] Current index assigned in HwlSetupTileInfo + ) const +{ + INT_32 index = curIndex; + + if (mode == ADDR_TM_LINEAR_GENERAL) + { + index = TileIndexLinearGeneral; + } + else + { + BOOL_32 macroTiled = IsMacroTiled(mode); + + // We need to find a new index if either of them is true + // 1. curIndex is invalid + // 2. tile mode is changed + // 3. tile info does not match for macro tiled + if ((index == TileIndexInvalid) || + (mode != m_tileTable[index].mode) || + (macroTiled && pInfo->pipeConfig != m_tileTable[index].info.pipeConfig)) + { + for (index = 0; index < static_cast<INT_32>(m_noOfEntries); index++) + { + if (macroTiled) + { + // macro tile modes need all to match + if ((pInfo->pipeConfig == m_tileTable[index].info.pipeConfig) && + (mode == m_tileTable[index].mode) && + (type == m_tileTable[index].type)) + { + // tileSplitBytes stored in m_tileTable is only valid for depth entries + if (type == ADDR_DEPTH_SAMPLE_ORDER) + { + if (pInfo->tileSplitBytes == m_tileTable[index].info.tileSplitBytes) + { + break; + } + } + else // other entries are determined by other 3 fields + { + break; + } + } + } + else if (mode == ADDR_TM_LINEAR_ALIGNED) + { + // linear mode only needs tile mode to match + if (mode == m_tileTable[index].mode) + { + break; + } + } + else + { + // micro tile modes only need tile mode and tile type to match + if (mode == m_tileTable[index].mode && + type == m_tileTable[index].type) + { + break; + } + } + } + } + } + + ADDR_ASSERT(index < static_cast<INT_32>(m_noOfEntries)); + + if (index >= static_cast<INT_32>(m_noOfEntries)) + { + index = TileIndexInvalid; + } + + return index; +} + +/** +*************************************************************************************************** +* CIAddrLib::HwlSetupTileCfg +* +* @brief +* Map tile index to tile setting. +* @return +* ADDR_E_RETURNCODE +*************************************************************************************************** +*/ +ADDR_E_RETURNCODE CIAddrLib::HwlSetupTileCfg( + INT_32 index, ///< [in] Tile index + INT_32 macroModeIndex, ///< [in] Index in macro tile mode table(CI) + ADDR_TILEINFO* pInfo, ///< [out] Tile Info + AddrTileMode* pMode, ///< [out] Tile mode + AddrTileType* pType ///< [out] Tile type + ) const +{ + ADDR_E_RETURNCODE returnCode = ADDR_OK; + + // Global flag to control usage of tileIndex + if (UseTileIndex(index)) + { + if (static_cast<UINT_32>(index) >= m_noOfEntries) + { + returnCode = ADDR_INVALIDPARAMS; + } + else + { + const ADDR_TILECONFIG* pCfgTable = GetTileSetting(index); + + if (pInfo != NULL) + { + if (IsMacroTiled(pCfgTable->mode)) + { + ADDR_ASSERT(((macroModeIndex != TileIndexInvalid) + && (macroModeIndex != TileIndexNoMacroIndex))); + // Here we used tile_bytes to replace of tile_split + // According info as below: + // "tile_split_c = MIN(ROW_SIZE, tile_split) + // "tile_bytes = MIN(tile_split_c, num_samples * tile_bytes_1x) + // when using tile_bytes replacing of tile_split, the result of + // alignment and others(such as slicesPerTile) are unaffected - + // since if tile_split_c is larger, split won't happen, otherwise + // (num_samples * tile_bytes_1x is larger), a correct tile_split is + // returned. + *pInfo = m_macroTileTable[macroModeIndex]; + + if (pCfgTable->type == ADDR_DEPTH_SAMPLE_ORDER) + { + pInfo->tileSplitBytes = pCfgTable->info.tileSplitBytes; + } + pInfo->pipeConfig = pCfgTable->info.pipeConfig; + } + else // 1D and linear modes, we return default value stored in table + { + *pInfo = pCfgTable->info; + } + } + + if (pMode != NULL) + { + *pMode = pCfgTable->mode; + } + + if (pType != NULL) + { + *pType = pCfgTable->type; + } + } + } + + return returnCode; +} + +/** +*************************************************************************************************** +* CIAddrLib::HwlComputeSurfaceInfo +* +* @brief +* Entry of ci's ComputeSurfaceInfo +* @return +* ADDR_E_RETURNCODE +*************************************************************************************************** +*/ +ADDR_E_RETURNCODE CIAddrLib::HwlComputeSurfaceInfo( + const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] input structure + ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [out] output structure + ) const +{ + // If tileIndex is invalid, force macroModeIndex to be invalid, too + if (pIn->tileIndex == TileIndexInvalid) + { + pOut->macroModeIndex = TileIndexInvalid; + } + + ADDR_E_RETURNCODE retCode = SIAddrLib::HwlComputeSurfaceInfo(pIn,pOut); + + if (pOut->macroModeIndex == TileIndexNoMacroIndex) + { + pOut->macroModeIndex = TileIndexInvalid; + } + + return retCode; +} + +/** +*************************************************************************************************** +* CIAddrLib::HwlFmaskSurfaceInfo +* @brief +* Entry of r800's ComputeFmaskInfo +* @return +* ADDR_E_RETURNCODE +*************************************************************************************************** +*/ +ADDR_E_RETURNCODE CIAddrLib::HwlComputeFmaskInfo( + const ADDR_COMPUTE_FMASK_INFO_INPUT* pIn, ///< [in] input structure + ADDR_COMPUTE_FMASK_INFO_OUTPUT* pOut ///< [out] output structure + ) +{ + ADDR_E_RETURNCODE retCode = ADDR_OK; + + ADDR_TILEINFO tileInfo = {0}; + ADDR_COMPUTE_FMASK_INFO_INPUT fmaskIn; + fmaskIn = *pIn; + + AddrTileMode tileMode = pIn->tileMode; + + // Use internal tile info if pOut does not have a valid pTileInfo + if (pOut->pTileInfo == NULL) + { + pOut->pTileInfo = &tileInfo; + } + + ADDR_ASSERT(tileMode == ADDR_TM_2D_TILED_THIN1 || + tileMode == ADDR_TM_3D_TILED_THIN1 || + tileMode == ADDR_TM_PRT_TILED_THIN1 || + tileMode == ADDR_TM_PRT_2D_TILED_THIN1 || + tileMode == ADDR_TM_PRT_3D_TILED_THIN1); + + ADDR_ASSERT(m_tileTable[14].mode == ADDR_TM_2D_TILED_THIN1); + ADDR_ASSERT(m_tileTable[15].mode == ADDR_TM_3D_TILED_THIN1); + + // The only valid tile modes for fmask are 2D_THIN1 and 3D_THIN1 plus non-displayable + INT_32 tileIndex = tileMode == ADDR_TM_2D_TILED_THIN1 ? 14 : 15; + ADDR_SURFACE_FLAGS flags = {{0}}; + flags.fmask = 1; + + INT_32 macroModeIndex = TileIndexInvalid; + + UINT_32 numSamples = pIn->numSamples; + UINT_32 numFrags = pIn->numFrags == 0 ? numSamples : pIn->numFrags; + + UINT_32 bpp = QLog2(numFrags); + + // EQAA needs one more bit + if (numSamples > numFrags) + { + bpp++; + } + + if (bpp == 3) + { + bpp = 4; + } + + bpp = Max(8u, bpp * numSamples); + + macroModeIndex = HwlComputeMacroModeIndex(tileIndex, flags, bpp, numSamples, pOut->pTileInfo); + + fmaskIn.tileIndex = tileIndex; + fmaskIn.pTileInfo = pOut->pTileInfo; + pOut->macroModeIndex = macroModeIndex; + pOut->tileIndex = tileIndex; + + retCode = DispatchComputeFmaskInfo(&fmaskIn, pOut); + + if (retCode == ADDR_OK) + { + pOut->tileIndex = + HwlPostCheckTileIndex(pOut->pTileInfo, pIn->tileMode, ADDR_NON_DISPLAYABLE, + pOut->tileIndex); + } + + // Resets pTileInfo to NULL if the internal tile info is used + if (pOut->pTileInfo == &tileInfo) + { + pOut->pTileInfo = NULL; + } + + return retCode; +} + +/** +*************************************************************************************************** +* CIAddrLib::HwlFmaskPreThunkSurfInfo +* +* @brief +* Some preparation before thunking a ComputeSurfaceInfo call for Fmask +* @return +* ADDR_E_RETURNCODE +*************************************************************************************************** +*/ +VOID CIAddrLib::HwlFmaskPreThunkSurfInfo( + const ADDR_COMPUTE_FMASK_INFO_INPUT* pFmaskIn, ///< [in] Input of fmask info + const ADDR_COMPUTE_FMASK_INFO_OUTPUT* pFmaskOut, ///< [in] Output of fmask info + ADDR_COMPUTE_SURFACE_INFO_INPUT* pSurfIn, ///< [out] Input of thunked surface info + ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pSurfOut ///< [out] Output of thunked surface info + ) const +{ + pSurfIn->tileIndex = pFmaskIn->tileIndex; + pSurfOut->macroModeIndex = pFmaskOut->macroModeIndex; +} + +/** +*************************************************************************************************** +* CIAddrLib::HwlFmaskPostThunkSurfInfo +* +* @brief +* Copy hwl extra field after calling thunked ComputeSurfaceInfo +* @return +* ADDR_E_RETURNCODE +*************************************************************************************************** +*/ +VOID CIAddrLib::HwlFmaskPostThunkSurfInfo( + const ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pSurfOut, ///< [in] Output of surface info + ADDR_COMPUTE_FMASK_INFO_OUTPUT* pFmaskOut ///< [out] Output of fmask info + ) const +{ + pFmaskOut->tileIndex = pSurfOut->tileIndex; + pFmaskOut->macroModeIndex = pSurfOut->macroModeIndex; +} + +/** +*************************************************************************************************** +* CIAddrLib::HwlDegradeThickTileMode +* +* @brief +* Degrades valid tile mode for thick modes if needed +* +* @return +* Suitable tile mode +*************************************************************************************************** +*/ +AddrTileMode CIAddrLib::HwlDegradeThickTileMode( + AddrTileMode baseTileMode, ///< [in] base tile mode + UINT_32 numSlices, ///< [in] current number of slices + UINT_32* pBytesPerTile ///< [in/out] pointer to bytes per slice + ) const +{ + return baseTileMode; +} + +/** +*************************************************************************************************** +* CIAddrLib::HwlOverrideTileMode +* +* @brief +* Override THICK to THIN, for specific formats on CI +* +* @return +* Suitable tile mode +* +*************************************************************************************************** +*/ +BOOL_32 CIAddrLib::HwlOverrideTileMode( + const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] input structure + AddrTileMode* pTileMode, ///< [in/out] pointer to the tile mode + AddrTileType* pTileType ///< [in/out] pointer to the tile type + ) const +{ + BOOL_32 bOverrided = FALSE; + AddrTileMode tileMode = *pTileMode; + + // currently, all CI/VI family do not + // support ADDR_TM_PRT_2D_TILED_THICK,ADDR_TM_PRT_3D_TILED_THICK and + // ADDR_TM_PRT_2D_TILED_THIN1, ADDR_TM_PRT_3D_TILED_THIN1 + switch (tileMode) + { + case ADDR_TM_PRT_2D_TILED_THICK: + case ADDR_TM_PRT_3D_TILED_THICK: + tileMode = ADDR_TM_PRT_TILED_THICK; + break; + case ADDR_TM_PRT_2D_TILED_THIN1: + case ADDR_TM_PRT_3D_TILED_THIN1: + tileMode = ADDR_TM_PRT_TILED_THIN1; + break; + default: + break; + } + + // UBTS#404321, we do not need such overriding, as THICK+THICK entries removed from the tile-mode table + if (!m_settings.isBonaire) + { + UINT_32 thickness = ComputeSurfaceThickness(tileMode); + + // tile_thickness = (array_mode == XTHICK) ? 8 : ((array_mode == THICK) ? 4 : 1) + if (thickness > 1) + { + switch (pIn->format) + { + // see //gfxip/gcB/devel/cds/src/verif/tc/models/csim/tcp.cpp + // tcpError("Thick micro tiling is not supported for format... + case ADDR_FMT_X24_8_32_FLOAT: + case ADDR_FMT_32_AS_8: + case ADDR_FMT_32_AS_8_8: + case ADDR_FMT_32_AS_32_32_32_32: + + // packed formats + case ADDR_FMT_GB_GR: + case ADDR_FMT_BG_RG: + case ADDR_FMT_1_REVERSED: + case ADDR_FMT_1: + case ADDR_FMT_BC1: + case ADDR_FMT_BC2: + case ADDR_FMT_BC3: + case ADDR_FMT_BC4: + case ADDR_FMT_BC5: + case ADDR_FMT_BC6: + case ADDR_FMT_BC7: + switch (tileMode) + { + case ADDR_TM_1D_TILED_THICK: + tileMode = ADDR_TM_1D_TILED_THIN1; + break; + + case ADDR_TM_2D_TILED_XTHICK: + case ADDR_TM_2D_TILED_THICK: + tileMode = ADDR_TM_2D_TILED_THIN1; + break; + + case ADDR_TM_3D_TILED_XTHICK: + case ADDR_TM_3D_TILED_THICK: + tileMode = ADDR_TM_3D_TILED_THIN1; + break; + + case ADDR_TM_PRT_TILED_THICK: + tileMode = ADDR_TM_PRT_TILED_THIN1; + break; + + case ADDR_TM_PRT_2D_TILED_THICK: + tileMode = ADDR_TM_PRT_2D_TILED_THIN1; + break; + + case ADDR_TM_PRT_3D_TILED_THICK: + tileMode = ADDR_TM_PRT_3D_TILED_THIN1; + break; + + default: + break; + + } + + // Switch tile type from thick to thin + if (tileMode != *pTileMode) + { + // see tileIndex: 13-18 + *pTileType = ADDR_NON_DISPLAYABLE; + } + + break; + default: + break; + } + } + } + + if (tileMode != *pTileMode) + { + *pTileMode = tileMode; + bOverrided = TRUE; + } + + return bOverrided; +} + +/** +*************************************************************************************************** +* CiAddrLib::GetPrtSwitchP4Threshold +* +* @brief +* Return the threshold of switching to P4_* instead of P16_* for PRT resources +*************************************************************************************************** +*/ +UINT_32 CIAddrLib::GetPrtSwitchP4Threshold() const +{ + UINT_32 threshold; + + switch (m_pipes) + { + case 8: + threshold = 32; + break; + case 16: + if (m_settings.isFiji) + { + threshold = 16; + } + else if (m_settings.isHawaii) + { + threshold = 8; + } + else + { + ///@todo add for possible new ASICs. + ADDR_ASSERT_ALWAYS(); + threshold = 16; + } + break; + default: + ///@todo add for possible new ASICs. + ADDR_ASSERT_ALWAYS(); + threshold = 32; + break; + } + + return threshold; +} + +/** +*************************************************************************************************** +* CIAddrLib::HwlSetupTileInfo +* +* @brief +* Setup default value of tile info for SI +*************************************************************************************************** +*/ +VOID CIAddrLib::HwlSetupTileInfo( + AddrTileMode tileMode, ///< [in] Tile mode + ADDR_SURFACE_FLAGS flags, ///< [in] Surface type flags + UINT_32 bpp, ///< [in] Bits per pixel + UINT_32 pitch, ///< [in] Pitch in pixels + UINT_32 height, ///< [in] Height in pixels + UINT_32 numSamples, ///< [in] Number of samples + ADDR_TILEINFO* pTileInfoIn, ///< [in] Tile info input: NULL for default + ADDR_TILEINFO* pTileInfoOut, ///< [out] Tile info output + AddrTileType inTileType, ///< [in] Tile type + ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [out] Output + ) const +{ + UINT_32 thickness = ComputeSurfaceThickness(tileMode); + ADDR_TILEINFO* pTileInfo = pTileInfoOut; + INT index = TileIndexInvalid; + INT macroModeIndex = TileIndexInvalid; + + // Fail-safe code + if (!IsLinear(tileMode)) + { + // Thick tile modes must use thick micro tile mode but Bonaire does not support due to + // old derived netlists (UBTS 404321) + if (thickness > 1) + { + if (m_settings.isBonaire) + { + inTileType = ADDR_NON_DISPLAYABLE; + } + else if ((m_allowNonDispThickModes == FALSE) || (inTileType != ADDR_NON_DISPLAYABLE)) + { + inTileType = ADDR_THICK; + } + } + // 128 bpp tiling must be non-displayable. + // Fmask reuse color buffer's entry but bank-height field can be from another entry + // To simplify the logic, fmask entry should be picked from non-displayable ones + else if (bpp == 128 || flags.fmask) + { + inTileType = ADDR_NON_DISPLAYABLE; + } + // These two modes only have non-disp entries though they can be other micro tile modes + else if (tileMode == ADDR_TM_3D_TILED_THIN1 || tileMode == ADDR_TM_PRT_3D_TILED_THIN1) + { + inTileType = ADDR_NON_DISPLAYABLE; + } + + if (flags.depth || flags.stencil) + { + inTileType = ADDR_DEPTH_SAMPLE_ORDER; + } + } + + if (IsTileInfoAllZero(pTileInfo)) + { + // See table entries 0-4 + if (flags.depth || flags.stencil) + { + if (flags.depth && flags.tcCompatible) + { + // tileSize = bpp * numSamples * 8 * 8 / 8 + UINT_32 tileSize = bpp * numSamples * 8; + + // Texure readable depth surface should not be split + switch (tileSize) + { + case 128: + index = 1; + break; + case 256: + index = 2; + break; + case 512: + index = 3; + break; + default: + index = 4; + break; + } + } + else + { + // Depth and stencil need to use the same index, thus the pre-defined tile_split + // can meet the requirement to choose the same macro mode index + // uncompressed depth/stencil are not supported for now + switch (numSamples) + { + case 1: + index = 0; + break; + case 2: + case 4: + index = 1; + break; + case 8: + index = 2; + break; + default: + break; + } + } + } + + // See table entries 5-6 + if (inTileType == ADDR_DEPTH_SAMPLE_ORDER) + { + switch (tileMode) + { + case ADDR_TM_1D_TILED_THIN1: + index = 5; + break; + case ADDR_TM_PRT_TILED_THIN1: + index = 6; + break; + default: + break; + } + } + + // See table entries 8-12 + if (inTileType == ADDR_DISPLAYABLE) + { + switch (tileMode) + { + case ADDR_TM_1D_TILED_THIN1: + index = 9; + break; + case ADDR_TM_2D_TILED_THIN1: + index = 10; + break; + case ADDR_TM_PRT_TILED_THIN1: + index = 11; + break; + default: + break; + } + } + + // See table entries 13-18 + if (inTileType == ADDR_NON_DISPLAYABLE) + { + switch (tileMode) + { + case ADDR_TM_1D_TILED_THIN1: + index = 13; + break; + case ADDR_TM_2D_TILED_THIN1: + index = 14; + break; + case ADDR_TM_3D_TILED_THIN1: + index = 15; + break; + case ADDR_TM_PRT_TILED_THIN1: + index = 16; + break; + default: + break; + } + } + + // See table entries 19-26 + if (thickness > 1) + { + switch (tileMode) + { + case ADDR_TM_1D_TILED_THICK: + //special check for bonaire, for the compatablity between old KMD and new UMD for bonaire + index = ((inTileType == ADDR_THICK) || m_settings.isBonaire) ? 19 : 18; + break; + case ADDR_TM_2D_TILED_THICK: + // special check for bonaire, for the compatablity between old KMD and new UMD for bonaire + index = ((inTileType == ADDR_THICK) || m_settings.isBonaire) ? 20 : 24; + break; + case ADDR_TM_3D_TILED_THICK: + index = 21; + break; + case ADDR_TM_PRT_TILED_THICK: + index = 22; + break; + case ADDR_TM_2D_TILED_XTHICK: + index = 25; + break; + case ADDR_TM_3D_TILED_XTHICK: + index = 26; + break; + default: + break; + } + } + + // See table entries 27-30 + if (inTileType == ADDR_ROTATED) + { + switch (tileMode) + { + case ADDR_TM_1D_TILED_THIN1: + index = 27; + break; + case ADDR_TM_2D_TILED_THIN1: + index = 28; + break; + case ADDR_TM_PRT_TILED_THIN1: + index = 29; + break; + case ADDR_TM_PRT_2D_TILED_THIN1: + index = 30; + break; + default: + break; + } + } + + if (m_pipes >= 8) + { + ADDR_ASSERT((index + 1) < static_cast<INT_32>(m_noOfEntries)); + // Only do this when tile mode table is updated. + if (((tileMode == ADDR_TM_PRT_TILED_THIN1) || (tileMode == ADDR_TM_PRT_TILED_THICK)) && + (m_tileTable[index+1].mode == tileMode)) + { + UINT_32 bytesXSamples = bpp * numSamples / 8; + UINT_32 bytesXThickness = bpp * thickness / 8; + UINT_32 switchP4Threshold = GetPrtSwitchP4Threshold(); + + if ((bytesXSamples > switchP4Threshold) || (bytesXThickness > switchP4Threshold)) + { + // Pick next 4 pipe entry + index += 1; + } + } + } + } + else + { + // A pre-filled tile info is ready + index = pOut->tileIndex; + macroModeIndex = pOut->macroModeIndex; + + // pass tile type back for post tile index compute + pOut->tileType = inTileType; + } + + // We only need to set up tile info if there is a valid index but macroModeIndex is invalid + if (index != TileIndexInvalid && macroModeIndex == TileIndexInvalid) + { + macroModeIndex = HwlComputeMacroModeIndex(index, flags, bpp, numSamples, pTileInfo); + + /// Copy to pOut->tileType/tileIndex/macroModeIndex + pOut->tileIndex = index; + pOut->tileType = m_tileTable[index].type; // Or inTileType, the samea + pOut->macroModeIndex = macroModeIndex; + } + else if (tileMode == ADDR_TM_LINEAR_GENERAL) + { + pOut->tileIndex = TileIndexLinearGeneral; + + // Copy linear-aligned entry?? + *pTileInfo = m_tileTable[8].info; + } + else if (tileMode == ADDR_TM_LINEAR_ALIGNED) + { + pOut->tileIndex = 8; + *pTileInfo = m_tileTable[8].info; + } +} + +/** +*************************************************************************************************** +* CIAddrLib::ReadGbTileMode +* +* @brief +* Convert GB_TILE_MODE HW value to ADDR_TILE_CONFIG. +* @return +* NA. +*************************************************************************************************** +*/ +VOID CIAddrLib::ReadGbTileMode( + UINT_32 regValue, ///< [in] GB_TILE_MODE register + ADDR_TILECONFIG* pCfg ///< [out] output structure + ) const +{ + GB_TILE_MODE gbTileMode; + gbTileMode.val = regValue; + + pCfg->type = static_cast<AddrTileType>(gbTileMode.f.micro_tile_mode_new); + pCfg->info.pipeConfig = static_cast<AddrPipeCfg>(gbTileMode.f.pipe_config + 1); + + if (pCfg->type == ADDR_DEPTH_SAMPLE_ORDER) + { + pCfg->info.tileSplitBytes = 64 << gbTileMode.f.tile_split; + } + else + { + pCfg->info.tileSplitBytes = 1 << gbTileMode.f.sample_split; + } + + UINT_32 regArrayMode = gbTileMode.f.array_mode; + + pCfg->mode = static_cast<AddrTileMode>(regArrayMode); + + switch (regArrayMode) + { + case 5: + pCfg->mode = ADDR_TM_PRT_TILED_THIN1; + break; + case 6: + pCfg->mode = ADDR_TM_PRT_2D_TILED_THIN1; + break; + case 8: + pCfg->mode = ADDR_TM_2D_TILED_XTHICK; + break; + case 9: + pCfg->mode = ADDR_TM_PRT_TILED_THICK; + break; + case 0xa: + pCfg->mode = ADDR_TM_PRT_2D_TILED_THICK; + break; + case 0xb: + pCfg->mode = ADDR_TM_PRT_3D_TILED_THIN1; + break; + case 0xe: + pCfg->mode = ADDR_TM_3D_TILED_XTHICK; + break; + case 0xf: + pCfg->mode = ADDR_TM_PRT_3D_TILED_THICK; + break; + default: + break; + } + + // Fail-safe code for these always convert tile info, as the non-macro modes + // return the entry of tile mode table directly without looking up macro mode table + if (!IsMacroTiled(pCfg->mode)) + { + pCfg->info.banks = 2; + pCfg->info.bankWidth = 1; + pCfg->info.bankHeight = 1; + pCfg->info.macroAspectRatio = 1; + pCfg->info.tileSplitBytes = 64; + } +} + +/** +*************************************************************************************************** +* CIAddrLib::InitTileSettingTable +* +* @brief +* Initialize the ADDR_TILE_CONFIG table. +* @return +* TRUE if tile table is correctly initialized +*************************************************************************************************** +*/ +BOOL_32 CIAddrLib::InitTileSettingTable( + const UINT_32* pCfg, ///< [in] Pointer to table of tile configs + UINT_32 noOfEntries ///< [in] Numbe of entries in the table above + ) +{ + BOOL_32 initOk = TRUE; + + ADDR_ASSERT(noOfEntries <= TileTableSize); + + memset(m_tileTable, 0, sizeof(m_tileTable)); + + if (noOfEntries != 0) + { + m_noOfEntries = noOfEntries; + } + else + { + m_noOfEntries = TileTableSize; + } + + if (pCfg) // From Client + { + for (UINT_32 i = 0; i < m_noOfEntries; i++) + { + ReadGbTileMode(*(pCfg + i), &m_tileTable[i]); + } + } + else + { + ADDR_ASSERT_ALWAYS(); + initOk = FALSE; + } + + if (initOk) + { + ADDR_ASSERT(m_tileTable[TILEINDEX_LINEAR_ALIGNED].mode == ADDR_TM_LINEAR_ALIGNED); + + if (m_settings.isBonaire == FALSE) + { + // Check if entry 18 is "thick+thin" combination + if ((m_tileTable[18].mode == ADDR_TM_1D_TILED_THICK) && + (m_tileTable[18].type == ADDR_NON_DISPLAYABLE)) + { + m_allowNonDispThickModes = TRUE; + ADDR_ASSERT(m_tileTable[24].mode == ADDR_TM_2D_TILED_THICK); + } + } + else + { + m_allowNonDispThickModes = TRUE; + } + + // Assume the first entry is always programmed with full pipes + m_pipes = HwlGetPipes(&m_tileTable[0].info); + } + + return initOk; +} + +/** +*************************************************************************************************** +* CIAddrLib::ReadGbMacroTileCfg +* +* @brief +* Convert GB_MACRO_TILE_CFG HW value to ADDR_TILE_CONFIG. +* @return +* NA. +*************************************************************************************************** +*/ +VOID CIAddrLib::ReadGbMacroTileCfg( + UINT_32 regValue, ///< [in] GB_MACRO_TILE_MODE register + ADDR_TILEINFO* pCfg ///< [out] output structure + ) const +{ + GB_MACROTILE_MODE gbTileMode; + gbTileMode.val = regValue; + + pCfg->bankHeight = 1 << gbTileMode.f.bank_height; + pCfg->bankWidth = 1 << gbTileMode.f.bank_width; + pCfg->banks = 1 << (gbTileMode.f.num_banks + 1); + pCfg->macroAspectRatio = 1 << gbTileMode.f.macro_tile_aspect; +} + +/** +*************************************************************************************************** +* CIAddrLib::InitMacroTileCfgTable +* +* @brief +* Initialize the ADDR_MACRO_TILE_CONFIG table. +* @return +* TRUE if macro tile table is correctly initialized +*************************************************************************************************** +*/ +BOOL_32 CIAddrLib::InitMacroTileCfgTable( + const UINT_32* pCfg, ///< [in] Pointer to table of tile configs + UINT_32 noOfMacroEntries ///< [in] Numbe of entries in the table above + ) +{ + BOOL_32 initOk = TRUE; + + ADDR_ASSERT(noOfMacroEntries <= MacroTileTableSize); + + memset(m_macroTileTable, 0, sizeof(m_macroTileTable)); + + if (noOfMacroEntries != 0) + { + m_noOfMacroEntries = noOfMacroEntries; + } + else + { + m_noOfMacroEntries = MacroTileTableSize; + } + + if (pCfg) // From Client + { + for (UINT_32 i = 0; i < m_noOfMacroEntries; i++) + { + ReadGbMacroTileCfg(*(pCfg + i), &m_macroTileTable[i]); + + m_macroTileTable[i].tileSplitBytes = 64 << (i % 8); + } + } + else + { + ADDR_ASSERT_ALWAYS(); + initOk = FALSE; + } + return initOk; +} + +/** +*************************************************************************************************** +* CIAddrLib::HwlComputeMacroModeIndex +* +* @brief +* Computes macro tile mode index +* @return +* TRUE if macro tile table is correctly initialized +*************************************************************************************************** +*/ +INT_32 CIAddrLib::HwlComputeMacroModeIndex( + INT_32 tileIndex, ///< [in] Tile mode index + ADDR_SURFACE_FLAGS flags, ///< [in] Surface flags + UINT_32 bpp, ///< [in] Bit per pixel + UINT_32 numSamples, ///< [in] Number of samples + ADDR_TILEINFO* pTileInfo, ///< [out] Pointer to ADDR_TILEINFO + AddrTileMode* pTileMode, ///< [out] Pointer to AddrTileMode + AddrTileType* pTileType ///< [out] Pointer to AddrTileType + ) const +{ + INT_32 macroModeIndex = TileIndexInvalid; + + if (flags.tcCompatible && flags.stencil) + { + // Don't compute macroModeIndex for tc compatible stencil surface + macroModeIndex = TileIndexNoMacroIndex; + } + else + { + AddrTileMode tileMode = m_tileTable[tileIndex].mode; + AddrTileType tileType = m_tileTable[tileIndex].type; + UINT_32 thickness = ComputeSurfaceThickness(tileMode); + + if (!IsMacroTiled(tileMode)) + { + *pTileInfo = m_tileTable[tileIndex].info; + macroModeIndex = TileIndexNoMacroIndex; + } + else + { + UINT_32 tileBytes1x = BITS_TO_BYTES(bpp * MicroTilePixels * thickness); + UINT_32 tileSplit; + + if (m_tileTable[tileIndex].type == ADDR_DEPTH_SAMPLE_ORDER) + { + // Depth entries store real tileSplitBytes + tileSplit = m_tileTable[tileIndex].info.tileSplitBytes; + } + else + { + // Non-depth entries store a split factor + UINT_32 sampleSplit = m_tileTable[tileIndex].info.tileSplitBytes; + UINT_32 colorTileSplit = Max(256u, sampleSplit * tileBytes1x); + + tileSplit = colorTileSplit; + } + + UINT_32 tileSplitC = Min(m_rowSize, tileSplit); + UINT_32 tileBytes; + + if (flags.fmask) + { + tileBytes = Min(tileSplitC, tileBytes1x); + } + else + { + tileBytes = Min(tileSplitC, numSamples * tileBytes1x); + } + + if (tileBytes < 64) + { + tileBytes = 64; + } + + macroModeIndex = Log2(tileBytes / 64); + + if (flags.prt || IsPrtTileMode(tileMode)) + { + // Unknown - assume it is 1/2 of table size + const UINT_32 PrtMacroModeOffset = MacroTileTableSize / 2; + + macroModeIndex += PrtMacroModeOffset; + *pTileInfo = m_macroTileTable[macroModeIndex]; + } + else + { + *pTileInfo = m_macroTileTable[macroModeIndex]; + } + + pTileInfo->pipeConfig = m_tileTable[tileIndex].info.pipeConfig; + + if (m_tileTable[tileIndex].type != ADDR_DEPTH_SAMPLE_ORDER) + { + pTileInfo->tileSplitBytes = tileSplitC; + } + else + { + pTileInfo->tileSplitBytes = m_tileTable[tileIndex].info.tileSplitBytes; + } + } + + if (NULL != pTileMode) + { + *pTileMode = tileMode; + } + + if (NULL != pTileType) + { + *pTileType = tileType; + } + } + + return macroModeIndex; +} + +/** +*************************************************************************************************** +* CIAddrLib::HwlComputeTileDataWidthAndHeightLinear +* +* @brief +* Compute the squared cache shape for per-tile data (CMASK and HTILE) for linear layout +* +* @return +* N/A +* +* @note +* MacroWidth and macroHeight are measured in pixels +*************************************************************************************************** +*/ +VOID CIAddrLib::HwlComputeTileDataWidthAndHeightLinear( + UINT_32* pMacroWidth, ///< [out] macro tile width + UINT_32* pMacroHeight, ///< [out] macro tile height + UINT_32 bpp, ///< [in] bits per pixel + ADDR_TILEINFO* pTileInfo ///< [in] tile info + ) const +{ + ADDR_ASSERT(pTileInfo != NULL); + + UINT_32 numTiles; + + switch (pTileInfo->pipeConfig) + { + case ADDR_PIPECFG_P16_32x32_8x16: + case ADDR_PIPECFG_P16_32x32_16x16: + case ADDR_PIPECFG_P8_32x64_32x32: + case ADDR_PIPECFG_P8_32x32_16x32: + case ADDR_PIPECFG_P8_32x32_16x16: + case ADDR_PIPECFG_P8_32x32_8x16: + case ADDR_PIPECFG_P4_32x32: + numTiles = 8; + break; + default: + numTiles = 4; + break; + } + + *pMacroWidth = numTiles * MicroTileWidth; + *pMacroHeight = numTiles * MicroTileHeight; +} + +/** +*************************************************************************************************** +* CIAddrLib::HwlStereoCheckRightOffsetPadding +* +* @brief +* check if the height needs extra padding for stereo right eye offset, to avoid swizzling +* +* @return +* TRUE is the extra padding is needed +* +* @note +* Kalindi (Kabini) is the only one that needs this padding as there is a uncertain +* possible HW issue where the right eye displays incorrectly with some type of swizzles, if +* the right eye offset is not 64KB aligned - EPR#366461 +* Other Kaveri APUs also need the padding according to DXX team's report otherwise +* corruption observed. - EPR#374788 +*************************************************************************************************** +*/ +BOOL_32 CIAddrLib::HwlStereoCheckRightOffsetPadding() const +{ + BOOL_32 bNeedPadding = FALSE; + + if (m_settings.isKaveri) + { + bNeedPadding = TRUE; + } + + return bNeedPadding; +} + +/** +*************************************************************************************************** +* CIAddrLib::HwlComputeMetadataNibbleAddress +* +* @brief +* calculate meta data address based on input information +* +* ¶meter +* uncompressedDataByteAddress - address of a pixel in color surface +* dataBaseByteAddress - base address of color surface +* metadataBaseByteAddress - base address of meta ram +* metadataBitSize - meta key size, 8 for DCC, 4 for cmask +* elementBitSize - element size of color surface +* blockByteSize - compression block size, 256 for DCC +* pipeInterleaveBytes - pipe interleave size +* numOfPipes - number of pipes +* numOfBanks - number of banks +* numOfSamplesPerSplit - number of samples per tile split +* @return +* meta data nibble address (nibble address is used to support DCC compatible cmask) +* +*************************************************************************************************** +*/ +UINT_64 CIAddrLib::HwlComputeMetadataNibbleAddress( + UINT_64 uncompressedDataByteAddress, + UINT_64 dataBaseByteAddress, + UINT_64 metadataBaseByteAddress, + UINT_32 metadataBitSize, + UINT_32 elementBitSize, + UINT_32 blockByteSize, + UINT_32 pipeInterleaveBytes, + UINT_32 numOfPipes, + UINT_32 numOfBanks, + UINT_32 numOfSamplesPerSplit) const +{ + ///-------------------------------------------------------------------------------------------- + /// Get pipe interleave, bank and pipe bits + ///-------------------------------------------------------------------------------------------- + UINT_32 pipeInterleaveBits = Log2(pipeInterleaveBytes); + UINT_32 pipeBits = Log2(numOfPipes); + UINT_32 bankBits = Log2(numOfBanks); + + ///-------------------------------------------------------------------------------------------- + /// Clear pipe and bank swizzles + ///-------------------------------------------------------------------------------------------- + UINT_32 dataMacrotileBits = pipeInterleaveBits + pipeBits + bankBits; + UINT_32 metadataMacrotileBits = pipeInterleaveBits + pipeBits + bankBits; + + UINT_64 dataMacrotileClearMask = ~((1L << dataMacrotileBits) - 1); + UINT_64 metadataMacrotileClearMask = ~((1L << metadataMacrotileBits) - 1); + + UINT_64 dataBaseByteAddressNoSwizzle = dataBaseByteAddress & dataMacrotileClearMask; + UINT_64 metadataBaseByteAddressNoSwizzle = metadataBaseByteAddress & metadataMacrotileClearMask; + + ///-------------------------------------------------------------------------------------------- + /// Modify metadata base before adding in so that when final address is divided by data ratio, + /// the base address returns to where it should be + ///-------------------------------------------------------------------------------------------- + ADDR_ASSERT((0 != metadataBitSize)); + UINT_64 metadataBaseShifted = metadataBaseByteAddressNoSwizzle * blockByteSize * 8 / + metadataBitSize; + UINT_64 offset = uncompressedDataByteAddress - + dataBaseByteAddressNoSwizzle + + metadataBaseShifted; + + ///-------------------------------------------------------------------------------------------- + /// Save bank data bits + ///-------------------------------------------------------------------------------------------- + UINT_32 lsb = pipeBits + pipeInterleaveBits; + UINT_32 msb = bankBits - 1 + lsb; + + UINT_64 bankDataBits = AddrGetBits(offset, msb, lsb); + + ///-------------------------------------------------------------------------------------------- + /// Save pipe data bits + ///-------------------------------------------------------------------------------------------- + lsb = pipeInterleaveBits; + msb = pipeBits - 1 + lsb; + + UINT_64 pipeDataBits = AddrGetBits(offset, msb, lsb); + + ///-------------------------------------------------------------------------------------------- + /// Remove pipe and bank bits + ///-------------------------------------------------------------------------------------------- + lsb = pipeInterleaveBits; + msb = dataMacrotileBits - 1; + + UINT_64 offsetWithoutPipeBankBits = AddrRemoveBits(offset, msb, lsb); + + ADDR_ASSERT((0 != blockByteSize)); + UINT_64 blockInBankpipe = offsetWithoutPipeBankBits / blockByteSize; + + UINT_32 tileSize = 8 * 8 * elementBitSize/8 * numOfSamplesPerSplit; + UINT_32 blocksInTile = tileSize / blockByteSize; + + if (0 == blocksInTile) + { + lsb = 0; + } + else + { + lsb = Log2(blocksInTile); + } + msb = bankBits - 1 + lsb; + + UINT_64 blockInBankpipeWithBankBits = AddrInsertBits(blockInBankpipe, bankDataBits, msb, lsb); + + /// NOTE *2 because we are converting to Nibble address in this step + UINT_64 metaAddressInPipe = blockInBankpipeWithBankBits * 2 * metadataBitSize / 8; + + + ///-------------------------------------------------------------------------------------------- + /// Reinsert pipe bits back into the final address + ///-------------------------------------------------------------------------------------------- + lsb = pipeInterleaveBits + 1; ///<+1 due to Nibble address now gives interleave bits extra lsb. + msb = pipeBits - 1 + lsb; + UINT_64 metadataAddress = AddrInsertBits(metaAddressInPipe, pipeDataBits, msb, lsb); + + return metadataAddress; +} + +/** +*************************************************************************************************** +* CIAddrLib::HwlPadDimensions +* +* @brief +* Helper function to pad dimensions +* +* @return +* N/A +* +*************************************************************************************************** +*/ +VOID CIAddrLib::HwlPadDimensions( + AddrTileMode tileMode, ///< [in] tile mode + UINT_32 bpp, ///< [in] bits per pixel + ADDR_SURFACE_FLAGS flags, ///< [in] surface flags + UINT_32 numSamples, ///< [in] number of samples + ADDR_TILEINFO* pTileInfo, ///< [in/out] bank structure. + UINT_32 padDims, ///< [in] Dimensions to pad valid value 1,2,3 + UINT_32 mipLevel, ///< [in] MipLevel + UINT_32* pPitch, ///< [in/out] pitch in pixels + UINT_32 pitchAlign, ///< [in] pitch alignment + UINT_32* pHeight, ///< [in/out] height in pixels + UINT_32 heightAlign, ///< [in] height alignment + UINT_32* pSlices, ///< [in/out] number of slices + UINT_32 sliceAlign ///< [in] number of slice alignment + ) const +{ + if (m_settings.isVolcanicIslands && + flags.dccCompatible && + (numSamples > 1) && + (mipLevel == 0) && + IsMacroTiled(tileMode)) + { + UINT_32 tileSizePerSample = BITS_TO_BYTES(bpp * MicroTileWidth * MicroTileHeight); + UINT_32 samplesPerSplit = pTileInfo->tileSplitBytes / tileSizePerSample; + + if (samplesPerSplit < numSamples) + { + UINT_32 dccFastClearByteAlign = HwlGetPipes(pTileInfo) * m_pipeInterleaveBytes * 256; + UINT_32 bytesPerSplit = BITS_TO_BYTES((*pPitch) * (*pHeight) * bpp * samplesPerSplit); + + ADDR_ASSERT(IsPow2(dccFastClearByteAlign)); + + if (0 != (bytesPerSplit & (dccFastClearByteAlign - 1))) + { + UINT_32 dccFastClearPixelAlign = dccFastClearByteAlign / + BITS_TO_BYTES(bpp) / + samplesPerSplit; + UINT_32 macroTilePixelAlign = pitchAlign * heightAlign; + + if ((dccFastClearPixelAlign >= macroTilePixelAlign) && + ((dccFastClearPixelAlign % macroTilePixelAlign) == 0)) + { + UINT_32 dccFastClearPitchAlignInMacroTile = + dccFastClearPixelAlign / macroTilePixelAlign; + UINT_32 heightInMacroTile = *pHeight / heightAlign; + UINT_32 dccFastClearPitchAlignInPixels; + + while ((heightInMacroTile > 1) && + ((heightInMacroTile % 2) == 0) && + (dccFastClearPitchAlignInMacroTile > 1) && + ((dccFastClearPitchAlignInMacroTile % 2) == 0)) + { + heightInMacroTile >>= 1; + dccFastClearPitchAlignInMacroTile >>= 1; + } + + dccFastClearPitchAlignInPixels = pitchAlign * dccFastClearPitchAlignInMacroTile; + + if (IsPow2(dccFastClearPitchAlignInPixels)) + { + *pPitch = PowTwoAlign((*pPitch), dccFastClearPitchAlignInPixels); + } + else + { + *pPitch += (dccFastClearPitchAlignInPixels - 1); + *pPitch /= dccFastClearPitchAlignInPixels; + *pPitch *= dccFastClearPitchAlignInPixels; + } + } + } + } + } +} + diff --git a/src/amd/addrlib/r800/ciaddrlib.h b/src/amd/addrlib/r800/ciaddrlib.h new file mode 100644 index 00000000000..de995fa4058 --- /dev/null +++ b/src/amd/addrlib/r800/ciaddrlib.h @@ -0,0 +1,202 @@ +/* + * Copyright © 2014 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS + * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + */ + +/** +*************************************************************************************************** +* @file ciaddrlib.h +* @brief Contains the CIAddrLib class definition. +*************************************************************************************************** +*/ + +#ifndef __CI_ADDR_LIB_H__ +#define __CI_ADDR_LIB_H__ + +#include "addrlib.h" +#include "siaddrlib.h" + +/** +*************************************************************************************************** +* @brief CI specific settings structure. +*************************************************************************************************** +*/ +struct CIChipSettings +{ + struct + { + UINT_32 isSeaIsland : 1; + UINT_32 isBonaire : 1; + UINT_32 isKaveri : 1; + UINT_32 isSpectre : 1; + UINT_32 isSpooky : 1; + UINT_32 isKalindi : 1; + // Hawaii is GFXIP 7.2, similar with CI (Bonaire) + UINT_32 isHawaii : 1; + + // VI + UINT_32 isVolcanicIslands : 1; + UINT_32 isIceland : 1; + UINT_32 isTonga : 1; + UINT_32 isFiji : 1; + UINT_32 isPolaris10 : 1; + UINT_32 isPolaris11 : 1; + // VI fusion (Carrizo) + UINT_32 isCarrizo : 1; + }; +}; + +/** +*************************************************************************************************** +* @brief This class is the CI specific address library +* function set. +*************************************************************************************************** +*/ +class CIAddrLib : public SIAddrLib +{ +public: + /// Creates CIAddrLib object + static AddrLib* CreateObj(const AddrClient* pClient) + { + return new(pClient) CIAddrLib(pClient); + } + +private: + CIAddrLib(const AddrClient* pClient); + virtual ~CIAddrLib(); + +protected: + + // Hwl interface - defined in AddrLib + virtual ADDR_E_RETURNCODE HwlComputeSurfaceInfo( + const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, + ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut) const; + + virtual ADDR_E_RETURNCODE HwlComputeFmaskInfo( + const ADDR_COMPUTE_FMASK_INFO_INPUT* pIn, + ADDR_COMPUTE_FMASK_INFO_OUTPUT* pOut); + + virtual AddrChipFamily HwlConvertChipFamily( + UINT_32 uChipFamily, UINT_32 uChipRevision); + + virtual BOOL_32 HwlInitGlobalParams( + const ADDR_CREATE_INPUT* pCreateIn); + + virtual ADDR_E_RETURNCODE HwlSetupTileCfg( + INT_32 index, INT_32 macroModeIndex, ADDR_TILEINFO* pInfo, + AddrTileMode* pMode = 0, AddrTileType* pType = 0) const; + + virtual VOID HwlComputeTileDataWidthAndHeightLinear( + UINT_32* pMacroWidth, UINT_32* pMacroHeight, + UINT_32 bpp, ADDR_TILEINFO* pTileInfo) const; + + virtual INT_32 HwlComputeMacroModeIndex( + INT_32 tileIndex, ADDR_SURFACE_FLAGS flags, UINT_32 bpp, UINT_32 numSamples, + ADDR_TILEINFO* pTileInfo, AddrTileMode* pTileMode = NULL, AddrTileType* pTileType = NULL + ) const; + + // Sub-hwl interface - defined in EgBasedAddrLib + virtual VOID HwlSetupTileInfo( + AddrTileMode tileMode, ADDR_SURFACE_FLAGS flags, + UINT_32 bpp, UINT_32 pitch, UINT_32 height, UINT_32 numSamples, + ADDR_TILEINFO* inputTileInfo, ADDR_TILEINFO* outputTileInfo, + AddrTileType inTileType, ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut) const; + + virtual INT_32 HwlPostCheckTileIndex( + const ADDR_TILEINFO* pInfo, AddrTileMode mode, AddrTileType type, + INT curIndex = TileIndexInvalid) const; + + virtual VOID HwlFmaskPreThunkSurfInfo( + const ADDR_COMPUTE_FMASK_INFO_INPUT* pFmaskIn, + const ADDR_COMPUTE_FMASK_INFO_OUTPUT* pFmaskOut, + ADDR_COMPUTE_SURFACE_INFO_INPUT* pSurfIn, + ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pSurfOut) const; + + virtual VOID HwlFmaskPostThunkSurfInfo( + const ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pSurfOut, + ADDR_COMPUTE_FMASK_INFO_OUTPUT* pFmaskOut) const; + + virtual AddrTileMode HwlDegradeThickTileMode( + AddrTileMode baseTileMode, UINT_32 numSlices, UINT_32* pBytesPerTile) const; + + virtual BOOL_32 HwlOverrideTileMode( + const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, + AddrTileMode* pTileMode, + AddrTileType* pTileType) const; + + virtual BOOL_32 HwlStereoCheckRightOffsetPadding() const; + + virtual ADDR_E_RETURNCODE HwlComputeDccInfo( + const ADDR_COMPUTE_DCCINFO_INPUT* pIn, + ADDR_COMPUTE_DCCINFO_OUTPUT* pOut) const; + + virtual ADDR_E_RETURNCODE HwlComputeCmaskAddrFromCoord( + const ADDR_COMPUTE_CMASK_ADDRFROMCOORD_INPUT* pIn, + ADDR_COMPUTE_CMASK_ADDRFROMCOORD_OUTPUT* pOut) const; + +protected: + virtual VOID HwlPadDimensions( + AddrTileMode tileMode, UINT_32 bpp, ADDR_SURFACE_FLAGS flags, + UINT_32 numSamples, ADDR_TILEINFO* pTileInfo, UINT_32 padDims, UINT_32 mipLevel, + UINT_32* pPitch, UINT_32 pitchAlign, UINT_32* pHeight, UINT_32 heightAlign, + UINT_32* pSlices, UINT_32 sliceAlign) const; + +private: + VOID ReadGbTileMode( + UINT_32 regValue, ADDR_TILECONFIG* pCfg) const; + + VOID ReadGbMacroTileCfg( + UINT_32 regValue, ADDR_TILEINFO* pCfg) const; + + UINT_32 GetPrtSwitchP4Threshold() const; + + BOOL_32 InitTileSettingTable( + const UINT_32 *pSetting, UINT_32 noOfEntries); + + BOOL_32 InitMacroTileCfgTable( + const UINT_32 *pSetting, UINT_32 noOfEntries); + + UINT_64 HwlComputeMetadataNibbleAddress( + UINT_64 uncompressedDataByteAddress, + UINT_64 dataBaseByteAddress, + UINT_64 metadataBaseByteAddress, + UINT_32 metadataBitSize, + UINT_32 elementBitSize, + UINT_32 blockByteSize, + UINT_32 pipeInterleaveBytes, + UINT_32 numOfPipes, + UINT_32 numOfBanks, + UINT_32 numOfSamplesPerSplit) const; + + static const UINT_32 MacroTileTableSize = 16; + ADDR_TILEINFO m_macroTileTable[MacroTileTableSize]; + UINT_32 m_noOfMacroEntries; + BOOL_32 m_allowNonDispThickModes; + + CIChipSettings m_settings; +}; + +#endif + + diff --git a/src/amd/addrlib/r800/egbaddrlib.cpp b/src/amd/addrlib/r800/egbaddrlib.cpp new file mode 100644 index 00000000000..e53479839e1 --- /dev/null +++ b/src/amd/addrlib/r800/egbaddrlib.cpp @@ -0,0 +1,4577 @@ +/* + * Copyright © 2014 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS + * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + */ + +/** +*************************************************************************************************** +* @file egbaddrlib.cpp +* @brief Contains the EgBasedAddrLib class implementation +*************************************************************************************************** +*/ + +#include "egbaddrlib.h" + +/** +*************************************************************************************************** +* EgBasedAddrLib::EgBasedAddrLib +* +* @brief +* Constructor +* +* @note +* +*************************************************************************************************** +*/ +EgBasedAddrLib::EgBasedAddrLib(const AddrClient* pClient) : + AddrLib(pClient), + m_ranks(0), + m_logicalBanks(0), + m_bankInterleave(1) +{ +} + +/** +*************************************************************************************************** +* EgBasedAddrLib::~EgBasedAddrLib +* +* @brief +* Destructor +*************************************************************************************************** +*/ +EgBasedAddrLib::~EgBasedAddrLib() +{ +} + +/** +*************************************************************************************************** +* EgBasedAddrLib::DispatchComputeSurfaceInfo +* +* @brief +* Compute surface sizes include padded pitch,height,slices,total size in bytes, +* meanwhile output suitable tile mode and base alignment might be changed in this +* call as well. Results are returned through output parameters. +* +* @return +* TRUE if no error occurs +*************************************************************************************************** +*/ +BOOL_32 EgBasedAddrLib::DispatchComputeSurfaceInfo( + const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] input structure + ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [out] output structure + ) const +{ + AddrTileMode tileMode = pIn->tileMode; + UINT_32 bpp = pIn->bpp; + UINT_32 numSamples = pIn->numSamples; + UINT_32 numFrags = ((pIn->numFrags == 0) ? numSamples : pIn->numFrags); + UINT_32 pitch = pIn->width; + UINT_32 height = pIn->height; + UINT_32 numSlices = pIn->numSlices; + UINT_32 mipLevel = pIn->mipLevel; + ADDR_SURFACE_FLAGS flags = pIn->flags; + + ADDR_TILEINFO tileInfoDef = {0}; + ADDR_TILEINFO* pTileInfo = &tileInfoDef; + + UINT_32 padDims = 0; + BOOL_32 valid; + + tileMode = DegradeLargeThickTile(tileMode, bpp); + + // Only override numSamples for NI above + if (m_chipFamily >= ADDR_CHIP_FAMILY_NI) + { + if (numFrags != numSamples) // This means EQAA + { + // The real surface size needed is determined by number of fragments + numSamples = numFrags; + } + + // Save altered numSamples in pOut + pOut->numSamples = numSamples; + } + + // Caller makes sure pOut->pTileInfo is not NULL, see HwlComputeSurfaceInfo + ADDR_ASSERT(pOut->pTileInfo); + + if (pOut->pTileInfo != NULL) + { + pTileInfo = pOut->pTileInfo; + } + + // Set default values + if (pIn->pTileInfo != NULL) + { + if (pTileInfo != pIn->pTileInfo) + { + *pTileInfo = *pIn->pTileInfo; + } + } + else + { + memset(pTileInfo, 0, sizeof(ADDR_TILEINFO)); + } + + // For macro tile mode, we should calculate default tiling parameters + HwlSetupTileInfo(tileMode, + flags, + bpp, + pitch, + height, + numSamples, + pIn->pTileInfo, + pTileInfo, + pIn->tileType, + pOut); + + if (flags.cube) + { + if (mipLevel == 0) + { + padDims = 2; + } + + if (numSlices == 1) + { + // This is calculating one face, remove cube flag + flags.cube = 0; + } + } + + switch (tileMode) + { + case ADDR_TM_LINEAR_GENERAL://fall through + case ADDR_TM_LINEAR_ALIGNED: + valid = ComputeSurfaceInfoLinear(pIn, pOut, padDims); + break; + + case ADDR_TM_1D_TILED_THIN1://fall through + case ADDR_TM_1D_TILED_THICK: + valid = ComputeSurfaceInfoMicroTiled(pIn, pOut, padDims, tileMode); + break; + + case ADDR_TM_2D_TILED_THIN1: //fall through + case ADDR_TM_2D_TILED_THICK: //fall through + case ADDR_TM_3D_TILED_THIN1: //fall through + case ADDR_TM_3D_TILED_THICK: //fall through + case ADDR_TM_2D_TILED_XTHICK: //fall through + case ADDR_TM_3D_TILED_XTHICK: //fall through + case ADDR_TM_PRT_TILED_THIN1: //fall through + case ADDR_TM_PRT_2D_TILED_THIN1://fall through + case ADDR_TM_PRT_3D_TILED_THIN1://fall through + case ADDR_TM_PRT_TILED_THICK: //fall through + case ADDR_TM_PRT_2D_TILED_THICK://fall through + case ADDR_TM_PRT_3D_TILED_THICK: + valid = ComputeSurfaceInfoMacroTiled(pIn, pOut, padDims, tileMode); + break; + + default: + valid = FALSE; + ADDR_ASSERT_ALWAYS(); + break; + } + + return valid; +} + +/** +*************************************************************************************************** +* EgBasedAddrLib::ComputeSurfaceInfoLinear +* +* @brief +* Compute linear surface sizes include padded pitch, height, slices, total size in +* bytes, meanwhile alignments as well. Since it is linear mode, so output tile mode +* will not be changed here. Results are returned through output parameters. +* +* @return +* TRUE if no error occurs +*************************************************************************************************** +*/ +BOOL_32 EgBasedAddrLib::ComputeSurfaceInfoLinear( + const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] Input structure + ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut, ///< [out] Output structure + UINT_32 padDims ///< [in] Dimensions to padd + ) const +{ + UINT_32 expPitch = pIn->width; + UINT_32 expHeight = pIn->height; + UINT_32 expNumSlices = pIn->numSlices; + + // No linear MSAA on real H/W, keep this for TGL + UINT_32 numSamples = pOut->numSamples; + + const UINT_32 microTileThickness = 1; + + // + // Compute the surface alignments. + // + ComputeSurfaceAlignmentsLinear(pIn->tileMode, + pIn->bpp, + pIn->flags, + &pOut->baseAlign, + &pOut->pitchAlign, + &pOut->heightAlign); + + if ((pIn->tileMode == ADDR_TM_LINEAR_GENERAL) && pIn->flags.color && (pIn->height > 1)) + { +#if !ALT_TEST + // When linear_general surface is accessed in multiple lines, it requires 8 pixels in pitch + // alignment since PITCH_TILE_MAX is in unit of 8 pixels. + // It is OK if it is accessed per line. + ADDR_ASSERT((pIn->width % 8) == 0); +#endif + } + + pOut->depthAlign = microTileThickness; + + expPitch = HwlPreHandleBaseLvl3xPitch(pIn, expPitch); + + // + // Pad pitch and height to the required granularities. + // + PadDimensions(pIn->tileMode, + pIn->bpp, + pIn->flags, + numSamples, + pOut->pTileInfo, + padDims, + pIn->mipLevel, + &expPitch, pOut->pitchAlign, + &expHeight, pOut->heightAlign, + &expNumSlices, microTileThickness); + + expPitch = HwlPostHandleBaseLvl3xPitch(pIn, expPitch); + + // + // Adjust per HWL + // + + UINT_64 logicalSliceSize; + + logicalSliceSize = HwlGetSizeAdjustmentLinear(pIn->tileMode, + pIn->bpp, + numSamples, + pOut->baseAlign, + pOut->pitchAlign, + &expPitch, + &expHeight, + &pOut->heightAlign); + + + pOut->pitch = expPitch; + pOut->height = expHeight; + pOut->depth = expNumSlices; + + pOut->surfSize = logicalSliceSize * expNumSlices; + + pOut->tileMode = pIn->tileMode; + + return TRUE; +} + +/** +*************************************************************************************************** +* EgBasedAddrLib::ComputeSurfaceInfoMicroTiled +* +* @brief +* Compute 1D/Micro Tiled surface sizes include padded pitch, height, slices, total +* size in bytes, meanwhile alignments as well. Results are returned through output +* parameters. +* +* @return +* TRUE if no error occurs +*************************************************************************************************** +*/ +BOOL_32 EgBasedAddrLib::ComputeSurfaceInfoMicroTiled( + const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] Input structure + ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut, ///< [out] Output structure + UINT_32 padDims, ///< [in] Dimensions to padd + AddrTileMode expTileMode ///< [in] Expected tile mode + ) const +{ + BOOL_32 valid = TRUE; + + UINT_32 microTileThickness; + UINT_32 expPitch = pIn->width; + UINT_32 expHeight = pIn->height; + UINT_32 expNumSlices = pIn->numSlices; + + // No 1D MSAA on real H/W, keep this for TGL + UINT_32 numSamples = pOut->numSamples; + + // + // Compute the micro tile thickness. + // + microTileThickness = ComputeSurfaceThickness(expTileMode); + + // + // Extra override for mip levels + // + if (pIn->mipLevel > 0) + { + // + // Reduce tiling mode from thick to thin if the number of slices is less than the + // micro tile thickness. + // + if ((expTileMode == ADDR_TM_1D_TILED_THICK) && + (expNumSlices < ThickTileThickness)) + { + expTileMode = HwlDegradeThickTileMode(ADDR_TM_1D_TILED_THICK, expNumSlices, NULL); + if (expTileMode != ADDR_TM_1D_TILED_THICK) + { + microTileThickness = 1; + } + } + } + + // + // Compute the surface restrictions. + // + ComputeSurfaceAlignmentsMicroTiled(expTileMode, + pIn->bpp, + pIn->flags, + pIn->mipLevel, + numSamples, + &pOut->baseAlign, + &pOut->pitchAlign, + &pOut->heightAlign); + + pOut->depthAlign = microTileThickness; + + // + // Pad pitch and height to the required granularities. + // Compute surface size. + // Return parameters. + // + PadDimensions(expTileMode, + pIn->bpp, + pIn->flags, + numSamples, + pOut->pTileInfo, + padDims, + pIn->mipLevel, + &expPitch, pOut->pitchAlign, + &expHeight, pOut->heightAlign, + &expNumSlices, microTileThickness); + + // + // Get HWL specific pitch adjustment + // + UINT_64 logicalSliceSize = HwlGetSizeAdjustmentMicroTiled(microTileThickness, + pIn->bpp, + pIn->flags, + numSamples, + pOut->baseAlign, + pOut->pitchAlign, + &expPitch, + &expHeight); + + + pOut->pitch = expPitch; + pOut->height = expHeight; + pOut->depth = expNumSlices; + + pOut->surfSize = logicalSliceSize * expNumSlices; + + pOut->tileMode = expTileMode; + + return valid; +} + + +/** +*************************************************************************************************** +* EgBasedAddrLib::ComputeSurfaceInfoMacroTiled +* +* @brief +* Compute 2D/macro tiled surface sizes include padded pitch, height, slices, total +* size in bytes, meanwhile output suitable tile mode and alignments might be changed +* in this call as well. Results are returned through output parameters. +* +* @return +* TRUE if no error occurs +*************************************************************************************************** +*/ +BOOL_32 EgBasedAddrLib::ComputeSurfaceInfoMacroTiled( + const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] Input structure + ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut, ///< [out] Output structure + UINT_32 padDims, ///< [in] Dimensions to padd + AddrTileMode expTileMode ///< [in] Expected tile mode + ) const +{ + BOOL_32 valid = TRUE; + + AddrTileMode origTileMode = expTileMode; + UINT_32 microTileThickness; + + UINT_32 paddedPitch; + UINT_32 paddedHeight; + UINT_64 bytesPerSlice; + + UINT_32 expPitch = pIn->width; + UINT_32 expHeight = pIn->height; + UINT_32 expNumSlices = pIn->numSlices; + + UINT_32 numSamples = pOut->numSamples; + + // + // Compute the surface restrictions as base + // SanityCheckMacroTiled is called in ComputeSurfaceAlignmentsMacroTiled + // + valid = ComputeSurfaceAlignmentsMacroTiled(expTileMode, + pIn->bpp, + pIn->flags, + pIn->mipLevel, + numSamples, + pOut->pTileInfo, + &pOut->baseAlign, + &pOut->pitchAlign, + &pOut->heightAlign); + + if (valid) + { + // + // Compute the micro tile thickness. + // + microTileThickness = ComputeSurfaceThickness(expTileMode); + + // + // Find the correct tiling mode for mip levels + // + if (pIn->mipLevel > 0) + { + // + // Try valid tile mode + // + expTileMode = ComputeSurfaceMipLevelTileMode(expTileMode, + pIn->bpp, + expPitch, + expHeight, + expNumSlices, + numSamples, + pOut->pitchAlign, + pOut->heightAlign, + pOut->pTileInfo); + + if (!IsMacroTiled(expTileMode)) // Downgraded to micro-tiled + { + return ComputeSurfaceInfoMicroTiled(pIn, pOut, padDims, expTileMode); + } + else + { + if (microTileThickness != ComputeSurfaceThickness(expTileMode)) + { + // + // Re-compute if thickness changed since bank-height may be changed! + // + return ComputeSurfaceInfoMacroTiled(pIn, pOut, padDims, expTileMode); + } + } + } + + paddedPitch = expPitch; + paddedHeight = expHeight; + + // + // Re-cal alignment + // + if (expTileMode != origTileMode) // Tile mode is changed but still macro-tiled + { + valid = ComputeSurfaceAlignmentsMacroTiled(expTileMode, + pIn->bpp, + pIn->flags, + pIn->mipLevel, + numSamples, + pOut->pTileInfo, + &pOut->baseAlign, + &pOut->pitchAlign, + &pOut->heightAlign); + } + + // + // Do padding + // + PadDimensions(expTileMode, + pIn->bpp, + pIn->flags, + numSamples, + pOut->pTileInfo, + padDims, + pIn->mipLevel, + &paddedPitch, pOut->pitchAlign, + &paddedHeight, pOut->heightAlign, + &expNumSlices, microTileThickness); + + if (pIn->flags.qbStereo && + (pOut->pStereoInfo != NULL) && + HwlStereoCheckRightOffsetPadding()) + { + // Eye height's bank bits are different from y == 0? + // Since 3D rendering treats right eye buffer starting from y == "eye height" while + // display engine treats it to be 0, so the bank bits may be different, we pad + // more in height to make sure y == "eye height" has the same bank bits as y == 0. + UINT_32 checkMask = pOut->pTileInfo->banks - 1; + UINT_32 bankBits = 0; + do + { + bankBits = (paddedHeight / 8 / pOut->pTileInfo->bankHeight) & checkMask; + + if (bankBits) + { + paddedHeight += pOut->heightAlign; + } + } while (bankBits); + } + + // + // Compute the size of a slice. + // + bytesPerSlice = BITS_TO_BYTES(static_cast<UINT_64>(paddedPitch) * + paddedHeight * NextPow2(pIn->bpp) * numSamples); + + pOut->pitch = paddedPitch; + // Put this check right here to workaround special mipmap cases which the original height + // is needed. + // The original height is pre-stored in pOut->height in PostComputeMipLevel and + // pOut->pitch is needed in HwlCheckLastMacroTiledLvl, too. + if (m_configFlags.checkLast2DLevel && numSamples == 1) // Don't check MSAA + { + // Set a TRUE in pOut if next Level is the first 1D sub level + HwlCheckLastMacroTiledLvl(pIn, pOut); + } + pOut->height = paddedHeight; + + pOut->depth = expNumSlices; + + pOut->surfSize = bytesPerSlice * expNumSlices; + + pOut->tileMode = expTileMode; + + pOut->depthAlign = microTileThickness; + + } // if (valid) + + return valid; +} + +/** +*************************************************************************************************** +* EgBasedAddrLib::ComputeSurfaceAlignmentsLinear +* +* @brief +* Compute linear surface alignment, calculation results are returned through +* output parameters. +* +* @return +* TRUE if no error occurs +*************************************************************************************************** +*/ +BOOL_32 EgBasedAddrLib::ComputeSurfaceAlignmentsLinear( + AddrTileMode tileMode, ///< [in] tile mode + UINT_32 bpp, ///< [in] bits per pixel + ADDR_SURFACE_FLAGS flags, ///< [in] surface flags + UINT_32* pBaseAlign, ///< [out] base address alignment in bytes + UINT_32* pPitchAlign, ///< [out] pitch alignment in pixels + UINT_32* pHeightAlign ///< [out] height alignment in pixels + ) const +{ + BOOL_32 valid = TRUE; + + switch (tileMode) + { + case ADDR_TM_LINEAR_GENERAL: + // + // The required base alignment and pitch and height granularities is to 1 element. + // + *pBaseAlign = (bpp > 8) ? bpp / 8 : 1; + *pPitchAlign = 1; + *pHeightAlign = 1; + break; + case ADDR_TM_LINEAR_ALIGNED: + // + // The required alignment for base is the pipe interleave size. + // The required granularity for pitch is hwl dependent. + // The required granularity for height is one row. + // + *pBaseAlign = m_pipeInterleaveBytes; + *pPitchAlign = HwlGetPitchAlignmentLinear(bpp, flags); + *pHeightAlign = 1; + break; + default: + *pBaseAlign = 1; + *pPitchAlign = 1; + *pHeightAlign = 1; + ADDR_UNHANDLED_CASE(); + break; + } + + AdjustPitchAlignment(flags, pPitchAlign); + + return valid; +} + +/** +*************************************************************************************************** +* EgBasedAddrLib::ComputeSurfaceAlignmentsMicroTiled +* +* @brief +* Compute 1D tiled surface alignment, calculation results are returned through +* output parameters. +* +* @return +* TRUE if no error occurs +*************************************************************************************************** +*/ +BOOL_32 EgBasedAddrLib::ComputeSurfaceAlignmentsMicroTiled( + AddrTileMode tileMode, ///< [in] tile mode + UINT_32 bpp, ///< [in] bits per pixel + ADDR_SURFACE_FLAGS flags, ///< [in] surface flags + UINT_32 mipLevel, ///< [in] mip level + UINT_32 numSamples, ///< [in] number of samples + UINT_32* pBaseAlign, ///< [out] base address alignment in bytes + UINT_32* pPitchAlign, ///< [out] pitch alignment in pixels + UINT_32* pHeightAlign ///< [out] height alignment in pixels + ) const +{ + BOOL_32 valid = TRUE; + + // + // The required alignment for base is the pipe interleave size. + // + *pBaseAlign = m_pipeInterleaveBytes; + + *pPitchAlign = HwlGetPitchAlignmentMicroTiled(tileMode, bpp, flags, numSamples); + + *pHeightAlign = MicroTileHeight; + + AdjustPitchAlignment(flags, pPitchAlign); + + // ECR#393489 + // Workaround 2 for 1D tiling - There is HW bug for Carrizo + // where it requires the following alignments for 1D tiling. + if (flags.czDispCompatible && (mipLevel == 0)) + { + *pBaseAlign = PowTwoAlign(*pBaseAlign, 4096); //Base address MOD 4096 = 0 + *pPitchAlign = PowTwoAlign(*pPitchAlign, 512 / (BITS_TO_BYTES(bpp))); //(8 lines * pitch * bytes per pixel) MOD 4096 = 0 + } + // end Carrizo workaround for 1D tilling + + return valid; +} + + +/** +*************************************************************************************************** +* EgBasedAddrLib::HwlReduceBankWidthHeight +* +* @brief +* Additional checks, reduce bankHeight/bankWidth if needed and possible +* tileSize*BANK_WIDTH*BANK_HEIGHT <= ROW_SIZE +* +* @return +* TRUE if no error occurs +*************************************************************************************************** +*/ +BOOL_32 EgBasedAddrLib::HwlReduceBankWidthHeight( + UINT_32 tileSize, ///< [in] tile size + UINT_32 bpp, ///< [in] bits per pixel + ADDR_SURFACE_FLAGS flags, ///< [in] surface flags + UINT_32 numSamples, ///< [in] number of samples + UINT_32 bankHeightAlign, ///< [in] bank height alignment + UINT_32 pipes, ///< [in] pipes + ADDR_TILEINFO* pTileInfo ///< [in/out] bank structure. + ) const +{ + UINT_32 macroAspectAlign; + BOOL_32 valid = TRUE; + + if (tileSize * pTileInfo->bankWidth * pTileInfo->bankHeight > m_rowSize) + { + BOOL_32 stillGreater = TRUE; + + // Try reducing bankWidth first + if (stillGreater && pTileInfo->bankWidth > 1) + { + while (stillGreater && pTileInfo->bankWidth > 0) + { + pTileInfo->bankWidth >>= 1; + + if (pTileInfo->bankWidth == 0) + { + pTileInfo->bankWidth = 1; + break; + } + + stillGreater = + tileSize * pTileInfo->bankWidth * pTileInfo->bankHeight > m_rowSize; + } + + // bankWidth is reduced above, so we need to recalculate bankHeight and ratio + bankHeightAlign = Max(1u, + m_pipeInterleaveBytes * m_bankInterleave / + (tileSize * pTileInfo->bankWidth) + ); + + // We cannot increase bankHeight so just assert this case. + ADDR_ASSERT((pTileInfo->bankHeight % bankHeightAlign) == 0); + + if (numSamples == 1) + { + macroAspectAlign = Max(1u, + m_pipeInterleaveBytes * m_bankInterleave / + (tileSize * pipes * pTileInfo->bankWidth) + ); + pTileInfo->macroAspectRatio = PowTwoAlign(pTileInfo->macroAspectRatio, + macroAspectAlign); + } + } + + // Early quit bank_height degradation for "64" bit z buffer + if (flags.depth && bpp >= 64) + { + stillGreater = FALSE; + } + + // Then try reducing bankHeight + if (stillGreater && pTileInfo->bankHeight > bankHeightAlign) + { + while (stillGreater && pTileInfo->bankHeight > bankHeightAlign) + { + pTileInfo->bankHeight >>= 1; + + if (pTileInfo->bankHeight < bankHeightAlign) + { + pTileInfo->bankHeight = bankHeightAlign; + break; + } + + stillGreater = + tileSize * pTileInfo->bankWidth * pTileInfo->bankHeight > m_rowSize; + } + } + + valid = !stillGreater; + + // Generate a warning if we still fail to meet this constraint + if (!valid) + { + ADDR_WARN( + 0, ("TILE_SIZE(%d)*BANK_WIDTH(%d)*BANK_HEIGHT(%d) <= ROW_SIZE(%d)", + tileSize, pTileInfo->bankWidth, pTileInfo->bankHeight, m_rowSize)); + } + } + + return valid; +} + +/** +*************************************************************************************************** +* EgBasedAddrLib::ComputeSurfaceAlignmentsMacroTiled +* +* @brief +* Compute 2D tiled surface alignment, calculation results are returned through +* output parameters. +* +* @return +* TRUE if no error occurs +*************************************************************************************************** +*/ +BOOL_32 EgBasedAddrLib::ComputeSurfaceAlignmentsMacroTiled( + AddrTileMode tileMode, ///< [in] tile mode + UINT_32 bpp, ///< [in] bits per pixel + ADDR_SURFACE_FLAGS flags, ///< [in] surface flags + UINT_32 mipLevel, ///< [in] mip level + UINT_32 numSamples, ///< [in] number of samples + ADDR_TILEINFO* pTileInfo, ///< [in/out] bank structure. + UINT_32* pBaseAlign, ///< [out] base address alignment in bytes + UINT_32* pPitchAlign, ///< [out] pitch alignment in pixels + UINT_32* pHeightAlign ///< [out] height alignment in pixels + ) const +{ + BOOL_32 valid = SanityCheckMacroTiled(pTileInfo); + + if (valid) + { + UINT_32 macroTileWidth; + UINT_32 macroTileHeight; + + UINT_32 tileSize; + UINT_32 bankHeightAlign; + UINT_32 macroAspectAlign; + + UINT_32 thickness = ComputeSurfaceThickness(tileMode); + UINT_32 pipes = HwlGetPipes(pTileInfo); + + // + // Align bank height first according to latest h/w spec + // + + // tile_size = MIN(tile_split, 64 * tile_thickness * element_bytes * num_samples) + tileSize = Min(pTileInfo->tileSplitBytes, + BITS_TO_BYTES(64 * thickness * bpp * numSamples)); + + // bank_height_align = + // MAX(1, (pipe_interleave_bytes * bank_interleave)/(tile_size*bank_width)) + bankHeightAlign = Max(1u, + m_pipeInterleaveBytes * m_bankInterleave / + (tileSize * pTileInfo->bankWidth) + ); + + pTileInfo->bankHeight = PowTwoAlign(pTileInfo->bankHeight, bankHeightAlign); + + // num_pipes * bank_width * macro_tile_aspect >= + // (pipe_interleave_size * bank_interleave) / tile_size + if (numSamples == 1) + { + // this restriction is only for mipmap (mipmap's numSamples must be 1) + macroAspectAlign = Max(1u, + m_pipeInterleaveBytes * m_bankInterleave / + (tileSize * pipes * pTileInfo->bankWidth) + ); + pTileInfo->macroAspectRatio = PowTwoAlign(pTileInfo->macroAspectRatio, macroAspectAlign); + } + + valid = HwlReduceBankWidthHeight(tileSize, + bpp, + flags, + numSamples, + bankHeightAlign, + pipes, + pTileInfo); + + // + // The required granularity for pitch is the macro tile width. + // + macroTileWidth = MicroTileWidth * pTileInfo->bankWidth * pipes * + pTileInfo->macroAspectRatio; + + *pPitchAlign = macroTileWidth; + + AdjustPitchAlignment(flags, pPitchAlign); + + // + // The required granularity for height is the macro tile height. + // + macroTileHeight = MicroTileHeight * pTileInfo->bankHeight * pTileInfo->banks / + pTileInfo->macroAspectRatio; + + *pHeightAlign = macroTileHeight; + + // + // Compute base alignment + // + *pBaseAlign = pipes * + pTileInfo->bankWidth * pTileInfo->banks * pTileInfo->bankHeight * tileSize; + + if ((mipLevel == 0) && (flags.prt) && (m_chipFamily == ADDR_CHIP_FAMILY_SI)) + { + static const UINT_32 PrtTileSize = 0x10000; + + UINT_32 macroTileSize = macroTileWidth * macroTileHeight * numSamples * bpp / 8; + + if (macroTileSize < PrtTileSize) + { + UINT_32 numMacroTiles = PrtTileSize / macroTileSize; + + ADDR_ASSERT((PrtTileSize % macroTileSize) == 0); + + *pPitchAlign *= numMacroTiles; + *pBaseAlign *= numMacroTiles; + } + } + } + + return valid; +} + +/** +*************************************************************************************************** +* EgBasedAddrLib::SanityCheckMacroTiled +* +* @brief +* Check if macro-tiled parameters are valid +* @return +* TRUE if valid +*************************************************************************************************** +*/ +BOOL_32 EgBasedAddrLib::SanityCheckMacroTiled( + ADDR_TILEINFO* pTileInfo ///< [in] macro-tiled parameters + ) const +{ + BOOL_32 valid = TRUE; + UINT_32 numPipes = HwlGetPipes(pTileInfo); + + switch (pTileInfo->banks) + { + case 2: //fall through + case 4: //fall through + case 8: //fall through + case 16: + break; + default: + valid = FALSE; + break; + + } + + if (valid) + { + switch (pTileInfo->bankWidth) + { + case 1: //fall through + case 2: //fall through + case 4: //fall through + case 8: + break; + default: + valid = FALSE; + break; + } + } + + if (valid) + { + switch (pTileInfo->bankHeight) + { + case 1: //fall through + case 2: //fall through + case 4: //fall through + case 8: + break; + default: + valid = FALSE; + break; + } + } + + if (valid) + { + switch (pTileInfo->macroAspectRatio) + { + case 1: //fall through + case 2: //fall through + case 4: //fall through + case 8: + break; + default: + valid = FALSE; + break; + } + } + + if (valid) + { + if (pTileInfo->banks < pTileInfo->macroAspectRatio) + { + // This will generate macro tile height <= 1 + valid = FALSE; + } + } + + if (valid) + { + if (pTileInfo->tileSplitBytes > m_rowSize) + { + valid = FALSE; + } + } + + if (valid) + { + valid = HwlSanityCheckMacroTiled(pTileInfo); + } + + ADDR_ASSERT(valid == TRUE); + + // Add this assert for guidance + ADDR_ASSERT(numPipes * pTileInfo->banks >= 4); + + return valid; +} + +/** +*************************************************************************************************** +* EgBasedAddrLib::ComputeSurfaceMipLevelTileMode +* +* @brief +* Compute valid tile mode for surface mipmap sub-levels +* +* @return +* Suitable tile mode +*************************************************************************************************** +*/ +AddrTileMode EgBasedAddrLib::ComputeSurfaceMipLevelTileMode( + AddrTileMode baseTileMode, ///< [in] base tile mode + UINT_32 bpp, ///< [in] bits per pixels + UINT_32 pitch, ///< [in] current level pitch + UINT_32 height, ///< [in] current level height + UINT_32 numSlices, ///< [in] current number of slices + UINT_32 numSamples, ///< [in] number of samples + UINT_32 pitchAlign, ///< [in] pitch alignment + UINT_32 heightAlign, ///< [in] height alignment + ADDR_TILEINFO* pTileInfo ///< [in] ptr to bank structure + ) const +{ + UINT_32 bytesPerTile; + + AddrTileMode expTileMode = baseTileMode; + UINT_32 microTileThickness = ComputeSurfaceThickness(expTileMode); + UINT_32 interleaveSize = m_pipeInterleaveBytes * m_bankInterleave; + + // + // Compute the size of a slice. + // + bytesPerTile = BITS_TO_BYTES(MicroTilePixels * microTileThickness * NextPow2(bpp) * numSamples); + + // + // Reduce tiling mode from thick to thin if the number of slices is less than the + // micro tile thickness. + // + if (numSlices < microTileThickness) + { + expTileMode = HwlDegradeThickTileMode(expTileMode, numSlices, &bytesPerTile); + } + + if (bytesPerTile > pTileInfo->tileSplitBytes) + { + bytesPerTile = pTileInfo->tileSplitBytes; + } + + UINT_32 threshold1 = + bytesPerTile * HwlGetPipes(pTileInfo) * pTileInfo->bankWidth * pTileInfo->macroAspectRatio; + + UINT_32 threshold2 = + bytesPerTile * pTileInfo->bankWidth * pTileInfo->bankHeight; + + // + // Reduce the tile mode from 2D/3D to 1D in following conditions + // + switch (expTileMode) + { + case ADDR_TM_2D_TILED_THIN1: //fall through + case ADDR_TM_3D_TILED_THIN1: + case ADDR_TM_PRT_TILED_THIN1: + case ADDR_TM_PRT_2D_TILED_THIN1: + case ADDR_TM_PRT_3D_TILED_THIN1: + if ((pitch < pitchAlign) || + (height < heightAlign) || + (interleaveSize > threshold1) || + (interleaveSize > threshold2)) + { + expTileMode = ADDR_TM_1D_TILED_THIN1; + } + break; + case ADDR_TM_2D_TILED_THICK: //fall through + case ADDR_TM_3D_TILED_THICK: + case ADDR_TM_2D_TILED_XTHICK: + case ADDR_TM_3D_TILED_XTHICK: + case ADDR_TM_PRT_TILED_THICK: + case ADDR_TM_PRT_2D_TILED_THICK: + case ADDR_TM_PRT_3D_TILED_THICK: + if ((pitch < pitchAlign) || + (height < heightAlign)) + { + expTileMode = ADDR_TM_1D_TILED_THICK; + } + break; + default: + break; + } + + return expTileMode; +} + +/** +*************************************************************************************************** +* EgBasedAddrLib::HwlDegradeBaseLevel +* @brief +* Check if degrade is needed for base level +* @return +* TRUE if degrade is suggested +*************************************************************************************************** +*/ +BOOL_32 EgBasedAddrLib::HwlDegradeBaseLevel( + const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn) const +{ + BOOL_32 degrade = FALSE; + BOOL_32 valid = TRUE; + + ADDR_ASSERT(IsMacroTiled(pIn->tileMode)); + + UINT_32 baseAlign; + UINT_32 pitchAlign; + UINT_32 heightAlign; + + ADDR_ASSERT(pIn->pTileInfo); + ADDR_TILEINFO tileInfo = *pIn->pTileInfo; + ADDR_COMPUTE_SURFACE_INFO_OUTPUT out = {0}; + + if (UseTileIndex(pIn->tileIndex)) + { + out.tileIndex = pIn->tileIndex; + out.macroModeIndex = TileIndexInvalid; + } + + HwlSetupTileInfo(pIn->tileMode, + pIn->flags, + pIn->bpp, + pIn->width, + pIn->height, + pIn->numSamples, + &tileInfo, + &tileInfo, + pIn->tileType, + &out); + + valid = ComputeSurfaceAlignmentsMacroTiled(pIn->tileMode, + pIn->bpp, + pIn->flags, + pIn->mipLevel, + pIn->numSamples, + &tileInfo, + &baseAlign, + &pitchAlign, + &heightAlign); + + if (valid) + { + degrade = (pIn->width < pitchAlign || pIn->height < heightAlign); + } + else + { + degrade = TRUE; + } + + return degrade; +} + +/** +*************************************************************************************************** +* EgBasedAddrLib::HwlDegradeThickTileMode +* +* @brief +* Degrades valid tile mode for thick modes if needed +* +* @return +* Suitable tile mode +*************************************************************************************************** +*/ +AddrTileMode EgBasedAddrLib::HwlDegradeThickTileMode( + AddrTileMode baseTileMode, ///< [in] base tile mode + UINT_32 numSlices, ///< [in] current number of slices + UINT_32* pBytesPerTile ///< [in/out] pointer to bytes per slice + ) const +{ + ADDR_ASSERT(numSlices < ComputeSurfaceThickness(baseTileMode)); + // if pBytesPerTile is NULL, this is a don't-care.... + UINT_32 bytesPerTile = pBytesPerTile != NULL ? *pBytesPerTile : 64; + + AddrTileMode expTileMode = baseTileMode; + switch (baseTileMode) + { + case ADDR_TM_1D_TILED_THICK: + expTileMode = ADDR_TM_1D_TILED_THIN1; + bytesPerTile >>= 2; + break; + case ADDR_TM_2D_TILED_THICK: + expTileMode = ADDR_TM_2D_TILED_THIN1; + bytesPerTile >>= 2; + break; + case ADDR_TM_3D_TILED_THICK: + expTileMode = ADDR_TM_3D_TILED_THIN1; + bytesPerTile >>= 2; + break; + case ADDR_TM_2D_TILED_XTHICK: + if (numSlices < ThickTileThickness) + { + expTileMode = ADDR_TM_2D_TILED_THIN1; + bytesPerTile >>= 3; + } + else + { + expTileMode = ADDR_TM_2D_TILED_THICK; + bytesPerTile >>= 1; + } + break; + case ADDR_TM_3D_TILED_XTHICK: + if (numSlices < ThickTileThickness) + { + expTileMode = ADDR_TM_3D_TILED_THIN1; + bytesPerTile >>= 3; + } + else + { + expTileMode = ADDR_TM_3D_TILED_THICK; + bytesPerTile >>= 1; + } + break; + default: + ADDR_ASSERT_ALWAYS(); + break; + } + + if (pBytesPerTile != NULL) + { + *pBytesPerTile = bytesPerTile; + } + + return expTileMode; +} + +/** +*************************************************************************************************** +* EgBasedAddrLib::DispatchComputeSurfaceAddrFromCoord +* +* @brief +* Compute surface address from given coord (x, y, slice,sample) +* +* @return +* Address in bytes +*************************************************************************************************** +*/ +UINT_64 EgBasedAddrLib::DispatchComputeSurfaceAddrFromCoord( + const ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn, ///< [in] input structure + ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT* pOut ///< [out] output structure + ) const +{ + UINT_32 x = pIn->x; + UINT_32 y = pIn->y; + UINT_32 slice = pIn->slice; + UINT_32 sample = pIn->sample; + UINT_32 bpp = pIn->bpp; + UINT_32 pitch = pIn->pitch; + UINT_32 height = pIn->height; + UINT_32 numSlices = pIn->numSlices; + UINT_32 numSamples = ((pIn->numSamples == 0) ? 1 : pIn->numSamples); + UINT_32 numFrags = ((pIn->numFrags == 0) ? numSamples : pIn->numFrags); + AddrTileMode tileMode = pIn->tileMode; + AddrTileType microTileType = pIn->tileType; + BOOL_32 ignoreSE = pIn->ignoreSE; + BOOL_32 isDepthSampleOrder = pIn->isDepth; + ADDR_TILEINFO* pTileInfo = pIn->pTileInfo; + + UINT_32* pBitPosition = &pOut->bitPosition; + UINT_64 addr; + +#if ADDR_AM_BUILD + UINT_32 addr5Bit = 0; + UINT_32 addr5Swizzle = pIn->addr5Swizzle; + BOOL_32 is32ByteTile = pIn->is32ByteTile; +#endif + + // ADDR_DEPTH_SAMPLE_ORDER = non-disp + depth-sample-order + if (microTileType == ADDR_DEPTH_SAMPLE_ORDER) + { + isDepthSampleOrder = TRUE; + } + + if (m_chipFamily >= ADDR_CHIP_FAMILY_NI) + { + if (numFrags != numSamples) + { + numSamples = numFrags; + ADDR_ASSERT(sample < numSamples); + } + + /// @note + /// 128 bit/thick tiled surface doesn't support display tiling and + /// mipmap chain must have the same tileType, so please fill tileType correctly + if (!IsLinear(pIn->tileMode)) + { + if (bpp >= 128 || ComputeSurfaceThickness(tileMode) > 1) + { + ADDR_ASSERT(microTileType != ADDR_DISPLAYABLE); + } + } + } + + switch (tileMode) + { + case ADDR_TM_LINEAR_GENERAL://fall through + case ADDR_TM_LINEAR_ALIGNED: + addr = ComputeSurfaceAddrFromCoordLinear(x, + y, + slice, + sample, + bpp, + pitch, + height, + numSlices, + pBitPosition); + break; + case ADDR_TM_1D_TILED_THIN1://fall through + case ADDR_TM_1D_TILED_THICK: + addr = ComputeSurfaceAddrFromCoordMicroTiled(x, + y, + slice, + sample, + bpp, + pitch, + height, + numSamples, + tileMode, + microTileType, + isDepthSampleOrder, + pBitPosition); + break; + case ADDR_TM_2D_TILED_THIN1: //fall through + case ADDR_TM_2D_TILED_THICK: //fall through + case ADDR_TM_3D_TILED_THIN1: //fall through + case ADDR_TM_3D_TILED_THICK: //fall through + case ADDR_TM_2D_TILED_XTHICK: //fall through + case ADDR_TM_3D_TILED_XTHICK: //fall through + case ADDR_TM_PRT_TILED_THIN1: //fall through + case ADDR_TM_PRT_2D_TILED_THIN1://fall through + case ADDR_TM_PRT_3D_TILED_THIN1://fall through + case ADDR_TM_PRT_TILED_THICK: //fall through + case ADDR_TM_PRT_2D_TILED_THICK://fall through + case ADDR_TM_PRT_3D_TILED_THICK: + UINT_32 pipeSwizzle; + UINT_32 bankSwizzle; + + if (m_configFlags.useCombinedSwizzle) + { + ExtractBankPipeSwizzle(pIn->tileSwizzle, pIn->pTileInfo, + &bankSwizzle, &pipeSwizzle); + } + else + { + pipeSwizzle = pIn->pipeSwizzle; + bankSwizzle = pIn->bankSwizzle; + } + + addr = ComputeSurfaceAddrFromCoordMacroTiled(x, + y, + slice, + sample, + bpp, + pitch, + height, + numSamples, + tileMode, + microTileType, + ignoreSE, + isDepthSampleOrder, + pipeSwizzle, + bankSwizzle, + pTileInfo, + pBitPosition); + break; + default: + addr = 0; + ADDR_ASSERT_ALWAYS(); + break; + } + +#if ADDR_AM_BUILD + if (m_chipFamily >= ADDR_CHIP_FAMILY_NI) + { + if (addr5Swizzle && isDepthSampleOrder && is32ByteTile) + { + UINT_32 tx = x >> 3; + UINT_32 ty = y >> 3; + UINT_32 tileBits = ((ty&0x3) << 2) | (tx&0x3); + + tileBits = tileBits & addr5Swizzle; + addr5Bit = XorReduce(tileBits, 4); + + addr = addr | static_cast<UINT_64>(addr5Bit << 5); + } + } +#endif + + return addr; +} + +/** +*************************************************************************************************** +* EgBasedAddrLib::ComputeSurfaceAddrFromCoordMicroTiled +* +* @brief +* Computes the surface address and bit position from a +* coordinate for 2D tilied (macro tiled) +* @return +* The byte address +*************************************************************************************************** +*/ +UINT_64 EgBasedAddrLib::ComputeSurfaceAddrFromCoordMacroTiled( + UINT_32 x, ///< [in] x coordinate + UINT_32 y, ///< [in] y coordinate + UINT_32 slice, ///< [in] slice index + UINT_32 sample, ///< [in] sample index + UINT_32 bpp, ///< [in] bits per pixel + UINT_32 pitch, ///< [in] surface pitch, in pixels + UINT_32 height, ///< [in] surface height, in pixels + UINT_32 numSamples, ///< [in] number of samples + AddrTileMode tileMode, ///< [in] tile mode + AddrTileType microTileType, ///< [in] micro tiling type + BOOL_32 ignoreSE, ///< [in] TRUE if shader enginers can be ignored + BOOL_32 isDepthSampleOrder, ///< [in] TRUE if it depth sample ordering is used + UINT_32 pipeSwizzle, ///< [in] pipe swizzle + UINT_32 bankSwizzle, ///< [in] bank swizzle + ADDR_TILEINFO* pTileInfo, ///< [in] bank structure + /// **All fields to be valid on entry** + UINT_32* pBitPosition ///< [out] bit position, e.g. FMT_1 will use this + ) const +{ + UINT_64 addr; + + UINT_32 microTileBytes; + UINT_32 microTileBits; + UINT_32 sampleOffset; + UINT_32 pixelIndex; + UINT_32 pixelOffset; + UINT_32 elementOffset; + UINT_32 tileSplitSlice; + UINT_32 pipe; + UINT_32 bank; + UINT_64 sliceBytes; + UINT_64 sliceOffset; + UINT_32 macroTilePitch; + UINT_32 macroTileHeight; + UINT_32 macroTilesPerRow; + UINT_32 macroTilesPerSlice; + UINT_64 macroTileBytes; + UINT_32 macroTileIndexX; + UINT_32 macroTileIndexY; + UINT_64 macroTileOffset; + UINT_64 totalOffset; + UINT_64 pipeInterleaveMask; + UINT_64 bankInterleaveMask; + UINT_64 pipeInterleaveOffset; + UINT_32 bankInterleaveOffset; + UINT_64 offset; + UINT_32 tileRowIndex; + UINT_32 tileColumnIndex; + UINT_32 tileIndex; + UINT_32 tileOffset; + + UINT_32 microTileThickness = ComputeSurfaceThickness(tileMode); + + // + // Compute the number of group, pipe, and bank bits. + // + UINT_32 numPipes = HwlGetPipes(pTileInfo); + UINT_32 numPipeInterleaveBits = Log2(m_pipeInterleaveBytes); + UINT_32 numPipeBits = Log2(numPipes); + UINT_32 numBankInterleaveBits = Log2(m_bankInterleave); + UINT_32 numBankBits = Log2(pTileInfo->banks); + + // + // Compute the micro tile size. + // + microTileBits = MicroTilePixels * microTileThickness * bpp * numSamples; + + microTileBytes = microTileBits / 8; + // + // Compute the pixel index within the micro tile. + // + pixelIndex = ComputePixelIndexWithinMicroTile(x, + y, + slice, + bpp, + tileMode, + microTileType); + + // + // Compute the sample offset and pixel offset. + // + if (isDepthSampleOrder) + { + // + // For depth surfaces, samples are stored contiguously for each element, so the sample + // offset is the sample number times the element size. + // + sampleOffset = sample * bpp; + pixelOffset = pixelIndex * bpp * numSamples; + } + else + { + // + // For color surfaces, all elements for a particular sample are stored contiguously, so + // the sample offset is the sample number times the micro tile size divided yBit the number + // of samples. + // + sampleOffset = sample * (microTileBits / numSamples); + pixelOffset = pixelIndex * bpp; + } + + // + // Compute the element offset. + // + elementOffset = pixelOffset + sampleOffset; + + *pBitPosition = static_cast<UINT_32>(elementOffset % 8); + + elementOffset /= 8; //bit-to-byte + + // + // Determine if tiles need to be split across slices. + // + // If the size of the micro tile is larger than the tile split size, then the tile will be + // split across multiple slices. + // + UINT_32 slicesPerTile = 1; + + if ((microTileBytes > pTileInfo->tileSplitBytes) && (microTileThickness == 1)) + { //don't support for thick mode + + // + // Compute the number of slices per tile. + // + slicesPerTile = microTileBytes / pTileInfo->tileSplitBytes; + + // + // Compute the tile split slice number for use in rotating the bank. + // + tileSplitSlice = elementOffset / pTileInfo->tileSplitBytes; + + // + // Adjust the element offset to account for the portion of the tile that is being moved to + // a new slice.. + // + elementOffset %= pTileInfo->tileSplitBytes; + + // + // Adjust the microTileBytes size to tileSplitBytes size since + // a new slice.. + // + microTileBytes = pTileInfo->tileSplitBytes; + } + else + { + tileSplitSlice = 0; + } + + // + // Compute macro tile pitch and height. + // + macroTilePitch = + (MicroTileWidth * pTileInfo->bankWidth * numPipes) * pTileInfo->macroAspectRatio; + macroTileHeight = + (MicroTileHeight * pTileInfo->bankHeight * pTileInfo->banks) / pTileInfo->macroAspectRatio; + + // + // Compute the number of bytes per macro tile. Note: bytes of the same bank/pipe actually + // + macroTileBytes = + static_cast<UINT_64>(microTileBytes) * + (macroTilePitch / MicroTileWidth) * (macroTileHeight / MicroTileHeight) / + (numPipes * pTileInfo->banks); + + // + // Compute the number of macro tiles per row. + // + macroTilesPerRow = pitch / macroTilePitch; + + // + // Compute the offset to the macro tile containing the specified coordinate. + // + macroTileIndexX = x / macroTilePitch; + macroTileIndexY = y / macroTileHeight; + macroTileOffset = ((macroTileIndexY * macroTilesPerRow) + macroTileIndexX) * macroTileBytes; + + // + // Compute the number of macro tiles per slice. + // + macroTilesPerSlice = macroTilesPerRow * (height / macroTileHeight); + + // + // Compute the slice size. + // + sliceBytes = macroTilesPerSlice * macroTileBytes; + + // + // Compute the slice offset. + // + sliceOffset = sliceBytes * (tileSplitSlice + slicesPerTile * (slice / microTileThickness)); + + // + // Compute tile offest + // + tileRowIndex = (y / MicroTileHeight) % pTileInfo->bankHeight; + tileColumnIndex = ((x / MicroTileWidth) / numPipes) % pTileInfo->bankWidth; + tileIndex = (tileRowIndex * pTileInfo->bankWidth) + tileColumnIndex; + tileOffset = tileIndex * microTileBytes; + + // + // Combine the slice offset and macro tile offset with the pixel and sample offsets, accounting + // for the pipe and bank bits in the middle of the address. + // + totalOffset = sliceOffset + macroTileOffset + elementOffset + tileOffset; + + // + // Get the pipe and bank. + // + + // when the tileMode is PRT type, then adjust x and y coordinates + if (IsPrtNoRotationTileMode(tileMode)) + { + x = x % macroTilePitch; + y = y % macroTileHeight; + } + + pipe = ComputePipeFromCoord(x, + y, + slice, + tileMode, + pipeSwizzle, + ignoreSE, + pTileInfo); + + bank = ComputeBankFromCoord(x, + y, + slice, + tileMode, + bankSwizzle, + tileSplitSlice, + pTileInfo); + + + // + // Split the offset to put some bits below the pipe+bank bits and some above. + // + pipeInterleaveMask = (1 << numPipeInterleaveBits) - 1; + bankInterleaveMask = (1 << numBankInterleaveBits) - 1; + pipeInterleaveOffset = totalOffset & pipeInterleaveMask; + bankInterleaveOffset = static_cast<UINT_32>((totalOffset >> numPipeInterleaveBits) & + bankInterleaveMask); + offset = totalOffset >> (numPipeInterleaveBits + numBankInterleaveBits); + + // + // Assemble the address from its components. + // + addr = pipeInterleaveOffset; + // This is to remove /analyze warnings + UINT_32 pipeBits = pipe << numPipeInterleaveBits; + UINT_32 bankInterleaveBits = bankInterleaveOffset << (numPipeInterleaveBits + numPipeBits); + UINT_32 bankBits = bank << (numPipeInterleaveBits + numPipeBits + + numBankInterleaveBits); + UINT_64 offsetBits = offset << (numPipeInterleaveBits + numPipeBits + + numBankInterleaveBits + numBankBits); + + addr |= pipeBits; + addr |= bankInterleaveBits; + addr |= bankBits; + addr |= offsetBits; + + return addr; +} + +/** +*************************************************************************************************** +* EgBasedAddrLib::ComputeSurfaceAddrFromCoordMicroTiled +* +* @brief +* Computes the surface address and bit position from a coordinate for 1D tilied +* (micro tiled) +* @return +* The byte address +*************************************************************************************************** +*/ +UINT_64 EgBasedAddrLib::ComputeSurfaceAddrFromCoordMicroTiled( + UINT_32 x, ///< [in] x coordinate + UINT_32 y, ///< [in] y coordinate + UINT_32 slice, ///< [in] slice index + UINT_32 sample, ///< [in] sample index + UINT_32 bpp, ///< [in] bits per pixel + UINT_32 pitch, ///< [in] pitch, in pixels + UINT_32 height, ///< [in] height, in pixels + UINT_32 numSamples, ///< [in] number of samples + AddrTileMode tileMode, ///< [in] tile mode + AddrTileType microTileType, ///< [in] micro tiling type + BOOL_32 isDepthSampleOrder, ///< [in] TRUE if depth sample ordering is used + UINT_32* pBitPosition ///< [out] bit position, e.g. FMT_1 will use this + ) const +{ + UINT_64 addr = 0; + + UINT_32 microTileBytes; + UINT_64 sliceBytes; + UINT_32 microTilesPerRow; + UINT_32 microTileIndexX; + UINT_32 microTileIndexY; + UINT_32 microTileIndexZ; + UINT_64 sliceOffset; + UINT_64 microTileOffset; + UINT_32 sampleOffset; + UINT_32 pixelIndex; + UINT_32 pixelOffset; + + UINT_32 microTileThickness = ComputeSurfaceThickness(tileMode); + + // + // Compute the micro tile size. + // + microTileBytes = BITS_TO_BYTES(MicroTilePixels * microTileThickness * bpp * numSamples); + + // + // Compute the slice size. + // + sliceBytes = + BITS_TO_BYTES(static_cast<UINT_64>(pitch) * height * microTileThickness * bpp * numSamples); + + // + // Compute the number of micro tiles per row. + // + microTilesPerRow = pitch / MicroTileWidth; + + // + // Compute the micro tile index. + // + microTileIndexX = x / MicroTileWidth; + microTileIndexY = y / MicroTileHeight; + microTileIndexZ = slice / microTileThickness; + + // + // Compute the slice offset. + // + sliceOffset = static_cast<UINT_64>(microTileIndexZ) * sliceBytes; + + // + // Compute the offset to the micro tile containing the specified coordinate. + // + microTileOffset = (static_cast<UINT_64>(microTileIndexY) * microTilesPerRow + microTileIndexX) * + microTileBytes; + + // + // Compute the pixel index within the micro tile. + // + pixelIndex = ComputePixelIndexWithinMicroTile(x, + y, + slice, + bpp, + tileMode, + microTileType); + + // Compute the sample offset. + // + if (isDepthSampleOrder) + { + // + // For depth surfaces, samples are stored contiguously for each element, so the sample + // offset is the sample number times the element size. + // + sampleOffset = sample * bpp; + pixelOffset = pixelIndex * bpp * numSamples; + } + else + { + // + // For color surfaces, all elements for a particular sample are stored contiguously, so + // the sample offset is the sample number times the micro tile size divided yBit the number + // of samples. + // + sampleOffset = sample * (microTileBytes*8 / numSamples); + pixelOffset = pixelIndex * bpp; + } + + // + // Compute the bit position of the pixel. Each element is stored with one bit per sample. + // + + UINT_32 elemOffset = sampleOffset + pixelOffset; + + *pBitPosition = elemOffset % 8; + elemOffset /= 8; + + // + // Combine the slice offset, micro tile offset, sample offset, and pixel offsets. + // + addr = sliceOffset + microTileOffset + elemOffset; + + return addr; +} + +/** +*************************************************************************************************** +* EgBasedAddrLib::HwlComputePixelCoordFromOffset +* +* @brief +* Compute pixel coordinate from offset inside a micro tile +* @return +* N/A +*************************************************************************************************** +*/ +VOID EgBasedAddrLib::HwlComputePixelCoordFromOffset( + UINT_32 offset, ///< [in] offset inside micro tile in bits + UINT_32 bpp, ///< [in] bits per pixel + UINT_32 numSamples, ///< [in] number of samples + AddrTileMode tileMode, ///< [in] tile mode + UINT_32 tileBase, ///< [in] base offset within a tile + UINT_32 compBits, ///< [in] component bits actually needed(for planar surface) + UINT_32* pX, ///< [out] x coordinate + UINT_32* pY, ///< [out] y coordinate + UINT_32* pSlice, ///< [out] slice index + UINT_32* pSample, ///< [out] sample index + AddrTileType microTileType, ///< [in] micro tiling type + BOOL_32 isDepthSampleOrder ///< [in] TRUE if depth sample order in microtile is used + ) const +{ + UINT_32 x = 0; + UINT_32 y = 0; + UINT_32 z = 0; + UINT_32 thickness = ComputeSurfaceThickness(tileMode); + + // For planar surface, we adjust offset acoording to tile base + if ((bpp != compBits) && (compBits != 0) && isDepthSampleOrder) + { + offset -= tileBase; + + ADDR_ASSERT(microTileType == ADDR_NON_DISPLAYABLE || + microTileType == ADDR_DEPTH_SAMPLE_ORDER); + + bpp = compBits; + } + + UINT_32 sampleTileBits; + UINT_32 samplePixelBits; + UINT_32 pixelIndex; + + if (isDepthSampleOrder) + { + samplePixelBits = bpp * numSamples; + pixelIndex = offset / samplePixelBits; + *pSample = (offset % samplePixelBits) / bpp; + } + else + { + sampleTileBits = MicroTilePixels * bpp * thickness; + *pSample = offset / sampleTileBits; + pixelIndex = (offset % sampleTileBits) / bpp; + } + + if (microTileType != ADDR_THICK) + { + if (microTileType == ADDR_DISPLAYABLE) // displayable + { + switch (bpp) + { + case 8: + x = pixelIndex & 0x7; + y = Bits2Number(3, _BIT(pixelIndex,5),_BIT(pixelIndex,3),_BIT(pixelIndex,4)); + break; + case 16: + x = pixelIndex & 0x7; + y = Bits2Number(3, _BIT(pixelIndex,5),_BIT(pixelIndex,4),_BIT(pixelIndex,3)); + break; + case 32: + x = Bits2Number(3, _BIT(pixelIndex,3),_BIT(pixelIndex,1),_BIT(pixelIndex,0)); + y = Bits2Number(3, _BIT(pixelIndex,5),_BIT(pixelIndex,4),_BIT(pixelIndex,2)); + break; + case 64: + x = Bits2Number(3, _BIT(pixelIndex,3),_BIT(pixelIndex,2),_BIT(pixelIndex,0)); + y = Bits2Number(3, _BIT(pixelIndex,5),_BIT(pixelIndex,4),_BIT(pixelIndex,1)); + break; + case 128: + x = Bits2Number(3, _BIT(pixelIndex,3),_BIT(pixelIndex,2),_BIT(pixelIndex,1)); + y = Bits2Number(3, _BIT(pixelIndex,5),_BIT(pixelIndex,4),_BIT(pixelIndex,0)); + break; + default: + break; + } + } + else if (microTileType == ADDR_NON_DISPLAYABLE || microTileType == ADDR_DEPTH_SAMPLE_ORDER) + { + x = Bits2Number(3, _BIT(pixelIndex,4),_BIT(pixelIndex,2),_BIT(pixelIndex,0)); + y = Bits2Number(3, _BIT(pixelIndex,5),_BIT(pixelIndex,3),_BIT(pixelIndex,1)); + } + else if (microTileType == ADDR_ROTATED) + { + /* + 8-Bit Elements + element_index[5:0] = { x[2], x[0], x[1], y[2], y[1], y[0] } + + 16-Bit Elements + element_index[5:0] = { x[2], x[1], x[0], y[2], y[1], y[0] } + + 32-Bit Elements + element_index[5:0] = { x[2], x[1], y[2], x[0], y[1], y[0] } + + 64-Bit Elements + element_index[5:0] = { y[2], x[2], x[1], y[1], x[0], y[0] } + */ + switch(bpp) + { + case 8: + x = Bits2Number(3, _BIT(pixelIndex,5),_BIT(pixelIndex,3),_BIT(pixelIndex,4)); + y = pixelIndex & 0x7; + break; + case 16: + x = Bits2Number(3, _BIT(pixelIndex,5),_BIT(pixelIndex,4),_BIT(pixelIndex,3)); + y = pixelIndex & 0x7; + break; + case 32: + x = Bits2Number(3, _BIT(pixelIndex,5),_BIT(pixelIndex,4),_BIT(pixelIndex,2)); + y = Bits2Number(3, _BIT(pixelIndex,3),_BIT(pixelIndex,1),_BIT(pixelIndex,0)); + break; + case 64: + x = Bits2Number(3, _BIT(pixelIndex,4),_BIT(pixelIndex,3),_BIT(pixelIndex,1)); + y = Bits2Number(3, _BIT(pixelIndex,5),_BIT(pixelIndex,2),_BIT(pixelIndex,0)); + break; + default: + ADDR_ASSERT_ALWAYS(); + break; + } + } + + if (thickness > 1) // thick + { + z = Bits2Number(3, _BIT(pixelIndex,8),_BIT(pixelIndex,7),_BIT(pixelIndex,6)); + } + } + else + { + ADDR_ASSERT((m_chipFamily >= ADDR_CHIP_FAMILY_CI) && (thickness > 1)); + /* + 8-Bit Elements and 16-Bit Elements + element_index[7:0] = { y[2], x[2], z[1], z[0], y[1], x[1], y[0], x[0] } + + 32-Bit Elements + element_index[7:0] = { y[2], x[2], z[1], y[1], z[0], x[1], y[0], x[0] } + + 64-Bit Elements and 128-Bit Elements + element_index[7:0] = { y[2], x[2], z[1], y[1], x[1], z[0], y[0], x[0] } + + The equation to compute the element index for the extra thick tile: + element_index[8] = z[2] + */ + switch (bpp) + { + case 8: + case 16: // fall-through + x = Bits2Number(3, _BIT(pixelIndex,6),_BIT(pixelIndex,2),_BIT(pixelIndex,0)); + y = Bits2Number(3, _BIT(pixelIndex,7),_BIT(pixelIndex,3),_BIT(pixelIndex,1)); + z = Bits2Number(2, _BIT(pixelIndex,5),_BIT(pixelIndex,4)); + break; + case 32: + x = Bits2Number(3, _BIT(pixelIndex,6),_BIT(pixelIndex,2),_BIT(pixelIndex,0)); + y = Bits2Number(3, _BIT(pixelIndex,7),_BIT(pixelIndex,4),_BIT(pixelIndex,1)); + z = Bits2Number(2, _BIT(pixelIndex,5),_BIT(pixelIndex,3)); + break; + case 64: + case 128: // fall-through + x = Bits2Number(3, _BIT(pixelIndex,6),_BIT(pixelIndex,3),_BIT(pixelIndex,0)); + y = Bits2Number(3, _BIT(pixelIndex,7),_BIT(pixelIndex,4),_BIT(pixelIndex,1)); + z = Bits2Number(2, _BIT(pixelIndex,5),_BIT(pixelIndex,2)); + break; + default: + ADDR_ASSERT_ALWAYS(); + break; + } + + if (thickness == 8) + { + z += Bits2Number(3,_BIT(pixelIndex,8),0,0); + } + } + + *pX = x; + *pY = y; + *pSlice += z; +} + + +/** +*************************************************************************************************** +* EgBasedAddrLib::DispatchComputeSurfaceCoordFromAddrDispatch +* +* @brief +* Compute (x,y,slice,sample) coordinates from surface address +* @return +* N/A +*************************************************************************************************** +*/ +VOID EgBasedAddrLib::DispatchComputeSurfaceCoordFromAddr( + const ADDR_COMPUTE_SURFACE_COORDFROMADDR_INPUT* pIn, ///< [in] input structure + ADDR_COMPUTE_SURFACE_COORDFROMADDR_OUTPUT* pOut ///< [out] output structure + ) const +{ + UINT_64 addr = pIn->addr; + UINT_32 bitPosition = pIn->bitPosition; + UINT_32 bpp = pIn->bpp; + UINT_32 pitch = pIn->pitch; + UINT_32 height = pIn->height; + UINT_32 numSlices = pIn->numSlices; + UINT_32 numSamples = ((pIn->numSamples == 0) ? 1 : pIn->numSamples); + UINT_32 numFrags = ((pIn->numFrags == 0) ? numSamples : pIn->numFrags); + AddrTileMode tileMode = pIn->tileMode; + UINT_32 tileBase = pIn->tileBase; + UINT_32 compBits = pIn->compBits; + AddrTileType microTileType = pIn->tileType; + BOOL_32 ignoreSE = pIn->ignoreSE; + BOOL_32 isDepthSampleOrder = pIn->isDepth; + ADDR_TILEINFO* pTileInfo = pIn->pTileInfo; + + UINT_32* pX = &pOut->x; + UINT_32* pY = &pOut->y; + UINT_32* pSlice = &pOut->slice; + UINT_32* pSample = &pOut->sample; + + if (microTileType == ADDR_DEPTH_SAMPLE_ORDER) + { + isDepthSampleOrder = TRUE; + } + + if (m_chipFamily >= ADDR_CHIP_FAMILY_NI) + { + if (numFrags != numSamples) + { + numSamples = numFrags; + } + + /// @note + /// 128 bit/thick tiled surface doesn't support display tiling and + /// mipmap chain must have the same tileType, so please fill tileType correctly + if (!IsLinear(pIn->tileMode)) + { + if (bpp >= 128 || ComputeSurfaceThickness(tileMode) > 1) + { + ADDR_ASSERT(microTileType != ADDR_DISPLAYABLE); + } + } + } + + switch (tileMode) + { + case ADDR_TM_LINEAR_GENERAL://fall through + case ADDR_TM_LINEAR_ALIGNED: + ComputeSurfaceCoordFromAddrLinear(addr, + bitPosition, + bpp, + pitch, + height, + numSlices, + pX, + pY, + pSlice, + pSample); + break; + case ADDR_TM_1D_TILED_THIN1://fall through + case ADDR_TM_1D_TILED_THICK: + ComputeSurfaceCoordFromAddrMicroTiled(addr, + bitPosition, + bpp, + pitch, + height, + numSamples, + tileMode, + tileBase, + compBits, + pX, + pY, + pSlice, + pSample, + microTileType, + isDepthSampleOrder); + break; + case ADDR_TM_2D_TILED_THIN1: //fall through + case ADDR_TM_2D_TILED_THICK: //fall through + case ADDR_TM_3D_TILED_THIN1: //fall through + case ADDR_TM_3D_TILED_THICK: //fall through + case ADDR_TM_2D_TILED_XTHICK: //fall through + case ADDR_TM_3D_TILED_XTHICK: //fall through + case ADDR_TM_PRT_TILED_THIN1: //fall through + case ADDR_TM_PRT_2D_TILED_THIN1://fall through + case ADDR_TM_PRT_3D_TILED_THIN1://fall through + case ADDR_TM_PRT_TILED_THICK: //fall through + case ADDR_TM_PRT_2D_TILED_THICK://fall through + case ADDR_TM_PRT_3D_TILED_THICK: + UINT_32 pipeSwizzle; + UINT_32 bankSwizzle; + + if (m_configFlags.useCombinedSwizzle) + { + ExtractBankPipeSwizzle(pIn->tileSwizzle, pIn->pTileInfo, + &bankSwizzle, &pipeSwizzle); + } + else + { + pipeSwizzle = pIn->pipeSwizzle; + bankSwizzle = pIn->bankSwizzle; + } + + ComputeSurfaceCoordFromAddrMacroTiled(addr, + bitPosition, + bpp, + pitch, + height, + numSamples, + tileMode, + tileBase, + compBits, + microTileType, + ignoreSE, + isDepthSampleOrder, + pipeSwizzle, + bankSwizzle, + pTileInfo, + pX, + pY, + pSlice, + pSample); + break; + default: + ADDR_ASSERT_ALWAYS(); + } +} + + +/** +*************************************************************************************************** +* EgBasedAddrLib::ComputeSurfaceCoordFromAddrMacroTiled +* +* @brief +* Compute surface coordinates from address for macro tiled surface +* @return +* N/A +*************************************************************************************************** +*/ +VOID EgBasedAddrLib::ComputeSurfaceCoordFromAddrMacroTiled( + UINT_64 addr, ///< [in] byte address + UINT_32 bitPosition, ///< [in] bit position + UINT_32 bpp, ///< [in] bits per pixel + UINT_32 pitch, ///< [in] pitch in pixels + UINT_32 height, ///< [in] height in pixels + UINT_32 numSamples, ///< [in] number of samples + AddrTileMode tileMode, ///< [in] tile mode + UINT_32 tileBase, ///< [in] tile base offset + UINT_32 compBits, ///< [in] component bits (for planar surface) + AddrTileType microTileType, ///< [in] micro tiling type + BOOL_32 ignoreSE, ///< [in] TRUE if shader engines can be ignored + BOOL_32 isDepthSampleOrder, ///< [in] TRUE if depth sample order is used + UINT_32 pipeSwizzle, ///< [in] pipe swizzle + UINT_32 bankSwizzle, ///< [in] bank swizzle + ADDR_TILEINFO* pTileInfo, ///< [in] bank structure. + /// **All fields to be valid on entry** + UINT_32* pX, ///< [out] X coord + UINT_32* pY, ///< [out] Y coord + UINT_32* pSlice, ///< [out] slice index + UINT_32* pSample ///< [out] sample index + ) const +{ + UINT_32 mx; + UINT_32 my; + UINT_64 tileBits; + UINT_64 macroTileBits; + UINT_32 slices; + UINT_32 tileSlices; + UINT_64 elementOffset; + UINT_64 macroTileIndex; + UINT_32 tileIndex; + UINT_64 totalOffset; + + + UINT_32 bank; + UINT_32 pipe; + UINT_32 groupBits = m_pipeInterleaveBytes << 3; + UINT_32 pipes = HwlGetPipes(pTileInfo); + UINT_32 banks = pTileInfo->banks; + + UINT_32 bankInterleave = m_bankInterleave; + + UINT_64 addrBits = BYTES_TO_BITS(addr) + bitPosition; + + // + // remove bits for bank and pipe + // + totalOffset = (addrBits % groupBits) + + (((addrBits / groupBits / pipes) % bankInterleave) * groupBits) + + (((addrBits / groupBits / pipes) / bankInterleave) / banks) * groupBits * bankInterleave; + + UINT_32 microTileThickness = ComputeSurfaceThickness(tileMode); + + UINT_32 microTileBits = bpp * microTileThickness * MicroTilePixels * numSamples; + + UINT_32 microTileBytes = BITS_TO_BYTES(microTileBits); + // + // Determine if tiles need to be split across slices. + // + // If the size of the micro tile is larger than the tile split size, then the tile will be + // split across multiple slices. + // + UINT_32 slicesPerTile = 1; //_State->TileSlices + + if ((microTileBytes > pTileInfo->tileSplitBytes) && (microTileThickness == 1)) + { //don't support for thick mode + + // + // Compute the number of slices per tile. + // + slicesPerTile = microTileBytes / pTileInfo->tileSplitBytes; + } + + tileBits = microTileBits / slicesPerTile; // micro tile bits + + // in micro tiles because not MicroTileWidth timed. + UINT_32 macroWidth = pTileInfo->bankWidth * pipes * pTileInfo->macroAspectRatio; + // in micro tiles as well + UINT_32 macroHeight = pTileInfo->bankHeight * banks / pTileInfo->macroAspectRatio; + + UINT_32 pitchInMacroTiles = pitch / MicroTileWidth / macroWidth; + + macroTileBits = (macroWidth * macroHeight) * tileBits / (banks * pipes); + + macroTileIndex = totalOffset / macroTileBits; + + // pitchMacros * height / heightMacros; macroTilesPerSlice == _State->SliceMacros + UINT_32 macroTilesPerSlice = (pitch / (macroWidth * MicroTileWidth)) * height / + (macroHeight * MicroTileWidth); + + slices = static_cast<UINT_32>(macroTileIndex / macroTilesPerSlice); + + *pSlice = static_cast<UINT_32>(slices / slicesPerTile * microTileThickness); + + // + // calculate element offset and x[2:0], y[2:0], z[1:0] for thick + // + tileSlices = slices % slicesPerTile; + + elementOffset = tileSlices * tileBits; + elementOffset += totalOffset % tileBits; + + UINT_32 coordZ = 0; + + HwlComputePixelCoordFromOffset(static_cast<UINT_32>(elementOffset), + bpp, + numSamples, + tileMode, + tileBase, + compBits, + pX, + pY, + &coordZ, + pSample, + microTileType, + isDepthSampleOrder); + + macroTileIndex = macroTileIndex % macroTilesPerSlice; + *pY += static_cast<UINT_32>(macroTileIndex / pitchInMacroTiles * macroHeight * MicroTileHeight); + *pX += static_cast<UINT_32>(macroTileIndex % pitchInMacroTiles * macroWidth * MicroTileWidth); + + *pSlice += coordZ; + + tileIndex = static_cast<UINT_32>((totalOffset % macroTileBits) / tileBits); + + my = (tileIndex / pTileInfo->bankWidth) % pTileInfo->bankHeight * MicroTileHeight; + mx = (tileIndex % pTileInfo->bankWidth) * pipes * MicroTileWidth; + + *pY += my; + *pX += mx; + + bank = ComputeBankFromAddr(addr, banks, pipes); + pipe = ComputePipeFromAddr(addr, pipes); + + HwlComputeSurfaceCoord2DFromBankPipe(tileMode, + pX, + pY, + *pSlice, + bank, + pipe, + bankSwizzle, + pipeSwizzle, + tileSlices, + ignoreSE, + pTileInfo); +} + +/** +*************************************************************************************************** +* EgBasedAddrLib::ComputeSurfaceCoord2DFromBankPipe +* +* @brief +* Compute surface x,y coordinates from bank/pipe info +* @return +* N/A +*************************************************************************************************** +*/ +VOID EgBasedAddrLib::ComputeSurfaceCoord2DFromBankPipe( + AddrTileMode tileMode, ///< [in] tile mode + UINT_32 x, ///< [in] x coordinate + UINT_32 y, ///< [in] y coordinate + UINT_32 slice, ///< [in] slice index + UINT_32 bank, ///< [in] bank number + UINT_32 pipe, ///< [in] pipe number + UINT_32 bankSwizzle,///< [in] bank swizzle + UINT_32 pipeSwizzle,///< [in] pipe swizzle + UINT_32 tileSlices, ///< [in] slices in a micro tile + ADDR_TILEINFO* pTileInfo, ///< [in] bank structure. **All fields to be valid on entry** + CoordFromBankPipe* pOutput ///< [out] pointer to extracted x/y bits + ) const +{ + UINT_32 yBit3 = 0; + UINT_32 yBit4 = 0; + UINT_32 yBit5 = 0; + UINT_32 yBit6 = 0; + + UINT_32 xBit3 = 0; + UINT_32 xBit4 = 0; + UINT_32 xBit5 = 0; + + UINT_32 tileSplitRotation; + + UINT_32 numPipes = HwlGetPipes(pTileInfo); + + UINT_32 bankRotation = ComputeBankRotation(tileMode, + pTileInfo->banks, numPipes); + + UINT_32 pipeRotation = ComputePipeRotation(tileMode, numPipes); + + UINT_32 xBit = x / (MicroTileWidth * pTileInfo->bankWidth * numPipes); + UINT_32 yBit = y / (MicroTileHeight * pTileInfo->bankHeight); + + //calculate the bank and pipe before rotation and swizzle + + switch (tileMode) + { + case ADDR_TM_2D_TILED_THIN1: //fall through + case ADDR_TM_2D_TILED_THICK: //fall through + case ADDR_TM_2D_TILED_XTHICK: //fall through + case ADDR_TM_3D_TILED_THIN1: //fall through + case ADDR_TM_3D_TILED_THICK: //fall through + case ADDR_TM_3D_TILED_XTHICK: + tileSplitRotation = ((pTileInfo->banks / 2) + 1); + break; + default: + tileSplitRotation = 0; + break; + } + + UINT_32 microTileThickness = ComputeSurfaceThickness(tileMode); + + bank ^= tileSplitRotation * tileSlices; + if (pipeRotation == 0) + { + bank ^= bankRotation * (slice / microTileThickness) + bankSwizzle; + bank %= pTileInfo->banks; + pipe ^= pipeSwizzle; + } + else + { + bank ^= bankRotation * (slice / microTileThickness) / numPipes + bankSwizzle; + bank %= pTileInfo->banks; + pipe ^= pipeRotation * (slice / microTileThickness) + pipeSwizzle; + } + + if (pTileInfo->macroAspectRatio == 1) + { + switch (pTileInfo->banks) + { + case 2: + yBit3 = _BIT(bank, 0) ^ _BIT(xBit,0); + break; + case 4: + yBit4 = _BIT(bank, 0) ^ _BIT(xBit,0); + yBit3 = _BIT(bank, 1) ^ _BIT(xBit,1); + break; + case 8: + yBit3 = _BIT(bank, 2) ^ _BIT(xBit,2); + yBit5 = _BIT(bank, 0) ^ _BIT(xBit,0); + yBit4 = _BIT(bank, 1) ^ _BIT(xBit,1) ^ yBit5; + break; + case 16: + yBit3 = _BIT(bank, 3) ^ _BIT(xBit, 3); + yBit4 = _BIT(bank, 2) ^ _BIT(xBit, 2); + yBit6 = _BIT(bank, 0) ^ _BIT(xBit, 0); + yBit5 = _BIT(bank, 1) ^ _BIT(xBit, 1) ^ yBit6; + break; + default: + break; + } + + } + else if (pTileInfo->macroAspectRatio == 2) + { + switch (pTileInfo->banks) + { + case 2: //xBit3 = yBit3^b0 + xBit3 = _BIT(bank, 0) ^ _BIT(yBit,0); + break; + case 4: //xBit3=yBit4^b0; yBit3=xBit4^b1 + xBit3 = _BIT(bank, 0) ^ _BIT(yBit,1); + yBit3 = _BIT(bank, 1) ^ _BIT(xBit,1); + break; + case 8: //xBit4, xBit5, yBit5 are known + xBit3 = _BIT(bank, 0) ^ _BIT(yBit,2); + yBit3 = _BIT(bank, 2) ^ _BIT(xBit,2); + yBit4 = _BIT(bank, 1) ^ _BIT(xBit,1) ^ _BIT(yBit, 2); + break; + case 16://x4,x5,x6,y6 are known + xBit3 = _BIT(bank, 0) ^ _BIT(yBit, 3); //x3 = y6 ^ b0 + yBit3 = _BIT(bank, 3) ^ _BIT(xBit, 3); //y3 = x6 ^ b3 + yBit4 = _BIT(bank, 2) ^ _BIT(xBit, 2); //y4 = x5 ^ b2 + yBit5 = _BIT(bank, 1) ^ _BIT(xBit, 1) ^ _BIT(yBit, 3); //y5=x4^y6^b1 + break; + default: + break; + } + } + else if (pTileInfo->macroAspectRatio == 4) + { + switch (pTileInfo->banks) + { + case 4: //yBit3, yBit4 + xBit3 = _BIT(bank, 0) ^ _BIT(yBit,1); + xBit4 = _BIT(bank, 1) ^ _BIT(yBit,0); + break; + case 8: //xBit5, yBit4, yBit5 + xBit3 = _BIT(bank, 0) ^ _BIT(yBit,2); + yBit3 = _BIT(bank, 2) ^ _BIT(xBit,2); + xBit4 = _BIT(bank, 1) ^ _BIT(yBit,1) ^ _BIT(yBit,2); + break; + case 16: //xBit5, xBit6, yBit5, yBit6 + xBit3 = _BIT(bank, 0) ^ _BIT(yBit, 3);//x3 = b0 ^ y6 + xBit4 = _BIT(bank, 1) ^ _BIT(yBit, 2) ^ _BIT(yBit, 3);//x4 = b1 ^ y5 ^ y6; + yBit3 = _BIT(bank, 3) ^ _BIT(xBit, 3); //y3 = b3 ^ x6; + yBit4 = _BIT(bank, 2) ^ _BIT(xBit, 2); //y4 = b2 ^ x5; + break; + default: + break; + } + } + else if (pTileInfo->macroAspectRatio == 8) + { + switch (pTileInfo->banks) + { + case 8: //yBit3, yBit4, yBit5 + xBit3 = _BIT(bank, 0) ^ _BIT(yBit,2); //x3 = b0 ^ y5; + xBit4 = _BIT(bank, 1) ^ _BIT(yBit,1) ^ _BIT(yBit, 2);//x4 = b1 ^ y4 ^ y5; + xBit5 = _BIT(bank, 2) ^ _BIT(yBit,0); + break; + case 16: //xBit6, yBit4, yBit5, yBit6 + xBit3 = _BIT(bank, 0) ^ _BIT(yBit, 3);//x3 = y6 ^ b0 + xBit4 = _BIT(bank, 1) ^ _BIT(yBit, 2) ^ _BIT(yBit, 3);//x4 = y5 ^ y6 ^ b1 + xBit5 = _BIT(bank, 2) ^ _BIT(yBit, 1);//x5 = y4 ^ b2 + yBit3 = _BIT(bank, 3) ^ _BIT(xBit, 3); //y3 = x6 ^ b3 + break; + default: + break; + } + } + + pOutput->xBits = xBit; + pOutput->yBits = yBit; + + pOutput->xBit3 = xBit3; + pOutput->xBit4 = xBit4; + pOutput->xBit5 = xBit5; + pOutput->yBit3 = yBit3; + pOutput->yBit4 = yBit4; + pOutput->yBit5 = yBit5; + pOutput->yBit6 = yBit6; +} + +/** +*************************************************************************************************** +* EgBasedAddrLib::HwlExtractBankPipeSwizzle +* @brief +* Entry of EgBasedAddrLib ExtractBankPipeSwizzle +* @return +* ADDR_E_RETURNCODE +*************************************************************************************************** +*/ +ADDR_E_RETURNCODE EgBasedAddrLib::HwlExtractBankPipeSwizzle( + const ADDR_EXTRACT_BANKPIPE_SWIZZLE_INPUT* pIn, ///< [in] input structure + ADDR_EXTRACT_BANKPIPE_SWIZZLE_OUTPUT* pOut ///< [out] output structure + ) const +{ + ExtractBankPipeSwizzle(pIn->base256b, + pIn->pTileInfo, + &pOut->bankSwizzle, + &pOut->pipeSwizzle); + + return ADDR_OK; +} + + +/** +*************************************************************************************************** +* EgBasedAddrLib::HwlCombineBankPipeSwizzle +* @brief +* Combine bank/pipe swizzle +* @return +* ADDR_E_RETURNCODE +*************************************************************************************************** +*/ +ADDR_E_RETURNCODE EgBasedAddrLib::HwlCombineBankPipeSwizzle( + UINT_32 bankSwizzle, ///< [in] bank swizzle + UINT_32 pipeSwizzle, ///< [in] pipe swizzle + ADDR_TILEINFO* pTileInfo, ///< [in] tile info + UINT_64 baseAddr, ///< [in] base address + UINT_32* pTileSwizzle ///< [out] combined swizzle + ) const +{ + ADDR_E_RETURNCODE retCode = ADDR_OK; + + if (pTileSwizzle) + { + *pTileSwizzle = GetBankPipeSwizzle(bankSwizzle, pipeSwizzle, baseAddr, pTileInfo); + } + else + { + retCode = ADDR_INVALIDPARAMS; + } + + return retCode; +} + +/** +*************************************************************************************************** +* EgBasedAddrLib::HwlComputeBaseSwizzle +* @brief +* Compute base swizzle +* @return +* ADDR_E_RETURNCODE +*************************************************************************************************** +*/ +ADDR_E_RETURNCODE EgBasedAddrLib::HwlComputeBaseSwizzle( + const ADDR_COMPUTE_BASE_SWIZZLE_INPUT* pIn, + ADDR_COMPUTE_BASE_SWIZZLE_OUTPUT* pOut + ) const +{ + UINT_32 bankSwizzle = 0; + UINT_32 pipeSwizzle = 0; + ADDR_TILEINFO* pTileInfo = pIn->pTileInfo; + + ADDR_ASSERT(IsMacroTiled(pIn->tileMode)); + ADDR_ASSERT(pIn->pTileInfo); + + /// This is a legacy misreading of h/w doc, use it as it doesn't hurt. + static const UINT_8 bankRotationArray[4][16] = { + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // ADDR_SURF_2_BANK + { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // ADDR_SURF_4_BANK + { 0, 3, 6, 1, 4, 7, 2, 5, 0, 0, 0, 0, 0, 0, 0, 0 }, // ADDR_SURF_8_BANK + { 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9 }, // ADDR_SURF_16_BANK + }; + + UINT_32 banks = pTileInfo ? pTileInfo->banks : 2; + UINT_32 hwNumBanks; + + // Uses less bank swizzle bits + if (pIn->option.reduceBankBit && banks > 2) + { + banks >>= 1; + } + + switch (banks) + { + case 2: + hwNumBanks = 0; + break; + case 4: + hwNumBanks = 1; + break; + case 8: + hwNumBanks = 2; + break; + case 16: + hwNumBanks = 3; + break; + default: + ADDR_ASSERT_ALWAYS(); + hwNumBanks = 0; + break; + } + + if (pIn->option.genOption == ADDR_SWIZZLE_GEN_LINEAR) + { + bankSwizzle = pIn->surfIndex & (banks - 1); + } + else // (pIn->option.genOption == ADDR_SWIZZLE_GEN_DEFAULT) + { + bankSwizzle = bankRotationArray[hwNumBanks][pIn->surfIndex & (banks - 1)]; + } + + if (IsMacro3dTiled(pIn->tileMode)) + { + pipeSwizzle = pIn->surfIndex & (HwlGetPipes(pTileInfo) - 1); + } + + return HwlCombineBankPipeSwizzle(bankSwizzle, pipeSwizzle, pTileInfo, 0, &pOut->tileSwizzle); +} + +/** +*************************************************************************************************** +* EgBasedAddrLib::ExtractBankPipeSwizzle +* @brief +* Extract bank/pipe swizzle from base256b +* @return +* N/A +*************************************************************************************************** +*/ +VOID EgBasedAddrLib::ExtractBankPipeSwizzle( + UINT_32 base256b, ///< [in] input base256b register value + ADDR_TILEINFO* pTileInfo, ///< [in] 2D tile parameters. Client must provide all data + UINT_32* pBankSwizzle, ///< [out] bank swizzle + UINT_32* pPipeSwizzle ///< [out] pipe swizzle + ) const +{ + UINT_32 bankSwizzle = 0; + UINT_32 pipeSwizzle = 0; + + if (base256b != 0) + { + UINT_32 numPipes = HwlGetPipes(pTileInfo); + UINT_32 bankBits = QLog2(pTileInfo->banks); + UINT_32 pipeBits = QLog2(numPipes); + UINT_32 groupBytes = m_pipeInterleaveBytes; + UINT_32 bankInterleave = m_bankInterleave; + + pipeSwizzle = + (base256b / (groupBytes >> 8)) & ((1<<pipeBits)-1); + + bankSwizzle = + (base256b / (groupBytes >> 8) / numPipes / bankInterleave) & ((1 << bankBits) - 1); + } + + *pPipeSwizzle = pipeSwizzle; + *pBankSwizzle = bankSwizzle; +} + +/** +*************************************************************************************************** +* EgBasedAddrLib::GetBankPipeSwizzle +* @brief +* Combine bank/pipe swizzle +* @return +* Base256b bits (only filled bank/pipe bits) +*************************************************************************************************** +*/ +UINT_32 EgBasedAddrLib::GetBankPipeSwizzle( + UINT_32 bankSwizzle, ///< [in] bank swizzle + UINT_32 pipeSwizzle, ///< [in] pipe swizzle + UINT_64 baseAddr, ///< [in] base address + ADDR_TILEINFO* pTileInfo ///< [in] tile info + ) const +{ + UINT_32 pipeBits = QLog2(HwlGetPipes(pTileInfo)); + UINT_32 bankInterleaveBits = QLog2(m_bankInterleave); + UINT_32 tileSwizzle = pipeSwizzle + ((bankSwizzle << bankInterleaveBits) << pipeBits); + + baseAddr ^= tileSwizzle * m_pipeInterleaveBytes; + baseAddr >>= 8; + + return static_cast<UINT_32>(baseAddr); +} + +/** +*************************************************************************************************** +* EgBasedAddrLib::ComputeSliceTileSwizzle +* @brief +* Compute cubemap/3d texture faces/slices tile swizzle +* @return +* Tile swizzle +*************************************************************************************************** +*/ +UINT_32 EgBasedAddrLib::ComputeSliceTileSwizzle( + AddrTileMode tileMode, ///< [in] Tile mode + UINT_32 baseSwizzle, ///< [in] Base swizzle + UINT_32 slice, ///< [in] Slice index, Cubemap face index, 0 means +X + UINT_64 baseAddr, ///< [in] Base address + ADDR_TILEINFO* pTileInfo ///< [in] Bank structure + ) const +{ + UINT_32 tileSwizzle = 0; + + if (IsMacroTiled(tileMode)) // Swizzle only for macro tile mode + { + UINT_32 firstSlice = slice / ComputeSurfaceThickness(tileMode); + + UINT_32 numPipes = HwlGetPipes(pTileInfo); + UINT_32 numBanks = pTileInfo->banks; + + UINT_32 pipeRotation; + UINT_32 bankRotation; + + UINT_32 bankSwizzle = 0; + UINT_32 pipeSwizzle = 0; + + pipeRotation = ComputePipeRotation(tileMode, numPipes); + bankRotation = ComputeBankRotation(tileMode, numBanks, numPipes); + + if (baseSwizzle != 0) + { + ExtractBankPipeSwizzle(baseSwizzle, + pTileInfo, + &bankSwizzle, + &pipeSwizzle); + } + + if (pipeRotation == 0) //2D mode + { + bankSwizzle += firstSlice * bankRotation; + bankSwizzle %= numBanks; + } + else //3D mode + { + pipeSwizzle += firstSlice * pipeRotation; + pipeSwizzle %= numPipes; + bankSwizzle += firstSlice * bankRotation / numPipes; + bankSwizzle %= numBanks; + } + + tileSwizzle = GetBankPipeSwizzle(bankSwizzle, + pipeSwizzle, + baseAddr, + pTileInfo); + } + + return tileSwizzle; +} + +/** +*************************************************************************************************** +* EgBasedAddrLib::HwlComputeQbStereoRightSwizzle +* +* @brief +* Compute right eye swizzle +* @return +* swizzle +*************************************************************************************************** +*/ +UINT_32 EgBasedAddrLib::HwlComputeQbStereoRightSwizzle( + ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pInfo ///< [in] Surface info, must be valid + ) const +{ + UINT_32 bankBits = 0; + UINT_32 swizzle = 0; + + // The assumption is default swizzle for left eye is 0 + if (IsMacroTiled(pInfo->tileMode) && pInfo->pStereoInfo && pInfo->pTileInfo) + { + bankBits = ComputeBankFromCoord(0, pInfo->height, 0, + pInfo->tileMode, 0, 0, pInfo->pTileInfo); + + if (bankBits) + { + HwlCombineBankPipeSwizzle(bankBits, 0, pInfo->pTileInfo, 0, &swizzle); + } + } + + return swizzle; +} + +/** +*************************************************************************************************** +* EgBasedAddrLib::ComputeBankFromCoord +* +* @brief +* Compute bank number from coordinates +* @return +* Bank number +*************************************************************************************************** +*/ +UINT_32 EgBasedAddrLib::ComputeBankFromCoord( + UINT_32 x, ///< [in] x coordinate + UINT_32 y, ///< [in] y coordinate + UINT_32 slice, ///< [in] slice index + AddrTileMode tileMode, ///< [in] tile mode + UINT_32 bankSwizzle, ///< [in] bank swizzle + UINT_32 tileSplitSlice, ///< [in] If the size of the pixel offset is larger than the + /// tile split size, then the pixel will be moved to a separate + /// slice. This value equals pixelOffset / tileSplitBytes + /// in this case. Otherwise this is 0. + ADDR_TILEINFO* pTileInfo ///< [in] tile info + ) const +{ + UINT_32 pipes = HwlGetPipes(pTileInfo); + UINT_32 bankBit0 = 0; + UINT_32 bankBit1 = 0; + UINT_32 bankBit2 = 0; + UINT_32 bankBit3 = 0; + UINT_32 sliceRotation; + UINT_32 tileSplitRotation; + UINT_32 bank; + UINT_32 numBanks = pTileInfo->banks; + UINT_32 bankWidth = pTileInfo->bankWidth; + UINT_32 bankHeight = pTileInfo->bankHeight; + + UINT_32 tx = x / MicroTileWidth / (bankWidth * pipes); + UINT_32 ty = y / MicroTileHeight / bankHeight; + + UINT_32 x3 = _BIT(tx,0); + UINT_32 x4 = _BIT(tx,1); + UINT_32 x5 = _BIT(tx,2); + UINT_32 x6 = _BIT(tx,3); + UINT_32 y3 = _BIT(ty,0); + UINT_32 y4 = _BIT(ty,1); + UINT_32 y5 = _BIT(ty,2); + UINT_32 y6 = _BIT(ty,3); + + switch (numBanks) + { + case 16: + bankBit0 = x3 ^ y6; + bankBit1 = x4 ^ y5 ^ y6; + bankBit2 = x5 ^ y4; + bankBit3 = x6 ^ y3; + break; + case 8: + bankBit0 = x3 ^ y5; + bankBit1 = x4 ^ y4 ^ y5; + bankBit2 = x5 ^ y3; + break; + case 4: + bankBit0 = x3 ^ y4; + bankBit1 = x4 ^ y3; + break; + case 2: + bankBit0 = x3 ^ y3; + break; + default: + ADDR_ASSERT_ALWAYS(); + break; + } + + bank = bankBit0 | (bankBit1 << 1) | (bankBit2 << 2) | (bankBit3 << 3); + + //Bits2Number(4, bankBit3, bankBit2, bankBit1, bankBit0); + + bank = HwlPreAdjustBank((x / MicroTileWidth), bank, pTileInfo); + // + // Compute bank rotation for the slice. + // + UINT_32 microTileThickness = ComputeSurfaceThickness(tileMode); + + switch (tileMode) + { + case ADDR_TM_2D_TILED_THIN1: // fall through + case ADDR_TM_2D_TILED_THICK: // fall through + case ADDR_TM_2D_TILED_XTHICK: + sliceRotation = ((numBanks / 2) - 1) * (slice / microTileThickness); + break; + case ADDR_TM_3D_TILED_THIN1: // fall through + case ADDR_TM_3D_TILED_THICK: // fall through + case ADDR_TM_3D_TILED_XTHICK: + sliceRotation = + Max(1u, (pipes / 2) - 1) * (slice / microTileThickness) / pipes; + break; + default: + sliceRotation = 0; + break; + } + + + // + // Compute bank rotation for the tile split slice. + // + // The sample slice will be non-zero if samples must be split across multiple slices. + // This situation arises when the micro tile size multiplied yBit the number of samples exceeds + // the split size (set in GB_ADDR_CONFIG). + // + switch (tileMode) + { + case ADDR_TM_2D_TILED_THIN1: //fall through + case ADDR_TM_3D_TILED_THIN1: //fall through + case ADDR_TM_PRT_2D_TILED_THIN1: //fall through + case ADDR_TM_PRT_3D_TILED_THIN1: //fall through + tileSplitRotation = ((numBanks / 2) + 1) * tileSplitSlice; + break; + default: + tileSplitRotation = 0; + break; + } + + // + // Apply bank rotation for the slice and tile split slice. + // + bank ^= bankSwizzle + sliceRotation; + bank ^= tileSplitRotation; + + bank &= (numBanks - 1); + + return bank; +} + +/** +*************************************************************************************************** +* EgBasedAddrLib::ComputeBankFromAddr +* +* @brief +* Compute the bank number from an address +* @return +* Bank number +*************************************************************************************************** +*/ +UINT_32 EgBasedAddrLib::ComputeBankFromAddr( + UINT_64 addr, ///< [in] address + UINT_32 numBanks, ///< [in] number of banks + UINT_32 numPipes ///< [in] number of pipes + ) const +{ + UINT_32 bank; + + // + // The LSBs of the address are arranged as follows: + // bank | bankInterleave | pipe | pipeInterleave + // + // To get the bank number, shift off the pipe interleave, pipe, and bank interlave bits and + // mask the bank bits. + // + bank = static_cast<UINT_32>( + (addr >> Log2(m_pipeInterleaveBytes * numPipes * m_bankInterleave)) & + (numBanks - 1) + ); + + return bank; +} + +/** +*************************************************************************************************** +* EgBasedAddrLib::ComputePipeRotation +* +* @brief +* Compute pipe rotation value +* @return +* Pipe rotation +*************************************************************************************************** +*/ +UINT_32 EgBasedAddrLib::ComputePipeRotation( + AddrTileMode tileMode, ///< [in] tile mode + UINT_32 numPipes ///< [in] number of pipes + ) const +{ + UINT_32 rotation; + + switch (tileMode) + { + case ADDR_TM_3D_TILED_THIN1: //fall through + case ADDR_TM_3D_TILED_THICK: //fall through + case ADDR_TM_3D_TILED_XTHICK: //fall through + case ADDR_TM_PRT_3D_TILED_THIN1: //fall through + case ADDR_TM_PRT_3D_TILED_THICK: + rotation = (numPipes < 4) ? 1 : (numPipes / 2 - 1); + break; + default: + rotation = 0; + } + + return rotation; +} + + + +/** +*************************************************************************************************** +* EgBasedAddrLib::ComputeBankRotation +* +* @brief +* Compute bank rotation value +* @return +* Bank rotation +*************************************************************************************************** +*/ +UINT_32 EgBasedAddrLib::ComputeBankRotation( + AddrTileMode tileMode, ///< [in] tile mode + UINT_32 numBanks, ///< [in] number of banks + UINT_32 numPipes ///< [in] number of pipes + ) const +{ + UINT_32 rotation; + + switch (tileMode) + { + case ADDR_TM_2D_TILED_THIN1: // fall through + case ADDR_TM_2D_TILED_THICK: // fall through + case ADDR_TM_2D_TILED_XTHICK: + case ADDR_TM_PRT_2D_TILED_THIN1: + case ADDR_TM_PRT_2D_TILED_THICK: + // Rotate banks per Z-slice yBit 1 for 4-bank or 3 for 8-bank + rotation = numBanks / 2 - 1; + break; + case ADDR_TM_3D_TILED_THIN1: // fall through + case ADDR_TM_3D_TILED_THICK: // fall through + case ADDR_TM_3D_TILED_XTHICK: + case ADDR_TM_PRT_3D_TILED_THIN1: + case ADDR_TM_PRT_3D_TILED_THICK: + rotation = (numPipes < 4) ? 1 : (numPipes / 2 - 1); // rotate pipes & banks + break; + default: + rotation = 0; + } + + return rotation; +} + + +/** +*************************************************************************************************** +* EgBasedAddrLib::ComputeHtileBytes +* +* @brief +* Compute htile size in bytes +* +* @return +* Htile size in bytes +*************************************************************************************************** +*/ +UINT_64 EgBasedAddrLib::ComputeHtileBytes( + UINT_32 pitch, ///< [in] pitch + UINT_32 height, ///< [in] height + UINT_32 bpp, ///< [in] bits per pixel + BOOL_32 isLinear, ///< [in] if it is linear mode + UINT_32 numSlices, ///< [in] number of slices + UINT_64* sliceBytes, ///< [out] bytes per slice + UINT_32 baseAlign ///< [in] base alignments + ) const +{ + UINT_64 surfBytes; + + const UINT_64 HtileCacheLineSize = BITS_TO_BYTES(HtileCacheBits); + + *sliceBytes = BITS_TO_BYTES(static_cast<UINT_64>(pitch) * height * bpp / 64); + + if (m_configFlags.useHtileSliceAlign) + { + // Align the sliceSize to htilecachelinesize * pipes at first + *sliceBytes = PowTwoAlign(*sliceBytes, HtileCacheLineSize * m_pipes); + surfBytes = *sliceBytes * numSlices; + } + else + { + // Align the surfSize to htilecachelinesize * pipes at last + surfBytes = *sliceBytes * numSlices; + surfBytes = PowTwoAlign(surfBytes, HtileCacheLineSize * m_pipes); + } + + return surfBytes; +} + +/** +*************************************************************************************************** +* EgBasedAddrLib::DispatchComputeFmaskInfo +* +* @brief +* Compute fmask sizes include padded pitch, height, slices, total size in bytes, +* meanwhile output suitable tile mode and alignments as well. Results are returned +* through output parameters. +* +* @return +* ADDR_E_RETURNCODE +*************************************************************************************************** +*/ +ADDR_E_RETURNCODE EgBasedAddrLib::DispatchComputeFmaskInfo( + const ADDR_COMPUTE_FMASK_INFO_INPUT* pIn, ///< [in] input structure + ADDR_COMPUTE_FMASK_INFO_OUTPUT* pOut) ///< [out] output structure +{ + ADDR_E_RETURNCODE retCode = ADDR_OK; + + ADDR_COMPUTE_SURFACE_INFO_INPUT surfIn = {0}; + ADDR_COMPUTE_SURFACE_INFO_OUTPUT surfOut = {0}; + + // Setup input structure + surfIn.tileMode = pIn->tileMode; + surfIn.width = pIn->pitch; + surfIn.height = pIn->height; + surfIn.numSlices = pIn->numSlices; + surfIn.pTileInfo = pIn->pTileInfo; + surfIn.tileType = ADDR_NON_DISPLAYABLE; + surfIn.flags.fmask = 1; + + // Setup output structure + surfOut.pTileInfo = pOut->pTileInfo; + + // Setup hwl specific fields + HwlFmaskPreThunkSurfInfo(pIn, pOut, &surfIn, &surfOut); + + surfIn.bpp = HwlComputeFmaskBits(pIn, &surfIn.numSamples); + + // ComputeSurfaceInfo needs numSamples in surfOut as surface routines need adjusted numSamples + surfOut.numSamples = surfIn.numSamples; + + retCode = HwlComputeSurfaceInfo(&surfIn, &surfOut); + + // Save bpp field for surface dump support + surfOut.bpp = surfIn.bpp; + + if (retCode == ADDR_OK) + { + pOut->bpp = surfOut.bpp; + pOut->pitch = surfOut.pitch; + pOut->height = surfOut.height; + pOut->numSlices = surfOut.depth; + pOut->fmaskBytes = surfOut.surfSize; + pOut->baseAlign = surfOut.baseAlign; + pOut->pitchAlign = surfOut.pitchAlign; + pOut->heightAlign = surfOut.heightAlign; + + if (surfOut.depth > 1) + { + // For fmask, expNumSlices is stored in depth. + pOut->sliceSize = surfOut.surfSize / surfOut.depth; + } + else + { + pOut->sliceSize = surfOut.surfSize; + } + + // Save numSamples field for surface dump support + pOut->numSamples = surfOut.numSamples; + + HwlFmaskPostThunkSurfInfo(&surfOut, pOut); + } + + return retCode; +} + +/** +*************************************************************************************************** +* EgBasedAddrLib::HwlFmaskSurfaceInfo +* @brief +* Entry of EgBasedAddrLib ComputeFmaskInfo +* @return +* ADDR_E_RETURNCODE +*************************************************************************************************** +*/ +ADDR_E_RETURNCODE EgBasedAddrLib::HwlComputeFmaskInfo( + const ADDR_COMPUTE_FMASK_INFO_INPUT* pIn, ///< [in] input structure + ADDR_COMPUTE_FMASK_INFO_OUTPUT* pOut ///< [out] output structure + ) +{ + ADDR_E_RETURNCODE retCode = ADDR_OK; + + ADDR_TILEINFO tileInfo = {0}; + + // Use internal tile info if pOut does not have a valid pTileInfo + if (pOut->pTileInfo == NULL) + { + pOut->pTileInfo = &tileInfo; + } + + retCode = DispatchComputeFmaskInfo(pIn, pOut); + + if (retCode == ADDR_OK) + { + pOut->tileIndex = + HwlPostCheckTileIndex(pOut->pTileInfo, pIn->tileMode, ADDR_NON_DISPLAYABLE, + pOut->tileIndex); + } + + // Resets pTileInfo to NULL if the internal tile info is used + if (pOut->pTileInfo == &tileInfo) + { + pOut->pTileInfo = NULL; + } + + return retCode; +} + +/** +*************************************************************************************************** +* EgBasedAddrLib::HwlComputeFmaskAddrFromCoord +* @brief +* Entry of EgBasedAddrLib ComputeFmaskAddrFromCoord +* @return +* ADDR_E_RETURNCODE +*************************************************************************************************** +*/ +ADDR_E_RETURNCODE EgBasedAddrLib::HwlComputeFmaskAddrFromCoord( + const ADDR_COMPUTE_FMASK_ADDRFROMCOORD_INPUT* pIn, ///< [in] input structure + ADDR_COMPUTE_FMASK_ADDRFROMCOORD_OUTPUT* pOut ///< [out] output structure + ) const +{ + ADDR_E_RETURNCODE retCode = ADDR_OK; + +#if ADDR_AM_BUILD + if ((pIn->x > pIn->pitch) || + (pIn->y > pIn->height) || + (pIn->numSamples > m_maxSamples) || + (pIn->sample >= m_maxSamples)) + { + retCode = ADDR_INVALIDPARAMS; + } + else + { + pOut->addr = DispatchComputeFmaskAddrFromCoord(pIn, pOut); + } +#endif + + return retCode; +} + +/** +*************************************************************************************************** +* EgBasedAddrLib::HwlComputeFmaskCoordFromAddr +* @brief +* Entry of EgBasedAddrLib ComputeFmaskCoordFromAddr +* @return +* ADDR_E_RETURNCODE +*************************************************************************************************** +*/ +ADDR_E_RETURNCODE EgBasedAddrLib::HwlComputeFmaskCoordFromAddr( + const ADDR_COMPUTE_FMASK_COORDFROMADDR_INPUT* pIn, ///< [in] input structure + ADDR_COMPUTE_FMASK_COORDFROMADDR_OUTPUT* pOut ///< [out] output structure + ) const +{ + ADDR_E_RETURNCODE retCode = ADDR_OK; + +#if ADDR_AM_BUILD + if ((pIn->bitPosition >= 8) || + (pIn->numSamples > m_maxSamples)) + { + retCode = ADDR_INVALIDPARAMS; + } + else + { + DispatchComputeFmaskCoordFromAddr(pIn, pOut); + } +#endif + + return retCode; +} + +#if ADDR_AM_BUILD +/** +*************************************************************************************************** +* EgBasedAddrLib::DispatchComputeFmaskAddrFromCoord +* +* @brief +* Computes the FMASK address and bit position from a coordinate. +* @return +* The byte address +*************************************************************************************************** +*/ +UINT_64 EgBasedAddrLib::DispatchComputeFmaskAddrFromCoord( + const ADDR_COMPUTE_FMASK_ADDRFROMCOORD_INPUT* pIn, ///< [in] input structure + ADDR_COMPUTE_FMASK_ADDRFROMCOORD_OUTPUT* pOut ///< [out] output structure + ) const +{ + UINT_32 x = pIn->x; + UINT_32 y = pIn->y; + UINT_32 slice = pIn->slice; + UINT_32 sample = pIn->sample; + UINT_32 plane = pIn->plane; + UINT_32 pitch = pIn->pitch; + UINT_32 height = pIn->height; + UINT_32 numSamples = pIn->numSamples; + AddrTileMode tileMode = pIn->tileMode; + BOOL_32 ignoreSE = pIn->ignoreSE; + ADDR_TILEINFO* pTileInfo = pIn->pTileInfo; + BOOL_32 resolved = pIn->resolved; + + UINT_32* pBitPosition = &pOut->bitPosition; + UINT_64 addr = 0; + + ADDR_ASSERT(numSamples > 1); + ADDR_ASSERT(ComputeSurfaceThickness(tileMode) == 1); + + switch (tileMode) + { + case ADDR_TM_1D_TILED_THIN1: + addr = ComputeFmaskAddrFromCoordMicroTiled(x, + y, + slice, + sample, + plane, + pitch, + height, + numSamples, + tileMode, + resolved, + pBitPosition); + break; + case ADDR_TM_2D_TILED_THIN1: //fall through + case ADDR_TM_3D_TILED_THIN1: + UINT_32 pipeSwizzle; + UINT_32 bankSwizzle; + + if (m_configFlags.useCombinedSwizzle) + { + ExtractBankPipeSwizzle(pIn->tileSwizzle, pIn->pTileInfo, + &bankSwizzle, &pipeSwizzle); + } + else + { + pipeSwizzle = pIn->pipeSwizzle; + bankSwizzle = pIn->bankSwizzle; + } + + addr = ComputeFmaskAddrFromCoordMacroTiled(x, + y, + slice, + sample, + plane, + pitch, + height, + numSamples, + tileMode, + pipeSwizzle, + bankSwizzle, + ignoreSE, + pTileInfo, + resolved, + pBitPosition); + break; + default: + *pBitPosition = 0; + break; + } + + return addr; +} + +/** +*************************************************************************************************** +* EgBasedAddrLib::ComputeFmaskAddrFromCoordMicroTiled +* +* @brief +* Computes the FMASK address and bit position from a coordinate for 1D tilied (micro +* tiled) +* @return +* The byte address +*************************************************************************************************** +*/ +UINT_64 EgBasedAddrLib::ComputeFmaskAddrFromCoordMicroTiled( + UINT_32 x, ///< [in] x coordinate + UINT_32 y, ///< [in] y coordinate + UINT_32 slice, ///< [in] slice index + UINT_32 sample, ///< [in] sample number + UINT_32 plane, ///< [in] plane number + UINT_32 pitch, ///< [in] surface pitch in pixels + UINT_32 height, ///< [in] surface height in pixels + UINT_32 numSamples, ///< [in] number of samples + AddrTileMode tileMode, ///< [in] tile mode + BOOL_32 resolved, ///< [in] TRUE if this is for resolved fmask + UINT_32* pBitPosition ///< [out] pointer to returned bit position + ) const +{ + UINT_64 addr = 0; + UINT_32 effectiveBpp; + UINT_32 effectiveSamples; + + // + // 2xAA use the same layout as 4xAA + // + if (numSamples == 2) + { + numSamples = 4; + } + + // + // Compute the number of planes. + // + if (!resolved) + { + effectiveSamples = ComputeFmaskNumPlanesFromNumSamples(numSamples); + effectiveBpp = numSamples; + + // + // Compute the address just like a color surface with numSamples bits per element and + // numPlanes samples. + // + addr = ComputeSurfaceAddrFromCoordMicroTiled(x, + y, + slice, + plane, // sample + effectiveBpp, + pitch, + height, + effectiveSamples, + tileMode, + ADDR_NON_DISPLAYABLE, + FALSE, + pBitPosition); + + // + // Compute the real bit position. Each (sample, plane) is stored with one bit per sample. + // + + // + // Compute the pixel index with in the micro tile + // + UINT_32 pixelIndex = ComputePixelIndexWithinMicroTile(x % 8, + y % 8, + slice, + 1, + tileMode, + ADDR_NON_DISPLAYABLE); + + *pBitPosition = ((pixelIndex * numSamples) + sample) & (BITS_PER_BYTE-1); + + UINT_64 bitAddr = BYTES_TO_BITS(addr) + *pBitPosition; + + addr = bitAddr / 8; + } + else + { + effectiveBpp = ComputeFmaskResolvedBppFromNumSamples(numSamples); + effectiveSamples = 1; + + // + // Compute the address just like a color surface with numSamples bits per element and + // numPlanes samples. + // + addr = ComputeSurfaceAddrFromCoordMicroTiled(x, + y, + slice, + sample, + effectiveBpp, + pitch, + height, + effectiveSamples, + tileMode, + ADDR_NON_DISPLAYABLE, + TRUE, + pBitPosition); + } + + return addr; +} + +/** +*************************************************************************************************** +* EgBasedAddrLib::ComputeFmaskAddrFromCoordMacroTiled +* +* @brief +* Computes the FMASK address and bit position from a coordinate for 2D tilied (macro +* tiled) +* @return +* The byte address +*************************************************************************************************** +*/ +UINT_64 EgBasedAddrLib::ComputeFmaskAddrFromCoordMacroTiled( + UINT_32 x, ///< [in] x coordinate + UINT_32 y, ///< [in] y coordinate + UINT_32 slice, ///< [in] slice index + UINT_32 sample, ///< [in] sample number + UINT_32 plane, ///< [in] plane number + UINT_32 pitch, ///< [in] surface pitch in pixels + UINT_32 height, ///< [in] surface height in pixels + UINT_32 numSamples, ///< [in] number of samples + AddrTileMode tileMode, ///< [in] tile mode + UINT_32 pipeSwizzle, ///< [in] pipe swizzle + UINT_32 bankSwizzle, ///< [in] bank swizzle + BOOL_32 ignoreSE, ///< [in] TRUE if ignore shader engine + ADDR_TILEINFO* pTileInfo, ///< [in] bank structure.**All fields to be valid on entry** + BOOL_32 resolved, ///< [in] TRUE if this is for resolved fmask + UINT_32* pBitPosition ///< [out] pointer to returned bit position + ) const +{ + UINT_64 addr = 0; + UINT_32 effectiveBpp; + UINT_32 effectiveSamples; + + // + // 2xAA use the same layout as 4xAA + // + if (numSamples == 2) + { + numSamples = 4; + } + + // + // Compute the number of planes. + // + if (!resolved) + { + effectiveSamples = ComputeFmaskNumPlanesFromNumSamples(numSamples); + effectiveBpp = numSamples; + + // + // Compute the address just like a color surface with numSamples bits per element and + // numPlanes samples. + // + addr = ComputeSurfaceAddrFromCoordMacroTiled(x, + y, + slice, + plane, // sample + effectiveBpp, + pitch, + height, + effectiveSamples, + tileMode, + ADDR_NON_DISPLAYABLE,// isdisp + ignoreSE,// ignore_shader + FALSE,// depth_sample_order + pipeSwizzle, + bankSwizzle, + pTileInfo, + pBitPosition); + + // + // Compute the real bit position. Each (sample, plane) is stored with one bit per sample. + // + + + // + // Compute the pixel index with in the micro tile + // + UINT_32 pixelIndex = ComputePixelIndexWithinMicroTile(x , + y , + slice, + effectiveBpp, + tileMode, + ADDR_NON_DISPLAYABLE); + + *pBitPosition = ((pixelIndex * numSamples) + sample) & (BITS_PER_BYTE-1); + + UINT_64 bitAddr = BYTES_TO_BITS(addr) + *pBitPosition; + + addr = bitAddr / 8; + + } + else + { + effectiveBpp = ComputeFmaskResolvedBppFromNumSamples(numSamples); + effectiveSamples = 1; + + // + // Compute the address just like a color surface with numSamples bits per element and + // numPlanes samples. + // + addr = ComputeSurfaceAddrFromCoordMacroTiled(x, + y, + slice, + sample, + effectiveBpp, + pitch, + height, + effectiveSamples, + tileMode, + ADDR_NON_DISPLAYABLE, + ignoreSE, + TRUE, + pipeSwizzle, + bankSwizzle, + pTileInfo, + pBitPosition); + } + + return addr; +} + +/** +*************************************************************************************************** +* EgBasedAddrLib::ComputeFmaskCoordFromAddrMicroTiled +* +* @brief +* Compute (x,y,slice,sample,plane) coordinates from fmask address +* @return +* N/A +* +*************************************************************************************************** +*/ +VOID EgBasedAddrLib::ComputeFmaskCoordFromAddrMicroTiled( + UINT_64 addr, ///< [in] byte address + UINT_32 bitPosition,///< [in] bit position + UINT_32 pitch, ///< [in] pitch in pixels + UINT_32 height, ///< [in] height in pixels + UINT_32 numSamples, ///< [in] number of samples (of color buffer) + AddrTileMode tileMode, ///< [in] tile mode + BOOL_32 resolved, ///< [in] TRUE if it is resolved fmask + UINT_32* pX, ///< [out] X coord + UINT_32* pY, ///< [out] Y coord + UINT_32* pSlice, ///< [out] slice index + UINT_32* pSample, ///< [out] sample index + UINT_32* pPlane ///< [out] plane index + ) const +{ + UINT_32 effectiveBpp; + UINT_32 effectiveSamples; + + // 2xAA use the same layout as 4xAA + if (numSamples == 2) + { + numSamples = 4; + } + + if (!resolved) + { + effectiveSamples = ComputeFmaskNumPlanesFromNumSamples(numSamples); + effectiveBpp = numSamples; + + ComputeSurfaceCoordFromAddrMicroTiled(addr, + bitPosition, + effectiveBpp, + pitch, + height, + effectiveSamples, + tileMode, + 0, // tileBase + 0, // compBits + pX, + pY, + pSlice, + pPlane, + ADDR_NON_DISPLAYABLE, // microTileType + FALSE // isDepthSampleOrder + ); + + + if ( pSample ) + { + *pSample = bitPosition % numSamples; + } + } + else + { + effectiveBpp = ComputeFmaskResolvedBppFromNumSamples(numSamples); + effectiveSamples = 1; + + ComputeSurfaceCoordFromAddrMicroTiled(addr, + bitPosition, + effectiveBpp, + pitch, + height, + effectiveSamples, + tileMode, + 0, // tileBase + 0, // compBits + pX, + pY, + pSlice, + pSample, + ADDR_NON_DISPLAYABLE, // microTileType + TRUE // isDepthSampleOrder + ); + } +} + +/** +*************************************************************************************************** +* EgBasedAddrLib::ComputeFmaskCoordFromAddrMacroTiled +* +* @brief +* Compute (x,y,slice,sample,plane) coordinates from +* fmask address +* @return +* N/A +* +*************************************************************************************************** +*/ +VOID EgBasedAddrLib::ComputeFmaskCoordFromAddrMacroTiled( + UINT_64 addr, ///< [in] byte address + UINT_32 bitPosition,///< [in] bit position + UINT_32 pitch, ///< [in] pitch in pixels + UINT_32 height, ///< [in] height in pixels + UINT_32 numSamples, ///< [in] number of samples (of color buffer) + AddrTileMode tileMode, ///< [in] tile mode + UINT_32 pipeSwizzle,///< [in] pipe swizzle + UINT_32 bankSwizzle,///< [in] bank swizzle + BOOL_32 ignoreSE, ///< [in] TRUE if ignore shader engine + ADDR_TILEINFO* pTileInfo, ///< [in] bank structure. **All fields to be valid on entry** + BOOL_32 resolved, ///< [in] TRUE if it is resolved fmask + UINT_32* pX, ///< [out] X coord + UINT_32* pY, ///< [out] Y coord + UINT_32* pSlice, ///< [out] slice index + UINT_32* pSample, ///< [out] sample index + UINT_32* pPlane ///< [out] plane index + ) const +{ + UINT_32 effectiveBpp; + UINT_32 effectiveSamples; + + // 2xAA use the same layout as 4xAA + if (numSamples == 2) + { + numSamples = 4; + } + + // + // Compute the number of planes. + // + if (!resolved) + { + effectiveSamples = ComputeFmaskNumPlanesFromNumSamples(numSamples); + effectiveBpp = numSamples; + + ComputeSurfaceCoordFromAddrMacroTiled(addr, + bitPosition, + effectiveBpp, + pitch, + height, + effectiveSamples, + tileMode, + 0, // No tileBase + 0, // No compBits + ADDR_NON_DISPLAYABLE, + ignoreSE, + FALSE, + pipeSwizzle, + bankSwizzle, + pTileInfo, + pX, + pY, + pSlice, + pPlane); + + if (pSample) + { + *pSample = bitPosition % numSamples; + } + } + else + { + effectiveBpp = ComputeFmaskResolvedBppFromNumSamples(numSamples); + effectiveSamples = 1; + + ComputeSurfaceCoordFromAddrMacroTiled(addr, + bitPosition, + effectiveBpp, + pitch, + height, + effectiveSamples, + tileMode, + 0, // No tileBase + 0, // No compBits + ADDR_NON_DISPLAYABLE, + ignoreSE, + TRUE, + pipeSwizzle, + bankSwizzle, + pTileInfo, + pX, + pY, + pSlice, + pSample); + } +} + +/** +*************************************************************************************************** +* EgBasedAddrLib::DispatchComputeFmaskCoordFromAddr +* +* @brief +* Compute (x,y,slice,sample,plane) coordinates from +* fmask address +* @return +* N/A +* +*************************************************************************************************** +*/ +VOID EgBasedAddrLib::DispatchComputeFmaskCoordFromAddr( + const ADDR_COMPUTE_FMASK_COORDFROMADDR_INPUT* pIn, ///< [in] input structure + ADDR_COMPUTE_FMASK_COORDFROMADDR_OUTPUT* pOut ///< [out] output structure + ) const +{ + UINT_64 addr = pIn->addr; + UINT_32 bitPosition = pIn->bitPosition; + UINT_32 pitch = pIn->pitch; + UINT_32 height = pIn->height; + UINT_32 numSamples = pIn->numSamples; + AddrTileMode tileMode = pIn->tileMode; + BOOL_32 ignoreSE = pIn->ignoreSE; + ADDR_TILEINFO* pTileInfo = pIn->pTileInfo; + BOOL_32 resolved = pIn->resolved; + + UINT_32* pX = &pOut->x; + UINT_32* pY = &pOut->y; + UINT_32* pSlice = &pOut->slice; + UINT_32* pSample = &pOut->sample; + UINT_32* pPlane = &pOut->plane; + + switch (tileMode) + { + case ADDR_TM_1D_TILED_THIN1: + ComputeFmaskCoordFromAddrMicroTiled(addr, + bitPosition, + pitch, + height, + numSamples, + tileMode, + resolved, + pX, + pY, + pSlice, + pSample, + pPlane); + break; + case ADDR_TM_2D_TILED_THIN1://fall through + case ADDR_TM_3D_TILED_THIN1: + UINT_32 pipeSwizzle; + UINT_32 bankSwizzle; + + if (m_configFlags.useCombinedSwizzle) + { + ExtractBankPipeSwizzle(pIn->tileSwizzle, pIn->pTileInfo, + &bankSwizzle, &pipeSwizzle); + } + else + { + pipeSwizzle = pIn->pipeSwizzle; + bankSwizzle = pIn->bankSwizzle; + } + + ComputeFmaskCoordFromAddrMacroTiled(addr, + bitPosition, + pitch, + height, + numSamples, + tileMode, + pipeSwizzle, + bankSwizzle, + ignoreSE, + pTileInfo, + resolved, + pX, + pY, + pSlice, + pSample, + pPlane); + break; + default: + ADDR_ASSERT_ALWAYS(); + break; + + } +} +#endif + +/** +*************************************************************************************************** +* EgBasedAddrLib::ComputeFmaskNumPlanesFromNumSamples +* +* @brief +* Compute fmask number of planes from number of samples +* +* @return +* Number of planes +*************************************************************************************************** +*/ +UINT_32 EgBasedAddrLib::ComputeFmaskNumPlanesFromNumSamples( + UINT_32 numSamples) ///< [in] number of samples +{ + UINT_32 numPlanes; + + // + // FMASK is stored such that each micro tile is composed of elements containing N bits, where + // N is the number of samples. There is a micro tile for each bit in the FMASK address, and + // micro tiles for each address bit, sometimes referred to as a plane, are stored sequentially. + // The FMASK for a 2-sample surface looks like a general surface with 2 bits per element. + // The FMASK for a 4-sample surface looks like a general surface with 4 bits per element and + // 2 samples. The FMASK for an 8-sample surface looks like a general surface with 8 bits per + // element and 4 samples. R6xx and R7xx only stored 3 planes for 8-sample FMASK surfaces. + // This was changed for R8xx to simplify the logic in the CB. + // + switch (numSamples) + { + case 2: + numPlanes = 1; + break; + case 4: + numPlanes = 2; + break; + case 8: + numPlanes = 4; + break; + default: + ADDR_UNHANDLED_CASE(); + numPlanes = 0; + break; + } + return numPlanes; +} + +/** +*************************************************************************************************** +* EgBasedAddrLib::ComputeFmaskResolvedBppFromNumSamples +* +* @brief +* Compute resolved fmask effective bpp based on number of samples +* +* @return +* bpp +*************************************************************************************************** +*/ +UINT_32 EgBasedAddrLib::ComputeFmaskResolvedBppFromNumSamples( + UINT_32 numSamples) ///< number of samples +{ + UINT_32 bpp; + + // + // Resolved FMASK surfaces are generated yBit the CB and read yBit the texture unit + // so that the texture unit can read compressed multi-sample color data. + // These surfaces store each index value packed per element. + // Each element contains at least num_samples * log2(num_samples) bits. + // Resolved FMASK surfaces are addressed as follows: + // 2-sample Addressed similarly to a color surface with 8 bits per element and 1 sample. + // 4-sample Addressed similarly to a color surface with 8 bits per element and 1 sample. + // 8-sample Addressed similarly to a color surface with 32 bits per element and 1 sample. + + switch (numSamples) + { + case 2: + bpp = 8; + break; + case 4: + bpp = 8; + break; + case 8: + bpp = 32; + break; + default: + ADDR_UNHANDLED_CASE(); + bpp = 0; + break; + } + return bpp; +} + +/** +*************************************************************************************************** +* EgBasedAddrLib::IsTileInfoAllZero +* +* @brief +* Return TRUE if all field are zero +* @note +* Since NULL input is consider to be all zero +*************************************************************************************************** +*/ +BOOL_32 EgBasedAddrLib::IsTileInfoAllZero( + ADDR_TILEINFO* pTileInfo) +{ + BOOL_32 allZero = TRUE; + + if (pTileInfo) + { + if ((pTileInfo->banks != 0) || + (pTileInfo->bankWidth != 0) || + (pTileInfo->bankHeight != 0) || + (pTileInfo->macroAspectRatio != 0) || + (pTileInfo->tileSplitBytes != 0) || + (pTileInfo->pipeConfig != 0) + ) + { + allZero = FALSE; + } + } + + return allZero; +} + +/** +*************************************************************************************************** +* EgBasedAddrLib::HwlTileInfoEqual +* +* @brief +* Return TRUE if all field are equal +* @note +* Only takes care of current HWL's data +*************************************************************************************************** +*/ +BOOL_32 EgBasedAddrLib::HwlTileInfoEqual( + const ADDR_TILEINFO* pLeft, ///<[in] Left compare operand + const ADDR_TILEINFO* pRight ///<[in] Right compare operand + ) const +{ + BOOL_32 equal = FALSE; + + if (pLeft->banks == pRight->banks && + pLeft->bankWidth == pRight->bankWidth && + pLeft->bankHeight == pRight->bankHeight && + pLeft->macroAspectRatio == pRight->macroAspectRatio && + pLeft->tileSplitBytes == pRight->tileSplitBytes) + { + equal = TRUE; + } + + return equal; +} + +/** +*************************************************************************************************** +* EgBasedAddrLib::HwlConvertTileInfoToHW +* @brief +* Entry of EgBasedAddrLib ConvertTileInfoToHW +* @return +* ADDR_E_RETURNCODE +*************************************************************************************************** +*/ +ADDR_E_RETURNCODE EgBasedAddrLib::HwlConvertTileInfoToHW( + const ADDR_CONVERT_TILEINFOTOHW_INPUT* pIn, ///< [in] input structure + ADDR_CONVERT_TILEINFOTOHW_OUTPUT* pOut ///< [out] output structure + ) const +{ + ADDR_E_RETURNCODE retCode = ADDR_OK; + + ADDR_TILEINFO *pTileInfoIn = pIn->pTileInfo; + ADDR_TILEINFO *pTileInfoOut = pOut->pTileInfo; + + if ((pTileInfoIn != NULL) && (pTileInfoOut != NULL)) + { + if (pIn->reverse == FALSE) + { + switch (pTileInfoIn->banks) + { + case 2: + pTileInfoOut->banks = 0; + break; + case 4: + pTileInfoOut->banks = 1; + break; + case 8: + pTileInfoOut->banks = 2; + break; + case 16: + pTileInfoOut->banks = 3; + break; + default: + ADDR_ASSERT_ALWAYS(); + retCode = ADDR_INVALIDPARAMS; + pTileInfoOut->banks = 0; + break; + } + + switch (pTileInfoIn->bankWidth) + { + case 1: + pTileInfoOut->bankWidth = 0; + break; + case 2: + pTileInfoOut->bankWidth = 1; + break; + case 4: + pTileInfoOut->bankWidth = 2; + break; + case 8: + pTileInfoOut->bankWidth = 3; + break; + default: + ADDR_ASSERT_ALWAYS(); + retCode = ADDR_INVALIDPARAMS; + pTileInfoOut->bankWidth = 0; + break; + } + + switch (pTileInfoIn->bankHeight) + { + case 1: + pTileInfoOut->bankHeight = 0; + break; + case 2: + pTileInfoOut->bankHeight = 1; + break; + case 4: + pTileInfoOut->bankHeight = 2; + break; + case 8: + pTileInfoOut->bankHeight = 3; + break; + default: + ADDR_ASSERT_ALWAYS(); + retCode = ADDR_INVALIDPARAMS; + pTileInfoOut->bankHeight = 0; + break; + } + + switch (pTileInfoIn->macroAspectRatio) + { + case 1: + pTileInfoOut->macroAspectRatio = 0; + break; + case 2: + pTileInfoOut->macroAspectRatio = 1; + break; + case 4: + pTileInfoOut->macroAspectRatio = 2; + break; + case 8: + pTileInfoOut->macroAspectRatio = 3; + break; + default: + ADDR_ASSERT_ALWAYS(); + retCode = ADDR_INVALIDPARAMS; + pTileInfoOut->macroAspectRatio = 0; + break; + } + + switch (pTileInfoIn->tileSplitBytes) + { + case 64: + pTileInfoOut->tileSplitBytes = 0; + break; + case 128: + pTileInfoOut->tileSplitBytes = 1; + break; + case 256: + pTileInfoOut->tileSplitBytes = 2; + break; + case 512: + pTileInfoOut->tileSplitBytes = 3; + break; + case 1024: + pTileInfoOut->tileSplitBytes = 4; + break; + case 2048: + pTileInfoOut->tileSplitBytes = 5; + break; + case 4096: + pTileInfoOut->tileSplitBytes = 6; + break; + default: + ADDR_ASSERT_ALWAYS(); + retCode = ADDR_INVALIDPARAMS; + pTileInfoOut->tileSplitBytes = 0; + break; + } + } + else + { + switch (pTileInfoIn->banks) + { + case 0: + pTileInfoOut->banks = 2; + break; + case 1: + pTileInfoOut->banks = 4; + break; + case 2: + pTileInfoOut->banks = 8; + break; + case 3: + pTileInfoOut->banks = 16; + break; + default: + ADDR_ASSERT_ALWAYS(); + retCode = ADDR_INVALIDPARAMS; + pTileInfoOut->banks = 2; + break; + } + + switch (pTileInfoIn->bankWidth) + { + case 0: + pTileInfoOut->bankWidth = 1; + break; + case 1: + pTileInfoOut->bankWidth = 2; + break; + case 2: + pTileInfoOut->bankWidth = 4; + break; + case 3: + pTileInfoOut->bankWidth = 8; + break; + default: + ADDR_ASSERT_ALWAYS(); + retCode = ADDR_INVALIDPARAMS; + pTileInfoOut->bankWidth = 1; + break; + } + + switch (pTileInfoIn->bankHeight) + { + case 0: + pTileInfoOut->bankHeight = 1; + break; + case 1: + pTileInfoOut->bankHeight = 2; + break; + case 2: + pTileInfoOut->bankHeight = 4; + break; + case 3: + pTileInfoOut->bankHeight = 8; + break; + default: + ADDR_ASSERT_ALWAYS(); + retCode = ADDR_INVALIDPARAMS; + pTileInfoOut->bankHeight = 1; + break; + } + + switch (pTileInfoIn->macroAspectRatio) + { + case 0: + pTileInfoOut->macroAspectRatio = 1; + break; + case 1: + pTileInfoOut->macroAspectRatio = 2; + break; + case 2: + pTileInfoOut->macroAspectRatio = 4; + break; + case 3: + pTileInfoOut->macroAspectRatio = 8; + break; + default: + ADDR_ASSERT_ALWAYS(); + retCode = ADDR_INVALIDPARAMS; + pTileInfoOut->macroAspectRatio = 1; + break; + } + + switch (pTileInfoIn->tileSplitBytes) + { + case 0: + pTileInfoOut->tileSplitBytes = 64; + break; + case 1: + pTileInfoOut->tileSplitBytes = 128; + break; + case 2: + pTileInfoOut->tileSplitBytes = 256; + break; + case 3: + pTileInfoOut->tileSplitBytes = 512; + break; + case 4: + pTileInfoOut->tileSplitBytes = 1024; + break; + case 5: + pTileInfoOut->tileSplitBytes = 2048; + break; + case 6: + pTileInfoOut->tileSplitBytes = 4096; + break; + default: + ADDR_ASSERT_ALWAYS(); + retCode = ADDR_INVALIDPARAMS; + pTileInfoOut->tileSplitBytes = 64; + break; + } + } + + if (pTileInfoIn != pTileInfoOut) + { + pTileInfoOut->pipeConfig = pTileInfoIn->pipeConfig; + } + } + else + { + ADDR_ASSERT_ALWAYS(); + retCode = ADDR_INVALIDPARAMS; + } + + return retCode; +} + +/** +*************************************************************************************************** +* EgBasedAddrLib::HwlComputeSurfaceInfo +* @brief +* Entry of EgBasedAddrLib ComputeSurfaceInfo +* @return +* ADDR_E_RETURNCODE +*************************************************************************************************** +*/ +ADDR_E_RETURNCODE EgBasedAddrLib::HwlComputeSurfaceInfo( + const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] input structure + ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [out] output structure + ) const +{ + ADDR_E_RETURNCODE retCode = ADDR_OK; + + if (pIn->numSamples < pIn->numFrags) + { + retCode = ADDR_INVALIDPARAMS; + } + + ADDR_TILEINFO tileInfo = {0}; + + if (retCode == ADDR_OK) + { + // Uses internal tile info if pOut does not have a valid pTileInfo + if (pOut->pTileInfo == NULL) + { + pOut->pTileInfo = &tileInfo; + } + + if (!DispatchComputeSurfaceInfo(pIn, pOut)) + { + retCode = ADDR_INVALIDPARAMS; + } + + // Returns an index + pOut->tileIndex = HwlPostCheckTileIndex(pOut->pTileInfo, + pOut->tileMode, + pOut->tileType, + pOut->tileIndex); + + if (IsMacroTiled(pOut->tileMode) && (pOut->macroModeIndex == TileIndexInvalid)) + { + pOut->macroModeIndex = HwlComputeMacroModeIndex(pOut->tileIndex, + pIn->flags, + pIn->bpp, + pIn->numSamples, + pOut->pTileInfo); + } + + // Resets pTileInfo to NULL if the internal tile info is used + if (pOut->pTileInfo == &tileInfo) + { +#if DEBUG + // Client does not pass in a valid pTileInfo + if (IsMacroTiled(pOut->tileMode)) + { + // If a valid index is returned, then no pTileInfo is okay + ADDR_ASSERT(!m_configFlags.useTileIndex || pOut->tileIndex != TileIndexInvalid); + + if (!IsTileInfoAllZero(pIn->pTileInfo)) + { + // The initial value of pIn->pTileInfo is copied to tileInfo + // We do not expect any of these value to be changed nor any 0 of inputs + ADDR_ASSERT(tileInfo.banks == pIn->pTileInfo->banks); + ADDR_ASSERT(tileInfo.bankWidth == pIn->pTileInfo->bankWidth); + ADDR_ASSERT(tileInfo.bankHeight == pIn->pTileInfo->bankHeight); + ADDR_ASSERT(tileInfo.macroAspectRatio == pIn->pTileInfo->macroAspectRatio); + ADDR_ASSERT(tileInfo.tileSplitBytes == pIn->pTileInfo->tileSplitBytes); + } + } +#endif + pOut->pTileInfo = NULL; + } + } + + return retCode; +} + +/** +*************************************************************************************************** +* EgBasedAddrLib::HwlComputeSurfaceAddrFromCoord +* @brief +* Entry of EgBasedAddrLib ComputeSurfaceAddrFromCoord +* @return +* ADDR_E_RETURNCODE +*************************************************************************************************** +*/ +ADDR_E_RETURNCODE EgBasedAddrLib::HwlComputeSurfaceAddrFromCoord( + const ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn, ///< [in] input structure + ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT* pOut ///< [out] output structure + ) const +{ + ADDR_E_RETURNCODE retCode = ADDR_OK; + + if ( +#if !ALT_TEST // Overflow test needs this out-of-boundary coord + (pIn->x > pIn->pitch) || + (pIn->y > pIn->height) || +#endif + (pIn->numSamples > m_maxSamples)) + { + retCode = ADDR_INVALIDPARAMS; + } + else + { + pOut->addr = DispatchComputeSurfaceAddrFromCoord(pIn, pOut); + } + + return retCode; +} + +/** +*************************************************************************************************** +* EgBasedAddrLib::HwlComputeSurfaceCoordFromAddr +* @brief +* Entry of EgBasedAddrLib ComputeSurfaceCoordFromAddr +* @return +* ADDR_E_RETURNCODE +*************************************************************************************************** +*/ +ADDR_E_RETURNCODE EgBasedAddrLib::HwlComputeSurfaceCoordFromAddr( + const ADDR_COMPUTE_SURFACE_COORDFROMADDR_INPUT* pIn, ///< [in] input structure + ADDR_COMPUTE_SURFACE_COORDFROMADDR_OUTPUT* pOut ///< [out] output structure + ) const +{ + ADDR_E_RETURNCODE retCode = ADDR_OK; + + if ((pIn->bitPosition >= 8) || + (pIn->numSamples > m_maxSamples)) + { + retCode = ADDR_INVALIDPARAMS; + } + else + { + DispatchComputeSurfaceCoordFromAddr(pIn, pOut); + } + return retCode; +} + +/** +*************************************************************************************************** +* EgBasedAddrLib::HwlComputeSliceTileSwizzle +* @brief +* Entry of EgBasedAddrLib ComputeSurfaceCoordFromAddr +* @return +* ADDR_E_RETURNCODE +*************************************************************************************************** +*/ +ADDR_E_RETURNCODE EgBasedAddrLib::HwlComputeSliceTileSwizzle( + const ADDR_COMPUTE_SLICESWIZZLE_INPUT* pIn, ///< [in] input structure + ADDR_COMPUTE_SLICESWIZZLE_OUTPUT* pOut ///< [out] output structure + ) const +{ + ADDR_E_RETURNCODE retCode = ADDR_OK; + + if (pIn->pTileInfo && (pIn->pTileInfo->banks > 0)) + { + + pOut->tileSwizzle = ComputeSliceTileSwizzle(pIn->tileMode, + pIn->baseSwizzle, + pIn->slice, + pIn->baseAddr, + pIn->pTileInfo); + } + else + { + retCode = ADDR_INVALIDPARAMS; + } + + return retCode; +} + +/** +*************************************************************************************************** +* EgBasedAddrLib::HwlComputeHtileBpp +* +* @brief +* Compute htile bpp +* +* @return +* Htile bpp +*************************************************************************************************** +*/ +UINT_32 EgBasedAddrLib::HwlComputeHtileBpp( + BOOL_32 isWidth8, ///< [in] TRUE if block width is 8 + BOOL_32 isHeight8 ///< [in] TRUE if block height is 8 + ) const +{ + // only support 8x8 mode + ADDR_ASSERT(isWidth8 && isHeight8); + return 32; +} + +/** +*************************************************************************************************** +* EgBasedAddrLib::HwlComputeHtileBaseAlign +* +* @brief +* Compute htile base alignment +* +* @return +* Htile base alignment +*************************************************************************************************** +*/ +UINT_32 EgBasedAddrLib::HwlComputeHtileBaseAlign( + BOOL_32 isTcCompatible, ///< [in] if TC compatible + BOOL_32 isLinear, ///< [in] if it is linear mode + ADDR_TILEINFO* pTileInfo ///< [in] Tile info + ) const +{ + UINT_32 baseAlign = m_pipeInterleaveBytes * HwlGetPipes(pTileInfo); + + if (isTcCompatible) + { + ADDR_ASSERT(pTileInfo != NULL); + if (pTileInfo) + { + baseAlign *= pTileInfo->banks; + } + } + + return baseAlign; +} + +/** +*************************************************************************************************** +* EgBasedAddrLib::HwlGetPitchAlignmentMicroTiled +* +* @brief +* Compute 1D tiled surface pitch alignment, calculation results are returned through +* output parameters. +* +* @return +* pitch alignment +*************************************************************************************************** +*/ +UINT_32 EgBasedAddrLib::HwlGetPitchAlignmentMicroTiled( + AddrTileMode tileMode, ///< [in] tile mode + UINT_32 bpp, ///< [in] bits per pixel + ADDR_SURFACE_FLAGS flags, ///< [in] surface flags + UINT_32 numSamples ///< [in] number of samples + ) const +{ + UINT_32 pitchAlign; + + UINT_32 microTileThickness = ComputeSurfaceThickness(tileMode); + + UINT_32 pixelsPerMicroTile; + UINT_32 pixelsPerPipeInterleave; + UINT_32 microTilesPerPipeInterleave; + + // + // Special workaround for depth/stencil buffer, use 8 bpp to meet larger requirement for + // stencil buffer since pitch alignment is related to bpp. + // For a depth only buffer do not set this. + // + // Note: this actually does not work for mipmap but mipmap depth texture is not really + // sampled with mipmap. + // + if (flags.depth && !flags.noStencil) + { + bpp = 8; + } + + pixelsPerMicroTile = MicroTilePixels * microTileThickness; + pixelsPerPipeInterleave = BYTES_TO_BITS(m_pipeInterleaveBytes) / (bpp * numSamples); + microTilesPerPipeInterleave = pixelsPerPipeInterleave / pixelsPerMicroTile; + + pitchAlign = Max(MicroTileWidth, microTilesPerPipeInterleave * MicroTileWidth); + + return pitchAlign; +} + +/** +*************************************************************************************************** +* EgBasedAddrLib::HwlGetSizeAdjustmentMicroTiled +* +* @brief +* Adjust 1D tiled surface pitch and slice size +* +* @return +* Logical slice size in bytes +*************************************************************************************************** +*/ +UINT_64 EgBasedAddrLib::HwlGetSizeAdjustmentMicroTiled( + UINT_32 thickness, ///< [in] thickness + UINT_32 bpp, ///< [in] bits per pixel + ADDR_SURFACE_FLAGS flags, ///< [in] surface flags + UINT_32 numSamples, ///< [in] number of samples + UINT_32 baseAlign, ///< [in] base alignment + UINT_32 pitchAlign, ///< [in] pitch alignment + UINT_32* pPitch, ///< [in/out] pointer to pitch + UINT_32* pHeight ///< [in/out] pointer to height + ) const +{ + UINT_64 logicalSliceSize; + UINT_64 physicalSliceSize; + + UINT_32 pitch = *pPitch; + UINT_32 height = *pHeight; + + // Logical slice: pitch * height * bpp * numSamples (no 1D MSAA so actually numSamples == 1) + logicalSliceSize = BITS_TO_BYTES(static_cast<UINT_64>(pitch) * height * bpp * numSamples); + + // Physical slice: multiplied by thickness + physicalSliceSize = logicalSliceSize * thickness; + + // + // R800 will always pad physical slice size to baseAlign which is pipe_interleave_bytes + // + ADDR_ASSERT((physicalSliceSize % baseAlign) == 0) + + return logicalSliceSize; +} + diff --git a/src/amd/addrlib/r800/egbaddrlib.h b/src/amd/addrlib/r800/egbaddrlib.h new file mode 100644 index 00000000000..25e38964be0 --- /dev/null +++ b/src/amd/addrlib/r800/egbaddrlib.h @@ -0,0 +1,412 @@ +/* + * Copyright © 2014 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS + * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + */ + +/** +*************************************************************************************************** +* @file egbaddrlib.h +* @brief Contains the EgBasedAddrLib class definition. +*************************************************************************************************** +*/ + +#ifndef __EG_BASED_ADDR_LIB_H__ +#define __EG_BASED_ADDR_LIB_H__ + +#include "addrlib.h" + + +/// Structures for functions +struct CoordFromBankPipe +{ + UINT_32 xBits : 3; + UINT_32 yBits : 4; + + UINT_32 xBit3 : 1; + UINT_32 xBit4 : 1; + UINT_32 xBit5 : 1; + UINT_32 yBit3 : 1; + UINT_32 yBit4 : 1; + UINT_32 yBit5 : 1; + UINT_32 yBit6 : 1; +}; + +/** +*************************************************************************************************** +* @brief This class is the Evergreen based address library +* @note Abstract class +*************************************************************************************************** +*/ +class EgBasedAddrLib : public AddrLib +{ +protected: + EgBasedAddrLib(const AddrClient* pClient); + virtual ~EgBasedAddrLib(); + +public: + + /// Surface info functions + + // NOTE: DispatchComputeSurfaceInfo using TileInfo takes both an input and an output. + // On input: + // One or more fields may be 0 to be calculated/defaulted - pre-SI h/w. + // H/W using tile mode index only accepts none or all 0's - SI and newer h/w. + // It then returns the actual tiling configuration used. + // Other methods' TileInfo must be valid on entry + BOOL_32 DispatchComputeSurfaceInfo( + const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, + ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut) const; + + ADDR_E_RETURNCODE DispatchComputeFmaskInfo( + const ADDR_COMPUTE_FMASK_INFO_INPUT* pIn, + ADDR_COMPUTE_FMASK_INFO_OUTPUT* pOut); + +protected: + // Hwl interface + virtual ADDR_E_RETURNCODE HwlComputeSurfaceInfo( + const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, + ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut) const; + + virtual ADDR_E_RETURNCODE HwlComputeSurfaceAddrFromCoord( + const ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn, + ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT* pOut) const; + + virtual ADDR_E_RETURNCODE HwlComputeSurfaceCoordFromAddr( + const ADDR_COMPUTE_SURFACE_COORDFROMADDR_INPUT* pIn, + ADDR_COMPUTE_SURFACE_COORDFROMADDR_OUTPUT* pOut) const; + + virtual ADDR_E_RETURNCODE HwlComputeSliceTileSwizzle( + const ADDR_COMPUTE_SLICESWIZZLE_INPUT* pIn, + ADDR_COMPUTE_SLICESWIZZLE_OUTPUT* pOut) const; + + virtual ADDR_E_RETURNCODE HwlExtractBankPipeSwizzle( + const ADDR_EXTRACT_BANKPIPE_SWIZZLE_INPUT* pIn, + ADDR_EXTRACT_BANKPIPE_SWIZZLE_OUTPUT* pOut) const; + + virtual ADDR_E_RETURNCODE HwlCombineBankPipeSwizzle( + UINT_32 bankSwizzle, UINT_32 pipeSwizzle, ADDR_TILEINFO* pTileInfo, + UINT_64 baseAddr, UINT_32* pTileSwizzle) const; + + virtual ADDR_E_RETURNCODE HwlComputeBaseSwizzle( + const ADDR_COMPUTE_BASE_SWIZZLE_INPUT* pIn, + ADDR_COMPUTE_BASE_SWIZZLE_OUTPUT* pOut) const; + + virtual ADDR_E_RETURNCODE HwlConvertTileInfoToHW( + const ADDR_CONVERT_TILEINFOTOHW_INPUT* pIn, + ADDR_CONVERT_TILEINFOTOHW_OUTPUT* pOut) const; + + virtual UINT_32 HwlComputeHtileBpp( + BOOL_32 isWidth8, BOOL_32 isHeight8) const; + + virtual UINT_32 HwlComputeHtileBaseAlign( + BOOL_32 isTcCompatible, BOOL_32 isLinear, ADDR_TILEINFO* pTileInfo) const; + + virtual ADDR_E_RETURNCODE HwlComputeFmaskInfo( + const ADDR_COMPUTE_FMASK_INFO_INPUT* pIn, + ADDR_COMPUTE_FMASK_INFO_OUTPUT* pOut); + + virtual ADDR_E_RETURNCODE HwlComputeFmaskAddrFromCoord( + const ADDR_COMPUTE_FMASK_ADDRFROMCOORD_INPUT* pIn, + ADDR_COMPUTE_FMASK_ADDRFROMCOORD_OUTPUT* pOut) const; + + virtual ADDR_E_RETURNCODE HwlComputeFmaskCoordFromAddr( + const ADDR_COMPUTE_FMASK_COORDFROMADDR_INPUT* pIn, + ADDR_COMPUTE_FMASK_COORDFROMADDR_OUTPUT* pOut) const; + + virtual BOOL_32 HwlDegradeBaseLevel( + const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn) const; + + virtual UINT_32 HwlComputeQbStereoRightSwizzle( + ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pInfo) const; + + virtual VOID HwlComputePixelCoordFromOffset( + UINT_32 offset, UINT_32 bpp, UINT_32 numSamples, + AddrTileMode tileMode, UINT_32 tileBase, UINT_32 compBits, + UINT_32* pX, UINT_32* pY, UINT_32* pSlice, UINT_32* pSample, + AddrTileType microTileType, BOOL_32 isDepthSampleOrder) const; + + /// Return Cmask block max + virtual BOOL_32 HwlGetMaxCmaskBlockMax() const + { + return 16383; // 14 bits + } + + // Sub-hwl interface + /// Pure virtual function to setup tile info (indices) if client requests to do so + virtual VOID HwlSetupTileInfo( + AddrTileMode tileMode, ADDR_SURFACE_FLAGS flags, + UINT_32 bpp, UINT_32 pitch, UINT_32 height, UINT_32 numSamples, + ADDR_TILEINFO* inputTileInfo, ADDR_TILEINFO* outputTileInfo, + AddrTileType inTileType, ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut) const = 0; + + /// Pure virtual function to get pitch alignment for linear modes + virtual UINT_32 HwlGetPitchAlignmentLinear(UINT_32 bpp, ADDR_SURFACE_FLAGS flags) const = 0; + + /// Pure virtual function to get size adjustment for linear modes + virtual UINT_64 HwlGetSizeAdjustmentLinear( + AddrTileMode tileMode, + UINT_32 bpp, UINT_32 numSamples, UINT_32 baseAlign, UINT_32 pitchAlign, + UINT_32 *pPitch, UINT_32 *pHeight, UINT_32 *pHeightAlign) const = 0; + + virtual UINT_32 HwlGetPitchAlignmentMicroTiled( + AddrTileMode tileMode, UINT_32 bpp, ADDR_SURFACE_FLAGS flags, UINT_32 numSamples) const; + + virtual UINT_64 HwlGetSizeAdjustmentMicroTiled( + UINT_32 thickness, UINT_32 bpp, ADDR_SURFACE_FLAGS flags, UINT_32 numSamples, + UINT_32 baseAlign, UINT_32 pitchAlign, + UINT_32 *pPitch, UINT_32 *pHeight) const; + + /// Pure virtual function to do extra sanity check + virtual BOOL_32 HwlSanityCheckMacroTiled( + ADDR_TILEINFO* pTileInfo) const = 0; + + /// Pure virtual function to check current level to be the last macro tiled one + virtual VOID HwlCheckLastMacroTiledLvl( + const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, + ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut) const = 0; + + /// Adjusts bank before bank is modified by rotation + virtual UINT_32 HwlPreAdjustBank( + UINT_32 tileX, UINT_32 bank, ADDR_TILEINFO* pTileInfo) const = 0; + + virtual VOID HwlComputeSurfaceCoord2DFromBankPipe( + AddrTileMode tileMode, UINT_32* pX, UINT_32* pY, UINT_32 slice, + UINT_32 bank, UINT_32 pipe, + UINT_32 bankSwizzle, UINT_32 pipeSwizzle, UINT_32 tileSlices, + BOOL_32 ignoreSE, + ADDR_TILEINFO* pTileInfo) const = 0; + + virtual BOOL_32 HwlTileInfoEqual( + const ADDR_TILEINFO* pLeft, const ADDR_TILEINFO* pRight) const; + + virtual AddrTileMode HwlDegradeThickTileMode( + AddrTileMode baseTileMode, UINT_32 numSlices, UINT_32* pBytesPerTile) const; + + virtual INT_32 HwlPostCheckTileIndex( + const ADDR_TILEINFO* pInfo, AddrTileMode mode, AddrTileType type, + INT curIndex = TileIndexInvalid) const + { + return TileIndexInvalid; + } + + virtual VOID HwlFmaskPreThunkSurfInfo( + const ADDR_COMPUTE_FMASK_INFO_INPUT* pFmaskIn, + const ADDR_COMPUTE_FMASK_INFO_OUTPUT* pFmaskOut, + ADDR_COMPUTE_SURFACE_INFO_INPUT* pSurfIn, + ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pSurfOut) const + { + } + + virtual VOID HwlFmaskPostThunkSurfInfo( + const ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pSurfOut, + ADDR_COMPUTE_FMASK_INFO_OUTPUT* pFmaskOut) const + { + } + + /// Virtual function to check if the height needs extra padding + /// for stereo right eye offset, to avoid bank pipe swizzle + virtual BOOL_32 HwlStereoCheckRightOffsetPadding() const + { + return FALSE; + } + + virtual BOOL_32 HwlReduceBankWidthHeight( + UINT_32 tileSize, UINT_32 bpp, ADDR_SURFACE_FLAGS flags, UINT_32 numSamples, + UINT_32 bankHeightAlign, UINT_32 pipes, + ADDR_TILEINFO* pTileInfo) const; + + // Protected non-virtual functions + + /// Mip level functions + AddrTileMode ComputeSurfaceMipLevelTileMode( + AddrTileMode baseTileMode, UINT_32 bpp, + UINT_32 pitch, UINT_32 height, UINT_32 numSlices, UINT_32 numSamples, + UINT_32 pitchAlign, UINT_32 heightAlign, + ADDR_TILEINFO* pTileInfo) const; + + /// Swizzle functions + VOID ExtractBankPipeSwizzle( + UINT_32 base256b, ADDR_TILEINFO* pTileInfo, + UINT_32* pBankSwizzle, UINT_32* pPipeSwizzle) const; + + UINT_32 GetBankPipeSwizzle( + UINT_32 bankSwizzle, UINT_32 pipeSwizzle, + UINT_64 baseAddr, ADDR_TILEINFO* pTileInfo) const; + + UINT_32 ComputeSliceTileSwizzle( + AddrTileMode tileMode, UINT_32 baseSwizzle, UINT_32 slice, UINT_64 baseAddr, + ADDR_TILEINFO* pTileInfo) const; + + /// Addressing functions + UINT_32 ComputeBankFromCoord( + UINT_32 x, UINT_32 y, UINT_32 slice, + AddrTileMode tileMode, UINT_32 bankSwizzle, UINT_32 tileSpitSlice, + ADDR_TILEINFO* pTileInfo) const; + + UINT_32 ComputeBankFromAddr( + UINT_64 addr, UINT_32 numBanks, UINT_32 numPipes) const; + + UINT_32 ComputePipeRotation( + AddrTileMode tileMode, UINT_32 numPipes) const; + + UINT_32 ComputeBankRotation( + AddrTileMode tileMode, UINT_32 numBanks, + UINT_32 numPipes) const; + + VOID ComputeSurfaceCoord2DFromBankPipe( + AddrTileMode tileMode, UINT_32 x, UINT_32 y, UINT_32 slice, + UINT_32 bank, UINT_32 pipe, + UINT_32 bankSwizzle, UINT_32 pipeSwizzle, UINT_32 tileSlices, + ADDR_TILEINFO* pTileInfo, + CoordFromBankPipe *pOutput) const; + + /// Htile/Cmask functions + UINT_64 ComputeHtileBytes( + UINT_32 pitch, UINT_32 height, UINT_32 bpp, + BOOL_32 isLinear, UINT_32 numSlices, UINT_64* sliceBytes, UINT_32 baseAlign) const; + + // Static functions + static BOOL_32 IsTileInfoAllZero(ADDR_TILEINFO* pTileInfo); + static UINT_32 ComputeFmaskNumPlanesFromNumSamples(UINT_32 numSamples); + static UINT_32 ComputeFmaskResolvedBppFromNumSamples(UINT_32 numSamples); + +private: + + BOOL_32 ComputeSurfaceInfoLinear( + const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, + ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut, + UINT_32 padDims) const; + + BOOL_32 ComputeSurfaceInfoMicroTiled( + const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, + ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut, + UINT_32 padDims, + AddrTileMode expTileMode) const; + + BOOL_32 ComputeSurfaceInfoMacroTiled( + const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, + ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut, + UINT_32 padDims, + AddrTileMode expTileMode) const; + + BOOL_32 ComputeSurfaceAlignmentsLinear( + AddrTileMode tileMode, UINT_32 bpp, ADDR_SURFACE_FLAGS flags, + UINT_32* pBaseAlign, UINT_32* pPitchAlign, UINT_32* pHeightAlign) const; + + BOOL_32 ComputeSurfaceAlignmentsMicroTiled( + AddrTileMode tileMode, UINT_32 bpp, ADDR_SURFACE_FLAGS flags, + UINT_32 mipLevel, UINT_32 numSamples, + UINT_32* pBaseAlign, UINT_32* pPitchAlign, UINT_32* pHeightAlign) const; + + BOOL_32 ComputeSurfaceAlignmentsMacroTiled( + AddrTileMode tileMode, UINT_32 bpp, ADDR_SURFACE_FLAGS flags, + UINT_32 mipLevel, UINT_32 numSamples, + ADDR_TILEINFO* pTileInfo, + UINT_32* pBaseAlign, UINT_32* pPitchAlign, UINT_32* pHeightAlign) const; + + /// Surface addressing functions + UINT_64 DispatchComputeSurfaceAddrFromCoord( + const ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn, + ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT* pOut) const; + + VOID DispatchComputeSurfaceCoordFromAddr( + const ADDR_COMPUTE_SURFACE_COORDFROMADDR_INPUT* pIn, + ADDR_COMPUTE_SURFACE_COORDFROMADDR_OUTPUT* pOut) const; + + UINT_64 ComputeSurfaceAddrFromCoordMicroTiled( + UINT_32 x, UINT_32 y, UINT_32 slice, UINT_32 sample, + UINT_32 bpp, UINT_32 pitch, UINT_32 height, UINT_32 numSamples, + AddrTileMode tileMode, + AddrTileType microTileType, BOOL_32 isDepthSampleOrder, + UINT_32* pBitPosition) const; + + UINT_64 ComputeSurfaceAddrFromCoordMacroTiled( + UINT_32 x, UINT_32 y, UINT_32 slice, UINT_32 sample, + UINT_32 bpp, UINT_32 pitch, UINT_32 height, UINT_32 numSamples, + AddrTileMode tileMode, + AddrTileType microTileType, BOOL_32 ignoreSE, BOOL_32 isDepthSampleOrder, + UINT_32 pipeSwizzle, UINT_32 bankSwizzle, + ADDR_TILEINFO* pTileInfo, + UINT_32* pBitPosition) const; + + VOID ComputeSurfaceCoordFromAddrMacroTiled( + UINT_64 addr, UINT_32 bitPosition, + UINT_32 bpp, UINT_32 pitch, UINT_32 height, UINT_32 numSamples, + AddrTileMode tileMode, UINT_32 tileBase, UINT_32 compBits, + AddrTileType microTileType, BOOL_32 ignoreSE, BOOL_32 isDepthSampleOrder, + UINT_32 pipeSwizzle, UINT_32 bankSwizzle, + ADDR_TILEINFO* pTileInfo, + UINT_32* pX, UINT_32* pY, UINT_32* pSlice, UINT_32* pSample) const; + + /// Fmask functions + UINT_64 DispatchComputeFmaskAddrFromCoord( + const ADDR_COMPUTE_FMASK_ADDRFROMCOORD_INPUT* pIn, + ADDR_COMPUTE_FMASK_ADDRFROMCOORD_OUTPUT* pOut) const; + + VOID DispatchComputeFmaskCoordFromAddr( + const ADDR_COMPUTE_FMASK_COORDFROMADDR_INPUT* pIn, + ADDR_COMPUTE_FMASK_COORDFROMADDR_OUTPUT* pOut) const; + + // FMASK related methods - private + UINT_64 ComputeFmaskAddrFromCoordMicroTiled( + UINT_32 x, UINT_32 y, UINT_32 slice, UINT_32 sample, UINT_32 plane, + UINT_32 pitch, UINT_32 height, UINT_32 numSamples, AddrTileMode tileMode, + BOOL_32 resolved, UINT_32* pBitPosition) const; + + VOID ComputeFmaskCoordFromAddrMicroTiled( + UINT_64 addr, UINT_32 bitPosition, + UINT_32 pitch, UINT_32 height, UINT_32 numSamples, + AddrTileMode tileMode, BOOL_32 resolved, + UINT_32* pX, UINT_32* pY, UINT_32* pSlice, UINT_32* pSample, UINT_32* pPlane) const; + + VOID ComputeFmaskCoordFromAddrMacroTiled( + UINT_64 addr, UINT_32 bitPosition, + UINT_32 pitch, UINT_32 height, UINT_32 numSamples, AddrTileMode tileMode, + UINT_32 pipeSwizzle, UINT_32 bankSwizzle, + BOOL_32 ignoreSE, + ADDR_TILEINFO* pTileInfo, + BOOL_32 resolved, + UINT_32* pX, UINT_32* pY, UINT_32* pSlice, UINT_32* pSample, UINT_32* pPlane) const; + + UINT_64 ComputeFmaskAddrFromCoordMacroTiled( + UINT_32 x, UINT_32 y, UINT_32 slice, UINT_32 sample, UINT_32 plane, + UINT_32 pitch, UINT_32 height, UINT_32 numSamples, + AddrTileMode tileMode, UINT_32 pipeSwizzle, UINT_32 bankSwizzle, + BOOL_32 ignoreSE, + ADDR_TILEINFO* pTileInfo, + BOOL_32 resolved, + UINT_32* pBitPosition) const; + + /// Sanity check functions + BOOL_32 SanityCheckMacroTiled( + ADDR_TILEINFO* pTileInfo) const; + +protected: + UINT_32 m_ranks; ///< Number of ranks - MC_ARB_RAMCFG.NOOFRANK + UINT_32 m_logicalBanks; ///< Logical banks = m_banks * m_ranks if m_banks != 16 + UINT_32 m_bankInterleave; ///< Bank interleave, as a multiple of pipe interleave size +}; + +#endif + diff --git a/src/amd/addrlib/r800/siaddrlib.cpp b/src/amd/addrlib/r800/siaddrlib.cpp new file mode 100644 index 00000000000..a858b55b7cf --- /dev/null +++ b/src/amd/addrlib/r800/siaddrlib.cpp @@ -0,0 +1,2818 @@ +/* + * Copyright © 2014 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS + * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + */ + +/** +*************************************************************************************************** +* @file siaddrlib.cpp +* @brief Contains the implementation for the SIAddrLib class. +*************************************************************************************************** +*/ + +#include "siaddrlib.h" + +#include "si_gb_reg.h" + +#include "si_ci_vi_merged_enum.h" + +#if BRAHMA_BUILD +#include "amdgpu_id.h" +#else +#include "si_id.h" +#endif + +/////////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////////// + +/** +*************************************************************************************************** +* AddrSIHwlInit +* +* @brief +* Creates an SIAddrLib object. +* +* @return +* Returns an SIAddrLib object pointer. +*************************************************************************************************** +*/ +AddrLib* AddrSIHwlInit(const AddrClient* pClient) +{ + return SIAddrLib::CreateObj(pClient); +} + +/** +*************************************************************************************************** +* SIAddrLib::SIAddrLib +* +* @brief +* Constructor +* +*************************************************************************************************** +*/ +SIAddrLib::SIAddrLib(const AddrClient* pClient) : + EgBasedAddrLib(pClient), + m_noOfEntries(0) +{ + m_class = SI_ADDRLIB; + memset(&m_settings, 0, sizeof(m_settings)); +} + +/** +*************************************************************************************************** +* SIAddrLib::~SIAddrLib +* +* @brief +* Destructor +*************************************************************************************************** +*/ +SIAddrLib::~SIAddrLib() +{ +} + +/** +*************************************************************************************************** +* SIAddrLib::HwlGetPipes +* +* @brief +* Get number pipes +* @return +* num pipes +*************************************************************************************************** +*/ +UINT_32 SIAddrLib::HwlGetPipes( + const ADDR_TILEINFO* pTileInfo ///< [in] Tile info + ) const +{ + UINT_32 numPipes; + + if (pTileInfo) + { + numPipes = GetPipePerSurf(pTileInfo->pipeConfig); + } + else + { + ADDR_ASSERT_ALWAYS(); + numPipes = m_pipes; // Suppose we should still have a global pipes + } + + return numPipes; +} + +/** +*************************************************************************************************** +* SIAddrLib::GetPipePerSurf +* @brief +* get pipe num base on inputing tileinfo->pipeconfig +* @return +* pipe number +*************************************************************************************************** +*/ +UINT_32 SIAddrLib::GetPipePerSurf( + AddrPipeCfg pipeConfig ///< [in] pipe config + ) const +{ + UINT_32 numPipes = 0; + + switch (pipeConfig) + { + case ADDR_PIPECFG_P2: + numPipes = 2; + break; + case ADDR_PIPECFG_P4_8x16: + case ADDR_PIPECFG_P4_16x16: + case ADDR_PIPECFG_P4_16x32: + case ADDR_PIPECFG_P4_32x32: + numPipes = 4; + break; + case ADDR_PIPECFG_P8_16x16_8x16: + case ADDR_PIPECFG_P8_16x32_8x16: + case ADDR_PIPECFG_P8_32x32_8x16: + case ADDR_PIPECFG_P8_16x32_16x16: + case ADDR_PIPECFG_P8_32x32_16x16: + case ADDR_PIPECFG_P8_32x32_16x32: + case ADDR_PIPECFG_P8_32x64_32x32: + numPipes = 8; + break; + case ADDR_PIPECFG_P16_32x32_8x16: + case ADDR_PIPECFG_P16_32x32_16x16: + numPipes = 16; + break; + default: + ADDR_ASSERT(!"Invalid pipe config"); + numPipes = m_pipes; + } + return numPipes; +} + +/** +*************************************************************************************************** +* SIAddrLib::ComputePipeFromCoord +* +* @brief +* Compute pipe number from coordinates +* @return +* Pipe number +*************************************************************************************************** +*/ +UINT_32 SIAddrLib::ComputePipeFromCoord( + UINT_32 x, ///< [in] x coordinate + UINT_32 y, ///< [in] y coordinate + UINT_32 slice, ///< [in] slice index + AddrTileMode tileMode, ///< [in] tile mode + UINT_32 pipeSwizzle, ///< [in] pipe swizzle + BOOL_32 ignoreSE, ///< [in] TRUE if shader engines are ignored + ADDR_TILEINFO* pTileInfo ///< [in] Tile info + ) const +{ + UINT_32 pipe; + UINT_32 pipeBit0 = 0; + UINT_32 pipeBit1 = 0; + UINT_32 pipeBit2 = 0; + UINT_32 pipeBit3 = 0; + UINT_32 sliceRotation; + UINT_32 numPipes = 0; + + UINT_32 tx = x / MicroTileWidth; + UINT_32 ty = y / MicroTileHeight; + UINT_32 x3 = _BIT(tx,0); + UINT_32 x4 = _BIT(tx,1); + UINT_32 x5 = _BIT(tx,2); + UINT_32 x6 = _BIT(tx,3); + UINT_32 y3 = _BIT(ty,0); + UINT_32 y4 = _BIT(ty,1); + UINT_32 y5 = _BIT(ty,2); + UINT_32 y6 = _BIT(ty,3); + + switch (pTileInfo->pipeConfig) + { + case ADDR_PIPECFG_P2: + pipeBit0 = x3 ^ y3; + numPipes = 2; + break; + case ADDR_PIPECFG_P4_8x16: + pipeBit0 = x4 ^ y3; + pipeBit1 = x3 ^ y4; + numPipes = 4; + break; + case ADDR_PIPECFG_P4_16x16: + pipeBit0 = x3 ^ y3 ^ x4; + pipeBit1 = x4 ^ y4; + numPipes = 4; + break; + case ADDR_PIPECFG_P4_16x32: + pipeBit0 = x3 ^ y3 ^ x4; + pipeBit1 = x4 ^ y5; + numPipes = 4; + break; + case ADDR_PIPECFG_P4_32x32: + pipeBit0 = x3 ^ y3 ^ x5; + pipeBit1 = x5 ^ y5; + numPipes = 4; + break; + case ADDR_PIPECFG_P8_16x16_8x16: + pipeBit0 = x4 ^ y3 ^ x5; + pipeBit1 = x3 ^ y5; + numPipes = 8; + break; + case ADDR_PIPECFG_P8_16x32_8x16: + pipeBit0 = x4 ^ y3 ^ x5; + pipeBit1 = x3 ^ y4; + pipeBit2 = x4 ^ y5; + numPipes = 8; + break; + case ADDR_PIPECFG_P8_16x32_16x16: + pipeBit0 = x3 ^ y3 ^ x4; + pipeBit1 = x5 ^ y4; + pipeBit2 = x4 ^ y5; + numPipes = 8; + break; + case ADDR_PIPECFG_P8_32x32_8x16: + pipeBit0 = x4 ^ y3 ^ x5; + pipeBit1 = x3 ^ y4; + pipeBit2 = x5 ^ y5; + numPipes = 8; + break; + case ADDR_PIPECFG_P8_32x32_16x16: + pipeBit0 = x3 ^ y3 ^ x4; + pipeBit1 = x4 ^ y4; + pipeBit2 = x5 ^ y5; + numPipes = 8; + break; + case ADDR_PIPECFG_P8_32x32_16x32: + pipeBit0 = x3 ^ y3 ^ x4; + pipeBit1 = x4 ^ y6; + pipeBit2 = x5 ^ y5; + numPipes = 8; + break; + case ADDR_PIPECFG_P8_32x64_32x32: + pipeBit0 = x3 ^ y3 ^ x5; + pipeBit1 = x6 ^ y5; + pipeBit2 = x5 ^ y6; + numPipes = 8; + break; + case ADDR_PIPECFG_P16_32x32_8x16: + pipeBit0 = x4 ^ y3; + pipeBit1 = x3 ^ y4; + pipeBit2 = x5 ^ y6; + pipeBit3 = x6 ^ y5; + numPipes = 16; + break; + case ADDR_PIPECFG_P16_32x32_16x16: + pipeBit0 = x3 ^ y3 ^ x4; + pipeBit1 = x4 ^ y4; + pipeBit2 = x5 ^ y6; + pipeBit3 = x6 ^ y5; + numPipes = 16; + break; + default: + ADDR_UNHANDLED_CASE(); + break; + } + pipe = pipeBit0 | (pipeBit1 << 1) | (pipeBit2 << 2) | (pipeBit3 << 3); + + UINT_32 microTileThickness = ComputeSurfaceThickness(tileMode); + + // + // Apply pipe rotation for the slice. + // + switch (tileMode) + { + case ADDR_TM_3D_TILED_THIN1: //fall through thin + case ADDR_TM_3D_TILED_THICK: //fall through thick + case ADDR_TM_3D_TILED_XTHICK: + sliceRotation = + Max(1, static_cast<INT_32>(numPipes / 2) - 1) * (slice / microTileThickness); + break; + default: + sliceRotation = 0; + break; + } + pipeSwizzle += sliceRotation; + pipeSwizzle &= (numPipes - 1); + + pipe = pipe ^ pipeSwizzle; + + return pipe; +} + +/** +*************************************************************************************************** +* SIAddrLib::ComputeTileCoordFromPipeAndElemIdx +* +* @brief +* Compute (x,y) of a tile within a macro tile from address +* @return +* Pipe number +*************************************************************************************************** +*/ +VOID SIAddrLib::ComputeTileCoordFromPipeAndElemIdx( + UINT_32 elemIdx, ///< [in] per pipe element index within a macro tile + UINT_32 pipe, ///< [in] pipe index + AddrPipeCfg pipeCfg, ///< [in] pipe config + UINT_32 pitchInMacroTile, ///< [in] surface pitch in macro tile + UINT_32 x, ///< [in] x coordinate of the (0,0) tile in a macro tile + UINT_32 y, ///< [in] y coordinate of the (0,0) tile in a macro tile + UINT_32* pX, ///< [out] x coordinate + UINT_32* pY ///< [out] y coordinate + ) const +{ + UINT_32 pipebit0 = _BIT(pipe,0); + UINT_32 pipebit1 = _BIT(pipe,1); + UINT_32 pipebit2 = _BIT(pipe,2); + UINT_32 pipebit3 = _BIT(pipe,3); + UINT_32 elemIdx0 = _BIT(elemIdx,0); + UINT_32 elemIdx1 = _BIT(elemIdx,1); + UINT_32 elemIdx2 = _BIT(elemIdx,2); + UINT_32 x3 = 0; + UINT_32 x4 = 0; + UINT_32 x5 = 0; + UINT_32 x6 = 0; + UINT_32 y3 = 0; + UINT_32 y4 = 0; + UINT_32 y5 = 0; + UINT_32 y6 = 0; + + switch(pipeCfg) + { + case ADDR_PIPECFG_P2: + x4 = elemIdx2; + y4 = elemIdx1 ^ x4; + y3 = elemIdx0 ^ x4; + x3 = pipebit0 ^ y3; + *pY = Bits2Number(2, y4, y3); + *pX = Bits2Number(2, x4, x3); + break; + case ADDR_PIPECFG_P4_8x16: + x4 = elemIdx1; + y4 = elemIdx0 ^ x4; + x3 = pipebit1 ^ y4; + y3 = pipebit0 ^ x4; + *pY = Bits2Number(2, y4, y3); + *pX = Bits2Number(2, x4, x3); + break; + case ADDR_PIPECFG_P4_16x16: + x4 = elemIdx1; + y3 = elemIdx0 ^ x4; + y4 = pipebit1 ^ x4; + x3 = pipebit0 ^ y3 ^ x4; + *pY = Bits2Number(2, y4, y3); + *pX = Bits2Number(2, x4, x3); + break; + case ADDR_PIPECFG_P4_16x32: + x3 = elemIdx0 ^ pipebit0; + y5 = _BIT(y,5); + x4 = pipebit1 ^ y5; + y3 = pipebit0 ^ x3 ^ x4; + y4 = elemIdx1 ^ x4; + *pY = Bits2Number(2, y4, y3); + *pX = Bits2Number(2, x4, x3); + break; + case ADDR_PIPECFG_P4_32x32: + x4 = elemIdx2; + y3 = elemIdx0 ^ x4; + y4 = elemIdx1 ^ x4; + if((pitchInMacroTile % 2) == 0) + { //even + y5 = _BIT(y,5); + x5 = pipebit1 ^ y5; + x3 = pipebit0 ^ y3 ^ x5; + *pY = Bits2Number(2, y4, y3); + *pX = Bits2Number(3, x5, x4, x3); + } + else + { //odd + x5 = _BIT(x,5); + x3 = pipebit0 ^ y3 ^ x5; + *pY = Bits2Number(2, y4, y3); + *pX = Bits2Number(2, x4, x3); + } + break; + case ADDR_PIPECFG_P8_16x16_8x16: + x4 = elemIdx0; + y5 = _BIT(y,5); + x5 = _BIT(x,5); + x3 = pipebit1 ^ y5; + y4 = pipebit2 ^ x4; + y3 = pipebit0 ^ x5 ^ x4; + *pY = Bits2Number(2, y4, y3); + *pX = Bits2Number(2, x4, x3); + break; + case ADDR_PIPECFG_P8_16x32_8x16: + x3 = elemIdx0; + y4 = pipebit1 ^ x3; + y5 = _BIT(y,5); + x5 = _BIT(x,5); + x4 = pipebit2 ^ y5; + y3 = pipebit0 ^ x4 ^ x5; + *pY = Bits2Number(2, y4, y3); + *pX = Bits2Number(2, x4, x3); + break; + case ADDR_PIPECFG_P8_32x32_8x16: + x4 = elemIdx1; + y4 = elemIdx0 ^ x4; + x3 = pipebit1 ^ y4; + if((pitchInMacroTile % 2) == 0) + { //even + y5 = _BIT(y,5); + x5 = _BIT(x,5); + x5 = pipebit2 ^ y5; + y3 = pipebit0 ^ x4 ^ x5; + *pY = Bits2Number(2, y4, y3); + *pX = Bits2Number(3, x5, x4, x3); + } + else + { //odd + x5 = _BIT(x,5); + y3 = pipebit0 ^ x4 ^ x5; + *pY = Bits2Number(2, y4, y3); + *pX = Bits2Number(2, x4, x3); + } + break; + case ADDR_PIPECFG_P8_16x32_16x16: + x3 = elemIdx0; + x5 = _BIT(x,5); + y5 = _BIT(y,5); + x4 = pipebit2 ^ y5; + y4 = pipebit1 ^ x5; + y3 = pipebit0 ^ x3 ^ x4; + *pY = Bits2Number(2, y4, y3); + *pX = Bits2Number(2, x4, x3); + break; + case ADDR_PIPECFG_P8_32x32_16x16: + x4 = elemIdx1; + y3 = elemIdx0 ^ x4; + x3 = y3^x4^pipebit0; + y4 = pipebit1 ^ x4; + if((pitchInMacroTile % 2) == 0) + { //even + y5 = _BIT(y,5); + x5 = pipebit2 ^ y5; + *pY = Bits2Number(2, y4, y3); + *pX = Bits2Number(3, x5, x4, x3); + } + else + { //odd + *pY = Bits2Number(2, y4, y3); + *pX = Bits2Number(2, x4, x3); + } + break; + case ADDR_PIPECFG_P8_32x32_16x32: + if((pitchInMacroTile % 2) == 0) + { //even + y5 = _BIT(y,5); + y6 = _BIT(y,6); + x4 = pipebit1 ^ y6; + y3 = elemIdx0 ^ x4; + y4 = elemIdx1 ^ x4; + x3 = pipebit0 ^ y3 ^ x4; + x5 = pipebit2 ^ y5; + *pY = Bits2Number(2, y4, y3); + *pX = Bits2Number(3, x5, x4, x3); + } + else + { //odd + y6 = _BIT(y,6); + x4 = pipebit1 ^ y6; + y3 = elemIdx0 ^ x4; + y4 = elemIdx1 ^ x4; + x3 = pipebit0 ^ y3 ^ x4; + *pY = Bits2Number(2, y4, y3); + *pX = Bits2Number(2, x4, x3); + } + break; + case ADDR_PIPECFG_P8_32x64_32x32: + x4 = elemIdx2; + y3 = elemIdx0 ^ x4; + y4 = elemIdx1 ^ x4; + if((pitchInMacroTile % 4) == 0) + { //multiple of 4 + y5 = _BIT(y,5); + y6 = _BIT(y,6); + x5 = pipebit2 ^ y6; + x6 = pipebit1 ^ y5; + x3 = pipebit0 ^ y3 ^ x5; + *pY = Bits2Number(2, y4, y3); + *pX = Bits2Number(4, x6, x5, x4, x3); + } + else + { + y6 = _BIT(y,6); + x5 = pipebit2 ^ y6; + x3 = pipebit0 ^ y3 ^ x5; + *pY = Bits2Number(2, y4, y3); + *pX = Bits2Number(3, x5, x4, x3); + } + break; + case ADDR_PIPECFG_P16_32x32_8x16: + x4 = elemIdx1; + y4 = elemIdx0 ^ x4; + y3 = pipebit0 ^ x4; + x3 = pipebit1 ^ y4; + if((pitchInMacroTile % 4) == 0) + { //multiple of 4 + y5 = _BIT(y,5); + y6 = _BIT(y,6); + x5 = pipebit2 ^ y6; + x6 = pipebit3 ^ y5; + *pY = Bits2Number(2, y4, y3); + *pX = Bits2Number(4, x6, x5,x4, x3); + } + else + { + y6 = _BIT(y,6); + x5 = pipebit2 ^ y6; + *pY = Bits2Number(2, y4, y3); + *pX = Bits2Number(3, x5, x4, x3); + } + break; + case ADDR_PIPECFG_P16_32x32_16x16: + x4 = elemIdx1; + y3 = elemIdx0 ^ x4; + y4 = pipebit1 ^ x4; + x3 = pipebit0 ^ y3 ^ x4; + if((pitchInMacroTile % 4) == 0) + { //multiple of 4 + y5 = _BIT(y,5); + y6 = _BIT(y,6); + x5 = pipebit2 ^ y6; + x6 = pipebit3 ^ y5; + *pY = Bits2Number(2, y4, y3); + *pX = Bits2Number(4, x6, x5, x4, x3); + } + else + { + y6 = _BIT(y,6); + x5 = pipebit2 ^ y6; + *pY = Bits2Number(2, y4, y3); + *pX = Bits2Number(3, x5, x4, x3); + } + break; + default: + ADDR_UNHANDLED_CASE(); + } +} + +/** +*************************************************************************************************** +* SIAddrLib::TileCoordToMaskElementIndex +* +* @brief +* Compute element index from coordinates in tiles +* @return +* Element index +*************************************************************************************************** +*/ +UINT_32 SIAddrLib::TileCoordToMaskElementIndex( + UINT_32 tx, ///< [in] x coord, in Tiles + UINT_32 ty, ///< [in] y coord, in Tiles + AddrPipeCfg pipeConfig, ///< [in] pipe config + UINT_32* macroShift, ///< [out] macro shift + UINT_32* elemIdxBits ///< [out] tile offset bits + ) const +{ + UINT_32 elemIdx = 0; + UINT_32 elemIdx0, elemIdx1, elemIdx2; + UINT_32 tx0, tx1; + UINT_32 ty0, ty1; + + tx0 = _BIT(tx,0); + tx1 = _BIT(tx,1); + ty0 = _BIT(ty,0); + ty1 = _BIT(ty,1); + + switch(pipeConfig) + { + case ADDR_PIPECFG_P2: + *macroShift = 3; + *elemIdxBits =3; + elemIdx2 = tx1; + elemIdx1 = tx1 ^ ty1; + elemIdx0 = tx1 ^ ty0; + elemIdx = Bits2Number(3,elemIdx2,elemIdx1,elemIdx0); + break; + case ADDR_PIPECFG_P4_8x16: + *macroShift = 2; + *elemIdxBits =2; + elemIdx1 = tx1; + elemIdx0 = tx1 ^ ty1; + elemIdx = Bits2Number(2,elemIdx1,elemIdx0); + break; + case ADDR_PIPECFG_P4_16x16: + *macroShift = 2; + *elemIdxBits =2; + elemIdx0 = tx1^ty0; + elemIdx1 = tx1; + elemIdx = Bits2Number(2, elemIdx1, elemIdx0); + break; + case ADDR_PIPECFG_P4_16x32: + *macroShift = 2; + *elemIdxBits =2; + elemIdx0 = tx1^ty0; + elemIdx1 = tx1^ty1; + elemIdx = Bits2Number(2, elemIdx1, elemIdx0); + break; + case ADDR_PIPECFG_P4_32x32: + *macroShift = 2; + *elemIdxBits =3; + elemIdx0 = tx1^ty0; + elemIdx1 = tx1^ty1; + elemIdx2 = tx1; + elemIdx = Bits2Number(3, elemIdx2, elemIdx1, elemIdx0); + break; + case ADDR_PIPECFG_P8_16x16_8x16: + *macroShift = 1; + *elemIdxBits =1; + elemIdx0 = tx1; + elemIdx = elemIdx0; + break; + case ADDR_PIPECFG_P8_16x32_8x16: + *macroShift = 1; + *elemIdxBits =1; + elemIdx0 = tx0; + elemIdx = elemIdx0; + break; + case ADDR_PIPECFG_P8_32x32_8x16: + *macroShift = 1; + *elemIdxBits =2; + elemIdx1 = tx1; + elemIdx0 = tx1^ty1; + elemIdx = Bits2Number(2, elemIdx1, elemIdx0); + break; + case ADDR_PIPECFG_P8_16x32_16x16: + *macroShift = 1; + *elemIdxBits =1; + elemIdx0 = tx0; + elemIdx = elemIdx0; + break; + case ADDR_PIPECFG_P8_32x32_16x16: + *macroShift = 1; + *elemIdxBits =2; + elemIdx0 = tx1^ty0; + elemIdx1 = tx1; + elemIdx = Bits2Number(2, elemIdx1, elemIdx0); + break; + case ADDR_PIPECFG_P8_32x32_16x32: + *macroShift = 1; + *elemIdxBits =2; + elemIdx0 = tx1^ty0; + elemIdx1 = tx1^ty1; + elemIdx = Bits2Number(2, elemIdx1, elemIdx0); + break; + case ADDR_PIPECFG_P8_32x64_32x32: + *macroShift = 1; + *elemIdxBits =3; + elemIdx0 = tx1^ty0; + elemIdx1 = tx1^ty1; + elemIdx2 = tx1; + elemIdx = Bits2Number(3, elemIdx2, elemIdx1, elemIdx0); + break; + case ADDR_PIPECFG_P16_32x32_8x16: + *macroShift = 0; + *elemIdxBits =2; + elemIdx0 = tx1^ty1; + elemIdx1 = tx1; + elemIdx = Bits2Number(2, elemIdx1, elemIdx0); + break; + case ADDR_PIPECFG_P16_32x32_16x16: + *macroShift = 0; + *elemIdxBits =2; + elemIdx0 = tx1^ty0; + elemIdx1 = tx1; + elemIdx = Bits2Number(2, elemIdx1, elemIdx0); + break; + default: + ADDR_UNHANDLED_CASE(); + break; + } + + return elemIdx; +} + +/** +*************************************************************************************************** +* SIAddrLib::HwlComputeTileDataWidthAndHeightLinear +* +* @brief +* Compute the squared cache shape for per-tile data (CMASK and HTILE) for linear layout +* +* @return +* N/A +* +* @note +* MacroWidth and macroHeight are measured in pixels +*************************************************************************************************** +*/ +VOID SIAddrLib::HwlComputeTileDataWidthAndHeightLinear( + UINT_32* pMacroWidth, ///< [out] macro tile width + UINT_32* pMacroHeight, ///< [out] macro tile height + UINT_32 bpp, ///< [in] bits per pixel + ADDR_TILEINFO* pTileInfo ///< [in] tile info + ) const +{ + ADDR_ASSERT(pTileInfo != NULL); + UINT_32 macroWidth; + UINT_32 macroHeight; + + /// In linear mode, the htile or cmask buffer must be padded out to 4 tiles + /// but for P8_32x64_32x32, it must be padded out to 8 tiles + /// Actually there are more pipe configs which need 8-tile padding but SI family + /// has a bug which is fixed in CI family + if ((pTileInfo->pipeConfig == ADDR_PIPECFG_P8_32x64_32x32) || + (pTileInfo->pipeConfig == ADDR_PIPECFG_P16_32x32_8x16) || + (pTileInfo->pipeConfig == ADDR_PIPECFG_P8_32x32_16x16)) + { + macroWidth = 8*MicroTileWidth; + macroHeight = 8*MicroTileHeight; + } + else + { + macroWidth = 4*MicroTileWidth; + macroHeight = 4*MicroTileHeight; + } + + *pMacroWidth = macroWidth; + *pMacroHeight = macroHeight; +} + +/** +*************************************************************************************************** +* SIAddrLib::HwlComputeHtileBytes +* +* @brief +* Compute htile size in bytes +* +* @return +* Htile size in bytes +*************************************************************************************************** +*/ +UINT_64 SIAddrLib::HwlComputeHtileBytes( + UINT_32 pitch, ///< [in] pitch + UINT_32 height, ///< [in] height + UINT_32 bpp, ///< [in] bits per pixel + BOOL_32 isLinear, ///< [in] if it is linear mode + UINT_32 numSlices, ///< [in] number of slices + UINT_64* pSliceBytes, ///< [out] bytes per slice + UINT_32 baseAlign ///< [in] base alignments + ) const +{ + return ComputeHtileBytes(pitch, height, bpp, isLinear, numSlices, pSliceBytes, baseAlign); +} + +/** +*************************************************************************************************** +* SIAddrLib::HwlComputeXmaskAddrFromCoord +* +* @brief +* Compute address from coordinates for htile/cmask +* @return +* Byte address +*************************************************************************************************** +*/ +UINT_64 SIAddrLib::HwlComputeXmaskAddrFromCoord( + UINT_32 pitch, ///< [in] pitch + UINT_32 height, ///< [in] height + UINT_32 x, ///< [in] x coord + UINT_32 y, ///< [in] y coord + UINT_32 slice, ///< [in] slice/depth index + UINT_32 numSlices, ///< [in] number of slices + UINT_32 factor, ///< [in] factor that indicates cmask(2) or htile(1) + BOOL_32 isLinear, ///< [in] linear or tiled HTILE layout + BOOL_32 isWidth8, ///< [in] TRUE if width is 8, FALSE means 4. It's register value + BOOL_32 isHeight8, ///< [in] TRUE if width is 8, FALSE means 4. It's register value + ADDR_TILEINFO* pTileInfo, ///< [in] Tile info + UINT_32* pBitPosition ///< [out] bit position inside a byte + ) const +{ + UINT_32 tx = x / MicroTileWidth; + UINT_32 ty = y / MicroTileHeight; + UINT_32 newPitch; + UINT_32 newHeight; + UINT_64 totalBytes; + UINT_32 macroWidth; + UINT_32 macroHeight; + UINT_64 pSliceBytes; + UINT_32 pBaseAlign; + UINT_32 tileNumPerPipe; + UINT_32 elemBits; + + if (factor == 2) //CMASK + { + ADDR_CMASK_FLAGS flags = {{0}}; + + tileNumPerPipe = 256; + + ComputeCmaskInfo(flags, + pitch, + height, + numSlices, + isLinear, + pTileInfo, + &newPitch, + &newHeight, + &totalBytes, + ¯oWidth, + ¯oHeight); + elemBits = CmaskElemBits; + } + else //HTile + { + ADDR_HTILE_FLAGS flags = {{0}}; + + tileNumPerPipe = 512; + + ComputeHtileInfo(flags, + pitch, + height, + numSlices, + isLinear, + TRUE, + TRUE, + pTileInfo, + &newPitch, + &newHeight, + &totalBytes, + ¯oWidth, + ¯oHeight, + &pSliceBytes, + &pBaseAlign); + elemBits = 32; + } + + const UINT_32 pitchInTile = newPitch / MicroTileWidth; + const UINT_32 heightInTile = newHeight / MicroTileWidth; + UINT_64 macroOffset; // Per pipe starting offset of the macro tile in which this tile lies. + UINT_64 microNumber; // Per pipe starting offset of the macro tile in which this tile lies. + UINT_32 microX; + UINT_32 microY; + UINT_64 microOffset; + UINT_32 microShift; + UINT_64 totalOffset; + UINT_32 elemIdxBits; + UINT_32 elemIdx = + TileCoordToMaskElementIndex(tx, ty, pTileInfo->pipeConfig, µShift, &elemIdxBits); + + UINT_32 numPipes = HwlGetPipes(pTileInfo); + + if (isLinear) + { //linear addressing + // Linear addressing is extremelly wasting memory if slice > 1, since each pipe has the full + // slice memory foot print instead of divided by numPipes. + microX = tx / 4; // Macro Tile is 4x4 + microY = ty / 4 ; + microNumber = static_cast<UINT_64>(microX + microY * (pitchInTile / 4)) << microShift; + + UINT_32 sliceBits = pitchInTile * heightInTile; + + // do htile single slice alignment if the flag is true + if (m_configFlags.useHtileSliceAlign && (factor == 1)) //Htile + { + sliceBits = PowTwoAlign(sliceBits, BITS_TO_BYTES(HtileCacheBits) * numPipes / elemBits); + } + macroOffset = slice * (sliceBits / numPipes) * elemBits ; + } + else + { //tiled addressing + const UINT_32 macroWidthInTile = macroWidth / MicroTileWidth; // Now in unit of Tiles + const UINT_32 macroHeightInTile = macroHeight / MicroTileHeight; + const UINT_32 pitchInCL = pitchInTile / macroWidthInTile; + const UINT_32 heightInCL = heightInTile / macroHeightInTile; + + const UINT_32 macroX = x / macroWidth; + const UINT_32 macroY = y / macroHeight; + const UINT_32 macroNumber = macroX + macroY * pitchInCL + slice * pitchInCL * heightInCL; + + // Per pipe starting offset of the cache line in which this tile lies. + microX = (x % macroWidth) / MicroTileWidth / 4; // Macro Tile is 4x4 + microY = (y % macroHeight) / MicroTileHeight / 4 ; + microNumber = static_cast<UINT_64>(microX + microY * (macroWidth / MicroTileWidth / 4)) << microShift; + + macroOffset = macroNumber * tileNumPerPipe * elemBits; + } + + if(elemIdxBits == microShift) + { + microNumber += elemIdx; + } + else + { + microNumber >>= elemIdxBits; + microNumber <<= elemIdxBits; + microNumber += elemIdx; + } + + microOffset = elemBits * microNumber; + totalOffset = microOffset + macroOffset; + + UINT_32 pipe = ComputePipeFromCoord(x, y, 0, ADDR_TM_2D_TILED_THIN1, 0, FALSE, pTileInfo); + UINT_64 addrInBits = totalOffset % (m_pipeInterleaveBytes * 8) + + pipe * (m_pipeInterleaveBytes * 8) + + totalOffset / (m_pipeInterleaveBytes * 8) * (m_pipeInterleaveBytes * 8) * numPipes; + *pBitPosition = static_cast<UINT_32>(addrInBits) % 8; + UINT_64 addr = addrInBits / 8; + + return addr; +} + +/** +*************************************************************************************************** +* SIAddrLib::HwlComputeXmaskCoordFromAddr +* +* @brief +* Compute the coord from an address of a cmask/htile +* +* @return +* N/A +* +* @note +* This method is reused by htile, so rename to Xmask +*************************************************************************************************** +*/ +VOID SIAddrLib::HwlComputeXmaskCoordFromAddr( + UINT_64 addr, ///< [in] address + UINT_32 bitPosition, ///< [in] bitPosition in a byte + UINT_32 pitch, ///< [in] pitch + UINT_32 height, ///< [in] height + UINT_32 numSlices, ///< [in] number of slices + UINT_32 factor, ///< [in] factor that indicates cmask or htile + BOOL_32 isLinear, ///< [in] linear or tiled HTILE layout + BOOL_32 isWidth8, ///< [in] Not used by SI + BOOL_32 isHeight8, ///< [in] Not used by SI + ADDR_TILEINFO* pTileInfo, ///< [in] Tile info + UINT_32* pX, ///< [out] x coord + UINT_32* pY, ///< [out] y coord + UINT_32* pSlice ///< [out] slice index + ) const +{ + UINT_32 newPitch; + UINT_32 newHeight; + UINT_64 totalBytes; + UINT_32 clWidth; + UINT_32 clHeight; + UINT_32 tileNumPerPipe; + UINT_64 sliceBytes; + + *pX = 0; + *pY = 0; + *pSlice = 0; + + if (factor == 2) //CMASK + { + ADDR_CMASK_FLAGS flags = {{0}}; + + tileNumPerPipe = 256; + + ComputeCmaskInfo(flags, + pitch, + height, + numSlices, + isLinear, + pTileInfo, + &newPitch, + &newHeight, + &totalBytes, + &clWidth, + &clHeight); + } + else //HTile + { + ADDR_HTILE_FLAGS flags = {{0}}; + + tileNumPerPipe = 512; + + ComputeHtileInfo(flags, + pitch, + height, + numSlices, + isLinear, + TRUE, + TRUE, + pTileInfo, + &newPitch, + &newHeight, + &totalBytes, + &clWidth, + &clHeight, + &sliceBytes); + } + + const UINT_32 pitchInTile = newPitch / MicroTileWidth; + const UINT_32 heightInTile = newHeight / MicroTileWidth; + const UINT_32 pitchInMacroTile = pitchInTile / 4; + UINT_32 macroShift; + UINT_32 elemIdxBits; + // get macroShift and elemIdxBits + TileCoordToMaskElementIndex(0, 0, pTileInfo->pipeConfig, ¯oShift, &elemIdxBits); + + const UINT_32 numPipes = HwlGetPipes(pTileInfo); + const UINT_32 pipe = (UINT_32)((addr / m_pipeInterleaveBytes) % numPipes); + // per pipe + UINT_64 localOffset = (addr % m_pipeInterleaveBytes) + + (addr / m_pipeInterleaveBytes / numPipes)* m_pipeInterleaveBytes; + + UINT_32 tileIndex; + if (factor == 2) //CMASK + { + tileIndex = (UINT_32)(localOffset * 2 + (bitPosition != 0)); + } + else + { + tileIndex = (UINT_32)(localOffset / 4); + } + + UINT_32 macroOffset; + if (isLinear) + { + UINT_32 sliceSizeInTile = pitchInTile * heightInTile; + + // do htile single slice alignment if the flag is true + if (m_configFlags.useHtileSliceAlign && (factor == 1)) //Htile + { + sliceSizeInTile = PowTwoAlign(sliceSizeInTile, static_cast<UINT_32>(sliceBytes) / 64); + } + *pSlice = tileIndex / (sliceSizeInTile / numPipes); + macroOffset = tileIndex % (sliceSizeInTile / numPipes); + } + else + { + const UINT_32 clWidthInTile = clWidth / MicroTileWidth; // Now in unit of Tiles + const UINT_32 clHeightInTile = clHeight / MicroTileHeight; + const UINT_32 pitchInCL = pitchInTile / clWidthInTile; + const UINT_32 heightInCL = heightInTile / clHeightInTile; + const UINT_32 clIndex = tileIndex / tileNumPerPipe; + + UINT_32 clX = clIndex % pitchInCL; + UINT_32 clY = (clIndex % (heightInCL * pitchInCL)) / pitchInCL; + + *pX = clX * clWidthInTile * MicroTileWidth; + *pY = clY * clHeightInTile * MicroTileHeight; + *pSlice = clIndex / (heightInCL * pitchInCL); + + macroOffset = tileIndex % tileNumPerPipe; + } + + UINT_32 elemIdx = macroOffset & 7; + macroOffset >>= elemIdxBits; + + if (elemIdxBits != macroShift) + { + macroOffset <<= (elemIdxBits - macroShift); + + UINT_32 pipebit1 = _BIT(pipe,1); + UINT_32 pipebit2 = _BIT(pipe,2); + UINT_32 pipebit3 = _BIT(pipe,3); + if (pitchInMacroTile % 2) + { //odd + switch (pTileInfo->pipeConfig) + { + case ADDR_PIPECFG_P4_32x32: + macroOffset |= pipebit1; + break; + case ADDR_PIPECFG_P8_32x32_8x16: + case ADDR_PIPECFG_P8_32x32_16x16: + case ADDR_PIPECFG_P8_32x32_16x32: + macroOffset |= pipebit2; + break; + default: + break; + } + + } + + if (pitchInMacroTile % 4) + { + if (pTileInfo->pipeConfig == ADDR_PIPECFG_P8_32x64_32x32) + { + macroOffset |= (pipebit1<<1); + } + if((pTileInfo->pipeConfig == ADDR_PIPECFG_P16_32x32_8x16) || + (pTileInfo->pipeConfig == ADDR_PIPECFG_P16_32x32_16x16)) + { + macroOffset |= (pipebit3<<1); + } + } + } + + UINT_32 macroX; + UINT_32 macroY; + + if (isLinear) + { + macroX = macroOffset % pitchInMacroTile; + macroY = macroOffset / pitchInMacroTile; + } + else + { + const UINT_32 clWidthInMacroTile = clWidth / (MicroTileWidth * 4); + macroX = macroOffset % clWidthInMacroTile; + macroY = macroOffset / clWidthInMacroTile; + } + + *pX += macroX * 4 * MicroTileWidth; + *pY += macroY * 4 * MicroTileHeight; + + UINT_32 microX; + UINT_32 microY; + ComputeTileCoordFromPipeAndElemIdx(elemIdx, pipe, pTileInfo->pipeConfig, pitchInMacroTile, + *pX, *pY, µX, µY); + + *pX += microX * MicroTileWidth; + *pY += microY * MicroTileWidth; +} + +/** +*************************************************************************************************** +* SIAddrLib::HwlGetPitchAlignmentLinear +* @brief +* Get pitch alignment +* @return +* pitch alignment +*************************************************************************************************** +*/ +UINT_32 SIAddrLib::HwlGetPitchAlignmentLinear( + UINT_32 bpp, ///< [in] bits per pixel + ADDR_SURFACE_FLAGS flags ///< [in] surface flags + ) const +{ + UINT_32 pitchAlign; + + // Interleaved access requires a 256B aligned pitch, so fall back to pre-SI alignment + if (flags.interleaved) + { + pitchAlign = Max(64u, m_pipeInterleaveBytes / BITS_TO_BYTES(bpp)); + + } + else + { + pitchAlign = Max(8u, 64 / BITS_TO_BYTES(bpp)); + } + + return pitchAlign; +} + +/** +*************************************************************************************************** +* SIAddrLib::HwlGetSizeAdjustmentLinear +* +* @brief +* Adjust linear surface pitch and slice size +* +* @return +* Logical slice size in bytes +*************************************************************************************************** +*/ +UINT_64 SIAddrLib::HwlGetSizeAdjustmentLinear( + AddrTileMode tileMode, ///< [in] tile mode + UINT_32 bpp, ///< [in] bits per pixel + UINT_32 numSamples, ///< [in] number of samples + UINT_32 baseAlign, ///< [in] base alignment + UINT_32 pitchAlign, ///< [in] pitch alignment + UINT_32* pPitch, ///< [in/out] pointer to pitch + UINT_32* pHeight, ///< [in/out] pointer to height + UINT_32* pHeightAlign ///< [in/out] pointer to height align + ) const +{ + UINT_64 sliceSize; + if (tileMode == ADDR_TM_LINEAR_GENERAL) + { + sliceSize = BITS_TO_BYTES(static_cast<UINT_64>(*pPitch) * (*pHeight) * bpp * numSamples); + } + else + { + UINT_32 pitch = *pPitch; + UINT_32 height = *pHeight; + + UINT_32 pixelsPerPipeInterleave = m_pipeInterleaveBytes / BITS_TO_BYTES(bpp); + UINT_32 sliceAlignInPixel = pixelsPerPipeInterleave < 64 ? 64 : pixelsPerPipeInterleave; + + // numSamples should be 1 in real cases (no MSAA for linear but TGL may pass non 1 value) + UINT_64 pixelPerSlice = static_cast<UINT_64>(pitch) * height * numSamples; + + while (pixelPerSlice % sliceAlignInPixel) + { + pitch += pitchAlign; + pixelPerSlice = static_cast<UINT_64>(pitch) * height * numSamples; + } + + *pPitch = pitch; + + UINT_32 heightAlign = 1; + + while ((pitch * heightAlign) % sliceAlignInPixel) + { + heightAlign++; + } + + *pHeightAlign = heightAlign; + + sliceSize = BITS_TO_BYTES(pixelPerSlice * bpp); + } + + return sliceSize; +} + +/** +*************************************************************************************************** +* SIAddrLib::HwlPreHandleBaseLvl3xPitch +* +* @brief +* Pre-handler of 3x pitch (96 bit) adjustment +* +* @return +* Expected pitch +*************************************************************************************************** +*/ +UINT_32 SIAddrLib::HwlPreHandleBaseLvl3xPitch( + const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] input + UINT_32 expPitch ///< [in] pitch + ) const +{ + ADDR_ASSERT(pIn->width == expPitch); + + // From SI, if pow2Pad is 1 the pitch is expanded 3x first, then padded to pow2, so nothing to + // do here + if (!pIn->flags.pow2Pad) + { + AddrLib::HwlPreHandleBaseLvl3xPitch(pIn, expPitch); + } + else + { + ADDR_ASSERT(IsPow2(expPitch)); + } + + return expPitch; +} + +/** +*************************************************************************************************** +* SIAddrLib::HwlPostHandleBaseLvl3xPitch +* +* @brief +* Post-handler of 3x pitch adjustment +* +* @return +* Expected pitch +*************************************************************************************************** +*/ +UINT_32 SIAddrLib::HwlPostHandleBaseLvl3xPitch( + const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] input + UINT_32 expPitch ///< [in] pitch + ) const +{ + /** + * @note The pitch will be divided by 3 in the end so the value will look odd but h/w should + * be able to compute a correct pitch from it as h/w address library is doing the job. + */ + // From SI, the pitch is expanded 3x first, then padded to pow2, so no special handler here + if (!pIn->flags.pow2Pad) + { + AddrLib::HwlPostHandleBaseLvl3xPitch(pIn, expPitch); + } + + return expPitch; +} + +/** +*************************************************************************************************** +* SIAddrLib::HwlGetPitchAlignmentMicroTiled +* +* @brief +* Compute 1D tiled surface pitch alignment +* +* @return +* pitch alignment +*************************************************************************************************** +*/ +UINT_32 SIAddrLib::HwlGetPitchAlignmentMicroTiled( + AddrTileMode tileMode, ///< [in] tile mode + UINT_32 bpp, ///< [in] bits per pixel + ADDR_SURFACE_FLAGS flags, ///< [in] surface flags + UINT_32 numSamples ///< [in] number of samples + ) const +{ + UINT_32 pitchAlign; + + if (flags.qbStereo) + { + pitchAlign = EgBasedAddrLib::HwlGetPitchAlignmentMicroTiled(tileMode,bpp,flags,numSamples); + } + else + { + pitchAlign = 8; + } + + return pitchAlign; +} + +/** +*************************************************************************************************** +* SIAddrLib::HwlGetSizeAdjustmentMicroTiled +* +* @brief +* Adjust 1D tiled surface pitch and slice size +* +* @return +* Logical slice size in bytes +*************************************************************************************************** +*/ +UINT_64 SIAddrLib::HwlGetSizeAdjustmentMicroTiled( + UINT_32 thickness, ///< [in] thickness + UINT_32 bpp, ///< [in] bits per pixel + ADDR_SURFACE_FLAGS flags, ///< [in] surface flags + UINT_32 numSamples, ///< [in] number of samples + UINT_32 baseAlign, ///< [in] base alignment + UINT_32 pitchAlign, ///< [in] pitch alignment + UINT_32* pPitch, ///< [in/out] pointer to pitch + UINT_32* pHeight ///< [in/out] pointer to height + ) const +{ + UINT_64 logicalSliceSize; + UINT_64 physicalSliceSize; + + UINT_32 pitch = *pPitch; + UINT_32 height = *pHeight; + + // Logical slice: pitch * height * bpp * numSamples (no 1D MSAA so actually numSamples == 1) + logicalSliceSize = BITS_TO_BYTES(static_cast<UINT_64>(pitch) * height * bpp * numSamples); + + // Physical slice: multiplied by thickness + physicalSliceSize = logicalSliceSize * thickness; + + // Pitch alignment is always 8, so if slice size is not padded to base alignment + // (pipe_interleave_size), we need to increase pitch + while ((physicalSliceSize % baseAlign) != 0) + { + pitch += pitchAlign; + + logicalSliceSize = BITS_TO_BYTES(static_cast<UINT_64>(pitch) * height * bpp * numSamples); + + physicalSliceSize = logicalSliceSize * thickness; + } + +#if !ALT_TEST + // + // Special workaround for depth/stencil buffer, use 8 bpp to align depth buffer again since + // the stencil plane may have larger pitch if the slice size is smaller than base alignment. + // + // Note: this actually does not work for mipmap but mipmap depth texture is not really + // sampled with mipmap. + // + if (flags.depth && !flags.noStencil) + { + ADDR_ASSERT(numSamples == 1); + + UINT_64 logicalSiceSizeStencil = static_cast<UINT_64>(pitch) * height; // 1 byte stencil + + while ((logicalSiceSizeStencil % baseAlign) != 0) + { + pitch += pitchAlign; // Stencil plane's pitch alignment is the same as depth plane's + + logicalSiceSizeStencil = static_cast<UINT_64>(pitch) * height; + } + + if (pitch != *pPitch) + { + // If this is a mipmap, this padded one cannot be sampled as a whole mipmap! + logicalSliceSize = logicalSiceSizeStencil * BITS_TO_BYTES(bpp); + } + } +#endif + *pPitch = pitch; + + // No adjust for pHeight + + return logicalSliceSize; +} + +/** +*************************************************************************************************** +* SIAddrLib::HwlConvertChipFamily +* +* @brief +* Convert familyID defined in atiid.h to AddrChipFamily and set m_chipFamily/m_chipRevision +* @return +* AddrChipFamily +*************************************************************************************************** +*/ +AddrChipFamily SIAddrLib::HwlConvertChipFamily( + UINT_32 uChipFamily, ///< [in] chip family defined in atiih.h + UINT_32 uChipRevision) ///< [in] chip revision defined in "asic_family"_id.h +{ + AddrChipFamily family = ADDR_CHIP_FAMILY_SI; + + switch (uChipFamily) + { + case FAMILY_SI: + m_settings.isSouthernIsland = 1; + m_settings.isTahiti = ASICREV_IS_TAHITI_P(uChipRevision); + m_settings.isPitCairn = ASICREV_IS_PITCAIRN_PM(uChipRevision); + m_settings.isCapeVerde = ASICREV_IS_CAPEVERDE_M(uChipRevision); + m_settings.isOland = ASICREV_IS_OLAND_M(uChipRevision); + m_settings.isHainan = ASICREV_IS_HAINAN_V(uChipRevision); + break; + default: + ADDR_ASSERT(!"This should be a Fusion"); + break; + } + + return family; +} + +/** +*************************************************************************************************** +* SIAddrLib::HwlSetupTileInfo +* +* @brief +* Setup default value of tile info for SI +*************************************************************************************************** +*/ +VOID SIAddrLib::HwlSetupTileInfo( + AddrTileMode tileMode, ///< [in] Tile mode + ADDR_SURFACE_FLAGS flags, ///< [in] Surface type flags + UINT_32 bpp, ///< [in] Bits per pixel + UINT_32 pitch, ///< [in] Pitch in pixels + UINT_32 height, ///< [in] Height in pixels + UINT_32 numSamples, ///< [in] Number of samples + ADDR_TILEINFO* pTileInfoIn, ///< [in] Tile info input: NULL for default + ADDR_TILEINFO* pTileInfoOut, ///< [out] Tile info output + AddrTileType inTileType, ///< [in] Tile type + ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [out] Output + ) const +{ + UINT_32 thickness = ComputeSurfaceThickness(tileMode); + ADDR_TILEINFO* pTileInfo = pTileInfoOut; + INT index = TileIndexInvalid; + + // Fail-safe code + if (!IsLinear(tileMode)) + { + // 128 bpp/thick tiling must be non-displayable. + // Fmask reuse color buffer's entry but bank-height field can be from another entry + // To simplify the logic, fmask entry should be picked from non-displayable ones + if (bpp == 128 || thickness > 1 || flags.fmask || flags.prt) + { + inTileType = ADDR_NON_DISPLAYABLE; + } + + if (flags.depth || flags.stencil) + { + inTileType = ADDR_DEPTH_SAMPLE_ORDER; + } + } + + // Partial valid fields are not allowed for SI. + if (IsTileInfoAllZero(pTileInfo)) + { + if (IsMacroTiled(tileMode)) + { + if (flags.prt) + { + if (numSamples == 1) + { + if (flags.depth) + { + switch (bpp) + { + case 16: + index = 3; + break; + case 32: + index = 6; + break; + default: + ADDR_ASSERT_ALWAYS(); + break; + } + } + else + { + switch (bpp) + { + case 8: + index = 21; + break; + case 16: + index = 22; + break; + case 32: + index = 23; + break; + case 64: + index = 24; + break; + case 128: + index = 25; + break; + default: + break; + } + + if (thickness > 1) + { + ADDR_ASSERT(bpp != 128); + index += 5; + } + } + } + else + { + ADDR_ASSERT(numSamples == 4); + + if (flags.depth) + { + switch (bpp) + { + case 16: + index = 5; + break; + case 32: + index = 7; + break; + default: + ADDR_ASSERT_ALWAYS(); + break; + } + } + else + { + switch (bpp) + { + case 8: + index = 23; + break; + case 16: + index = 24; + break; + case 32: + index = 25; + break; + case 64: + index = 30; + break; + default: + ADDR_ASSERT_ALWAYS(); + break; + } + } + } + }//end of PRT part + // See table entries 0-7 + else if (flags.depth || flags.stencil) + { + if (flags.compressZ) + { + if (flags.stencil) + { + index = 0; + } + else + { + // optimal tile index for compressed depth/stencil. + switch (numSamples) + { + case 1: + index = 0; + break; + case 2: + case 4: + index = 1; + break; + case 8: + index = 2; + break; + default: + break; + } + } + } + else // unCompressZ + { + index = 3; + } + } + else //non PRT & non Depth & non Stencil + { + // See table entries 9-12 + if (inTileType == ADDR_DISPLAYABLE) + { + switch (bpp) + { + case 8: + index = 10; + break; + case 16: + index = 11; + break; + case 32: + index = 12; + break; + case 64: + index = 12; + break; + default: + break; + } + } + else + { + // See table entries 13-17 + if (thickness == 1) + { + if (flags.fmask) + { + UINT_32 fmaskPixelSize = bpp * numSamples; + + switch (fmaskPixelSize) + { + case 8: + index = 14; + break; + case 16: + index = 15; + break; + case 32: + index = 16; + break; + case 64: + index = 17; + break; + default: + ADDR_ASSERT_ALWAYS(); + } + } + else + { + switch (bpp) + { + case 8: + index = 14; + break; + case 16: + index = 15; + break; + case 32: + index = 16; + break; + case 64: + index = 17; + break; + case 128: + index = 17; + break; + default: + break; + } + } + } + else // thick tiling - entries 18-20 + { + switch (thickness) + { + case 4: + index = 20; + break; + case 8: + index = 19; + break; + default: + break; + } + } + } + } + } + else + { + if (tileMode == ADDR_TM_LINEAR_ALIGNED) + { + index = 8; + } + else if (tileMode == ADDR_TM_LINEAR_GENERAL) + { + index = TileIndexLinearGeneral; + } + else + { + if (flags.depth || flags.stencil) + { + index = 4; + } + else if (inTileType == ADDR_DISPLAYABLE) + { + index = 9; + } + else if (thickness == 1) + { + index = 13; + } + else + { + index = 18; + } + } + } + + if (index >= 0 && index <= 31) + { + *pTileInfo = m_tileTable[index].info; + pOut->tileType = m_tileTable[index].type; + } + + if (index == TileIndexLinearGeneral) + { + *pTileInfo = m_tileTable[8].info; + pOut->tileType = m_tileTable[8].type; + } + } + else + { + if (pTileInfoIn) + { + if (flags.stencil && pTileInfoIn->tileSplitBytes == 0) + { + // Stencil always uses index 0 + *pTileInfo = m_tileTable[0].info; + } + } + // Pass through tile type + pOut->tileType = inTileType; + } + + pOut->tileIndex = index; +} + +/** +*************************************************************************************************** +* SIAddrLib::DecodeGbRegs +* +* @brief +* Decodes GB_ADDR_CONFIG and noOfBanks/noOfRanks +* +* @return +* TRUE if all settings are valid +* +*************************************************************************************************** +*/ +BOOL_32 SIAddrLib::DecodeGbRegs( + const ADDR_REGISTER_VALUE* pRegValue) ///< [in] create input +{ + GB_ADDR_CONFIG reg; + BOOL_32 valid = TRUE; + + reg.val = pRegValue->gbAddrConfig; + + switch (reg.f.pipe_interleave_size) + { + case ADDR_CONFIG_PIPE_INTERLEAVE_256B: + m_pipeInterleaveBytes = ADDR_PIPEINTERLEAVE_256B; + break; + case ADDR_CONFIG_PIPE_INTERLEAVE_512B: + m_pipeInterleaveBytes = ADDR_PIPEINTERLEAVE_512B; + break; + default: + valid = FALSE; + ADDR_UNHANDLED_CASE(); + break; + } + + switch (reg.f.row_size) + { + case ADDR_CONFIG_1KB_ROW: + m_rowSize = ADDR_ROWSIZE_1KB; + break; + case ADDR_CONFIG_2KB_ROW: + m_rowSize = ADDR_ROWSIZE_2KB; + break; + case ADDR_CONFIG_4KB_ROW: + m_rowSize = ADDR_ROWSIZE_4KB; + break; + default: + valid = FALSE; + ADDR_UNHANDLED_CASE(); + break; + } + + switch (pRegValue->noOfBanks) + { + case 0: + m_banks = 4; + break; + case 1: + m_banks = 8; + break; + case 2: + m_banks = 16; + break; + default: + valid = FALSE; + ADDR_UNHANDLED_CASE(); + break; + } + + switch (pRegValue->noOfRanks) + { + case 0: + m_ranks = 1; + break; + case 1: + m_ranks = 2; + break; + default: + valid = FALSE; + ADDR_UNHANDLED_CASE(); + break; + } + + m_logicalBanks = m_banks * m_ranks; + + ADDR_ASSERT(m_logicalBanks <= 16); + + return valid; +} + +/** +*************************************************************************************************** +* SIAddrLib::HwlInitGlobalParams +* +* @brief +* Initializes global parameters +* +* @return +* TRUE if all settings are valid +* +*************************************************************************************************** +*/ +BOOL_32 SIAddrLib::HwlInitGlobalParams( + const ADDR_CREATE_INPUT* pCreateIn) ///< [in] create input +{ + BOOL_32 valid = TRUE; + const ADDR_REGISTER_VALUE* pRegValue = &pCreateIn->regValue; + + valid = DecodeGbRegs(pRegValue); + + if (valid) + { + if (m_settings.isTahiti || m_settings.isPitCairn) + { + m_pipes = 8; + } + else if (m_settings.isCapeVerde || m_settings.isOland) + { + m_pipes = 4; + } + else + { + // Hainan is 2-pipe (m_settings.isHainan == 1) + m_pipes = 2; + } + + valid = InitTileSettingTable(pRegValue->pTileConfig, pRegValue->noOfEntries); + + m_maxSamples = 16; + } + + return valid; +} + +/** +*************************************************************************************************** +* SIAddrLib::HwlConvertTileInfoToHW +* @brief +* Entry of si's ConvertTileInfoToHW +* @return +* ADDR_E_RETURNCODE +*************************************************************************************************** +*/ +ADDR_E_RETURNCODE SIAddrLib::HwlConvertTileInfoToHW( + const ADDR_CONVERT_TILEINFOTOHW_INPUT* pIn, ///< [in] input structure + ADDR_CONVERT_TILEINFOTOHW_OUTPUT* pOut ///< [out] output structure + ) const +{ + ADDR_E_RETURNCODE retCode = ADDR_OK; + + retCode = EgBasedAddrLib::HwlConvertTileInfoToHW(pIn, pOut); + + if (retCode == ADDR_OK) + { + if (pIn->reverse == FALSE) + { + if (pIn->pTileInfo->pipeConfig == ADDR_PIPECFG_INVALID) + { + retCode = ADDR_INVALIDPARAMS; + } + else + { + pOut->pTileInfo->pipeConfig = + static_cast<AddrPipeCfg>(pIn->pTileInfo->pipeConfig - 1); + } + } + else + { + pOut->pTileInfo->pipeConfig = + static_cast<AddrPipeCfg>(pIn->pTileInfo->pipeConfig + 1); + } + } + + return retCode; +} + +/** +*************************************************************************************************** +* SIAddrLib::HwlComputeXmaskCoordYFrom8Pipe +* +* @brief +* Compute the Y coord which will be added to Xmask Y +* coord. +* @return +* Y coord +*************************************************************************************************** +*/ +UINT_32 SIAddrLib::HwlComputeXmaskCoordYFrom8Pipe( + UINT_32 pipe, ///< [in] pipe id + UINT_32 x ///< [in] tile coord x, which is original x coord / 8 + ) const +{ + // This function should never be called since it is 6xx/8xx specfic. + // Keep this empty implementation to avoid any mis-use. + ADDR_ASSERT_ALWAYS(); + + return 0; +} + +/** +*************************************************************************************************** +* SIAddrLib::HwlComputeSurfaceCoord2DFromBankPipe +* +* @brief +* Compute surface x,y coordinates from bank/pipe info +* @return +* N/A +*************************************************************************************************** +*/ +VOID SIAddrLib::HwlComputeSurfaceCoord2DFromBankPipe( + AddrTileMode tileMode, ///< [in] tile mode + UINT_32* pX, ///< [in/out] x coordinate + UINT_32* pY, ///< [in/out] y coordinate + UINT_32 slice, ///< [in] slice index + UINT_32 bank, ///< [in] bank number + UINT_32 pipe, ///< [in] pipe number + UINT_32 bankSwizzle,///< [in] bank swizzle + UINT_32 pipeSwizzle,///< [in] pipe swizzle + UINT_32 tileSlices, ///< [in] slices in a micro tile + BOOL_32 ignoreSE, ///< [in] TRUE if shader engines are ignored + ADDR_TILEINFO* pTileInfo ///< [in] bank structure. **All fields to be valid on entry** + ) const +{ + UINT_32 xBit; + UINT_32 yBit; + UINT_32 yBit3 = 0; + UINT_32 yBit4 = 0; + UINT_32 yBit5 = 0; + UINT_32 yBit6 = 0; + + UINT_32 xBit3 = 0; + UINT_32 xBit4 = 0; + UINT_32 xBit5 = 0; + + UINT_32 numPipes = GetPipePerSurf(pTileInfo->pipeConfig); + + CoordFromBankPipe xyBits = {0}; + ComputeSurfaceCoord2DFromBankPipe(tileMode, *pX, *pY, slice, bank, pipe, + bankSwizzle, pipeSwizzle, tileSlices, pTileInfo, + &xyBits); + yBit3 = xyBits.yBit3; + yBit4 = xyBits.yBit4; + yBit5 = xyBits.yBit5; + yBit6 = xyBits.yBit6; + + xBit3 = xyBits.xBit3; + xBit4 = xyBits.xBit4; + xBit5 = xyBits.xBit5; + + yBit = xyBits.yBits; + + UINT_32 yBitTemp = 0; + + if ((pTileInfo->pipeConfig == ADDR_PIPECFG_P4_32x32) || + (pTileInfo->pipeConfig == ADDR_PIPECFG_P8_32x64_32x32)) + { + ADDR_ASSERT(pTileInfo->bankWidth == 1 && pTileInfo->macroAspectRatio > 1); + UINT_32 yBitToCheck = QLog2(pTileInfo->banks) - 1; + + ADDR_ASSERT(yBitToCheck <= 3); + + yBitTemp = _BIT(yBit, yBitToCheck); + + xBit3 = 0; + } + + yBit = Bits2Number(4, yBit6, yBit5, yBit4, yBit3); + xBit = Bits2Number(3, xBit5, xBit4, xBit3); + + *pY += yBit * pTileInfo->bankHeight * MicroTileHeight; + *pX += xBit * numPipes * pTileInfo->bankWidth * MicroTileWidth; + + //calculate the bank and pipe bits in x, y + UINT_32 xTile; //x in micro tile + UINT_32 x3 = 0; + UINT_32 x4 = 0; + UINT_32 x5 = 0; + UINT_32 x6 = 0; + UINT_32 y = *pY; + + UINT_32 pipeBit0 = _BIT(pipe,0); + UINT_32 pipeBit1 = _BIT(pipe,1); + UINT_32 pipeBit2 = _BIT(pipe,2); + + UINT_32 y3 = _BIT(y, 3); + UINT_32 y4 = _BIT(y, 4); + UINT_32 y5 = _BIT(y, 5); + UINT_32 y6 = _BIT(y, 6); + + // bankbit0 after ^x4^x5 + UINT_32 bankBit00 = _BIT(bank,0); + UINT_32 bankBit0 = 0; + + switch (pTileInfo->pipeConfig) + { + case ADDR_PIPECFG_P2: + x3 = pipeBit0 ^ y3; + break; + case ADDR_PIPECFG_P4_8x16: + x4 = pipeBit0 ^ y3; + x3 = pipeBit0 ^ y4; + break; + case ADDR_PIPECFG_P4_16x16: + x4 = pipeBit1 ^ y4; + x3 = pipeBit0 ^ y3 ^ x4; + break; + case ADDR_PIPECFG_P4_16x32: + x4 = pipeBit1 ^ y4; + x3 = pipeBit0 ^ y3 ^ x4; + break; + case ADDR_PIPECFG_P4_32x32: + x5 = pipeBit1 ^ y5; + x3 = pipeBit0 ^ y3 ^ x5; + bankBit0 = yBitTemp ^ x5; + x4 = bankBit00 ^ x5 ^ bankBit0; + *pX += x5 * 4 * 1 * 8; // x5 * num_pipes * bank_width * 8; + break; + case ADDR_PIPECFG_P8_16x16_8x16: + x3 = pipeBit1 ^ y5; + x4 = pipeBit2 ^ y4; + x5 = pipeBit0 ^ y3 ^ x4; + break; + case ADDR_PIPECFG_P8_16x32_8x16: + x3 = pipeBit1 ^ y4; + x4 = pipeBit2 ^ y5; + x5 = pipeBit0 ^ y3 ^ x4; + break; + case ADDR_PIPECFG_P8_32x32_8x16: + x3 = pipeBit1 ^ y4; + x5 = pipeBit2 ^ y5; + x4 = pipeBit0 ^ y3 ^ x5; + break; + case ADDR_PIPECFG_P8_16x32_16x16: + x4 = pipeBit2 ^ y5; + x5 = pipeBit1 ^ y4; + x3 = pipeBit0 ^ y3 ^ x4; + break; + case ADDR_PIPECFG_P8_32x32_16x16: + x5 = pipeBit2 ^ y5; + x4 = pipeBit1 ^ y4; + x3 = pipeBit0 ^ y3 ^ x4; + break; + case ADDR_PIPECFG_P8_32x32_16x32: + x5 = pipeBit2 ^ y5; + x4 = pipeBit1 ^ y6; + x3 = pipeBit0 ^ y3 ^ x4; + break; + case ADDR_PIPECFG_P8_32x64_32x32: + x6 = pipeBit1 ^ y5; + x5 = pipeBit2 ^ y6; + x3 = pipeBit0 ^ y3 ^ x5; + bankBit0 = yBitTemp ^ x6; + x4 = bankBit00 ^ x5 ^ bankBit0; + *pX += x6 * 8 * 1 * 8; // x6 * num_pipes * bank_width * 8; + break; + default: + ADDR_ASSERT_ALWAYS(); + } + + xTile = Bits2Number(3, x5, x4, x3); + + *pX += xTile << 3; +} + +/** +*************************************************************************************************** +* SIAddrLib::HwlPreAdjustBank +* +* @brief +* Adjust bank before calculating address acoording to bank/pipe +* @return +* Adjusted bank +*************************************************************************************************** +*/ +UINT_32 SIAddrLib::HwlPreAdjustBank( + UINT_32 tileX, ///< [in] x coordinate in unit of tile + UINT_32 bank, ///< [in] bank + ADDR_TILEINFO* pTileInfo ///< [in] tile info + ) const +{ + if (((pTileInfo->pipeConfig == ADDR_PIPECFG_P4_32x32) || + (pTileInfo->pipeConfig == ADDR_PIPECFG_P8_32x64_32x32)) && (pTileInfo->bankWidth == 1)) + { + UINT_32 bankBit0 = _BIT(bank, 0); + UINT_32 x4 = _BIT(tileX, 1); + UINT_32 x5 = _BIT(tileX, 2); + + bankBit0 = bankBit0 ^ x4 ^ x5; + bank |= bankBit0; + + ADDR_ASSERT(pTileInfo->macroAspectRatio > 1) + } + + return bank; +} + +/** +*************************************************************************************************** +* SIAddrLib::HwlComputeSurfaceInfo +* +* @brief +* Entry of si's ComputeSurfaceInfo +* @return +* ADDR_E_RETURNCODE +*************************************************************************************************** +*/ +ADDR_E_RETURNCODE SIAddrLib::HwlComputeSurfaceInfo( + const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] input structure + ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [out] output structure + ) const +{ + pOut->tileIndex = pIn->tileIndex; + + return EgBasedAddrLib::HwlComputeSurfaceInfo(pIn,pOut); +} + +/** +*************************************************************************************************** +* SIAddrLib::HwlComputeMipLevel +* @brief +* Compute MipLevel info (including level 0) +* @return +* TRUE if HWL's handled +*************************************************************************************************** +*/ +BOOL_32 SIAddrLib::HwlComputeMipLevel( + ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn ///< [in/out] Input structure + ) const +{ + // basePitch is calculated from level 0 so we only check this for mipLevel > 0 + if (pIn->mipLevel > 0) + { + // Note: Don't check expand 3x formats(96 bit) as the basePitch is not pow2 even if + // we explicity set pow2Pad flag. The 3x base pitch is padded to pow2 but after being + // divided by expandX factor (3) - to program texture pitch, the basePitch is never pow2. + if (!AddrElemLib::IsExpand3x(pIn->format)) + { + // Sublevel pitches are generated from base level pitch instead of width on SI + // If pow2Pad is 0, we don't assert - as this is not really used for a mip chain + ADDR_ASSERT(!pIn->flags.pow2Pad || ((pIn->basePitch != 0) && IsPow2(pIn->basePitch))); + } + + if (pIn->basePitch != 0) + { + pIn->width = Max(1u, pIn->basePitch >> pIn->mipLevel); + } + } + + // pow2Pad is done in PostComputeMipLevel + + return TRUE; +} + +/** +*************************************************************************************************** +* SIAddrLib::HwlCheckLastMacroTiledLvl +* +* @brief +* Sets pOut->last2DLevel to TRUE if it is +* @note +* +*************************************************************************************************** +*/ +VOID SIAddrLib::HwlCheckLastMacroTiledLvl( + const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] Input structure + ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [in/out] Output structure (used as input, too) + ) const +{ + // pow2Pad covers all mipmap cases + if (pIn->flags.pow2Pad) + { + ADDR_ASSERT(IsMacroTiled(pIn->tileMode)); + + UINT_32 nextPitch; + UINT_32 nextHeight; + UINT_32 nextSlices; + + AddrTileMode nextTileMode; + + if (pIn->mipLevel == 0 || pIn->basePitch == 0) + { + // Base level or fail-safe case (basePitch == 0) + nextPitch = pOut->pitch >> 1; + } + else + { + // Sub levels + nextPitch = pIn->basePitch >> (pIn->mipLevel + 1); + } + + // nextHeight must be shifted from this level's original height rather than a pow2 padded + // one but this requires original height stored somewhere (pOut->height) + ADDR_ASSERT(pOut->height != 0); + + // next level's height is just current level's >> 1 in pixels + nextHeight = pOut->height >> 1; + // Special format such as FMT_1 and FMT_32_32_32 can be linear only so we consider block + // compressed foramts + if (AddrElemLib::IsBlockCompressed(pIn->format)) + { + nextHeight = (nextHeight + 3) / 4; + } + nextHeight = NextPow2(nextHeight); + + // nextSlices may be 0 if this level's is 1 + if (pIn->flags.volume) + { + nextSlices = Max(1u, pIn->numSlices >> 1); + } + else + { + nextSlices = pIn->numSlices; + } + + nextTileMode = ComputeSurfaceMipLevelTileMode(pIn->tileMode, + pIn->bpp, + nextPitch, + nextHeight, + nextSlices, + pIn->numSamples, + pOut->pitchAlign, + pOut->heightAlign, + pOut->pTileInfo); + + pOut->last2DLevel = IsMicroTiled(nextTileMode); + } +} + +/** +*************************************************************************************************** +* SIAddrLib::HwlDegradeThickTileMode +* +* @brief +* Degrades valid tile mode for thick modes if needed +* +* @return +* Suitable tile mode +*************************************************************************************************** +*/ +AddrTileMode SIAddrLib::HwlDegradeThickTileMode( + AddrTileMode baseTileMode, ///< [in] base tile mode + UINT_32 numSlices, ///< [in] current number of slices + UINT_32* pBytesPerTile ///< [in/out] pointer to bytes per slice + ) const +{ + return EgBasedAddrLib::HwlDegradeThickTileMode(baseTileMode, numSlices, pBytesPerTile); +} + +/** +*************************************************************************************************** +* SIAddrLib::HwlTileInfoEqual +* +* @brief +* Return TRUE if all field are equal +* @note +* Only takes care of current HWL's data +*************************************************************************************************** +*/ +BOOL_32 SIAddrLib::HwlTileInfoEqual( + const ADDR_TILEINFO* pLeft, ///<[in] Left compare operand + const ADDR_TILEINFO* pRight ///<[in] Right compare operand + ) const +{ + BOOL_32 equal = FALSE; + + if (pLeft->pipeConfig == pRight->pipeConfig) + { + equal = EgBasedAddrLib::HwlTileInfoEqual(pLeft, pRight); + } + + return equal; +} + +/** +*************************************************************************************************** +* SIAddrLib::GetTileSettings +* +* @brief +* Get tile setting infos by index. +* @return +* Tile setting info. +*************************************************************************************************** +*/ +const ADDR_TILECONFIG* SIAddrLib::GetTileSetting( + UINT_32 index ///< [in] Tile index + ) const +{ + ADDR_ASSERT(index < m_noOfEntries); + return &m_tileTable[index]; +} + +/** +*************************************************************************************************** +* SIAddrLib::HwlPostCheckTileIndex +* +* @brief +* Map a tile setting to index if curIndex is invalid, otherwise check if curIndex matches +* tile mode/type/info and change the index if needed +* @return +* Tile index. +*************************************************************************************************** +*/ +INT_32 SIAddrLib::HwlPostCheckTileIndex( + const ADDR_TILEINFO* pInfo, ///< [in] Tile Info + AddrTileMode mode, ///< [in] Tile mode + AddrTileType type, ///< [in] Tile type + INT curIndex ///< [in] Current index assigned in HwlSetupTileInfo + ) const +{ + INT_32 index = curIndex; + + if (mode == ADDR_TM_LINEAR_GENERAL) + { + index = TileIndexLinearGeneral; + } + else + { + BOOL_32 macroTiled = IsMacroTiled(mode); + + // We need to find a new index if either of them is true + // 1. curIndex is invalid + // 2. tile mode is changed + // 3. tile info does not match for macro tiled + if ((index == TileIndexInvalid || + (mode != m_tileTable[index].mode) || + (macroTiled && !HwlTileInfoEqual(pInfo, &m_tileTable[index].info)))) + { + for (index = 0; index < static_cast<INT_32>(m_noOfEntries); index++) + { + if (macroTiled) + { + // macro tile modes need all to match + if (HwlTileInfoEqual(pInfo, &m_tileTable[index].info) && + (mode == m_tileTable[index].mode) && + (type == m_tileTable[index].type)) + { + break; + } + } + else if (mode == ADDR_TM_LINEAR_ALIGNED) + { + // linear mode only needs tile mode to match + if (mode == m_tileTable[index].mode) + { + break; + } + } + else + { + // micro tile modes only need tile mode and tile type to match + if (mode == m_tileTable[index].mode && + type == m_tileTable[index].type) + { + break; + } + } + } + } + } + + ADDR_ASSERT(index < static_cast<INT_32>(m_noOfEntries)); + + if (index >= static_cast<INT_32>(m_noOfEntries)) + { + index = TileIndexInvalid; + } + + return index; +} + +/** +*************************************************************************************************** +* SIAddrLib::HwlSetupTileCfg +* +* @brief +* Map tile index to tile setting. +* @return +* ADDR_E_RETURNCODE +*************************************************************************************************** +*/ +ADDR_E_RETURNCODE SIAddrLib::HwlSetupTileCfg( + INT_32 index, ///< [in] Tile index + INT_32 macroModeIndex, ///< [in] Index in macro tile mode table(CI) + ADDR_TILEINFO* pInfo, ///< [out] Tile Info + AddrTileMode* pMode, ///< [out] Tile mode + AddrTileType* pType ///< [out] Tile type + ) const +{ + ADDR_E_RETURNCODE returnCode = ADDR_OK; + + // Global flag to control usage of tileIndex + if (UseTileIndex(index)) + { + if (index == TileIndexLinearGeneral) + { + if (pMode) + { + *pMode = ADDR_TM_LINEAR_GENERAL; + } + + if (pType) + { + *pType = ADDR_DISPLAYABLE; + } + + if (pInfo) + { + pInfo->banks = 2; + pInfo->bankWidth = 1; + pInfo->bankHeight = 1; + pInfo->macroAspectRatio = 1; + pInfo->tileSplitBytes = 64; + pInfo->pipeConfig = ADDR_PIPECFG_P2; + } + } + else if (static_cast<UINT_32>(index) >= m_noOfEntries) + { + returnCode = ADDR_INVALIDPARAMS; + } + else + { + const ADDR_TILECONFIG* pCfgTable = GetTileSetting(index); + + if (pInfo) + { + *pInfo = pCfgTable->info; + } + else + { + if (IsMacroTiled(pCfgTable->mode)) + { + returnCode = ADDR_INVALIDPARAMS; + } + } + + if (pMode) + { + *pMode = pCfgTable->mode; + } + + if (pType) + { + *pType = pCfgTable->type; + } + } + } + + return returnCode; +} + +/** +*************************************************************************************************** +* SIAddrLib::ReadGbTileMode +* +* @brief +* Convert GB_TILE_MODE HW value to ADDR_TILE_CONFIG. +* @return +* NA. +*************************************************************************************************** +*/ +VOID SIAddrLib::ReadGbTileMode( + UINT_32 regValue, ///< [in] GB_TILE_MODE register + ADDR_TILECONFIG* pCfg ///< [out] output structure + ) const +{ + GB_TILE_MODE gbTileMode; + gbTileMode.val = regValue; + + pCfg->type = static_cast<AddrTileType>(gbTileMode.f.micro_tile_mode); + pCfg->info.bankHeight = 1 << gbTileMode.f.bank_height; + pCfg->info.bankWidth = 1 << gbTileMode.f.bank_width; + pCfg->info.banks = 1 << (gbTileMode.f.num_banks + 1); + pCfg->info.macroAspectRatio = 1 << gbTileMode.f.macro_tile_aspect; + pCfg->info.tileSplitBytes = 64 << gbTileMode.f.tile_split; + pCfg->info.pipeConfig = static_cast<AddrPipeCfg>(gbTileMode.f.pipe_config + 1); + + UINT_32 regArrayMode = gbTileMode.f.array_mode; + + pCfg->mode = static_cast<AddrTileMode>(regArrayMode); + + if (regArrayMode == 8) //ARRAY_2D_TILED_XTHICK + { + pCfg->mode = ADDR_TM_2D_TILED_XTHICK; + } + else if (regArrayMode >= 14) //ARRAY_3D_TILED_XTHICK + { + pCfg->mode = static_cast<AddrTileMode>(pCfg->mode + 3); + } +} + +/** +*************************************************************************************************** +* SIAddrLib::InitTileSettingTable +* +* @brief +* Initialize the ADDR_TILE_CONFIG table. +* @return +* TRUE if tile table is correctly initialized +*************************************************************************************************** +*/ +BOOL_32 SIAddrLib::InitTileSettingTable( + const UINT_32* pCfg, ///< [in] Pointer to table of tile configs + UINT_32 noOfEntries ///< [in] Numbe of entries in the table above + ) +{ + BOOL_32 initOk = TRUE; + + ADDR_ASSERT(noOfEntries <= TileTableSize); + + memset(m_tileTable, 0, sizeof(m_tileTable)); + + if (noOfEntries != 0) + { + m_noOfEntries = noOfEntries; + } + else + { + m_noOfEntries = TileTableSize; + } + + if (pCfg) // From Client + { + for (UINT_32 i = 0; i < m_noOfEntries; i++) + { + ReadGbTileMode(*(pCfg + i), &m_tileTable[i]); + } + } + else + { + ADDR_ASSERT_ALWAYS(); + initOk = FALSE; + } + + if (initOk) + { + ADDR_ASSERT(m_tileTable[TILEINDEX_LINEAR_ALIGNED].mode == ADDR_TM_LINEAR_ALIGNED); + } + + return initOk; +} + +/** +*************************************************************************************************** +* SIAddrLib::HwlGetTileIndex +* +* @brief +* Return the virtual/real index for given mode/type/info +* @return +* ADDR_OK if successful. +*************************************************************************************************** +*/ +ADDR_E_RETURNCODE SIAddrLib::HwlGetTileIndex( + const ADDR_GET_TILEINDEX_INPUT* pIn, + ADDR_GET_TILEINDEX_OUTPUT* pOut) const +{ + ADDR_E_RETURNCODE returnCode = ADDR_OK; + + pOut->index = HwlPostCheckTileIndex(pIn->pTileInfo, pIn->tileMode, pIn->tileType); + + return returnCode; +} + +/** +*************************************************************************************************** +* SIAddrLib::HwlFmaskPreThunkSurfInfo +* +* @brief +* Some preparation before thunking a ComputeSurfaceInfo call for Fmask +* @return +* ADDR_E_RETURNCODE +*************************************************************************************************** +*/ +VOID SIAddrLib::HwlFmaskPreThunkSurfInfo( + const ADDR_COMPUTE_FMASK_INFO_INPUT* pFmaskIn, ///< [in] Input of fmask info + const ADDR_COMPUTE_FMASK_INFO_OUTPUT* pFmaskOut, ///< [in] Output of fmask info + ADDR_COMPUTE_SURFACE_INFO_INPUT* pSurfIn, ///< [out] Input of thunked surface info + ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pSurfOut ///< [out] Output of thunked surface info + ) const +{ + pSurfIn->tileIndex = pFmaskIn->tileIndex; +} + +/** +*************************************************************************************************** +* SIAddrLib::HwlFmaskPostThunkSurfInfo +* +* @brief +* Copy hwl extra field after calling thunked ComputeSurfaceInfo +* @return +* ADDR_E_RETURNCODE +*************************************************************************************************** +*/ +VOID SIAddrLib::HwlFmaskPostThunkSurfInfo( + const ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pSurfOut, ///< [in] Output of surface info + ADDR_COMPUTE_FMASK_INFO_OUTPUT* pFmaskOut ///< [out] Output of fmask info + ) const +{ + pFmaskOut->macroModeIndex = TileIndexInvalid; + pFmaskOut->tileIndex = pSurfOut->tileIndex; +} + +/** +*************************************************************************************************** +* SIAddrLib::HwlComputeFmaskBits +* @brief +* Computes fmask bits +* @return +* Fmask bits +*************************************************************************************************** +*/ +UINT_32 SIAddrLib::HwlComputeFmaskBits( + const ADDR_COMPUTE_FMASK_INFO_INPUT* pIn, + UINT_32* pNumSamples + ) const +{ + UINT_32 numSamples = pIn->numSamples; + UINT_32 numFrags = GetNumFragments(numSamples, pIn->numFrags); + UINT_32 bpp; + + if (numFrags != numSamples) // EQAA + { + ADDR_ASSERT(numFrags <= 8); + + if (!pIn->resolved) + { + if (numFrags == 1) + { + bpp = 1; + numSamples = numSamples == 16 ? 16 : 8; + } + else if (numFrags == 2) + { + ADDR_ASSERT(numSamples >= 4); + + bpp = 2; + numSamples = numSamples; + } + else if (numFrags == 4) + { + ADDR_ASSERT(numSamples >= 4); + + bpp = 4; + numSamples = numSamples; + } + else // numFrags == 8 + { + ADDR_ASSERT(numSamples == 16); + + bpp = 4; + numSamples = numSamples; + } + } + else + { + if (numFrags == 1) + { + bpp = (numSamples == 16) ? 16 : 8; + numSamples = 1; + } + else if (numFrags == 2) + { + ADDR_ASSERT(numSamples >= 4); + + bpp = numSamples*2; + numSamples = 1; + } + else if (numFrags == 4) + { + ADDR_ASSERT(numSamples >= 4); + + bpp = numSamples*4; + numSamples = 1; + } + else // numFrags == 8 + { + ADDR_ASSERT(numSamples >= 16); + + bpp = 16*4; + numSamples = 1; + } + } + } + else // Normal AA + { + if (!pIn->resolved) + { + bpp = ComputeFmaskNumPlanesFromNumSamples(numSamples); + numSamples = numSamples == 2 ? 8 : numSamples; + } + else + { + // The same as 8XX + bpp = ComputeFmaskResolvedBppFromNumSamples(numSamples); + numSamples = 1; // 1x sample + } + } + + SafeAssign(pNumSamples, numSamples); + + return bpp; +} + +/** +*************************************************************************************************** +* SIAddrLib::HwlOverrideTileMode +* +* @brief +* Override tile modes (for PRT only, avoid client passes in an invalid PRT mode for SI. +* +* @return +* Suitable tile mode +* +*************************************************************************************************** +*/ +BOOL_32 SIAddrLib::HwlOverrideTileMode( + const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] input structure + AddrTileMode* pTileMode, ///< [in/out] pointer to the tile mode + AddrTileType* pTileType ///< [in/out] pointer to the tile type + ) const +{ + BOOL_32 bOverrided = FALSE; + AddrTileMode tileMode = *pTileMode; + + switch (tileMode) + { + case ADDR_TM_PRT_TILED_THIN1: + tileMode = ADDR_TM_2D_TILED_THIN1; + break; + + case ADDR_TM_PRT_TILED_THICK: + tileMode = ADDR_TM_2D_TILED_THICK; + break; + + case ADDR_TM_PRT_2D_TILED_THICK: + tileMode = ADDR_TM_2D_TILED_THICK; + break; + + case ADDR_TM_PRT_3D_TILED_THICK: + tileMode = ADDR_TM_3D_TILED_THICK; + break; + + default: + break; + } + + if (tileMode != *pTileMode) + { + *pTileMode = tileMode; + bOverrided = TRUE; + ADDR_ASSERT(pIn->flags.prt == TRUE); + } + + return bOverrided; +} + diff --git a/src/amd/addrlib/r800/siaddrlib.h b/src/amd/addrlib/r800/siaddrlib.h new file mode 100644 index 00000000000..897beb1bb92 --- /dev/null +++ b/src/amd/addrlib/r800/siaddrlib.h @@ -0,0 +1,262 @@ +/* + * Copyright © 2014 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS + * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + */ + +/** +*************************************************************************************************** +* @file siaddrlib.h +* @brief Contains the R800AddrLib class definition. +*************************************************************************************************** +*/ + +#ifndef __SI_ADDR_LIB_H__ +#define __SI_ADDR_LIB_H__ + +#include "addrlib.h" +#include "egbaddrlib.h" + +/** +*************************************************************************************************** +* @brief Describes the information in tile mode table +*************************************************************************************************** +*/ +struct ADDR_TILECONFIG +{ + AddrTileMode mode; + AddrTileType type; + ADDR_TILEINFO info; +}; + +/** +*************************************************************************************************** +* @brief SI specific settings structure. +*************************************************************************************************** +*/ +struct SIChipSettings +{ + struct + { + UINT_32 isSouthernIsland : 1; + UINT_32 isTahiti : 1; + UINT_32 isPitCairn : 1; + UINT_32 isCapeVerde : 1; + /// Oland/Hainan are of GFXIP 6.0, similar with SI + UINT_32 isOland : 1; + UINT_32 isHainan : 1; + }; +}; + +/** +*************************************************************************************************** +* @brief This class is the SI specific address library +* function set. +*************************************************************************************************** +*/ +class SIAddrLib : public EgBasedAddrLib +{ +public: + /// Creates SIAddrLib object + static AddrLib* CreateObj(const AddrClient* pClient) + { + return new(pClient) SIAddrLib(pClient); + } + +protected: + SIAddrLib(const AddrClient* pClient); + virtual ~SIAddrLib(); + + // Hwl interface - defined in AddrLib + virtual ADDR_E_RETURNCODE HwlComputeSurfaceInfo( + const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, + ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut) const; + + virtual ADDR_E_RETURNCODE HwlConvertTileInfoToHW( + const ADDR_CONVERT_TILEINFOTOHW_INPUT* pIn, + ADDR_CONVERT_TILEINFOTOHW_OUTPUT* pOut) const; + + virtual UINT_64 HwlComputeXmaskAddrFromCoord( + UINT_32 pitch, UINT_32 height, UINT_32 x, UINT_32 y, UINT_32 slice, UINT_32 numSlices, + UINT_32 factor, BOOL_32 isLinear, BOOL_32 isWidth8, BOOL_32 isHeight8, + ADDR_TILEINFO* pTileInfo, UINT_32* pBitPosition) const; + + virtual VOID HwlComputeXmaskCoordFromAddr( + UINT_64 addr, UINT_32 bitPosition, UINT_32 pitch, UINT_32 height, UINT_32 numSlices, + UINT_32 factor, BOOL_32 isLinear, BOOL_32 isWidth8, BOOL_32 isHeight8, + ADDR_TILEINFO* pTileInfo, UINT_32* pX, UINT_32* pY, UINT_32* pSlice) const; + + virtual ADDR_E_RETURNCODE HwlGetTileIndex( + const ADDR_GET_TILEINDEX_INPUT* pIn, + ADDR_GET_TILEINDEX_OUTPUT* pOut) const; + + virtual BOOL_32 HwlComputeMipLevel( + ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn) const; + + virtual AddrChipFamily HwlConvertChipFamily( + UINT_32 uChipFamily, UINT_32 uChipRevision); + + virtual BOOL_32 HwlInitGlobalParams( + const ADDR_CREATE_INPUT* pCreateIn); + + virtual ADDR_E_RETURNCODE HwlSetupTileCfg( + INT_32 index, INT_32 macroModeIndex, + ADDR_TILEINFO* pInfo, AddrTileMode* pMode = 0, AddrTileType* pType = 0) const; + + virtual VOID HwlComputeTileDataWidthAndHeightLinear( + UINT_32* pMacroWidth, UINT_32* pMacroHeight, + UINT_32 bpp, ADDR_TILEINFO* pTileInfo) const; + + virtual UINT_64 HwlComputeHtileBytes( + UINT_32 pitch, UINT_32 height, UINT_32 bpp, + BOOL_32 isLinear, UINT_32 numSlices, UINT_64* pSliceBytes, UINT_32 baseAlign) const; + + virtual UINT_32 ComputePipeFromCoord( + UINT_32 x, UINT_32 y, UINT_32 slice, + AddrTileMode tileMode, UINT_32 pipeSwizzle, BOOL_32 ignoreSE, + ADDR_TILEINFO* pTileInfo) const; + + virtual UINT_32 HwlGetPipes(const ADDR_TILEINFO* pTileInfo) const; + + /// Pre-handler of 3x pitch (96 bit) adjustment + virtual UINT_32 HwlPreHandleBaseLvl3xPitch( + const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, UINT_32 expPitch) const; + /// Post-handler of 3x pitch adjustment + virtual UINT_32 HwlPostHandleBaseLvl3xPitch( + const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, UINT_32 expPitch) const; + + /// Dummy function to finalize the inheritance + virtual UINT_32 HwlComputeXmaskCoordYFrom8Pipe( + UINT_32 pipe, UINT_32 x) const; + + // Sub-hwl interface - defined in EgBasedAddrLib + virtual VOID HwlSetupTileInfo( + AddrTileMode tileMode, ADDR_SURFACE_FLAGS flags, + UINT_32 bpp, UINT_32 pitch, UINT_32 height, UINT_32 numSamples, + ADDR_TILEINFO* inputTileInfo, ADDR_TILEINFO* outputTileInfo, + AddrTileType inTileType, ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut) const; + + virtual UINT_32 HwlGetPitchAlignmentMicroTiled( + AddrTileMode tileMode, UINT_32 bpp, ADDR_SURFACE_FLAGS flags, UINT_32 numSamples) const; + + virtual UINT_64 HwlGetSizeAdjustmentMicroTiled( + UINT_32 thickness, UINT_32 bpp, ADDR_SURFACE_FLAGS flags, UINT_32 numSamples, + UINT_32 baseAlign, UINT_32 pitchAlign, + UINT_32 *pPitch, UINT_32 *pHeight) const; + + virtual VOID HwlCheckLastMacroTiledLvl( + const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut) const; + + virtual BOOL_32 HwlTileInfoEqual( + const ADDR_TILEINFO* pLeft, const ADDR_TILEINFO* pRight) const; + + virtual AddrTileMode HwlDegradeThickTileMode( + AddrTileMode baseTileMode, UINT_32 numSlices, UINT_32* pBytesPerTile) const; + + virtual BOOL_32 HwlOverrideTileMode( + const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, + AddrTileMode* pTileMode, + AddrTileType* pTileType) const; + + virtual BOOL_32 HwlSanityCheckMacroTiled( + ADDR_TILEINFO* pTileInfo) const + { + return TRUE; + } + + virtual UINT_32 HwlGetPitchAlignmentLinear(UINT_32 bpp, ADDR_SURFACE_FLAGS flags) const; + + virtual UINT_64 HwlGetSizeAdjustmentLinear( + AddrTileMode tileMode, + UINT_32 bpp, UINT_32 numSamples, UINT_32 baseAlign, UINT_32 pitchAlign, + UINT_32 *pPitch, UINT_32 *pHeight, UINT_32 *pHeightAlign) const; + + virtual VOID HwlComputeSurfaceCoord2DFromBankPipe( + AddrTileMode tileMode, UINT_32* pX, UINT_32* pY, UINT_32 slice, + UINT_32 bank, UINT_32 pipe, + UINT_32 bankSwizzle, UINT_32 pipeSwizzle, UINT_32 tileSlices, + BOOL_32 ignoreSE, + ADDR_TILEINFO* pTileInfo) const; + + virtual UINT_32 HwlPreAdjustBank( + UINT_32 tileX, UINT_32 bank, ADDR_TILEINFO* pTileInfo) const; + + virtual INT_32 HwlPostCheckTileIndex( + const ADDR_TILEINFO* pInfo, AddrTileMode mode, AddrTileType type, + INT curIndex = TileIndexInvalid) const; + + virtual VOID HwlFmaskPreThunkSurfInfo( + const ADDR_COMPUTE_FMASK_INFO_INPUT* pFmaskIn, + const ADDR_COMPUTE_FMASK_INFO_OUTPUT* pFmaskOut, + ADDR_COMPUTE_SURFACE_INFO_INPUT* pSurfIn, + ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pSurfOut) const; + + virtual VOID HwlFmaskPostThunkSurfInfo( + const ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pSurfOut, + ADDR_COMPUTE_FMASK_INFO_OUTPUT* pFmaskOut) const; + + virtual UINT_32 HwlComputeFmaskBits( + const ADDR_COMPUTE_FMASK_INFO_INPUT* pIn, + UINT_32* pNumSamples) const; + + virtual BOOL_32 HwlReduceBankWidthHeight( + UINT_32 tileSize, UINT_32 bpp, ADDR_SURFACE_FLAGS flags, UINT_32 numSamples, + UINT_32 bankHeightAlign, UINT_32 pipes, + ADDR_TILEINFO* pTileInfo) const + { + return TRUE; + } + + // Protected non-virtual functions + VOID ComputeTileCoordFromPipeAndElemIdx( + UINT_32 elemIdx, UINT_32 pipe, AddrPipeCfg pipeCfg, UINT_32 pitchInMacroTile, + UINT_32 x, UINT_32 y, UINT_32* pX, UINT_32* pY) const; + + UINT_32 TileCoordToMaskElementIndex( + UINT_32 tx, UINT_32 ty, AddrPipeCfg pipeConfig, + UINT_32 *macroShift, UINT_32 *elemIdxBits) const; + + BOOL_32 DecodeGbRegs( + const ADDR_REGISTER_VALUE* pRegValue); + + const ADDR_TILECONFIG* GetTileSetting( + UINT_32 index) const; + + static const UINT_32 TileTableSize = 32; + ADDR_TILECONFIG m_tileTable[TileTableSize]; + UINT_32 m_noOfEntries; + +private: + + UINT_32 GetPipePerSurf(AddrPipeCfg pipeConfig) const; + + VOID ReadGbTileMode( + UINT_32 regValue, ADDR_TILECONFIG* pCfg) const; + BOOL_32 InitTileSettingTable( + const UINT_32 *pSetting, UINT_32 noOfEntries); + + SIChipSettings m_settings; +}; + +#endif + |