mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-25 06:30:10 +01:00
2175 lines
72 KiB
C++
2175 lines
72 KiB
C++
/*
|
|
* 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 CiLib 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
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
namespace Addr
|
|
{
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* CiHwlInit
|
|
*
|
|
* @brief
|
|
* Creates an CiLib object.
|
|
*
|
|
* @return
|
|
* Returns an CiLib object pointer.
|
|
****************************************************************************************************
|
|
*/
|
|
Lib* CiHwlInit(const Client* pClient)
|
|
{
|
|
return V1::CiLib::CreateObj(pClient);
|
|
}
|
|
|
|
namespace V1
|
|
{
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* Mask
|
|
*
|
|
* @brief
|
|
* Gets a mask of "width"
|
|
* @return
|
|
* Bit mask
|
|
****************************************************************************************************
|
|
*/
|
|
static UINT_64 Mask(
|
|
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;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* GetBits
|
|
*
|
|
* @brief
|
|
* Gets bits within a range of [msb, lsb]
|
|
* @return
|
|
* Bits of this range
|
|
****************************************************************************************************
|
|
*/
|
|
static UINT_64 GetBits(
|
|
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) & (Mask(1 + msb - lsb));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* RemoveBits
|
|
*
|
|
* @brief
|
|
* Removes bits within the range of [msb, lsb]
|
|
* @return
|
|
* Modified bits
|
|
****************************************************************************************************
|
|
*/
|
|
static UINT_64 RemoveBits(
|
|
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 = GetBits(bits, lsb - 1, 0) // low bits
|
|
| (GetBits(bits, 8 * sizeof(bits) - 1, msb + 1) << lsb); //high bits
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* InsertBits
|
|
*
|
|
* @brief
|
|
* Inserts new bits into the range of [msb, lsb]
|
|
* @return
|
|
* Modified bits
|
|
****************************************************************************************************
|
|
*/
|
|
static UINT_64 InsertBits(
|
|
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 = GetBits(bits, lsb - 1, 0) // old low bitss
|
|
| (GetBits(newBits, msb - lsb, 0) << lsb) //new bits
|
|
| (GetBits(bits, 8 * sizeof(bits) - 1, lsb) << (msb + 1)); //old high bits
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* CiLib::CiLib
|
|
*
|
|
* @brief
|
|
* Constructor
|
|
*
|
|
****************************************************************************************************
|
|
*/
|
|
CiLib::CiLib(const Client* pClient)
|
|
:
|
|
SiLib(pClient),
|
|
m_noOfMacroEntries(0),
|
|
m_allowNonDispThickModes(FALSE)
|
|
{
|
|
m_class = CI_ADDRLIB;
|
|
memset(&m_settings, 0, sizeof(m_settings));
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* CiLib::~CiLib
|
|
*
|
|
* @brief
|
|
* Destructor
|
|
****************************************************************************************************
|
|
*/
|
|
CiLib::~CiLib()
|
|
{
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* CiLib::HwlComputeDccInfo
|
|
*
|
|
* @brief
|
|
* Compute DCC key size, base alignment
|
|
* @return
|
|
* ADDR_E_RETURNCODE
|
|
****************************************************************************************************
|
|
*/
|
|
ADDR_E_RETURNCODE CiLib::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;
|
|
pOut->dccRamSizeAligned = TRUE;
|
|
|
|
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);
|
|
}
|
|
if ((pOut->dccRamSize & (dccRamSizeAlign - 1)) != 0)
|
|
{
|
|
pOut->dccRamSizeAligned = FALSE;
|
|
}
|
|
pOut->dccRamSize = PowTwoAlign(pOut->dccRamSize, dccRamSizeAlign);
|
|
pOut->subLvlCompressible = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
returnCode = ADDR_NOTSUPPORTED;
|
|
}
|
|
|
|
return returnCode;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* CiLib::HwlComputeCmaskAddrFromCoord
|
|
*
|
|
* @brief
|
|
* Compute tc compatible Cmask address from fmask ram address
|
|
*
|
|
* @return
|
|
* ADDR_E_RETURNCODE
|
|
****************************************************************************************************
|
|
*/
|
|
ADDR_E_RETURNCODE CiLib::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, // cmask 4 bits
|
|
elemBits,
|
|
blockByte,
|
|
m_pipeInterleaveBytes,
|
|
numOfPipes,
|
|
numOfBanks,
|
|
1);
|
|
pOut->addr = (metaNibbleAddress >> 1);
|
|
pOut->bitPosition = (metaNibbleAddress % 2) ? 4 : 0;
|
|
returnCode = ADDR_OK;
|
|
}
|
|
|
|
return returnCode;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* CiLib::HwlComputeHtileAddrFromCoord
|
|
*
|
|
* @brief
|
|
* Compute tc compatible Htile address from depth/stencil address
|
|
*
|
|
* @return
|
|
* ADDR_E_RETURNCODE
|
|
****************************************************************************************************
|
|
*/
|
|
ADDR_E_RETURNCODE CiLib::HwlComputeHtileAddrFromCoord(
|
|
const ADDR_COMPUTE_HTILE_ADDRFROMCOORD_INPUT* pIn, ///< [in] depth/stencil addr/bpp/tile input
|
|
ADDR_COMPUTE_HTILE_ADDRFROMCOORD_OUTPUT* pOut ///< [out] htile 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 zStencilAddr = pIn->zStencilAddr;
|
|
UINT_32 elemBits = pIn->bpp;
|
|
UINT_32 blockByte = 64 * elemBits / 8;
|
|
UINT_64 metaNibbleAddress = HwlComputeMetadataNibbleAddress(zStencilAddr,
|
|
0,
|
|
0,
|
|
32, // htile 32 bits
|
|
elemBits,
|
|
blockByte,
|
|
m_pipeInterleaveBytes,
|
|
numOfPipes,
|
|
numOfBanks,
|
|
1);
|
|
pOut->addr = (metaNibbleAddress >> 1);
|
|
pOut->bitPosition = 0;
|
|
returnCode = ADDR_OK;
|
|
}
|
|
|
|
return returnCode;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* CiLib::HwlConvertChipFamily
|
|
*
|
|
* @brief
|
|
* Convert familyID defined in atiid.h to ChipFamily and set m_chipFamily/m_chipRevision
|
|
* @return
|
|
* ChipFamily
|
|
****************************************************************************************************
|
|
*/
|
|
ChipFamily CiLib::HwlConvertChipFamily(
|
|
UINT_32 uChipFamily, ///< [in] chip family defined in atiih.h
|
|
UINT_32 uChipRevision) ///< [in] chip revision defined in "asic_family"_id.h
|
|
{
|
|
ChipFamily 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);
|
|
m_settings.isPolaris12 = ASICREV_IS_POLARIS12_V(uChipRevision);
|
|
family = ADDR_CHIP_FAMILY_VI;
|
|
break;
|
|
case FAMILY_CZ:
|
|
m_settings.isCarrizo = 1;
|
|
m_settings.isVolcanicIslands = 1;
|
|
family = ADDR_CHIP_FAMILY_VI;
|
|
break;
|
|
default:
|
|
ADDR_ASSERT(!"This should be a unexpected Fusion");
|
|
break;
|
|
}
|
|
|
|
return family;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* CiLib::HwlInitGlobalParams
|
|
*
|
|
* @brief
|
|
* Initializes global parameters
|
|
*
|
|
* @return
|
|
* TRUE if all settings are valid
|
|
*
|
|
****************************************************************************************************
|
|
*/
|
|
BOOL_32 CiLib::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_settings.isPolaris12)
|
|
{
|
|
m_pipes = 4;
|
|
}
|
|
|
|
if (valid)
|
|
{
|
|
valid = InitTileSettingTable(pRegValue->pTileConfig, pRegValue->noOfEntries);
|
|
}
|
|
if (valid)
|
|
{
|
|
valid = InitMacroTileCfgTable(pRegValue->pMacroTileConfig, pRegValue->noOfMacroEntries);
|
|
}
|
|
|
|
if (valid)
|
|
{
|
|
InitEquationTable();
|
|
}
|
|
|
|
return valid;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* CiLib::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 CiLib::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 (Min(m_tileTable[index].info.tileSplitBytes,
|
|
m_rowSize) == pInfo->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;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* CiLib::HwlSetupTileCfg
|
|
*
|
|
* @brief
|
|
* Map tile index to tile setting.
|
|
* @return
|
|
* ADDR_E_RETURNCODE
|
|
****************************************************************************************************
|
|
*/
|
|
ADDR_E_RETURNCODE CiLib::HwlSetupTileCfg(
|
|
UINT_32 bpp, ///< [in] Bits per pixel
|
|
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)
|
|
{
|
|
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 TileConfig* pCfgTable = GetTileSetting(index);
|
|
|
|
if (pInfo != NULL)
|
|
{
|
|
if (IsMacroTiled(pCfgTable->mode))
|
|
{
|
|
ADDR_ASSERT((macroModeIndex != TileIndexInvalid) &&
|
|
(macroModeIndex != TileIndexNoMacroIndex));
|
|
|
|
UINT_32 tileSplit;
|
|
|
|
*pInfo = m_macroTileTable[macroModeIndex];
|
|
|
|
if (pCfgTable->type == ADDR_DEPTH_SAMPLE_ORDER)
|
|
{
|
|
tileSplit = pCfgTable->info.tileSplitBytes;
|
|
}
|
|
else
|
|
{
|
|
if (bpp > 0)
|
|
{
|
|
UINT_32 thickness = Thickness(pCfgTable->mode);
|
|
UINT_32 tileBytes1x = BITS_TO_BYTES(bpp * MicroTilePixels * thickness);
|
|
// Non-depth entries store a split factor
|
|
UINT_32 sampleSplit = m_tileTable[index].info.tileSplitBytes;
|
|
tileSplit = Max(256u, sampleSplit * tileBytes1x);
|
|
}
|
|
else
|
|
{
|
|
// Return tileBytes instead if not enough info
|
|
tileSplit = pInfo->tileSplitBytes;
|
|
}
|
|
}
|
|
|
|
// Clamp to row_size
|
|
pInfo->tileSplitBytes = Min(m_rowSize, tileSplit);
|
|
|
|
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;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* CiLib::HwlComputeSurfaceInfo
|
|
*
|
|
* @brief
|
|
* Entry of CI's ComputeSurfaceInfo
|
|
* @return
|
|
* ADDR_E_RETURNCODE
|
|
****************************************************************************************************
|
|
*/
|
|
ADDR_E_RETURNCODE CiLib::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;
|
|
}
|
|
|
|
// Pass tcCompatible flag from input to output; and turn off it if tile split occurs
|
|
pOut->tcCompatible = pIn->flags.tcCompatible;
|
|
|
|
ADDR_E_RETURNCODE retCode = SiLib::HwlComputeSurfaceInfo(pIn,pOut);
|
|
|
|
if (pOut->macroModeIndex == TileIndexNoMacroIndex)
|
|
{
|
|
pOut->macroModeIndex = TileIndexInvalid;
|
|
}
|
|
|
|
return retCode;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* CiLib::HwlFmaskSurfaceInfo
|
|
* @brief
|
|
* Entry of r800's ComputeFmaskInfo
|
|
* @return
|
|
* ADDR_E_RETURNCODE
|
|
****************************************************************************************************
|
|
*/
|
|
ADDR_E_RETURNCODE CiLib::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;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* CiLib::HwlFmaskPreThunkSurfInfo
|
|
*
|
|
* @brief
|
|
* Some preparation before thunking a ComputeSurfaceInfo call for Fmask
|
|
* @return
|
|
* ADDR_E_RETURNCODE
|
|
****************************************************************************************************
|
|
*/
|
|
VOID CiLib::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;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* CiLib::HwlFmaskPostThunkSurfInfo
|
|
*
|
|
* @brief
|
|
* Copy hwl extra field after calling thunked ComputeSurfaceInfo
|
|
* @return
|
|
* ADDR_E_RETURNCODE
|
|
****************************************************************************************************
|
|
*/
|
|
VOID CiLib::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;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* CiLib::HwlDegradeThickTileMode
|
|
*
|
|
* @brief
|
|
* Degrades valid tile mode for thick modes if needed
|
|
*
|
|
* @return
|
|
* Suitable tile mode
|
|
****************************************************************************************************
|
|
*/
|
|
AddrTileMode CiLib::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;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* CiLib::HwlOptimizeTileMode
|
|
*
|
|
* @brief
|
|
* Optimize tile mode on CI
|
|
*
|
|
* @return
|
|
* N/A
|
|
*
|
|
****************************************************************************************************
|
|
*/
|
|
VOID CiLib::HwlOptimizeTileMode(
|
|
ADDR_COMPUTE_SURFACE_INFO_INPUT* pInOut ///< [in,out] input output structure
|
|
) const
|
|
{
|
|
AddrTileMode tileMode = pInOut->tileMode;
|
|
|
|
// Override 2D/3D macro tile mode to PRT_* tile mode if
|
|
// client driver requests this surface is equation compatible
|
|
if ((pInOut->flags.needEquation == TRUE) &&
|
|
(pInOut->numSamples <= 1) &&
|
|
(IsMacroTiled(tileMode) == TRUE) &&
|
|
(IsPrtTileMode(tileMode) == FALSE))
|
|
{
|
|
UINT_32 thickness = Thickness(tileMode);
|
|
|
|
if ((pInOut->maxBaseAlign != 0) && (pInOut->maxBaseAlign < Block64K))
|
|
{
|
|
tileMode = (thickness == 1) ? ADDR_TM_1D_TILED_THIN1 : ADDR_TM_1D_TILED_THICK;
|
|
}
|
|
else if (thickness == 1)
|
|
{
|
|
tileMode = ADDR_TM_PRT_TILED_THIN1;
|
|
}
|
|
else
|
|
{
|
|
static const UINT_32 PrtTileBytes = 0x10000;
|
|
// First prt thick tile index in the tile mode table
|
|
static const UINT_32 PrtThickTileIndex = 22;
|
|
ADDR_TILEINFO tileInfo = {0};
|
|
|
|
HwlComputeMacroModeIndex(PrtThickTileIndex,
|
|
pInOut->flags,
|
|
pInOut->bpp,
|
|
pInOut->numSamples,
|
|
&tileInfo);
|
|
|
|
UINT_32 macroTileBytes = ((pInOut->bpp) >> 3) * 64 * pInOut->numSamples *
|
|
thickness * HwlGetPipes(&tileInfo) *
|
|
tileInfo.banks * tileInfo.bankWidth *
|
|
tileInfo.bankHeight;
|
|
|
|
if (macroTileBytes <= PrtTileBytes)
|
|
{
|
|
tileMode = ADDR_TM_PRT_TILED_THICK;
|
|
}
|
|
else
|
|
{
|
|
tileMode = ADDR_TM_PRT_TILED_THIN1;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (tileMode != pInOut->tileMode)
|
|
{
|
|
pInOut->tileMode = tileMode;
|
|
}
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* CiLib::HwlOverrideTileMode
|
|
*
|
|
* @brief
|
|
* Override THICK to THIN, for specific formats on CI
|
|
*
|
|
* @return
|
|
* N/A
|
|
*
|
|
****************************************************************************************************
|
|
*/
|
|
VOID CiLib::HwlOverrideTileMode(
|
|
ADDR_COMPUTE_SURFACE_INFO_INPUT* pInOut ///< [in,out] input output structure
|
|
) const
|
|
{
|
|
AddrTileMode tileMode = pInOut->tileMode;
|
|
AddrTileType tileType = pInOut->tileType;
|
|
|
|
// 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 = Thickness(tileMode);
|
|
|
|
// tile_thickness = (array_mode == XTHICK) ? 8 : ((array_mode == THICK) ? 4 : 1)
|
|
if (thickness > 1)
|
|
{
|
|
switch (pInOut->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 != pInOut->tileMode)
|
|
{
|
|
// see tileIndex: 13-18
|
|
tileType = ADDR_NON_DISPLAYABLE;
|
|
}
|
|
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (tileMode != pInOut->tileMode)
|
|
{
|
|
pInOut->tileMode = tileMode;
|
|
pInOut->tileType = tileType;
|
|
}
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* CiLib::HwlSelectTileMode
|
|
*
|
|
* @brief
|
|
* Select tile modes.
|
|
*
|
|
* @return
|
|
* N/A
|
|
*
|
|
****************************************************************************************************
|
|
*/
|
|
VOID CiLib::HwlSelectTileMode(
|
|
ADDR_COMPUTE_SURFACE_INFO_INPUT* pInOut ///< [in,out] input output structure
|
|
) const
|
|
{
|
|
AddrTileMode tileMode;
|
|
AddrTileType tileType;
|
|
|
|
if (pInOut->flags.rotateDisplay)
|
|
{
|
|
tileMode = ADDR_TM_2D_TILED_THIN1;
|
|
tileType = ADDR_ROTATED;
|
|
}
|
|
else if (pInOut->flags.volume)
|
|
{
|
|
BOOL_32 bThin = (m_settings.isBonaire == TRUE) ||
|
|
((m_allowNonDispThickModes == TRUE) && (pInOut->flags.color == TRUE));
|
|
|
|
if (pInOut->numSlices >= 8)
|
|
{
|
|
tileMode = ADDR_TM_2D_TILED_XTHICK;
|
|
tileType = (bThin == TRUE) ? ADDR_NON_DISPLAYABLE : ADDR_THICK;
|
|
}
|
|
else if (pInOut->numSlices >= 4)
|
|
{
|
|
tileMode = ADDR_TM_2D_TILED_THICK;
|
|
tileType = (bThin == TRUE) ? ADDR_NON_DISPLAYABLE : ADDR_THICK;
|
|
}
|
|
else
|
|
{
|
|
tileMode = ADDR_TM_2D_TILED_THIN1;
|
|
tileType = ADDR_NON_DISPLAYABLE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
tileMode = ADDR_TM_2D_TILED_THIN1;
|
|
|
|
if (pInOut->flags.depth || pInOut->flags.stencil)
|
|
{
|
|
tileType = ADDR_DEPTH_SAMPLE_ORDER;
|
|
}
|
|
else if ((pInOut->bpp <= 32) ||
|
|
(pInOut->flags.display == TRUE) ||
|
|
(pInOut->flags.overlay == TRUE))
|
|
{
|
|
tileType = ADDR_DISPLAYABLE;
|
|
}
|
|
else
|
|
{
|
|
tileType = ADDR_NON_DISPLAYABLE;
|
|
}
|
|
}
|
|
|
|
if (pInOut->flags.prt)
|
|
{
|
|
if (Thickness(tileMode) > 1)
|
|
{
|
|
tileMode = ADDR_TM_PRT_TILED_THICK;
|
|
tileType = (m_settings.isBonaire == TRUE) ? ADDR_NON_DISPLAYABLE : ADDR_THICK;
|
|
}
|
|
else
|
|
{
|
|
tileMode = ADDR_TM_PRT_TILED_THIN1;
|
|
}
|
|
}
|
|
|
|
pInOut->tileMode = tileMode;
|
|
pInOut->tileType = tileType;
|
|
|
|
if ((pInOut->flags.dccCompatible == FALSE) &&
|
|
(pInOut->flags.tcCompatible == FALSE))
|
|
{
|
|
pInOut->flags.opt4Space = TRUE;
|
|
pInOut->maxBaseAlign = Block64K;
|
|
|
|
// Optimize tile mode if possible
|
|
OptimizeTileMode(pInOut);
|
|
}
|
|
|
|
HwlOverrideTileMode(pInOut);
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* CiLib::HwlSetPrtTileMode
|
|
*
|
|
* @brief
|
|
* Set PRT tile mode.
|
|
*
|
|
* @return
|
|
* N/A
|
|
*
|
|
****************************************************************************************************
|
|
*/
|
|
VOID CiLib::HwlSetPrtTileMode(
|
|
ADDR_COMPUTE_SURFACE_INFO_INPUT* pInOut ///< [in,out] input output structure
|
|
) const
|
|
{
|
|
AddrTileMode tileMode = pInOut->tileMode;
|
|
AddrTileType tileType = pInOut->tileType;
|
|
|
|
if (Thickness(tileMode) > 1)
|
|
{
|
|
tileMode = ADDR_TM_PRT_TILED_THICK;
|
|
tileType = (m_settings.isBonaire == TRUE) ? ADDR_NON_DISPLAYABLE : ADDR_THICK;
|
|
}
|
|
else
|
|
{
|
|
tileMode = ADDR_TM_PRT_TILED_THIN1;
|
|
tileType = (tileType == ADDR_THICK) ? ADDR_NON_DISPLAYABLE : tileType;
|
|
}
|
|
|
|
pInOut->tileMode = tileMode;
|
|
pInOut->tileType = tileType;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* CiLib::HwlSetupTileInfo
|
|
*
|
|
* @brief
|
|
* Setup default value of tile info for SI
|
|
****************************************************************************************************
|
|
*/
|
|
VOID CiLib::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 = Thickness(tileMode);
|
|
ADDR_TILEINFO* pTileInfo = pTileInfoOut;
|
|
INT index = TileIndexInvalid;
|
|
INT macroModeIndex = TileIndexInvalid;
|
|
|
|
// Fail-safe code
|
|
if (IsLinear(tileMode) == FALSE)
|
|
{
|
|
// 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) ||
|
|
// There is no PRT_THICK + THIN entry in tile mode table except Bonaire
|
|
(IsPrtTileMode(tileMode) == TRUE))
|
|
{
|
|
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)
|
|
{
|
|
// tileSize = thickness * bpp * numSamples * 8 * 8 / 8
|
|
UINT_32 tileSize = thickness * bpp * numSamples * 8;
|
|
|
|
// Turn off tc compatible if row_size is smaller than tile size (tile split occurs).
|
|
if (m_rowSize < tileSize)
|
|
{
|
|
flags.tcCompatible = FALSE;
|
|
pOut->tcCompatible = FALSE;
|
|
}
|
|
|
|
if (flags.depth && (flags.nonSplit || flags.tcCompatible || flags.needEquation))
|
|
{
|
|
// Texture 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
|
|
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
|
|
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))
|
|
{
|
|
static const UINT_32 PrtTileBytes = 0x10000;
|
|
ADDR_TILEINFO tileInfo = {0};
|
|
|
|
HwlComputeMacroModeIndex(index, flags, bpp, numSamples, &tileInfo);
|
|
|
|
UINT_32 macroTileBytes = (bpp >> 3) * 64 * numSamples * thickness *
|
|
HwlGetPipes(&tileInfo) * tileInfo.banks *
|
|
tileInfo.bankWidth * tileInfo.bankHeight;
|
|
|
|
if (macroTileBytes != PrtTileBytes)
|
|
{
|
|
// Switching to next tile mode entry to make sure macro tile size is 64KB
|
|
index += 1;
|
|
|
|
tileInfo.pipeConfig = m_tileTable[index].info.pipeConfig;
|
|
|
|
macroTileBytes = (bpp >> 3) * 64 * numSamples * thickness *
|
|
HwlGetPipes(&tileInfo) * tileInfo.banks *
|
|
tileInfo.bankWidth * tileInfo.bankHeight;
|
|
|
|
ADDR_ASSERT(macroTileBytes == PrtTileBytes);
|
|
|
|
pOut->tcCompatible = FALSE;
|
|
pOut->dccUnsupport = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
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;
|
|
|
|
if (flags.depth || flags.stencil)
|
|
{
|
|
// tileSize = thickness * bpp * numSamples * 8 * 8 / 8
|
|
UINT_32 tileSize = thickness * bpp * numSamples * 8;
|
|
|
|
// Turn off tc compatible if row_size is smaller than tile size (tile split occurs).
|
|
if (m_rowSize < tileSize)
|
|
{
|
|
flags.tcCompatible = FALSE;
|
|
pOut->tcCompatible = FALSE;
|
|
}
|
|
}
|
|
|
|
UINT_32 numPipes = GetPipePerSurf(pTileInfo->pipeConfig);
|
|
|
|
if (m_pipes != numPipes)
|
|
{
|
|
pOut->dccUnsupport = TRUE;
|
|
}
|
|
}
|
|
|
|
// 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;
|
|
}
|
|
|
|
if (pOut->tcCompatible)
|
|
{
|
|
if (IsMacroTiled(tileMode))
|
|
{
|
|
if (inTileType != ADDR_DEPTH_SAMPLE_ORDER)
|
|
{
|
|
// Turn off tcCompatible for color surface if tileSplit happens. Depth/stencil
|
|
// tileSplit case was handled at tileIndex selecting time.
|
|
INT_32 tileIndex = pOut->tileIndex;
|
|
|
|
if ((tileIndex == TileIndexInvalid) && (IsTileInfoAllZero(pTileInfo) == FALSE))
|
|
{
|
|
tileIndex = HwlPostCheckTileIndex(pTileInfo, tileMode, inTileType, tileIndex);
|
|
}
|
|
|
|
if (tileIndex != TileIndexInvalid)
|
|
{
|
|
ADDR_ASSERT(static_cast<UINT_32>(tileIndex) < TileTableSize);
|
|
// Non-depth entries store a split factor
|
|
UINT_32 sampleSplit = m_tileTable[tileIndex].info.tileSplitBytes;
|
|
UINT_32 tileBytes1x = BITS_TO_BYTES(bpp * MicroTilePixels * thickness);
|
|
UINT_32 colorTileSplit = Max(256u, sampleSplit * tileBytes1x);
|
|
|
|
if (m_rowSize < colorTileSplit)
|
|
{
|
|
pOut->tcCompatible = FALSE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Client should not enable tc compatible for linear and 1D tile modes.
|
|
pOut->tcCompatible = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* CiLib::ReadGbTileMode
|
|
*
|
|
* @brief
|
|
* Convert GB_TILE_MODE HW value to ADDR_TILE_CONFIG.
|
|
****************************************************************************************************
|
|
*/
|
|
VOID CiLib::ReadGbTileMode(
|
|
UINT_32 regValue, ///< [in] GB_TILE_MODE register
|
|
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;
|
|
}
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* CiLib::InitTileSettingTable
|
|
*
|
|
* @brief
|
|
* Initialize the ADDR_TILE_CONFIG table.
|
|
* @return
|
|
* TRUE if tile table is correctly initialized
|
|
****************************************************************************************************
|
|
*/
|
|
BOOL_32 CiLib::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;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* CiLib::ReadGbMacroTileCfg
|
|
*
|
|
* @brief
|
|
* Convert GB_MACRO_TILE_CFG HW value to ADDR_TILE_CONFIG.
|
|
****************************************************************************************************
|
|
*/
|
|
VOID CiLib::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;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* CiLib::InitMacroTileCfgTable
|
|
*
|
|
* @brief
|
|
* Initialize the ADDR_MACRO_TILE_CONFIG table.
|
|
* @return
|
|
* TRUE if macro tile table is correctly initialized
|
|
****************************************************************************************************
|
|
*/
|
|
BOOL_32 CiLib::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;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* CiLib::HwlComputeMacroModeIndex
|
|
*
|
|
* @brief
|
|
* Computes macro tile mode index
|
|
* @return
|
|
* TRUE if macro tile table is correctly initialized
|
|
****************************************************************************************************
|
|
*/
|
|
INT_32 CiLib::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;
|
|
|
|
AddrTileMode tileMode = m_tileTable[tileIndex].mode;
|
|
AddrTileType tileType = m_tileTable[tileIndex].type;
|
|
UINT_32 thickness = Thickness(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))
|
|
{
|
|
macroModeIndex += PrtMacroModeOffset;
|
|
*pTileInfo = m_macroTileTable[macroModeIndex];
|
|
}
|
|
else
|
|
{
|
|
*pTileInfo = m_macroTileTable[macroModeIndex];
|
|
}
|
|
|
|
pTileInfo->pipeConfig = m_tileTable[tileIndex].info.pipeConfig;
|
|
|
|
pTileInfo->tileSplitBytes = tileSplitC;
|
|
}
|
|
|
|
if (NULL != pTileMode)
|
|
{
|
|
*pTileMode = tileMode;
|
|
}
|
|
|
|
if (NULL != pTileType)
|
|
{
|
|
*pTileType = tileType;
|
|
}
|
|
|
|
return macroModeIndex;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* CiLib::HwlComputeTileDataWidthAndHeightLinear
|
|
*
|
|
* @brief
|
|
* Compute the squared cache shape for per-tile data (CMASK and HTILE) for linear layout
|
|
*
|
|
* @note
|
|
* MacroWidth and macroHeight are measured in pixels
|
|
****************************************************************************************************
|
|
*/
|
|
VOID CiLib::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;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* CiLib::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 CiLib::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 = GetBits(offset, msb, lsb);
|
|
|
|
///--------------------------------------------------------------------------------------------
|
|
/// Save pipe data bits
|
|
///--------------------------------------------------------------------------------------------
|
|
lsb = pipeInterleaveBits;
|
|
msb = pipeBits - 1 + lsb;
|
|
|
|
UINT_64 pipeDataBits = GetBits(offset, msb, lsb);
|
|
|
|
///--------------------------------------------------------------------------------------------
|
|
/// Remove pipe and bank bits
|
|
///--------------------------------------------------------------------------------------------
|
|
lsb = pipeInterleaveBits;
|
|
msb = dataMacrotileBits - 1;
|
|
|
|
UINT_64 offsetWithoutPipeBankBits = RemoveBits(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 = InsertBits(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 = InsertBits(metaAddressInPipe, pipeDataBits, msb, lsb);
|
|
|
|
return metadataAddress;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* CiLib::HwlComputeSurfaceAlignmentsMacroTiled
|
|
*
|
|
* @brief
|
|
* Hardware layer function to compute alignment request for macro tile mode
|
|
*
|
|
****************************************************************************************************
|
|
*/
|
|
VOID CiLib::HwlComputeSurfaceAlignmentsMacroTiled(
|
|
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_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [in,out] Surface output
|
|
) const
|
|
{
|
|
// This is to workaround a H/W limitation that DCC doesn't work when pipe config is switched to
|
|
// P4. In theory, all asics that have such switching should be patched but we now only know what
|
|
// to pad for Fiji.
|
|
if ((m_settings.isFiji == TRUE) &&
|
|
(flags.dccCompatible == TRUE) &&
|
|
(flags.prt == FALSE) &&
|
|
(mipLevel == 0) &&
|
|
(tileMode == ADDR_TM_PRT_TILED_THIN1) &&
|
|
(pOut->dccUnsupport == TRUE))
|
|
{
|
|
pOut->pitchAlign = PowTwoAlign(pOut->pitchAlign, 256);
|
|
// In case the client still requests DCC usage.
|
|
pOut->dccUnsupport = FALSE;
|
|
}
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* CiLib::HwlPadDimensions
|
|
*
|
|
* @brief
|
|
* Helper function to pad dimensions
|
|
*
|
|
****************************************************************************************************
|
|
*/
|
|
VOID CiLib::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] tile info
|
|
UINT_32 mipLevel, ///< [in] mip level
|
|
UINT_32* pPitch, ///< [in,out] pitch in pixels
|
|
UINT_32* pPitchAlign, ///< [in,out] pitch alignment
|
|
UINT_32 height, ///< [in] height in pixels
|
|
UINT_32 heightAlign ///< [in] height alignment
|
|
) const
|
|
{
|
|
if ((m_settings.isVolcanicIslands == TRUE) &&
|
|
(flags.dccCompatible == TRUE) &&
|
|
(numSamples > 1) &&
|
|
(mipLevel == 0) &&
|
|
(IsMacroTiled(tileMode) == TRUE))
|
|
{
|
|
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) * height * bpp * samplesPerSplit);
|
|
|
|
ADDR_ASSERT(IsPow2(dccFastClearByteAlign));
|
|
|
|
if (0 != (bytesPerSplit & (dccFastClearByteAlign - 1)))
|
|
{
|
|
UINT_32 dccFastClearPixelAlign = dccFastClearByteAlign /
|
|
BITS_TO_BYTES(bpp) /
|
|
samplesPerSplit;
|
|
UINT_32 macroTilePixelAlign = (*pPitchAlign) * heightAlign;
|
|
|
|
if ((dccFastClearPixelAlign >= macroTilePixelAlign) &&
|
|
((dccFastClearPixelAlign % macroTilePixelAlign) == 0))
|
|
{
|
|
UINT_32 dccFastClearPitchAlignInMacroTile =
|
|
dccFastClearPixelAlign / macroTilePixelAlign;
|
|
UINT_32 heightInMacroTile = height / heightAlign;
|
|
|
|
while ((heightInMacroTile > 1) &&
|
|
((heightInMacroTile % 2) == 0) &&
|
|
(dccFastClearPitchAlignInMacroTile > 1) &&
|
|
((dccFastClearPitchAlignInMacroTile % 2) == 0))
|
|
{
|
|
heightInMacroTile >>= 1;
|
|
dccFastClearPitchAlignInMacroTile >>= 1;
|
|
}
|
|
|
|
UINT_32 dccFastClearPitchAlignInPixels =
|
|
(*pPitchAlign) * dccFastClearPitchAlignInMacroTile;
|
|
|
|
if (IsPow2(dccFastClearPitchAlignInPixels))
|
|
{
|
|
*pPitch = PowTwoAlign((*pPitch), dccFastClearPitchAlignInPixels);
|
|
}
|
|
else
|
|
{
|
|
*pPitch += (dccFastClearPitchAlignInPixels - 1);
|
|
*pPitch /= dccFastClearPitchAlignInPixels;
|
|
*pPitch *= dccFastClearPitchAlignInPixels;
|
|
}
|
|
|
|
*pPitchAlign = dccFastClearPitchAlignInPixels;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* CiLib::HwlGetMaxAlignments
|
|
*
|
|
* @brief
|
|
* Gets maximum alignments
|
|
* @return
|
|
* ADDR_E_RETURNCODE
|
|
****************************************************************************************************
|
|
*/
|
|
ADDR_E_RETURNCODE CiLib::HwlGetMaxAlignments(
|
|
ADDR_GET_MAX_ALINGMENTS_OUTPUT* pOut ///< [out] output structure
|
|
) const
|
|
{
|
|
const UINT_32 pipes = HwlGetPipes(&m_tileTable[0].info);
|
|
|
|
// Initial size is 64 KiB for PRT.
|
|
UINT_64 maxBaseAlign = 64 * 1024;
|
|
|
|
for (UINT_32 i = 0; i < m_noOfMacroEntries; i++)
|
|
{
|
|
// The maximum tile size is 16 byte-per-pixel and either 8-sample or 8-slice.
|
|
UINT_32 tileSize = m_macroTileTable[i].tileSplitBytes;
|
|
|
|
UINT_64 baseAlign = tileSize * pipes * m_macroTileTable[i].banks *
|
|
m_macroTileTable[i].bankWidth * m_macroTileTable[i].bankHeight;
|
|
|
|
if (baseAlign > maxBaseAlign)
|
|
{
|
|
maxBaseAlign = baseAlign;
|
|
}
|
|
}
|
|
|
|
if (pOut != NULL)
|
|
{
|
|
pOut->baseAlign = maxBaseAlign;
|
|
}
|
|
|
|
return ADDR_OK;
|
|
}
|
|
|
|
} // V1
|
|
} // Addr
|