mesa/src/amd/addrlib/core/addrlib1.cpp
Nicolai Hähnle 8b110f0319 amdgpu/addrlib: Add a member "bpp" for input of method AddrConvertTileIndex and AddrConvertTileInfoToHW
When clients queries tile Info from tile index and expects accurate
tileSplit info,  bits per pixel info is required to be provided since
this is necessary for computing tileSplitBytes; otherwise Addrlib will
return value of "tileBytes" instead if bpp is 0 - which is also
current logic. If clients don't need tileSplit info, it's OK to pass
bpp with value 0.
2017-03-30 14:44:33 +02:00

3630 lines
113 KiB
C++

/*
* Copyright © 2016 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 addr1lib.cpp
* @brief Contains the implementation for the AddrLib1 base class..
***************************************************************************************************
*/
#include "addrinterface.h"
#include "addrlib1.h"
#include "addrcommon.h"
///////////////////////////////////////////////////////////////////////////////////////////////////
// Static Const Member
///////////////////////////////////////////////////////////////////////////////////////////////////
const AddrTileModeFlags AddrLib1::m_modeFlags[ADDR_TM_COUNT] =
{// T L 1 2 3 P Pr B
{1, 1, 0, 0, 0, 0, 0, 0}, // ADDR_TM_LINEAR_GENERAL
{1, 1, 0, 0, 0, 0, 0, 0}, // ADDR_TM_LINEAR_ALIGNED
{1, 0, 1, 0, 0, 0, 0, 0}, // ADDR_TM_1D_TILED_THIN1
{4, 0, 1, 0, 0, 0, 0, 0}, // ADDR_TM_1D_TILED_THICK
{1, 0, 0, 1, 0, 0, 0, 0}, // ADDR_TM_2D_TILED_THIN1
{1, 0, 0, 1, 0, 0, 0, 0}, // ADDR_TM_2D_TILED_THIN2
{1, 0, 0, 1, 0, 0, 0, 0}, // ADDR_TM_2D_TILED_THIN4
{4, 0, 0, 1, 0, 0, 0, 0}, // ADDR_TM_2D_TILED_THICK
{1, 0, 0, 1, 0, 0, 0, 1}, // ADDR_TM_2B_TILED_THIN1
{1, 0, 0, 1, 0, 0, 0, 1}, // ADDR_TM_2B_TILED_THIN2
{1, 0, 0, 1, 0, 0, 0, 1}, // ADDR_TM_2B_TILED_THIN4
{4, 0, 0, 1, 0, 0, 0, 1}, // ADDR_TM_2B_TILED_THICK
{1, 0, 0, 1, 1, 0, 0, 0}, // ADDR_TM_3D_TILED_THIN1
{4, 0, 0, 1, 1, 0, 0, 0}, // ADDR_TM_3D_TILED_THICK
{1, 0, 0, 1, 1, 0, 0, 1}, // ADDR_TM_3B_TILED_THIN1
{4, 0, 0, 1, 1, 0, 0, 1}, // ADDR_TM_3B_TILED_THICK
{8, 0, 0, 1, 0, 0, 0, 0}, // ADDR_TM_2D_TILED_XTHICK
{8, 0, 0, 1, 1, 0, 0, 0}, // ADDR_TM_3D_TILED_XTHICK
{1, 0, 0, 0, 0, 0, 0, 0}, // ADDR_TM_POWER_SAVE
{1, 0, 0, 1, 0, 1, 1, 0}, // ADDR_TM_PRT_TILED_THIN1
{1, 0, 0, 1, 0, 1, 0, 0}, // ADDR_TM_PRT_2D_TILED_THIN1
{1, 0, 0, 1, 1, 1, 0, 0}, // ADDR_TM_PRT_3D_TILED_THIN1
{4, 0, 0, 1, 0, 1, 1, 0}, // ADDR_TM_PRT_TILED_THICK
{4, 0, 0, 1, 0, 1, 0, 0}, // ADDR_TM_PRT_2D_TILED_THICK
{4, 0, 0, 1, 1, 1, 0, 0}, // ADDR_TM_PRT_3D_TILED_THICK
};
///////////////////////////////////////////////////////////////////////////////////////////////////
// Constructor/Destructor
///////////////////////////////////////////////////////////////////////////////////////////////////
/**
***************************************************************************************************
* AddrLib1::AddrLib1
*
* @brief
* Constructor for the AddrLib1 class
*
***************************************************************************************************
*/
AddrLib1::AddrLib1() :
AddrLib()
{
}
/**
***************************************************************************************************
* AddrLib1::AddrLib1
*
* @brief
* Constructor for the AddrLib1 class with hClient as parameter
*
***************************************************************************************************
*/
AddrLib1::AddrLib1(const AddrClient* pClient) :
AddrLib(pClient)
{
}
/**
***************************************************************************************************
* AddrLib1::~AddrLib1
*
* @brief
* Destructor for the AddrLib1 class
*
***************************************************************************************************
*/
AddrLib1::~AddrLib1()
{
}
/**
***************************************************************************************************
* AddrLib1::GetAddrLib1
*
* @brief
* Get AddrLib1 pointer
*
* @return
* An AddrLib1 class pointer
***************************************************************************************************
*/
AddrLib1* AddrLib1::GetAddrLib1(
ADDR_HANDLE hLib) ///< [in] handle of ADDR_HANDLE
{
AddrLib* pAddrLib = AddrLib::GetAddrLib(hLib);
if ((pAddrLib != NULL) &&
((pAddrLib->GetAddrChipFamily() == ADDR_CHIP_FAMILY_IVLD) ||
(pAddrLib->GetAddrChipFamily() > ADDR_CHIP_FAMILY_VI)))
{
// only valid and pre-VI AISC can use AddrLib1 function.
ADDR_ASSERT_ALWAYS();
hLib = NULL;
}
return static_cast<AddrLib1 *>(hLib);
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Surface Methods
///////////////////////////////////////////////////////////////////////////////////////////////////
/**
***************************************************************************************************
* AddrLib1::ComputeSurfaceInfo
*
* @brief
* Interface function stub of AddrComputeSurfaceInfo.
*
* @return
* ADDR_E_RETURNCODE
***************************************************************************************************
*/
ADDR_E_RETURNCODE AddrLib1::ComputeSurfaceInfo(
const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] input structure
ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [out] output structure
) const
{
ADDR_E_RETURNCODE returnCode = ADDR_OK;
if (GetFillSizeFieldsFlags() == TRUE)
{
if ((pIn->size != sizeof(ADDR_COMPUTE_SURFACE_INFO_INPUT)) ||
(pOut->size != sizeof(ADDR_COMPUTE_SURFACE_INFO_OUTPUT)))
{
returnCode = ADDR_PARAMSIZEMISMATCH;
}
}
// We suggest client do sanity check but a check here is also good
if (pIn->bpp > 128)
{
returnCode = ADDR_INVALIDPARAMS;
}
// Thick modes don't support multisample
if (ComputeSurfaceThickness(pIn->tileMode) > 1 && pIn->numSamples > 1)
{
returnCode = ADDR_INVALIDPARAMS;
}
if (returnCode == ADDR_OK)
{
// Get a local copy of input structure and only reference pIn for unadjusted values
ADDR_COMPUTE_SURFACE_INFO_INPUT localIn = *pIn;
ADDR_TILEINFO tileInfoNull = {0};
if (UseTileInfo())
{
// If the original input has a valid ADDR_TILEINFO pointer then copy its contents.
// Otherwise the default 0's in tileInfoNull are used.
if (pIn->pTileInfo)
{
tileInfoNull = *pIn->pTileInfo;
}
localIn.pTileInfo = &tileInfoNull;
}
localIn.numSamples = pIn->numSamples == 0 ? 1 : pIn->numSamples;
// Do mipmap check first
// If format is BCn, pre-pad dimension to power-of-two according to HWL
ComputeMipLevel(&localIn);
if (m_configFlags.checkLast2DLevel)
{
// Save this level's original height in pixels
pOut->height = pIn->height;
}
UINT_32 expandX = 1;
UINT_32 expandY = 1;
AddrElemMode elemMode;
// Save outputs that may not go through HWL
pOut->pixelBits = localIn.bpp;
pOut->numSamples = localIn.numSamples;
pOut->last2DLevel = FALSE;
pOut->tcCompatible = FALSE;
#if !ALT_TEST
if (localIn.numSamples > 1)
{
ADDR_ASSERT(localIn.mipLevel == 0);
}
#endif
if (localIn.format != ADDR_FMT_INVALID) // Set format to INVALID will skip this conversion
{
// Get compression/expansion factors and element mode
// (which indicates compression/expansion
localIn.bpp = GetElemLib()->GetBitsPerPixel(localIn.format,
&elemMode,
&expandX,
&expandY);
// Special flag for 96 bit surface. 96 (or 48 if we support) bit surface's width is
// pre-multiplied by 3 and bpp is divided by 3. So pitch alignment for linear-
// aligned does not meet 64-pixel in real. We keep special handling in hwl since hw
// restrictions are different.
// Also Mip 1+ needs an element pitch of 32 bits so we do not need this workaround
// but we use this flag to skip RestoreSurfaceInfo below
if ((elemMode == ADDR_EXPANDED) &&
(expandX > 1))
{
ADDR_ASSERT(localIn.tileMode == ADDR_TM_LINEAR_ALIGNED || localIn.height == 1);
}
GetElemLib()->AdjustSurfaceInfo(elemMode,
expandX,
expandY,
&localIn.bpp,
&localIn.basePitch,
&localIn.width,
&localIn.height);
// Overwrite these parameters if we have a valid format
}
else if (localIn.bpp != 0)
{
localIn.width = (localIn.width != 0) ? localIn.width : 1;
localIn.height = (localIn.height != 0) ? localIn.height : 1;
}
else // Rule out some invalid parameters
{
ADDR_ASSERT_ALWAYS();
returnCode = ADDR_INVALIDPARAMS;
}
// Check mipmap after surface expansion
if (returnCode == ADDR_OK)
{
returnCode = PostComputeMipLevel(&localIn, pOut);
}
if (returnCode == ADDR_OK)
{
if (UseTileIndex(localIn.tileIndex))
{
// Make sure pTileInfo is not NULL
ADDR_ASSERT(localIn.pTileInfo);
UINT_32 numSamples = GetNumFragments(localIn.numSamples, localIn.numFrags);
INT_32 macroModeIndex = TileIndexNoMacroIndex;
if (localIn.tileIndex != TileIndexLinearGeneral)
{
// Try finding a macroModeIndex
macroModeIndex = HwlComputeMacroModeIndex(localIn.tileIndex,
localIn.flags,
localIn.bpp,
numSamples,
localIn.pTileInfo,
&localIn.tileMode,
&localIn.tileType);
}
// If macroModeIndex is not needed, then call HwlSetupTileCfg to get tile info
if (macroModeIndex == TileIndexNoMacroIndex)
{
returnCode = HwlSetupTileCfg(localIn.bpp,
localIn.tileIndex, macroModeIndex,
localIn.pTileInfo,
&localIn.tileMode, &localIn.tileType);
}
// If macroModeIndex is invalid, then assert this is not macro tiled
else if (macroModeIndex == TileIndexInvalid)
{
ADDR_ASSERT(!IsMacroTiled(localIn.tileMode));
}
pOut->macroModeIndex = macroModeIndex;
}
}
if (returnCode == ADDR_OK)
{
AddrTileMode tileMode = localIn.tileMode;
AddrTileType tileType = localIn.tileType;
// HWL layer may override tile mode if necessary
if (HwlOverrideTileMode(&localIn, &tileMode, &tileType))
{
localIn.tileMode = tileMode;
localIn.tileType = tileType;
}
// Optimize tile mode if possible
if (OptimizeTileMode(&localIn, &tileMode))
{
localIn.tileMode = tileMode;
}
}
// Call main function to compute surface info
if (returnCode == ADDR_OK)
{
returnCode = HwlComputeSurfaceInfo(&localIn, pOut);
}
if (returnCode == ADDR_OK)
{
// Since bpp might be changed we just pass it through
pOut->bpp = localIn.bpp;
// Also original width/height/bpp
pOut->pixelPitch = pOut->pitch;
pOut->pixelHeight = pOut->height;
#if DEBUG
if (localIn.flags.display)
{
ADDR_ASSERT((pOut->pitchAlign % 32) == 0);
}
#endif //DEBUG
if (localIn.format != ADDR_FMT_INVALID)
{
//
// 96 bits surface of level 1+ requires element pitch of 32 bits instead
// In hwl function we skip multiplication of 3 then we should skip division of 3
// We keep pitch that represents 32 bit element instead of 96 bits since we
// will get an odd number if divided by 3.
//
if (!((expandX == 3) && (localIn.mipLevel > 0)))
{
GetElemLib()->RestoreSurfaceInfo(elemMode,
expandX,
expandY,
&localIn.bpp,
&pOut->pixelPitch,
&pOut->pixelHeight);
}
}
if (localIn.flags.qbStereo)
{
if (pOut->pStereoInfo)
{
ComputeQbStereoInfo(pOut);
}
}
if (localIn.flags.volume) // For volume sliceSize equals to all z-slices
{
pOut->sliceSize = pOut->surfSize;
}
else // For array: sliceSize is likely to have slice-padding (the last one)
{
pOut->sliceSize = pOut->surfSize / pOut->depth;
// array or cubemap
if (pIn->numSlices > 1)
{
// If this is the last slice then add the padding size to this slice
if (pIn->slice == (pIn->numSlices - 1))
{
pOut->sliceSize += pOut->sliceSize * (pOut->depth - pIn->numSlices);
}
else if (m_configFlags.checkLast2DLevel)
{
// Reset last2DLevel flag if this is not the last array slice
pOut->last2DLevel = FALSE;
}
}
}
pOut->pitchTileMax = pOut->pitch / 8 - 1;
pOut->heightTileMax = pOut->height / 8 - 1;
pOut->sliceTileMax = pOut->pitch * pOut->height / 64 - 1;
}
}
return returnCode;
}
/**
***************************************************************************************************
* AddrLib1::ComputeSurfaceInfo
*
* @brief
* Interface function stub of AddrComputeSurfaceInfo.
*
* @return
* ADDR_E_RETURNCODE
***************************************************************************************************
*/
ADDR_E_RETURNCODE AddrLib1::ComputeSurfaceAddrFromCoord(
const ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn, ///< [in] input structure
ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT* pOut ///< [out] output structure
) const
{
ADDR_E_RETURNCODE returnCode = ADDR_OK;
if (GetFillSizeFieldsFlags() == TRUE)
{
if ((pIn->size != sizeof(ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT)) ||
(pOut->size != sizeof(ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT)))
{
returnCode = ADDR_PARAMSIZEMISMATCH;
}
}
if (returnCode == ADDR_OK)
{
ADDR_TILEINFO tileInfoNull;
ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT input;
if (UseTileIndex(pIn->tileIndex))
{
input = *pIn;
// Use temp tile info for calcalation
input.pTileInfo = &tileInfoNull;
const ADDR_SURFACE_FLAGS flags = {{0}};
UINT_32 numSamples = GetNumFragments(pIn->numSamples, pIn->numFrags);
// Try finding a macroModeIndex
INT_32 macroModeIndex = HwlComputeMacroModeIndex(input.tileIndex,
flags,
input.bpp,
numSamples,
input.pTileInfo,
&input.tileMode,
&input.tileType);
// If macroModeIndex is not needed, then call HwlSetupTileCfg to get tile info
if (macroModeIndex == TileIndexNoMacroIndex)
{
returnCode = HwlSetupTileCfg(input.bpp, input.tileIndex, macroModeIndex,
input.pTileInfo, &input.tileMode, &input.tileType);
}
// If macroModeIndex is invalid, then assert this is not macro tiled
else if (macroModeIndex == TileIndexInvalid)
{
ADDR_ASSERT(!IsMacroTiled(input.tileMode));
}
// Change the input structure
pIn = &input;
}
if (returnCode == ADDR_OK)
{
returnCode = HwlComputeSurfaceAddrFromCoord(pIn, pOut);
if (returnCode == ADDR_OK)
{
pOut->prtBlockIndex = static_cast<UINT_32>(pOut->addr / (64 * 1024));
}
}
}
return returnCode;
}
/**
***************************************************************************************************
* AddrLib1::ComputeSurfaceCoordFromAddr
*
* @brief
* Interface function stub of ComputeSurfaceCoordFromAddr.
*
* @return
* ADDR_E_RETURNCODE
***************************************************************************************************
*/
ADDR_E_RETURNCODE AddrLib1::ComputeSurfaceCoordFromAddr(
const ADDR_COMPUTE_SURFACE_COORDFROMADDR_INPUT* pIn, ///< [in] input structure
ADDR_COMPUTE_SURFACE_COORDFROMADDR_OUTPUT* pOut ///< [out] output structure
) const
{
ADDR_E_RETURNCODE returnCode = ADDR_OK;
if (GetFillSizeFieldsFlags() == TRUE)
{
if ((pIn->size != sizeof(ADDR_COMPUTE_SURFACE_COORDFROMADDR_INPUT)) ||
(pOut->size != sizeof(ADDR_COMPUTE_SURFACE_COORDFROMADDR_OUTPUT)))
{
returnCode = ADDR_PARAMSIZEMISMATCH;
}
}
if (returnCode == ADDR_OK)
{
ADDR_TILEINFO tileInfoNull;
ADDR_COMPUTE_SURFACE_COORDFROMADDR_INPUT input;
if (UseTileIndex(pIn->tileIndex))
{
input = *pIn;
// Use temp tile info for calcalation
input.pTileInfo = &tileInfoNull;
const ADDR_SURFACE_FLAGS flags = {{0}};
UINT_32 numSamples = GetNumFragments(pIn->numSamples, pIn->numFrags);
// Try finding a macroModeIndex
INT_32 macroModeIndex = HwlComputeMacroModeIndex(input.tileIndex,
flags,
input.bpp,
numSamples,
input.pTileInfo,
&input.tileMode,
&input.tileType);
// If macroModeIndex is not needed, then call HwlSetupTileCfg to get tile info
if (macroModeIndex == TileIndexNoMacroIndex)
{
returnCode = HwlSetupTileCfg(input.bpp, input.tileIndex, macroModeIndex,
input.pTileInfo, &input.tileMode, &input.tileType);
}
// If macroModeIndex is invalid, then assert this is not macro tiled
else if (macroModeIndex == TileIndexInvalid)
{
ADDR_ASSERT(!IsMacroTiled(input.tileMode));
}
// Change the input structure
pIn = &input;
}
if (returnCode == ADDR_OK)
{
returnCode = HwlComputeSurfaceCoordFromAddr(pIn, pOut);
}
}
return returnCode;
}
/**
***************************************************************************************************
* AddrLib1::ComputeSliceTileSwizzle
*
* @brief
* Interface function stub of ComputeSliceTileSwizzle.
*
* @return
* ADDR_E_RETURNCODE
***************************************************************************************************
*/
ADDR_E_RETURNCODE AddrLib1::ComputeSliceTileSwizzle(
const ADDR_COMPUTE_SLICESWIZZLE_INPUT* pIn, ///< [in] input structure
ADDR_COMPUTE_SLICESWIZZLE_OUTPUT* pOut ///< [out] output structure
) const
{
ADDR_E_RETURNCODE returnCode = ADDR_OK;
if (GetFillSizeFieldsFlags() == TRUE)
{
if ((pIn->size != sizeof(ADDR_COMPUTE_SLICESWIZZLE_INPUT)) ||
(pOut->size != sizeof(ADDR_COMPUTE_SLICESWIZZLE_OUTPUT)))
{
returnCode = ADDR_PARAMSIZEMISMATCH;
}
}
if (returnCode == ADDR_OK)
{
ADDR_TILEINFO tileInfoNull;
ADDR_COMPUTE_SLICESWIZZLE_INPUT input;
if (UseTileIndex(pIn->tileIndex))
{
input = *pIn;
// Use temp tile info for calcalation
input.pTileInfo = &tileInfoNull;
returnCode = HwlSetupTileCfg(0, input.tileIndex, input.macroModeIndex,
input.pTileInfo, &input.tileMode);
// Change the input structure
pIn = &input;
}
if (returnCode == ADDR_OK)
{
returnCode = HwlComputeSliceTileSwizzle(pIn, pOut);
}
}
return returnCode;
}
/**
***************************************************************************************************
* AddrLib1::ExtractBankPipeSwizzle
*
* @brief
* Interface function stub of AddrExtractBankPipeSwizzle.
*
* @return
* ADDR_E_RETURNCODE
***************************************************************************************************
*/
ADDR_E_RETURNCODE AddrLib1::ExtractBankPipeSwizzle(
const ADDR_EXTRACT_BANKPIPE_SWIZZLE_INPUT* pIn, ///< [in] input structure
ADDR_EXTRACT_BANKPIPE_SWIZZLE_OUTPUT* pOut ///< [out] output structure
) const
{
ADDR_E_RETURNCODE returnCode = ADDR_OK;
if (GetFillSizeFieldsFlags() == TRUE)
{
if ((pIn->size != sizeof(ADDR_EXTRACT_BANKPIPE_SWIZZLE_INPUT)) ||
(pOut->size != sizeof(ADDR_EXTRACT_BANKPIPE_SWIZZLE_OUTPUT)))
{
returnCode = ADDR_PARAMSIZEMISMATCH;
}
}
if (returnCode == ADDR_OK)
{
ADDR_TILEINFO tileInfoNull;
ADDR_EXTRACT_BANKPIPE_SWIZZLE_INPUT input;
if (UseTileIndex(pIn->tileIndex))
{
input = *pIn;
// Use temp tile info for calcalation
input.pTileInfo = &tileInfoNull;
returnCode = HwlSetupTileCfg(0, input.tileIndex, input.macroModeIndex, input.pTileInfo);
// Change the input structure
pIn = &input;
}
if (returnCode == ADDR_OK)
{
returnCode = HwlExtractBankPipeSwizzle(pIn, pOut);
}
}
return returnCode;
}
/**
***************************************************************************************************
* AddrLib1::CombineBankPipeSwizzle
*
* @brief
* Interface function stub of AddrCombineBankPipeSwizzle.
*
* @return
* ADDR_E_RETURNCODE
***************************************************************************************************
*/
ADDR_E_RETURNCODE AddrLib1::CombineBankPipeSwizzle(
const ADDR_COMBINE_BANKPIPE_SWIZZLE_INPUT* pIn, ///< [in] input structure
ADDR_COMBINE_BANKPIPE_SWIZZLE_OUTPUT* pOut ///< [out] output structure
) const
{
ADDR_E_RETURNCODE returnCode = ADDR_OK;
if (GetFillSizeFieldsFlags() == TRUE)
{
if ((pIn->size != sizeof(ADDR_COMPUTE_FMASK_INFO_INPUT)) ||
(pOut->size != sizeof(ADDR_COMPUTE_FMASK_INFO_OUTPUT)))
{
returnCode = ADDR_PARAMSIZEMISMATCH;
}
}
if (returnCode == ADDR_OK)
{
ADDR_TILEINFO tileInfoNull;
ADDR_COMBINE_BANKPIPE_SWIZZLE_INPUT input;
if (UseTileIndex(pIn->tileIndex))
{
input = *pIn;
// Use temp tile info for calcalation
input.pTileInfo = &tileInfoNull;
returnCode = HwlSetupTileCfg(0, input.tileIndex, input.macroModeIndex, input.pTileInfo);
// Change the input structure
pIn = &input;
}
if (returnCode == ADDR_OK)
{
returnCode = HwlCombineBankPipeSwizzle(pIn->bankSwizzle,
pIn->pipeSwizzle,
pIn->pTileInfo,
pIn->baseAddr,
&pOut->tileSwizzle);
}
}
return returnCode;
}
/**
***************************************************************************************************
* AddrLib1::ComputeBaseSwizzle
*
* @brief
* Interface function stub of AddrCompueBaseSwizzle.
* @return
* ADDR_E_RETURNCODE
***************************************************************************************************
*/
ADDR_E_RETURNCODE AddrLib1::ComputeBaseSwizzle(
const ADDR_COMPUTE_BASE_SWIZZLE_INPUT* pIn,
ADDR_COMPUTE_BASE_SWIZZLE_OUTPUT* pOut) const
{
ADDR_E_RETURNCODE returnCode = ADDR_OK;
if (GetFillSizeFieldsFlags() == TRUE)
{
if ((pIn->size != sizeof(ADDR_COMPUTE_BASE_SWIZZLE_INPUT)) ||
(pOut->size != sizeof(ADDR_COMPUTE_BASE_SWIZZLE_OUTPUT)))
{
returnCode = ADDR_PARAMSIZEMISMATCH;
}
}
if (returnCode == ADDR_OK)
{
ADDR_TILEINFO tileInfoNull;
ADDR_COMPUTE_BASE_SWIZZLE_INPUT input;
if (UseTileIndex(pIn->tileIndex))
{
input = *pIn;
// Use temp tile info for calcalation
input.pTileInfo = &tileInfoNull;
returnCode = HwlSetupTileCfg(0, input.tileIndex, input.macroModeIndex, input.pTileInfo);
// Change the input structure
pIn = &input;
}
if (returnCode == ADDR_OK)
{
if (IsMacroTiled(pIn->tileMode))
{
returnCode = HwlComputeBaseSwizzle(pIn, pOut);
}
else
{
pOut->tileSwizzle = 0;
}
}
}
return returnCode;
}
/**
***************************************************************************************************
* AddrLib1::ComputeFmaskInfo
*
* @brief
* Interface function stub of ComputeFmaskInfo.
*
* @return
* ADDR_E_RETURNCODE
***************************************************************************************************
*/
ADDR_E_RETURNCODE AddrLib1::ComputeFmaskInfo(
const ADDR_COMPUTE_FMASK_INFO_INPUT* pIn, ///< [in] input structure
ADDR_COMPUTE_FMASK_INFO_OUTPUT* pOut ///< [out] output structure
)
{
ADDR_E_RETURNCODE returnCode = ADDR_OK;
if (GetFillSizeFieldsFlags() == TRUE)
{
if ((pIn->size != sizeof(ADDR_COMPUTE_FMASK_INFO_INPUT)) ||
(pOut->size != sizeof(ADDR_COMPUTE_FMASK_INFO_OUTPUT)))
{
returnCode = ADDR_PARAMSIZEMISMATCH;
}
}
// No thick MSAA
if (ComputeSurfaceThickness(pIn->tileMode) > 1)
{
returnCode = ADDR_INVALIDPARAMS;
}
if (returnCode == ADDR_OK)
{
ADDR_TILEINFO tileInfoNull;
ADDR_COMPUTE_FMASK_INFO_INPUT input;
if (UseTileIndex(pIn->tileIndex))
{
input = *pIn;
if (pOut->pTileInfo)
{
// Use temp tile info for calcalation
input.pTileInfo = pOut->pTileInfo;
}
else
{
input.pTileInfo = &tileInfoNull;
}
ADDR_SURFACE_FLAGS flags = {{0}};
flags.fmask = 1;
// Try finding a macroModeIndex
INT_32 macroModeIndex = HwlComputeMacroModeIndex(pIn->tileIndex,
flags,
HwlComputeFmaskBits(pIn, NULL),
pIn->numSamples,
input.pTileInfo,
&input.tileMode);
// If macroModeIndex is not needed, then call HwlSetupTileCfg to get tile info
if (macroModeIndex == TileIndexNoMacroIndex)
{
returnCode = HwlSetupTileCfg(0, input.tileIndex, macroModeIndex,
input.pTileInfo, &input.tileMode);
}
ADDR_ASSERT(macroModeIndex != TileIndexInvalid);
// Change the input structure
pIn = &input;
}
if (returnCode == ADDR_OK)
{
if (pIn->numSamples > 1)
{
returnCode = HwlComputeFmaskInfo(pIn, pOut);
}
else
{
memset(pOut, 0, sizeof(ADDR_COMPUTE_FMASK_INFO_OUTPUT));
returnCode = ADDR_INVALIDPARAMS;
}
}
}
return returnCode;
}
/**
***************************************************************************************************
* AddrLib1::ComputeFmaskAddrFromCoord
*
* @brief
* Interface function stub of ComputeFmaskAddrFromCoord.
*
* @return
* ADDR_E_RETURNCODE
***************************************************************************************************
*/
ADDR_E_RETURNCODE AddrLib1::ComputeFmaskAddrFromCoord(
const ADDR_COMPUTE_FMASK_ADDRFROMCOORD_INPUT* pIn, ///< [in] input structure
ADDR_COMPUTE_FMASK_ADDRFROMCOORD_OUTPUT* pOut ///< [out] output structure
) const
{
ADDR_E_RETURNCODE returnCode = ADDR_OK;
if (GetFillSizeFieldsFlags() == TRUE)
{
if ((pIn->size != sizeof(ADDR_COMPUTE_FMASK_ADDRFROMCOORD_INPUT)) ||
(pOut->size != sizeof(ADDR_COMPUTE_FMASK_ADDRFROMCOORD_OUTPUT)))
{
returnCode = ADDR_PARAMSIZEMISMATCH;
}
}
if (returnCode == ADDR_OK)
{
ADDR_ASSERT(pIn->numSamples > 1);
if (pIn->numSamples > 1)
{
returnCode = HwlComputeFmaskAddrFromCoord(pIn, pOut);
}
else
{
returnCode = ADDR_INVALIDPARAMS;
}
}
return returnCode;
}
/**
***************************************************************************************************
* AddrLib1::ComputeFmaskCoordFromAddr
*
* @brief
* Interface function stub of ComputeFmaskAddrFromCoord.
*
* @return
* ADDR_E_RETURNCODE
***************************************************************************************************
*/
ADDR_E_RETURNCODE AddrLib1::ComputeFmaskCoordFromAddr(
const ADDR_COMPUTE_FMASK_COORDFROMADDR_INPUT* pIn, ///< [in] input structure
ADDR_COMPUTE_FMASK_COORDFROMADDR_OUTPUT* pOut ///< [out] output structure
) const
{
ADDR_E_RETURNCODE returnCode = ADDR_OK;
if (GetFillSizeFieldsFlags() == TRUE)
{
if ((pIn->size != sizeof(ADDR_COMPUTE_FMASK_COORDFROMADDR_INPUT)) ||
(pOut->size != sizeof(ADDR_COMPUTE_FMASK_COORDFROMADDR_OUTPUT)))
{
returnCode = ADDR_PARAMSIZEMISMATCH;
}
}
if (returnCode == ADDR_OK)
{
ADDR_ASSERT(pIn->numSamples > 1);
if (pIn->numSamples > 1)
{
returnCode = HwlComputeFmaskCoordFromAddr(pIn, pOut);
}
else
{
returnCode = ADDR_INVALIDPARAMS;
}
}
return returnCode;
}
/**
***************************************************************************************************
* AddrLib1::ConvertTileInfoToHW
*
* @brief
* Convert tile info from real value to HW register value in HW layer
*
* @return
* ADDR_E_RETURNCODE
***************************************************************************************************
*/
ADDR_E_RETURNCODE AddrLib1::ConvertTileInfoToHW(
const ADDR_CONVERT_TILEINFOTOHW_INPUT* pIn, ///< [in] input structure
ADDR_CONVERT_TILEINFOTOHW_OUTPUT* pOut ///< [out] output structure
) const
{
ADDR_E_RETURNCODE returnCode = ADDR_OK;
if (GetFillSizeFieldsFlags() == TRUE)
{
if ((pIn->size != sizeof(ADDR_CONVERT_TILEINFOTOHW_INPUT)) ||
(pOut->size != sizeof(ADDR_CONVERT_TILEINFOTOHW_OUTPUT)))
{
returnCode = ADDR_PARAMSIZEMISMATCH;
}
}
if (returnCode == ADDR_OK)
{
ADDR_TILEINFO tileInfoNull;
ADDR_CONVERT_TILEINFOTOHW_INPUT input;
// if pIn->reverse is TRUE, indices are ignored
if (pIn->reverse == FALSE && UseTileIndex(pIn->tileIndex))
{
input = *pIn;
input.pTileInfo = &tileInfoNull;
returnCode = HwlSetupTileCfg(input.bpp, input.tileIndex,
input.macroModeIndex, input.pTileInfo);
pIn = &input;
}
if (returnCode == ADDR_OK)
{
returnCode = HwlConvertTileInfoToHW(pIn, pOut);
}
}
return returnCode;
}
/**
***************************************************************************************************
* AddrLib1::ConvertTileIndex
*
* @brief
* Convert tile index to tile mode/type/info
*
* @return
* ADDR_E_RETURNCODE
***************************************************************************************************
*/
ADDR_E_RETURNCODE AddrLib1::ConvertTileIndex(
const ADDR_CONVERT_TILEINDEX_INPUT* pIn, ///< [in] input structure
ADDR_CONVERT_TILEINDEX_OUTPUT* pOut ///< [out] output structure
) const
{
ADDR_E_RETURNCODE returnCode = ADDR_OK;
if (GetFillSizeFieldsFlags() == TRUE)
{
if ((pIn->size != sizeof(ADDR_CONVERT_TILEINDEX_INPUT)) ||
(pOut->size != sizeof(ADDR_CONVERT_TILEINDEX_OUTPUT)))
{
returnCode = ADDR_PARAMSIZEMISMATCH;
}
}
if (returnCode == ADDR_OK)
{
returnCode = HwlSetupTileCfg(pIn->bpp, pIn->tileIndex, pIn->macroModeIndex,
pOut->pTileInfo, &pOut->tileMode, &pOut->tileType);
if (returnCode == ADDR_OK && pIn->tileInfoHw)
{
ADDR_CONVERT_TILEINFOTOHW_INPUT hwInput = {0};
ADDR_CONVERT_TILEINFOTOHW_OUTPUT hwOutput = {0};
hwInput.pTileInfo = pOut->pTileInfo;
hwInput.tileIndex = -1;
hwOutput.pTileInfo = pOut->pTileInfo;
returnCode = HwlConvertTileInfoToHW(&hwInput, &hwOutput);
}
}
return returnCode;
}
/**
***************************************************************************************************
* AddrLib1::ConvertTileIndex1
*
* @brief
* Convert tile index to tile mode/type/info
*
* @return
* ADDR_E_RETURNCODE
***************************************************************************************************
*/
ADDR_E_RETURNCODE AddrLib1::ConvertTileIndex1(
const ADDR_CONVERT_TILEINDEX1_INPUT* pIn, ///< [in] input structure
ADDR_CONVERT_TILEINDEX_OUTPUT* pOut ///< [out] output structure
) const
{
ADDR_E_RETURNCODE returnCode = ADDR_OK;
if (GetFillSizeFieldsFlags() == TRUE)
{
if ((pIn->size != sizeof(ADDR_CONVERT_TILEINDEX1_INPUT)) ||
(pOut->size != sizeof(ADDR_CONVERT_TILEINDEX_OUTPUT)))
{
returnCode = ADDR_PARAMSIZEMISMATCH;
}
}
if (returnCode == ADDR_OK)
{
ADDR_SURFACE_FLAGS flags = {{0}};
HwlComputeMacroModeIndex(pIn->tileIndex, flags, pIn->bpp, pIn->numSamples,
pOut->pTileInfo, &pOut->tileMode, &pOut->tileType);
if (pIn->tileInfoHw)
{
ADDR_CONVERT_TILEINFOTOHW_INPUT hwInput = {0};
ADDR_CONVERT_TILEINFOTOHW_OUTPUT hwOutput = {0};
hwInput.pTileInfo = pOut->pTileInfo;
hwInput.tileIndex = -1;
hwOutput.pTileInfo = pOut->pTileInfo;
returnCode = HwlConvertTileInfoToHW(&hwInput, &hwOutput);
}
}
return returnCode;
}
/**
***************************************************************************************************
* AddrLib1::GetTileIndex
*
* @brief
* Get tile index from tile mode/type/info
*
* @return
* ADDR_E_RETURNCODE
***************************************************************************************************
*/
ADDR_E_RETURNCODE AddrLib1::GetTileIndex(
const ADDR_GET_TILEINDEX_INPUT* pIn, ///< [in] input structure
ADDR_GET_TILEINDEX_OUTPUT* pOut ///< [out] output structure
) const
{
ADDR_E_RETURNCODE returnCode = ADDR_OK;
if (GetFillSizeFieldsFlags() == TRUE)
{
if ((pIn->size != sizeof(ADDR_GET_TILEINDEX_INPUT)) ||
(pOut->size != sizeof(ADDR_GET_TILEINDEX_OUTPUT)))
{
returnCode = ADDR_PARAMSIZEMISMATCH;
}
}
if (returnCode == ADDR_OK)
{
returnCode = HwlGetTileIndex(pIn, pOut);
}
return returnCode;
}
/**
***************************************************************************************************
* AddrLib1::ComputeSurfaceThickness
*
* @brief
* Compute surface thickness
*
* @return
* Surface thickness
***************************************************************************************************
*/
UINT_32 AddrLib1::ComputeSurfaceThickness(
AddrTileMode tileMode) ///< [in] tile mode
{
return m_modeFlags[tileMode].thickness;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// CMASK/HTILE
///////////////////////////////////////////////////////////////////////////////////////////////////
/**
***************************************************************************************************
* AddrLib1::ComputeHtileInfo
*
* @brief
* Interface function stub of AddrComputeHtilenfo
*
* @return
* ADDR_E_RETURNCODE
***************************************************************************************************
*/
ADDR_E_RETURNCODE AddrLib1::ComputeHtileInfo(
const ADDR_COMPUTE_HTILE_INFO_INPUT* pIn, ///< [in] input structure
ADDR_COMPUTE_HTILE_INFO_OUTPUT* pOut ///< [out] output structure
) const
{
ADDR_E_RETURNCODE returnCode = ADDR_OK;
BOOL_32 isWidth8 = (pIn->blockWidth == 8) ? TRUE : FALSE;
BOOL_32 isHeight8 = (pIn->blockHeight == 8) ? TRUE : FALSE;
if (GetFillSizeFieldsFlags() == TRUE)
{
if ((pIn->size != sizeof(ADDR_COMPUTE_HTILE_INFO_INPUT)) ||
(pOut->size != sizeof(ADDR_COMPUTE_HTILE_INFO_OUTPUT)))
{
returnCode = ADDR_PARAMSIZEMISMATCH;
}
}
if (returnCode == ADDR_OK)
{
ADDR_TILEINFO tileInfoNull;
ADDR_COMPUTE_HTILE_INFO_INPUT input;
if (UseTileIndex(pIn->tileIndex))
{
input = *pIn;
// Use temp tile info for calcalation
input.pTileInfo = &tileInfoNull;
returnCode = HwlSetupTileCfg(0, input.tileIndex, input.macroModeIndex, input.pTileInfo);
// Change the input structure
pIn = &input;
}
if (returnCode == ADDR_OK)
{
pOut->bpp = ComputeHtileInfo(pIn->flags,
pIn->pitch,
pIn->height,
pIn->numSlices,
pIn->isLinear,
isWidth8,
isHeight8,
pIn->pTileInfo,
&pOut->pitch,
&pOut->height,
&pOut->htileBytes,
&pOut->macroWidth,
&pOut->macroHeight,
&pOut->sliceSize,
&pOut->baseAlign);
}
}
return returnCode;
}
/**
***************************************************************************************************
* AddrLib1::ComputeCmaskInfo
*
* @brief
* Interface function stub of AddrComputeCmaskInfo
*
* @return
* ADDR_E_RETURNCODE
***************************************************************************************************
*/
ADDR_E_RETURNCODE AddrLib1::ComputeCmaskInfo(
const ADDR_COMPUTE_CMASK_INFO_INPUT* pIn, ///< [in] input structure
ADDR_COMPUTE_CMASK_INFO_OUTPUT* pOut ///< [out] output structure
) const
{
ADDR_E_RETURNCODE returnCode = ADDR_OK;
if (GetFillSizeFieldsFlags() == TRUE)
{
if ((pIn->size != sizeof(ADDR_COMPUTE_CMASK_INFO_INPUT)) ||
(pOut->size != sizeof(ADDR_COMPUTE_CMASK_INFO_OUTPUT)))
{
returnCode = ADDR_PARAMSIZEMISMATCH;
}
}
if (returnCode == ADDR_OK)
{
ADDR_TILEINFO tileInfoNull;
ADDR_COMPUTE_CMASK_INFO_INPUT input;
if (UseTileIndex(pIn->tileIndex))
{
input = *pIn;
// Use temp tile info for calcalation
input.pTileInfo = &tileInfoNull;
returnCode = HwlSetupTileCfg(0, input.tileIndex, input.macroModeIndex, input.pTileInfo);
// Change the input structure
pIn = &input;
}
if (returnCode == ADDR_OK)
{
returnCode = ComputeCmaskInfo(pIn->flags,
pIn->pitch,
pIn->height,
pIn->numSlices,
pIn->isLinear,
pIn->pTileInfo,
&pOut->pitch,
&pOut->height,
&pOut->cmaskBytes,
&pOut->macroWidth,
&pOut->macroHeight,
&pOut->sliceSize,
&pOut->baseAlign,
&pOut->blockMax);
}
}
return returnCode;
}
/**
***************************************************************************************************
* AddrLib1::ComputeDccInfo
*
* @brief
* Interface function to compute DCC key info
*
* @return
* return code of HwlComputeDccInfo
***************************************************************************************************
*/
ADDR_E_RETURNCODE AddrLib1::ComputeDccInfo(
const ADDR_COMPUTE_DCCINFO_INPUT* pIn, ///< [in] input structure
ADDR_COMPUTE_DCCINFO_OUTPUT* pOut ///< [out] output structure
) const
{
ADDR_E_RETURNCODE ret = ADDR_OK;
if (GetFillSizeFieldsFlags() == TRUE)
{
if ((pIn->size != sizeof(ADDR_COMPUTE_DCCINFO_INPUT)) ||
(pOut->size != sizeof(ADDR_COMPUTE_DCCINFO_OUTPUT)))
{
ret = ADDR_PARAMSIZEMISMATCH;
}
}
if (ret == ADDR_OK)
{
ADDR_COMPUTE_DCCINFO_INPUT input;
if (UseTileIndex(pIn->tileIndex))
{
input = *pIn;
ret = HwlSetupTileCfg(input.bpp, input.tileIndex, input.macroModeIndex,
&input.tileInfo, &input.tileMode);
pIn = &input;
}
if (ADDR_OK == ret)
{
ret = HwlComputeDccInfo(pIn, pOut);
}
}
return ret;
}
/**
***************************************************************************************************
* AddrLib1::ComputeHtileAddrFromCoord
*
* @brief
* Interface function stub of AddrComputeHtileAddrFromCoord
*
* @return
* ADDR_E_RETURNCODE
***************************************************************************************************
*/
ADDR_E_RETURNCODE AddrLib1::ComputeHtileAddrFromCoord(
const ADDR_COMPUTE_HTILE_ADDRFROMCOORD_INPUT* pIn, ///< [in] input structure
ADDR_COMPUTE_HTILE_ADDRFROMCOORD_OUTPUT* pOut ///< [out] output structure
) const
{
ADDR_E_RETURNCODE returnCode = ADDR_OK;
BOOL_32 isWidth8 = (pIn->blockWidth == 8) ? TRUE : FALSE;
BOOL_32 isHeight8 = (pIn->blockHeight == 8) ? TRUE : FALSE;
if (GetFillSizeFieldsFlags() == TRUE)
{
if ((pIn->size != sizeof(ADDR_COMPUTE_HTILE_ADDRFROMCOORD_INPUT)) ||
(pOut->size != sizeof(ADDR_COMPUTE_HTILE_ADDRFROMCOORD_OUTPUT)))
{
returnCode = ADDR_PARAMSIZEMISMATCH;
}
}
if (returnCode == ADDR_OK)
{
ADDR_TILEINFO tileInfoNull;
ADDR_COMPUTE_HTILE_ADDRFROMCOORD_INPUT input;
if (UseTileIndex(pIn->tileIndex))
{
input = *pIn;
// Use temp tile info for calcalation
input.pTileInfo = &tileInfoNull;
returnCode = HwlSetupTileCfg(0, input.tileIndex, input.macroModeIndex, input.pTileInfo);
// Change the input structure
pIn = &input;
}
if (returnCode == ADDR_OK)
{
pOut->addr = HwlComputeXmaskAddrFromCoord(pIn->pitch,
pIn->height,
pIn->x,
pIn->y,
pIn->slice,
pIn->numSlices,
1,
pIn->isLinear,
isWidth8,
isHeight8,
pIn->pTileInfo,
&pOut->bitPosition);
}
}
return returnCode;
}
/**
***************************************************************************************************
* AddrLib1::ComputeHtileCoordFromAddr
*
* @brief
* Interface function stub of AddrComputeHtileCoordFromAddr
*
* @return
* ADDR_E_RETURNCODE
***************************************************************************************************
*/
ADDR_E_RETURNCODE AddrLib1::ComputeHtileCoordFromAddr(
const ADDR_COMPUTE_HTILE_COORDFROMADDR_INPUT* pIn, ///< [in] input structure
ADDR_COMPUTE_HTILE_COORDFROMADDR_OUTPUT* pOut ///< [out] output structure
) const
{
ADDR_E_RETURNCODE returnCode = ADDR_OK;
BOOL_32 isWidth8 = (pIn->blockWidth == 8) ? TRUE : FALSE;
BOOL_32 isHeight8 = (pIn->blockHeight == 8) ? TRUE : FALSE;
if (GetFillSizeFieldsFlags() == TRUE)
{
if ((pIn->size != sizeof(ADDR_COMPUTE_HTILE_COORDFROMADDR_INPUT)) ||
(pOut->size != sizeof(ADDR_COMPUTE_HTILE_COORDFROMADDR_OUTPUT)))
{
returnCode = ADDR_PARAMSIZEMISMATCH;
}
}
if (returnCode == ADDR_OK)
{
ADDR_TILEINFO tileInfoNull;
ADDR_COMPUTE_HTILE_COORDFROMADDR_INPUT input;
if (UseTileIndex(pIn->tileIndex))
{
input = *pIn;
// Use temp tile info for calcalation
input.pTileInfo = &tileInfoNull;
returnCode = HwlSetupTileCfg(0, input.tileIndex, input.macroModeIndex, input.pTileInfo);
// Change the input structure
pIn = &input;
}
if (returnCode == ADDR_OK)
{
HwlComputeXmaskCoordFromAddr(pIn->addr,
pIn->bitPosition,
pIn->pitch,
pIn->height,
pIn->numSlices,
1,
pIn->isLinear,
isWidth8,
isHeight8,
pIn->pTileInfo,
&pOut->x,
&pOut->y,
&pOut->slice);
}
}
return returnCode;
}
/**
***************************************************************************************************
* AddrLib1::ComputeCmaskAddrFromCoord
*
* @brief
* Interface function stub of AddrComputeCmaskAddrFromCoord
*
* @return
* ADDR_E_RETURNCODE
***************************************************************************************************
*/
ADDR_E_RETURNCODE AddrLib1::ComputeCmaskAddrFromCoord(
const ADDR_COMPUTE_CMASK_ADDRFROMCOORD_INPUT* pIn, ///< [in] input structure
ADDR_COMPUTE_CMASK_ADDRFROMCOORD_OUTPUT* pOut ///< [out] output structure
) const
{
ADDR_E_RETURNCODE returnCode = ADDR_OK;
if (GetFillSizeFieldsFlags() == TRUE)
{
if ((pIn->size != sizeof(ADDR_COMPUTE_CMASK_ADDRFROMCOORD_INPUT)) ||
(pOut->size != sizeof(ADDR_COMPUTE_CMASK_ADDRFROMCOORD_OUTPUT)))
{
returnCode = ADDR_PARAMSIZEMISMATCH;
}
}
if (returnCode == ADDR_OK)
{
ADDR_TILEINFO tileInfoNull;
ADDR_COMPUTE_CMASK_ADDRFROMCOORD_INPUT input;
if (UseTileIndex(pIn->tileIndex))
{
input = *pIn;
// Use temp tile info for calcalation
input.pTileInfo = &tileInfoNull;
returnCode = HwlSetupTileCfg(0, input.tileIndex, input.macroModeIndex, input.pTileInfo);
// Change the input structure
pIn = &input;
}
if (returnCode == ADDR_OK)
{
if (pIn->flags.tcCompatible == TRUE)
{
returnCode = HwlComputeCmaskAddrFromCoord(pIn, pOut);
}
else
{
pOut->addr = HwlComputeXmaskAddrFromCoord(pIn->pitch,
pIn->height,
pIn->x,
pIn->y,
pIn->slice,
pIn->numSlices,
2,
pIn->isLinear,
FALSE, //this is cmask, isWidth8 is not needed
FALSE, //this is cmask, isHeight8 is not needed
pIn->pTileInfo,
&pOut->bitPosition);
}
}
}
return returnCode;
}
/**
***************************************************************************************************
* AddrLib1::ComputeCmaskCoordFromAddr
*
* @brief
* Interface function stub of AddrComputeCmaskCoordFromAddr
*
* @return
* ADDR_E_RETURNCODE
***************************************************************************************************
*/
ADDR_E_RETURNCODE AddrLib1::ComputeCmaskCoordFromAddr(
const ADDR_COMPUTE_CMASK_COORDFROMADDR_INPUT* pIn, ///< [in] input structure
ADDR_COMPUTE_CMASK_COORDFROMADDR_OUTPUT* pOut ///< [out] output structure
) const
{
ADDR_E_RETURNCODE returnCode = ADDR_OK;
if (GetFillSizeFieldsFlags() == TRUE)
{
if ((pIn->size != sizeof(ADDR_COMPUTE_CMASK_COORDFROMADDR_INPUT)) ||
(pOut->size != sizeof(ADDR_COMPUTE_CMASK_COORDFROMADDR_OUTPUT)))
{
returnCode = ADDR_PARAMSIZEMISMATCH;
}
}
if (returnCode == ADDR_OK)
{
ADDR_TILEINFO tileInfoNull;
ADDR_COMPUTE_CMASK_COORDFROMADDR_INPUT input;
if (UseTileIndex(pIn->tileIndex))
{
input = *pIn;
// Use temp tile info for calcalation
input.pTileInfo = &tileInfoNull;
returnCode = HwlSetupTileCfg(0, input.tileIndex, input.macroModeIndex, input.pTileInfo);
// Change the input structure
pIn = &input;
}
if (returnCode == ADDR_OK)
{
HwlComputeXmaskCoordFromAddr(pIn->addr,
pIn->bitPosition,
pIn->pitch,
pIn->height,
pIn->numSlices,
2,
pIn->isLinear,
FALSE,
FALSE,
pIn->pTileInfo,
&pOut->x,
&pOut->y,
&pOut->slice);
}
}
return returnCode;
}
/**
***************************************************************************************************
* AddrLib1::ComputeTileDataWidthAndHeight
*
* @brief
* Compute the squared cache shape for per-tile data (CMASK and HTILE)
*
* @return
* N/A
*
* @note
* MacroWidth and macroHeight are measured in pixels
***************************************************************************************************
*/
VOID AddrLib1::ComputeTileDataWidthAndHeight(
UINT_32 bpp, ///< [in] bits per pixel
UINT_32 cacheBits, ///< [in] bits of cache
ADDR_TILEINFO* pTileInfo, ///< [in] Tile info
UINT_32* pMacroWidth, ///< [out] macro tile width
UINT_32* pMacroHeight ///< [out] macro tile height
) const
{
UINT_32 height = 1;
UINT_32 width = cacheBits / bpp;
UINT_32 pipes = HwlGetPipes(pTileInfo);
// Double height until the macro-tile is close to square
// Height can only be doubled if width is even
while ((width > height * 2 * pipes) && !(width & 1))
{
width /= 2;
height *= 2;
}
*pMacroWidth = 8 * width;
*pMacroHeight = 8 * height * pipes;
// Note: The above iterative comptuation is equivalent to the following
//
//int log2_height = ((log2(cacheBits)-log2(bpp)-log2(pipes))/2);
//int macroHeight = pow2( 3+log2(pipes)+log2_height );
}
/**
***************************************************************************************************
* AddrLib1::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 AddrLib1::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(bpp != 4); // Cmask does not support linear layout prior to SI
*pMacroWidth = 8 * 512 / bpp; // Align width to 512-bit memory accesses
*pMacroHeight = 8 * m_pipes; // Align height to number of pipes
}
/**
***************************************************************************************************
* AddrLib1::ComputeHtileInfo
*
* @brief
* Compute htile pitch,width, bytes per 2D slice
*
* @return
* Htile bpp i.e. How many bits for an 8x8 tile
* Also returns by output parameters:
* *Htile pitch, height, total size in bytes, macro-tile dimensions and slice size*
***************************************************************************************************
*/
UINT_32 AddrLib1::ComputeHtileInfo(
ADDR_HTILE_FLAGS flags, ///< [in] htile flags
UINT_32 pitchIn, ///< [in] pitch input
UINT_32 heightIn, ///< [in] height input
UINT_32 numSlices, ///< [in] number of slices
BOOL_32 isLinear, ///< [in] if it is linear mode
BOOL_32 isWidth8, ///< [in] if htile block width is 8
BOOL_32 isHeight8, ///< [in] if htile block height is 8
ADDR_TILEINFO* pTileInfo, ///< [in] Tile info
UINT_32* pPitchOut, ///< [out] pitch output
UINT_32* pHeightOut, ///< [out] height output
UINT_64* pHtileBytes, ///< [out] bytes per 2D slice
UINT_32* pMacroWidth, ///< [out] macro-tile width in pixels
UINT_32* pMacroHeight, ///< [out] macro-tile width in pixels
UINT_64* pSliceSize, ///< [out] slice size in bytes
UINT_32* pBaseAlign ///< [out] base alignment
) const
{
UINT_32 macroWidth;
UINT_32 macroHeight;
UINT_32 baseAlign;
UINT_64 surfBytes;
UINT_64 sliceBytes;
numSlices = Max(1u, numSlices);
const UINT_32 bpp = HwlComputeHtileBpp(isWidth8, isHeight8);
const UINT_32 cacheBits = HtileCacheBits;
if (isLinear)
{
HwlComputeTileDataWidthAndHeightLinear(&macroWidth,
&macroHeight,
bpp,
pTileInfo);
}
else
{
ComputeTileDataWidthAndHeight(bpp,
cacheBits,
pTileInfo,
&macroWidth,
&macroHeight);
}
*pPitchOut = PowTwoAlign(pitchIn, macroWidth);
*pHeightOut = PowTwoAlign(heightIn, macroHeight);
baseAlign = HwlComputeHtileBaseAlign(flags.tcCompatible, isLinear, pTileInfo);
surfBytes = HwlComputeHtileBytes(*pPitchOut,
*pHeightOut,
bpp,
isLinear,
numSlices,
&sliceBytes,
baseAlign);
*pHtileBytes = surfBytes;
//
// Use SafeAssign since they are optional
//
SafeAssign(pMacroWidth, macroWidth);
SafeAssign(pMacroHeight, macroHeight);
SafeAssign(pSliceSize, sliceBytes);
SafeAssign(pBaseAlign, baseAlign);
return bpp;
}
/**
***************************************************************************************************
* AddrLib1::ComputeCmaskBaseAlign
*
* @brief
* Compute cmask base alignment
*
* @return
* Cmask base alignment
***************************************************************************************************
*/
UINT_32 AddrLib1::ComputeCmaskBaseAlign(
ADDR_CMASK_FLAGS flags, ///< [in] Cmask flags
ADDR_TILEINFO* pTileInfo ///< [in] Tile info
) const
{
UINT_32 baseAlign = m_pipeInterleaveBytes * HwlGetPipes(pTileInfo);
if (flags.tcCompatible)
{
ADDR_ASSERT(pTileInfo != NULL);
if (pTileInfo)
{
baseAlign *= pTileInfo->banks;
}
}
return baseAlign;
}
/**
***************************************************************************************************
* AddrLib1::ComputeCmaskBytes
*
* @brief
* Compute cmask size in bytes
*
* @return
* Cmask size in bytes
***************************************************************************************************
*/
UINT_64 AddrLib1::ComputeCmaskBytes(
UINT_32 pitch, ///< [in] pitch
UINT_32 height, ///< [in] height
UINT_32 numSlices ///< [in] number of slices
) const
{
return BITS_TO_BYTES(static_cast<UINT_64>(pitch) * height * numSlices * CmaskElemBits) /
MicroTilePixels;
}
/**
***************************************************************************************************
* AddrLib1::ComputeCmaskInfo
*
* @brief
* Compute cmask pitch,width, bytes per 2D slice
*
* @return
* BlockMax. Also by output parameters: Cmask pitch,height, total size in bytes,
* macro-tile dimensions
***************************************************************************************************
*/
ADDR_E_RETURNCODE AddrLib1::ComputeCmaskInfo(
ADDR_CMASK_FLAGS flags, ///< [in] cmask flags
UINT_32 pitchIn, ///< [in] pitch input
UINT_32 heightIn, ///< [in] height input
UINT_32 numSlices, ///< [in] number of slices
BOOL_32 isLinear, ///< [in] is linear mode
ADDR_TILEINFO* pTileInfo, ///< [in] Tile info
UINT_32* pPitchOut, ///< [out] pitch output
UINT_32* pHeightOut, ///< [out] height output
UINT_64* pCmaskBytes, ///< [out] bytes per 2D slice
UINT_32* pMacroWidth, ///< [out] macro-tile width in pixels
UINT_32* pMacroHeight, ///< [out] macro-tile width in pixels
UINT_64* pSliceSize, ///< [out] slice size in bytes
UINT_32* pBaseAlign, ///< [out] base alignment
UINT_32* pBlockMax ///< [out] block max == slice / 128 / 128 - 1
) const
{
UINT_32 macroWidth;
UINT_32 macroHeight;
UINT_32 baseAlign;
UINT_64 surfBytes;
UINT_64 sliceBytes;
numSlices = Max(1u, numSlices);
const UINT_32 bpp = CmaskElemBits;
const UINT_32 cacheBits = CmaskCacheBits;
ADDR_E_RETURNCODE returnCode = ADDR_OK;
if (isLinear)
{
HwlComputeTileDataWidthAndHeightLinear(&macroWidth,
&macroHeight,
bpp,
pTileInfo);
}
else
{
ComputeTileDataWidthAndHeight(bpp,
cacheBits,
pTileInfo,
&macroWidth,
&macroHeight);
}
*pPitchOut = (pitchIn + macroWidth - 1) & ~(macroWidth - 1);
*pHeightOut = (heightIn + macroHeight - 1) & ~(macroHeight - 1);
sliceBytes = ComputeCmaskBytes(*pPitchOut,
*pHeightOut,
1);
baseAlign = ComputeCmaskBaseAlign(flags, pTileInfo);
while (sliceBytes % baseAlign)
{
*pHeightOut += macroHeight;
sliceBytes = ComputeCmaskBytes(*pPitchOut,
*pHeightOut,
1);
}
surfBytes = sliceBytes * numSlices;
*pCmaskBytes = surfBytes;
//
// Use SafeAssign since they are optional
//
SafeAssign(pMacroWidth, macroWidth);
SafeAssign(pMacroHeight, macroHeight);
SafeAssign(pBaseAlign, baseAlign);
SafeAssign(pSliceSize, sliceBytes);
UINT_32 slice = (*pPitchOut) * (*pHeightOut);
UINT_32 blockMax = slice / 128 / 128 - 1;
#if DEBUG
if (slice % (64*256) != 0)
{
ADDR_ASSERT_ALWAYS();
}
#endif //DEBUG
UINT_32 maxBlockMax = HwlGetMaxCmaskBlockMax();
if (blockMax > maxBlockMax)
{
blockMax = maxBlockMax;
returnCode = ADDR_INVALIDPARAMS;
}
SafeAssign(pBlockMax, blockMax);
return returnCode;
}
/**
***************************************************************************************************
* AddrLib1::ComputeXmaskCoordYFromPipe
*
* @brief
* Compute the Y coord from pipe number for cmask/htile
*
* @return
* Y coordinate
*
***************************************************************************************************
*/
UINT_32 AddrLib1::ComputeXmaskCoordYFromPipe(
UINT_32 pipe, ///< [in] pipe number
UINT_32 x ///< [in] x coordinate
) const
{
UINT_32 pipeBit0;
UINT_32 pipeBit1;
UINT_32 xBit0;
UINT_32 xBit1;
UINT_32 yBit0;
UINT_32 yBit1;
UINT_32 y = 0;
UINT_32 numPipes = m_pipes; // SI has its implementation
//
// Convert pipe + x to y coordinate.
//
switch (numPipes)
{
case 1:
//
// 1 pipe
//
// p0 = 0
//
y = 0;
break;
case 2:
//
// 2 pipes
//
// p0 = x0 ^ y0
//
// y0 = p0 ^ x0
//
pipeBit0 = pipe & 0x1;
xBit0 = x & 0x1;
yBit0 = pipeBit0 ^ xBit0;
y = yBit0;
break;
case 4:
//
// 4 pipes
//
// p0 = x1 ^ y0
// p1 = x0 ^ y1
//
// y0 = p0 ^ x1
// y1 = p1 ^ x0
//
pipeBit0 = pipe & 0x1;
pipeBit1 = (pipe & 0x2) >> 1;
xBit0 = x & 0x1;
xBit1 = (x & 0x2) >> 1;
yBit0 = pipeBit0 ^ xBit1;
yBit1 = pipeBit1 ^ xBit0;
y = (yBit0 |
(yBit1 << 1));
break;
case 8:
//
// 8 pipes
//
// r600 and r800 have different method
//
y = HwlComputeXmaskCoordYFrom8Pipe(pipe, x);
break;
default:
break;
}
return y;
}
/**
***************************************************************************************************
* AddrLib1::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 AddrLib1::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] 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* pX, ///< [out] x coord
UINT_32* pY, ///< [out] y coord
UINT_32* pSlice ///< [out] slice index
) const
{
UINT_32 pipe;
UINT_32 numPipes;
UINT_32 numPipeBits;
UINT_32 macroTilePitch;
UINT_32 macroTileHeight;
UINT_64 bitAddr;
UINT_32 microTileCoordY;
UINT_32 elemBits;
UINT_32 pitchAligned = pitch;
UINT_32 heightAligned = height;
UINT_64 totalBytes;
UINT_64 elemOffset;
UINT_64 macroIndex;
UINT_32 microIndex;
UINT_64 macroNumber;
UINT_32 microNumber;
UINT_32 macroX;
UINT_32 macroY;
UINT_32 macroZ;
UINT_32 microX;
UINT_32 microY;
UINT_32 tilesPerMacro;
UINT_32 macrosPerPitch;
UINT_32 macrosPerSlice;
//
// Extract pipe.
//
numPipes = HwlGetPipes(pTileInfo);
pipe = ComputePipeFromAddr(addr, numPipes);
//
// Compute the number of group and pipe bits.
//
numPipeBits = Log2(numPipes);
UINT_32 groupBits = 8 * m_pipeInterleaveBytes;
UINT_32 pipes = numPipes;
//
// Compute the micro tile size, in bits. And macro tile pitch and height.
//
if (factor == 2) //CMASK
{
ADDR_CMASK_FLAGS flags = {{0}};
elemBits = CmaskElemBits;
ComputeCmaskInfo(flags,
pitch,
height,
numSlices,
isLinear,
pTileInfo,
&pitchAligned,
&heightAligned,
&totalBytes,
&macroTilePitch,
&macroTileHeight);
}
else //HTILE
{
ADDR_HTILE_FLAGS flags = {{0}};
if (factor != 1)
{
factor = 1;
}
elemBits = HwlComputeHtileBpp(isWidth8, isHeight8);
ComputeHtileInfo(flags,
pitch,
height,
numSlices,
isLinear,
isWidth8,
isHeight8,
pTileInfo,
&pitchAligned,
&heightAligned,
&totalBytes,
&macroTilePitch,
&macroTileHeight);
}
// Should use aligned dims
//
pitch = pitchAligned;
height = heightAligned;
//
// Convert byte address to bit address.
//
bitAddr = BYTES_TO_BITS(addr) + bitPosition;
//
// Remove pipe bits from address.
//
bitAddr = (bitAddr % groupBits) + ((bitAddr/groupBits/pipes)*groupBits);
elemOffset = bitAddr / elemBits;
tilesPerMacro = (macroTilePitch/factor) * macroTileHeight / MicroTilePixels >> numPipeBits;
macrosPerPitch = pitch / (macroTilePitch/factor);
macrosPerSlice = macrosPerPitch * height / macroTileHeight;
macroIndex = elemOffset / factor / tilesPerMacro;
microIndex = static_cast<UINT_32>(elemOffset % (tilesPerMacro * factor));
macroNumber = macroIndex * factor + microIndex % factor;
microNumber = microIndex / factor;
macroX = static_cast<UINT_32>((macroNumber % macrosPerPitch));
macroY = static_cast<UINT_32>((macroNumber % macrosPerSlice) / macrosPerPitch);
macroZ = static_cast<UINT_32>((macroNumber / macrosPerSlice));
microX = microNumber % (macroTilePitch / factor / MicroTileWidth);
microY = (microNumber / (macroTilePitch / factor / MicroTileHeight));
*pX = macroX * (macroTilePitch/factor) + microX * MicroTileWidth;
*pY = macroY * macroTileHeight + (microY * MicroTileHeight << numPipeBits);
*pSlice = macroZ;
microTileCoordY = ComputeXmaskCoordYFromPipe(pipe,
*pX/MicroTileWidth);
//
// Assemble final coordinates.
//
*pY += microTileCoordY * MicroTileHeight;
}
/**
***************************************************************************************************
* AddrLib1::HwlComputeXmaskAddrFromCoord
*
* @brief
* Compute the address from an address of cmask (prior to si)
*
* @return
* Address in bytes
*
***************************************************************************************************
*/
UINT_64 AddrLib1::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_64 addr;
UINT_32 numGroupBits;
UINT_32 numPipeBits;
UINT_32 newPitch = 0;
UINT_32 newHeight = 0;
UINT_64 sliceBytes = 0;
UINT_64 totalBytes = 0;
UINT_64 sliceOffset;
UINT_32 pipe;
UINT_32 macroTileWidth;
UINT_32 macroTileHeight;
UINT_32 macroTilesPerRow;
UINT_32 macroTileBytes;
UINT_32 macroTileIndexX;
UINT_32 macroTileIndexY;
UINT_64 macroTileOffset;
UINT_32 pixelBytesPerRow;
UINT_32 pixelOffsetX;
UINT_32 pixelOffsetY;
UINT_32 pixelOffset;
UINT_64 totalOffset;
UINT_64 offsetLo;
UINT_64 offsetHi;
UINT_64 groupMask;
UINT_32 elemBits = 0;
UINT_32 numPipes = m_pipes; // This function is accessed prior to si only
if (factor == 2) //CMASK
{
elemBits = CmaskElemBits;
// For asics before SI, cmask is always tiled
isLinear = FALSE;
}
else //HTILE
{
if (factor != 1) // Fix compile warning
{
factor = 1;
}
elemBits = HwlComputeHtileBpp(isWidth8, isHeight8);
}
//
// Compute the number of group bits and pipe bits.
//
numGroupBits = Log2(m_pipeInterleaveBytes);
numPipeBits = Log2(numPipes);
//
// Compute macro tile dimensions.
//
if (factor == 2) // CMASK
{
ADDR_CMASK_FLAGS flags = {{0}};
ComputeCmaskInfo(flags,
pitch,
height,
numSlices,
isLinear,
pTileInfo,
&newPitch,
&newHeight,
&totalBytes,
&macroTileWidth,
&macroTileHeight);
sliceBytes = totalBytes / numSlices;
}
else // HTILE
{
ADDR_HTILE_FLAGS flags = {{0}};
ComputeHtileInfo(flags,
pitch,
height,
numSlices,
isLinear,
isWidth8,
isHeight8,
pTileInfo,
&newPitch,
&newHeight,
&totalBytes,
&macroTileWidth,
&macroTileHeight,
&sliceBytes);
}
sliceOffset = slice * sliceBytes;
//
// Get the pipe. Note that neither slice rotation nor pipe swizzling apply for CMASK.
//
pipe = ComputePipeFromCoord(x,
y,
0,
ADDR_TM_2D_TILED_THIN1,
0,
FALSE,
pTileInfo);
//
// Compute the number of macro tiles per row.
//
macroTilesPerRow = newPitch / macroTileWidth;
//
// Compute the number of bytes per macro tile.
//
macroTileBytes = BITS_TO_BYTES((macroTileWidth * macroTileHeight * elemBits) / MicroTilePixels);
//
// Compute the offset to the macro tile containing the specified coordinate.
//
macroTileIndexX = x / macroTileWidth;
macroTileIndexY = y / macroTileHeight;
macroTileOffset = ((macroTileIndexY * macroTilesPerRow) + macroTileIndexX) * macroTileBytes;
//
// Compute the pixel offset within the macro tile.
//
pixelBytesPerRow = BITS_TO_BYTES(macroTileWidth * elemBits) / MicroTileWidth;
//
// The nibbles are interleaved (see below), so the part of the offset relative to the x
// coordinate repeats halfway across the row. (Not for HTILE)
//
if (factor == 2)
{
pixelOffsetX = (x % (macroTileWidth / 2)) / MicroTileWidth;
}
else
{
pixelOffsetX = (x % (macroTileWidth)) / MicroTileWidth * BITS_TO_BYTES(elemBits);
}
//
// Compute the y offset within the macro tile.
//
pixelOffsetY = (((y % macroTileHeight) / MicroTileHeight) / numPipes) * pixelBytesPerRow;
pixelOffset = pixelOffsetX + pixelOffsetY;
//
// Combine the slice offset and macro tile offset with the pixel offset, accounting for the
// pipe bits in the middle of the address.
//
totalOffset = ((sliceOffset + macroTileOffset) >> numPipeBits) + pixelOffset;
//
// Split the offset to put some bits below the pipe bits and some above.
//
groupMask = (1 << numGroupBits) - 1;
offsetLo = totalOffset & groupMask;
offsetHi = (totalOffset & ~groupMask) << numPipeBits;
//
// Assemble the address from its components.
//
addr = offsetLo;
addr |= offsetHi;
// This is to remove warning with /analyze option
UINT_32 pipeBits = pipe << numGroupBits;
addr |= pipeBits;
//
// Compute the bit position. The lower nibble is used when the x coordinate within the macro
// tile is less than half of the macro tile width, and the upper nibble is used when the x
// coordinate within the macro tile is greater than or equal to half the macro tile width.
//
*pBitPosition = ((x % macroTileWidth) < (macroTileWidth / factor)) ? 0 : 4;
return addr;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Surface Addressing Shared
///////////////////////////////////////////////////////////////////////////////////////////////////
/**
***************************************************************************************************
* AddrLib1::ComputeSurfaceAddrFromCoordLinear
*
* @brief
* Compute address from coord for linear surface
*
* @return
* Address in bytes
*
***************************************************************************************************
*/
UINT_64 AddrLib1::ComputeSurfaceAddrFromCoordLinear(
UINT_32 x, ///< [in] x coord
UINT_32 y, ///< [in] y coord
UINT_32 slice, ///< [in] slice/depth index
UINT_32 sample, ///< [in] sample index
UINT_32 bpp, ///< [in] bits per pixel
UINT_32 pitch, ///< [in] pitch
UINT_32 height, ///< [in] height
UINT_32 numSlices, ///< [in] number of slices
UINT_32* pBitPosition ///< [out] bit position inside a byte
) const
{
const UINT_64 sliceSize = static_cast<UINT_64>(pitch) * height;
UINT_64 sliceOffset = (slice + sample * numSlices)* sliceSize;
UINT_64 rowOffset = static_cast<UINT_64>(y) * pitch;
UINT_64 pixOffset = x;
UINT_64 addr = (sliceOffset + rowOffset + pixOffset) * bpp;
*pBitPosition = static_cast<UINT_32>(addr % 8);
addr /= 8;
return addr;
}
/**
***************************************************************************************************
* AddrLib1::ComputeSurfaceCoordFromAddrLinear
*
* @brief
* Compute the coord from an address of a linear surface
*
* @return
* N/A
***************************************************************************************************
*/
VOID AddrLib1::ComputeSurfaceCoordFromAddrLinear(
UINT_64 addr, ///< [in] address
UINT_32 bitPosition, ///< [in] bitPosition in a byte
UINT_32 bpp, ///< [in] bits per pixel
UINT_32 pitch, ///< [in] pitch
UINT_32 height, ///< [in] height
UINT_32 numSlices, ///< [in] number of slices
UINT_32* pX, ///< [out] x coord
UINT_32* pY, ///< [out] y coord
UINT_32* pSlice, ///< [out] slice/depth index
UINT_32* pSample ///< [out] sample index
) const
{
const UINT_64 sliceSize = static_cast<UINT_64>(pitch) * height;
const UINT_64 linearOffset = (BYTES_TO_BITS(addr) + bitPosition) / bpp;
*pX = static_cast<UINT_32>((linearOffset % sliceSize) % pitch);
*pY = static_cast<UINT_32>((linearOffset % sliceSize) / pitch % height);
*pSlice = static_cast<UINT_32>((linearOffset / sliceSize) % numSlices);
*pSample = static_cast<UINT_32>((linearOffset / sliceSize) / numSlices);
}
/**
***************************************************************************************************
* AddrLib1::ComputeSurfaceCoordFromAddrMicroTiled
*
* @brief
* Compute the coord from an address of a micro tiled surface
*
* @return
* N/A
***************************************************************************************************
*/
VOID AddrLib1::ComputeSurfaceCoordFromAddrMicroTiled(
UINT_64 addr, ///< [in] address
UINT_32 bitPosition, ///< [in] bitPosition in a byte
UINT_32 bpp, ///< [in] bits per pixel
UINT_32 pitch, ///< [in] pitch
UINT_32 height, ///< [in] height
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 coord
UINT_32* pY, ///< [out] y coord
UINT_32* pSlice, ///< [out] slice/depth index
UINT_32* pSample, ///< [out] sample index,
AddrTileType microTileType, ///< [in] micro tiling order
BOOL_32 isDepthSampleOrder ///< [in] TRUE if in depth sample order
) const
{
UINT_64 bitAddr;
UINT_32 microTileThickness;
UINT_32 microTileBits;
UINT_64 sliceBits;
UINT_64 rowBits;
UINT_32 sliceIndex;
UINT_32 microTileCoordX;
UINT_32 microTileCoordY;
UINT_32 pixelOffset;
UINT_32 pixelCoordX = 0;
UINT_32 pixelCoordY = 0;
UINT_32 pixelCoordZ = 0;
UINT_32 pixelCoordS = 0;
//
// Convert byte address to bit address.
//
bitAddr = BYTES_TO_BITS(addr) + bitPosition;
//
// Compute the micro tile size, in bits.
//
switch (tileMode)
{
case ADDR_TM_1D_TILED_THICK:
microTileThickness = ThickTileThickness;
break;
default:
microTileThickness = 1;
break;
}
microTileBits = MicroTilePixels * microTileThickness * bpp * numSamples;
//
// Compute number of bits per slice and number of bits per row of micro tiles.
//
sliceBits = static_cast<UINT_64>(pitch) * height * microTileThickness * bpp * numSamples;
rowBits = (pitch / MicroTileWidth) * microTileBits;
//
// Extract the slice index.
//
sliceIndex = static_cast<UINT_32>(bitAddr / sliceBits);
bitAddr -= sliceIndex * sliceBits;
//
// Extract the y coordinate of the micro tile.
//
microTileCoordY = static_cast<UINT_32>(bitAddr / rowBits) * MicroTileHeight;
bitAddr -= (microTileCoordY / MicroTileHeight) * rowBits;
//
// Extract the x coordinate of the micro tile.
//
microTileCoordX = static_cast<UINT_32>(bitAddr / microTileBits) * MicroTileWidth;
//
// Compute the pixel offset within the micro tile.
//
pixelOffset = static_cast<UINT_32>(bitAddr % microTileBits);
//
// Extract pixel coordinates from the offset.
//
HwlComputePixelCoordFromOffset(pixelOffset,
bpp,
numSamples,
tileMode,
tileBase,
compBits,
&pixelCoordX,
&pixelCoordY,
&pixelCoordZ,
&pixelCoordS,
microTileType,
isDepthSampleOrder);
//
// Assemble final coordinates.
//
*pX = microTileCoordX + pixelCoordX;
*pY = microTileCoordY + pixelCoordY;
*pSlice = (sliceIndex * microTileThickness) + pixelCoordZ;
*pSample = pixelCoordS;
if (microTileThickness > 1)
{
*pSample = 0;
}
}
/**
***************************************************************************************************
* AddrLib1::ComputePipeFromAddr
*
* @brief
* Compute the pipe number from an address
*
* @return
* Pipe number
*
***************************************************************************************************
*/
UINT_32 AddrLib1::ComputePipeFromAddr(
UINT_64 addr, ///< [in] address
UINT_32 numPipes ///< [in] number of banks
) const
{
UINT_32 pipe;
UINT_32 groupBytes = m_pipeInterleaveBytes; //just different terms
// R600
// The LSBs of the address are arranged as follows:
// bank | pipe | group
//
// To get the pipe number, shift off the group bits and mask the pipe bits.
//
// R800
// The LSBs of the address are arranged as follows:
// bank | bankInterleave | pipe | pipeInterleave
//
// To get the pipe number, shift off the pipe interleave bits and mask the pipe bits.
//
pipe = static_cast<UINT_32>(addr >> Log2(groupBytes)) & (numPipes - 1);
return pipe;
}
/**
***************************************************************************************************
* AddrLib1::ComputePixelIndexWithinMicroTile
*
* @brief
* Compute the pixel index inside a micro tile of surface
*
* @return
* Pixel index
*
***************************************************************************************************
*/
UINT_32 AddrLib1::ComputePixelIndexWithinMicroTile(
UINT_32 x, ///< [in] x coord
UINT_32 y, ///< [in] y coord
UINT_32 z, ///< [in] slice/depth index
UINT_32 bpp, ///< [in] bits per pixel
AddrTileMode tileMode, ///< [in] tile mode
AddrTileType microTileType ///< [in] pixel order in display/non-display mode
) const
{
UINT_32 pixelBit0 = 0;
UINT_32 pixelBit1 = 0;
UINT_32 pixelBit2 = 0;
UINT_32 pixelBit3 = 0;
UINT_32 pixelBit4 = 0;
UINT_32 pixelBit5 = 0;
UINT_32 pixelBit6 = 0;
UINT_32 pixelBit7 = 0;
UINT_32 pixelBit8 = 0;
UINT_32 pixelNumber;
UINT_32 x0 = _BIT(x, 0);
UINT_32 x1 = _BIT(x, 1);
UINT_32 x2 = _BIT(x, 2);
UINT_32 y0 = _BIT(y, 0);
UINT_32 y1 = _BIT(y, 1);
UINT_32 y2 = _BIT(y, 2);
UINT_32 z0 = _BIT(z, 0);
UINT_32 z1 = _BIT(z, 1);
UINT_32 z2 = _BIT(z, 2);
UINT_32 thickness = ComputeSurfaceThickness(tileMode);
// Compute the pixel number within the micro tile.
if (microTileType != ADDR_THICK)
{
if (microTileType == ADDR_DISPLAYABLE)
{
switch (bpp)
{
case 8:
pixelBit0 = x0;
pixelBit1 = x1;
pixelBit2 = x2;
pixelBit3 = y1;
pixelBit4 = y0;
pixelBit5 = y2;
break;
case 16:
pixelBit0 = x0;
pixelBit1 = x1;
pixelBit2 = x2;
pixelBit3 = y0;
pixelBit4 = y1;
pixelBit5 = y2;
break;
case 32:
pixelBit0 = x0;
pixelBit1 = x1;
pixelBit2 = y0;
pixelBit3 = x2;
pixelBit4 = y1;
pixelBit5 = y2;
break;
case 64:
pixelBit0 = x0;
pixelBit1 = y0;
pixelBit2 = x1;
pixelBit3 = x2;
pixelBit4 = y1;
pixelBit5 = y2;
break;
case 128:
pixelBit0 = y0;
pixelBit1 = x0;
pixelBit2 = x1;
pixelBit3 = x2;
pixelBit4 = y1;
pixelBit5 = y2;
break;
default:
ADDR_ASSERT_ALWAYS();
break;
}
}
else if (microTileType == ADDR_NON_DISPLAYABLE || microTileType == ADDR_DEPTH_SAMPLE_ORDER)
{
pixelBit0 = x0;
pixelBit1 = y0;
pixelBit2 = x1;
pixelBit3 = y1;
pixelBit4 = x2;
pixelBit5 = y2;
}
else if (microTileType == ADDR_ROTATED)
{
ADDR_ASSERT(thickness == 1);
switch (bpp)
{
case 8:
pixelBit0 = y0;
pixelBit1 = y1;
pixelBit2 = y2;
pixelBit3 = x1;
pixelBit4 = x0;
pixelBit5 = x2;
break;
case 16:
pixelBit0 = y0;
pixelBit1 = y1;
pixelBit2 = y2;
pixelBit3 = x0;
pixelBit4 = x1;
pixelBit5 = x2;
break;
case 32:
pixelBit0 = y0;
pixelBit1 = y1;
pixelBit2 = x0;
pixelBit3 = y2;
pixelBit4 = x1;
pixelBit5 = x2;
break;
case 64:
pixelBit0 = y0;
pixelBit1 = x0;
pixelBit2 = y1;
pixelBit3 = x1;
pixelBit4 = x2;
pixelBit5 = y2;
break;
default:
ADDR_ASSERT_ALWAYS();
break;
}
}
if (thickness > 1)
{
pixelBit6 = z0;
pixelBit7 = z1;
}
}
else // ADDR_THICK
{
ADDR_ASSERT(thickness > 1);
switch (bpp)
{
case 8:
case 16:
pixelBit0 = x0;
pixelBit1 = y0;
pixelBit2 = x1;
pixelBit3 = y1;
pixelBit4 = z0;
pixelBit5 = z1;
break;
case 32:
pixelBit0 = x0;
pixelBit1 = y0;
pixelBit2 = x1;
pixelBit3 = z0;
pixelBit4 = y1;
pixelBit5 = z1;
break;
case 64:
case 128:
pixelBit0 = y0;
pixelBit1 = x0;
pixelBit2 = z0;
pixelBit3 = x1;
pixelBit4 = y1;
pixelBit5 = z1;
break;
default:
ADDR_ASSERT_ALWAYS();
break;
}
pixelBit6 = x2;
pixelBit7 = y2;
}
if (thickness == 8)
{
pixelBit8 = z2;
}
pixelNumber = ((pixelBit0 ) |
(pixelBit1 << 1) |
(pixelBit2 << 2) |
(pixelBit3 << 3) |
(pixelBit4 << 4) |
(pixelBit5 << 5) |
(pixelBit6 << 6) |
(pixelBit7 << 7) |
(pixelBit8 << 8));
return pixelNumber;
}
/**
***************************************************************************************************
* AddrLib1::AdjustPitchAlignment
*
* @brief
* Adjusts pitch alignment for flipping surface
*
* @return
* N/A
*
***************************************************************************************************
*/
VOID AddrLib1::AdjustPitchAlignment(
ADDR_SURFACE_FLAGS flags, ///< [in] Surface flags
UINT_32* pPitchAlign ///< [out] Pointer to pitch alignment
) const
{
// Display engine hardwires lower 5 bit of GRPH_PITCH to ZERO which means 32 pixel alignment
// Maybe it will be fixed in future but let's make it general for now.
if (flags.display || flags.overlay)
{
*pPitchAlign = PowTwoAlign(*pPitchAlign, 32);
if(flags.display)
{
*pPitchAlign = Max(m_minPitchAlignPixels, *pPitchAlign);
}
}
}
/**
***************************************************************************************************
* AddrLib1::PadDimensions
*
* @brief
* Helper function to pad dimensions
*
* @return
* N/A
*
***************************************************************************************************
*/
VOID AddrLib1::PadDimensions(
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
{
UINT_32 thickness = ComputeSurfaceThickness(tileMode);
ADDR_ASSERT(padDims <= 3);
//
// Override padding for mip levels
//
if (mipLevel > 0)
{
if (flags.cube)
{
// for cubemap, we only pad when client call with 6 faces as an identity
if (*pSlices > 1)
{
padDims = 3; // we should pad cubemap sub levels when we treat it as 3d texture
}
else
{
padDims = 2;
}
}
}
// Any possibilities that padDims is 0?
if (padDims == 0)
{
padDims = 3;
}
if (IsPow2(pitchAlign))
{
*pPitch = PowTwoAlign((*pPitch), pitchAlign);
}
else // add this code to pass unit test, r600 linear mode is not align bpp to pow2 for linear
{
*pPitch += pitchAlign - 1;
*pPitch /= pitchAlign;
*pPitch *= pitchAlign;
}
if (padDims > 1)
{
*pHeight = PowTwoAlign((*pHeight), heightAlign);
}
if (padDims > 2 || thickness > 1)
{
// for cubemap single face, we do not pad slices.
// if we pad it, the slice number should be set to 6 and current mip level > 1
if (flags.cube && (!m_configFlags.noCubeMipSlicesPad || flags.cubeAsArray))
{
*pSlices = NextPow2(*pSlices);
}
// normal 3D texture or arrays or cubemap has a thick mode? (Just pass unit test)
if (thickness > 1)
{
*pSlices = PowTwoAlign((*pSlices), sliceAlign);
}
}
HwlPadDimensions(tileMode,
bpp,
flags,
numSamples,
pTileInfo,
padDims,
mipLevel,
pPitch,
pitchAlign,
pHeight,
heightAlign,
pSlices,
sliceAlign);
}
/**
***************************************************************************************************
* AddrLib1::HwlPreHandleBaseLvl3xPitch
*
* @brief
* Pre-handler of 3x pitch (96 bit) adjustment
*
* @return
* Expected pitch
***************************************************************************************************
*/
UINT_32 AddrLib1::HwlPreHandleBaseLvl3xPitch(
const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] input
UINT_32 expPitch ///< [in] pitch
) const
{
ADDR_ASSERT(pIn->width == expPitch);
//
// If pitch is pre-multiplied by 3, we retrieve original one here to get correct miplevel size
//
if (AddrElemLib::IsExpand3x(pIn->format) &&
pIn->mipLevel == 0 &&
pIn->tileMode == ADDR_TM_LINEAR_ALIGNED)
{
expPitch /= 3;
expPitch = NextPow2(expPitch);
}
return expPitch;
}
/**
***************************************************************************************************
* AddrLib1::HwlPostHandleBaseLvl3xPitch
*
* @brief
* Post-handler of 3x pitch adjustment
*
* @return
* Expected pitch
***************************************************************************************************
*/
UINT_32 AddrLib1::HwlPostHandleBaseLvl3xPitch(
const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] input
UINT_32 expPitch ///< [in] pitch
) const
{
//
// 96 bits surface of sub levels require element pitch of 32 bits instead
// So we just return pitch in 32 bit pixels without timing 3
//
if (AddrElemLib::IsExpand3x(pIn->format) &&
pIn->mipLevel == 0 &&
pIn->tileMode == ADDR_TM_LINEAR_ALIGNED)
{
expPitch *= 3;
}
return expPitch;
}
/**
***************************************************************************************************
* AddrLib1::IsMacroTiled
*
* @brief
* Check if the tile mode is macro tiled
*
* @return
* TRUE if it is macro tiled (2D/2B/3D/3B)
***************************************************************************************************
*/
BOOL_32 AddrLib1::IsMacroTiled(
AddrTileMode tileMode) ///< [in] tile mode
{
return m_modeFlags[tileMode].isMacro;
}
/**
***************************************************************************************************
* AddrLib1::IsMacro3dTiled
*
* @brief
* Check if the tile mode is 3D macro tiled
*
* @return
* TRUE if it is 3D macro tiled
***************************************************************************************************
*/
BOOL_32 AddrLib1::IsMacro3dTiled(
AddrTileMode tileMode) ///< [in] tile mode
{
return m_modeFlags[tileMode].isMacro3d;
}
/**
***************************************************************************************************
* AddrLib1::IsMicroTiled
*
* @brief
* Check if the tile mode is micro tiled
*
* @return
* TRUE if micro tiled
***************************************************************************************************
*/
BOOL_32 AddrLib1::IsMicroTiled(
AddrTileMode tileMode) ///< [in] tile mode
{
return m_modeFlags[tileMode].isMicro;
}
/**
***************************************************************************************************
* AddrLib1::IsLinear
*
* @brief
* Check if the tile mode is linear
*
* @return
* TRUE if linear
***************************************************************************************************
*/
BOOL_32 AddrLib1::IsLinear(
AddrTileMode tileMode) ///< [in] tile mode
{
return m_modeFlags[tileMode].isLinear;
}
/**
***************************************************************************************************
* AddrLib1::IsPrtNoRotationTileMode
*
* @brief
* Return TRUE if it is prt tile without rotation
* @note
* This function just used by CI
***************************************************************************************************
*/
BOOL_32 AddrLib1::IsPrtNoRotationTileMode(
AddrTileMode tileMode)
{
return m_modeFlags[tileMode].isPrtNoRotation;
}
/**
***************************************************************************************************
* AddrLib1::IsPrtTileMode
*
* @brief
* Return TRUE if it is prt tile
* @note
* This function just used by CI
***************************************************************************************************
*/
BOOL_32 AddrLib1::IsPrtTileMode(
AddrTileMode tileMode)
{
return m_modeFlags[tileMode].isPrt;
}
/**
***************************************************************************************************
* AddrLib1::ComputeMipLevel
*
* @brief
* Compute mipmap level width/height/slices
* @return
* N/A
***************************************************************************************************
*/
VOID AddrLib1::ComputeMipLevel(
ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn ///< [in/out] Input structure
) const
{
if (AddrElemLib::IsBlockCompressed(pIn->format))
{
if (pIn->mipLevel == 0)
{
// DXTn's level 0 must be multiple of 4
// But there are exceptions:
// 1. Internal surface creation in hostblt/vsblt/etc...
// 2. Runtime doesn't reject ATI1/ATI2 whose width/height are not multiple of 4
pIn->width = PowTwoAlign(pIn->width, 4);
pIn->height = PowTwoAlign(pIn->height, 4);
}
}
HwlComputeMipLevel(pIn);
}
/**
***************************************************************************************************
* AddrLib1::OptimizeTileMode
*
* @brief
* Check if base level's tile mode can be optimized (degraded)
* @return
* TRUE if degraded, also returns degraded tile mode (unchanged if not degraded)
***************************************************************************************************
*/
BOOL_32 AddrLib1::OptimizeTileMode(
const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] Input structure for surface info
AddrTileMode* pTileMode ///< [out] Degraded tile mode
) const
{
AddrTileMode tileMode = pIn->tileMode;
UINT_32 thickness = ComputeSurfaceThickness(tileMode);
// Optimization can only be done on level 0 and samples <= 1
if ((pIn->flags.opt4Space == TRUE) &&
(pIn->mipLevel == 0) &&
(pIn->numSamples <= 1) &&
(pIn->flags.display == FALSE) &&
(IsPrtTileMode(tileMode) == FALSE) &&
(pIn->flags.prt == FALSE))
{
// Check if linear mode is optimal
if ((pIn->height == 1) &&
(IsLinear(tileMode) == FALSE) &&
(AddrElemLib::IsBlockCompressed(pIn->format) == FALSE) &&
(pIn->flags.depth == FALSE) &&
(pIn->flags.stencil == FALSE) &&
(m_configFlags.disableLinearOpt == FALSE) &&
(pIn->flags.disableLinearOpt == FALSE))
{
tileMode = ADDR_TM_LINEAR_ALIGNED;
}
else if (IsMacroTiled(tileMode))
{
if (HwlDegradeBaseLevel(pIn))
{
tileMode = (thickness == 1) ? ADDR_TM_1D_TILED_THIN1 : ADDR_TM_1D_TILED_THICK;
}
else if (thickness > 1)
{
// As in the following HwlComputeSurfaceInfo, thick modes may be degraded to
// thinner modes, we should re-evaluate whether the corresponding thinner modes
// need to be degraded. If so, we choose 1D thick mode instead.
tileMode = DegradeLargeThickTile(pIn->tileMode, pIn->bpp);
if (tileMode != pIn->tileMode)
{
ADDR_COMPUTE_SURFACE_INFO_INPUT input = *pIn;
input.tileMode = tileMode;
if (HwlDegradeBaseLevel(&input))
{
tileMode = ADDR_TM_1D_TILED_THICK;
}
}
}
}
}
BOOL_32 optimized = (tileMode != pIn->tileMode);
if (optimized)
{
*pTileMode = tileMode;
}
return optimized;
}
/**
***************************************************************************************************
* AddrLib1::DegradeLargeThickTile
*
* @brief
* Check if the thickness needs to be reduced if a tile is too large
* @return
* The degraded tile mode (unchanged if not degraded)
***************************************************************************************************
*/
AddrTileMode AddrLib1::DegradeLargeThickTile(
AddrTileMode tileMode,
UINT_32 bpp) const
{
// Override tilemode
// When tile_width (8) * tile_height (8) * thickness * element_bytes is > row_size,
// it is better to just use THIN mode in this case
UINT_32 thickness = ComputeSurfaceThickness(tileMode);
if (thickness > 1 && m_configFlags.allowLargeThickTile == 0)
{
UINT_32 tileSize = MicroTilePixels * thickness * (bpp >> 3);
if (tileSize > m_rowSize)
{
switch (tileMode)
{
case ADDR_TM_2D_TILED_XTHICK:
if ((tileSize >> 1) <= m_rowSize)
{
tileMode = ADDR_TM_2D_TILED_THICK;
break;
}
// else fall through
case ADDR_TM_2D_TILED_THICK:
tileMode = ADDR_TM_2D_TILED_THIN1;
break;
case ADDR_TM_3D_TILED_XTHICK:
if ((tileSize >> 1) <= m_rowSize)
{
tileMode = ADDR_TM_3D_TILED_THICK;
break;
}
// else fall through
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;
}
}
}
return tileMode;
}
/**
***************************************************************************************************
* AddrLib1::PostComputeMipLevel
* @brief
* Compute MipLevel info (including level 0) after surface adjustment
* @return
* ADDR_E_RETURNCODE
***************************************************************************************************
*/
ADDR_E_RETURNCODE AddrLib1::PostComputeMipLevel(
ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in/out] Input structure
ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [out] Output structure
) const
{
// Mipmap including level 0 must be pow2 padded since either SI hw expects so or it is
// required by CFX for Hw Compatibility between NI and SI. Otherwise it is only needed for
// mipLevel > 0. Any h/w has different requirement should implement its own virtual function
if (pIn->flags.pow2Pad)
{
pIn->width = NextPow2(pIn->width);
pIn->height = NextPow2(pIn->height);
pIn->numSlices = NextPow2(pIn->numSlices);
}
else if (pIn->mipLevel > 0)
{
pIn->width = NextPow2(pIn->width);
pIn->height = NextPow2(pIn->height);
if (!pIn->flags.cube)
{
pIn->numSlices = NextPow2(pIn->numSlices);
}
// for cubemap, we keep its value at first
}
return ADDR_OK;
}
/**
***************************************************************************************************
* AddrLib1::HwlSetupTileCfg
*
* @brief
* Map tile index to tile setting.
* @return
* ADDR_E_RETURNCODE
***************************************************************************************************
*/
ADDR_E_RETURNCODE AddrLib1::HwlSetupTileCfg(
UINT_32 bpp, ///< 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
{
return ADDR_NOTSUPPORTED;
}
/**
***************************************************************************************************
* AddrLib1::HwlGetPipes
*
* @brief
* Get number pipes
* @return
* num pipes
***************************************************************************************************
*/
UINT_32 AddrLib1::HwlGetPipes(
const ADDR_TILEINFO* pTileInfo ///< [in] Tile info
) const
{
//pTileInfo can be NULL when asic is 6xx and 8xx.
return m_pipes;
}
/**
***************************************************************************************************
* AddrLib1::ComputeQbStereoInfo
*
* @brief
* Get quad buffer stereo information
* @return
* TRUE if no error
***************************************************************************************************
*/
BOOL_32 AddrLib1::ComputeQbStereoInfo(
ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [in/out] updated pOut+pStereoInfo
) const
{
BOOL_32 success = FALSE;
if (pOut->pStereoInfo)
{
ADDR_ASSERT(pOut->bpp >= 8);
ADDR_ASSERT((pOut->surfSize % pOut->baseAlign) == 0);
// Save original height
pOut->pStereoInfo->eyeHeight = pOut->height;
// Right offset
pOut->pStereoInfo->rightOffset = static_cast<UINT_32>(pOut->surfSize);
pOut->pStereoInfo->rightSwizzle = HwlComputeQbStereoRightSwizzle(pOut);
// Double height
pOut->height <<= 1;
pOut->pixelHeight <<= 1;
// Double size
pOut->surfSize <<= 1;
// Right start address meets the base align since it is guaranteed by AddrLib1
// 1D surface on SI may break this rule, but we can force it to meet by checking .qbStereo.
success = TRUE;
}
return success;
}
/**
***************************************************************************************************
* AddrLib1::ComputePrtInfo
*
* @brief
* Compute prt surface related info
*
* @return
* ADDR_E_RETURNCODE
***************************************************************************************************
*/
ADDR_E_RETURNCODE AddrLib1::ComputePrtInfo(
const ADDR_PRT_INFO_INPUT* pIn,
ADDR_PRT_INFO_OUTPUT* pOut) const
{
ADDR_ASSERT(pOut != NULL);
ADDR_E_RETURNCODE returnCode = ADDR_OK;
UINT_32 expandX = 1;
UINT_32 expandY = 1;
AddrElemMode elemMode;
UINT_32 bpp = GetElemLib()->GetBitsPerPixel(pIn->format,
&elemMode,
&expandX,
&expandY);
if (bpp <8 || bpp == 24 || bpp == 48 || bpp == 96)
{
returnCode = ADDR_INVALIDPARAMS;
}
UINT_32 numFrags = pIn->numFrags;
ADDR_ASSERT(numFrags <= 8);
UINT_32 tileWidth = 0;
UINT_32 tileHeight = 0;
if (returnCode == ADDR_OK)
{
// 3D texture without depth or 2d texture
if (pIn->baseMipDepth > 1 || pIn->baseMipHeight > 1)
{
if (bpp == 8)
{
tileWidth = 256;
tileHeight = 256;
}
else if (bpp == 16)
{
tileWidth = 256;
tileHeight = 128;
}
else if (bpp == 32)
{
tileWidth = 128;
tileHeight = 128;
}
else if (bpp == 64)
{
// assume it is BC1/4
tileWidth = 512;
tileHeight = 256;
if (elemMode == ADDR_UNCOMPRESSED)
{
tileWidth = 128;
tileHeight = 64;
}
}
else if (bpp == 128)
{
// assume it is BC2/3/5/6H/7
tileWidth = 256;
tileHeight = 256;
if (elemMode == ADDR_UNCOMPRESSED)
{
tileWidth = 64;
tileHeight = 64;
}
}
if (numFrags == 2)
{
tileWidth = tileWidth / 2;
}
else if (numFrags == 4)
{
tileWidth = tileWidth / 2;
tileHeight = tileHeight / 2;
}
else if (numFrags == 8)
{
tileWidth = tileWidth / 4;
tileHeight = tileHeight / 2;
}
}
else // 1d
{
tileHeight = 1;
if (bpp == 8)
{
tileWidth = 65536;
}
else if (bpp == 16)
{
tileWidth = 32768;
}
else if (bpp == 32)
{
tileWidth = 16384;
}
else if (bpp == 64)
{
tileWidth = 8192;
}
else if (bpp == 128)
{
tileWidth = 4096;
}
}
}
pOut->prtTileWidth = tileWidth;
pOut->prtTileHeight = tileHeight;
return returnCode;
}