4781 lines
167 KiB
C++
4781 lines
167 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 egbaddrlib.cpp
|
|
* @brief Contains the EgBasedLib class implementation.
|
|
****************************************************************************************************
|
|
*/
|
|
|
|
#include "egbaddrlib.h"
|
|
|
|
namespace Addr
|
|
{
|
|
namespace V1
|
|
{
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::EgBasedLib
|
|
*
|
|
* @brief
|
|
* Constructor
|
|
*
|
|
* @note
|
|
*
|
|
****************************************************************************************************
|
|
*/
|
|
EgBasedLib::EgBasedLib(const Client* pClient)
|
|
:
|
|
Lib(pClient),
|
|
m_ranks(0),
|
|
m_logicalBanks(0),
|
|
m_bankInterleave(1)
|
|
{
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::~EgBasedLib
|
|
*
|
|
* @brief
|
|
* Destructor
|
|
****************************************************************************************************
|
|
*/
|
|
EgBasedLib::~EgBasedLib()
|
|
{
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::DispatchComputeSurfaceInfo
|
|
*
|
|
* @brief
|
|
* Compute surface sizes include padded pitch,height,slices,total size in bytes,
|
|
* meanwhile output suitable tile mode and base alignment might be changed in this
|
|
* call as well. Results are returned through output parameters.
|
|
*
|
|
* @return
|
|
* TRUE if no error occurs
|
|
****************************************************************************************************
|
|
*/
|
|
BOOL_32 EgBasedLib::DispatchComputeSurfaceInfo(
|
|
const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] input structure
|
|
ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [out] output structure
|
|
) const
|
|
{
|
|
AddrTileMode tileMode = pIn->tileMode;
|
|
UINT_32 bpp = pIn->bpp;
|
|
UINT_32 numSamples = pIn->numSamples;
|
|
UINT_32 numFrags = ((pIn->numFrags == 0) ? numSamples : pIn->numFrags);
|
|
UINT_32 pitch = pIn->width;
|
|
UINT_32 height = pIn->height;
|
|
UINT_32 numSlices = pIn->numSlices;
|
|
UINT_32 mipLevel = pIn->mipLevel;
|
|
ADDR_SURFACE_FLAGS flags = pIn->flags;
|
|
|
|
ADDR_TILEINFO tileInfoDef = {0};
|
|
ADDR_TILEINFO* pTileInfo = &tileInfoDef;
|
|
|
|
UINT_32 padDims = 0;
|
|
BOOL_32 valid;
|
|
|
|
tileMode = DegradeLargeThickTile(tileMode, bpp);
|
|
|
|
// Only override numSamples for NI above
|
|
if (m_chipFamily >= ADDR_CHIP_FAMILY_NI)
|
|
{
|
|
if (numFrags != numSamples) // This means EQAA
|
|
{
|
|
// The real surface size needed is determined by number of fragments
|
|
numSamples = numFrags;
|
|
}
|
|
|
|
// Save altered numSamples in pOut
|
|
pOut->numSamples = numSamples;
|
|
}
|
|
|
|
// Caller makes sure pOut->pTileInfo is not NULL, see HwlComputeSurfaceInfo
|
|
ADDR_ASSERT(pOut->pTileInfo);
|
|
|
|
if (pOut->pTileInfo != NULL)
|
|
{
|
|
pTileInfo = pOut->pTileInfo;
|
|
}
|
|
|
|
// Set default values
|
|
if (pIn->pTileInfo != NULL)
|
|
{
|
|
if (pTileInfo != pIn->pTileInfo)
|
|
{
|
|
*pTileInfo = *pIn->pTileInfo;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
memset(pTileInfo, 0, sizeof(ADDR_TILEINFO));
|
|
}
|
|
|
|
// For macro tile mode, we should calculate default tiling parameters
|
|
HwlSetupTileInfo(tileMode,
|
|
flags,
|
|
bpp,
|
|
pitch,
|
|
height,
|
|
numSamples,
|
|
pIn->pTileInfo,
|
|
pTileInfo,
|
|
pIn->tileType,
|
|
pOut);
|
|
|
|
if (flags.cube)
|
|
{
|
|
if (mipLevel == 0)
|
|
{
|
|
padDims = 2;
|
|
}
|
|
|
|
if (numSlices == 1)
|
|
{
|
|
// This is calculating one face, remove cube flag
|
|
flags.cube = 0;
|
|
}
|
|
}
|
|
|
|
switch (tileMode)
|
|
{
|
|
case ADDR_TM_LINEAR_GENERAL://fall through
|
|
case ADDR_TM_LINEAR_ALIGNED:
|
|
valid = ComputeSurfaceInfoLinear(pIn, pOut, padDims);
|
|
break;
|
|
|
|
case ADDR_TM_1D_TILED_THIN1://fall through
|
|
case ADDR_TM_1D_TILED_THICK:
|
|
valid = ComputeSurfaceInfoMicroTiled(pIn, pOut, padDims, tileMode);
|
|
break;
|
|
|
|
case ADDR_TM_2D_TILED_THIN1: //fall through
|
|
case ADDR_TM_2D_TILED_THICK: //fall through
|
|
case ADDR_TM_3D_TILED_THIN1: //fall through
|
|
case ADDR_TM_3D_TILED_THICK: //fall through
|
|
case ADDR_TM_2D_TILED_XTHICK: //fall through
|
|
case ADDR_TM_3D_TILED_XTHICK: //fall through
|
|
case ADDR_TM_PRT_TILED_THIN1: //fall through
|
|
case ADDR_TM_PRT_2D_TILED_THIN1://fall through
|
|
case ADDR_TM_PRT_3D_TILED_THIN1://fall through
|
|
case ADDR_TM_PRT_TILED_THICK: //fall through
|
|
case ADDR_TM_PRT_2D_TILED_THICK://fall through
|
|
case ADDR_TM_PRT_3D_TILED_THICK:
|
|
valid = ComputeSurfaceInfoMacroTiled(pIn, pOut, padDims, tileMode);
|
|
break;
|
|
|
|
default:
|
|
valid = FALSE;
|
|
ADDR_ASSERT_ALWAYS();
|
|
break;
|
|
}
|
|
|
|
return valid;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::ComputeSurfaceInfoLinear
|
|
*
|
|
* @brief
|
|
* Compute linear surface sizes include padded pitch, height, slices, total size in
|
|
* bytes, meanwhile alignments as well. Since it is linear mode, so output tile mode
|
|
* will not be changed here. Results are returned through output parameters.
|
|
*
|
|
* @return
|
|
* TRUE if no error occurs
|
|
****************************************************************************************************
|
|
*/
|
|
BOOL_32 EgBasedLib::ComputeSurfaceInfoLinear(
|
|
const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] Input structure
|
|
ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut, ///< [out] Output structure
|
|
UINT_32 padDims ///< [in] Dimensions to padd
|
|
) const
|
|
{
|
|
UINT_32 expPitch = pIn->width;
|
|
UINT_32 expHeight = pIn->height;
|
|
UINT_32 expNumSlices = pIn->numSlices;
|
|
|
|
// No linear MSAA on real H/W, keep this for TGL
|
|
UINT_32 numSamples = pOut->numSamples;
|
|
|
|
const UINT_32 microTileThickness = 1;
|
|
|
|
//
|
|
// Compute the surface alignments.
|
|
//
|
|
ComputeSurfaceAlignmentsLinear(pIn->tileMode,
|
|
pIn->bpp,
|
|
pIn->flags,
|
|
&pOut->baseAlign,
|
|
&pOut->pitchAlign,
|
|
&pOut->heightAlign);
|
|
|
|
if (pIn->pitchAlign != 0)
|
|
{
|
|
ADDR_ASSERT((pIn->pitchAlign % pOut->pitchAlign) == 0);
|
|
pOut->pitchAlign = pIn->pitchAlign;
|
|
}
|
|
|
|
if (pIn->heightAlign != 0)
|
|
{
|
|
ADDR_ASSERT((pIn->heightAlign % pOut->heightAlign) == 0);
|
|
pOut->heightAlign = pIn->heightAlign;
|
|
}
|
|
|
|
if ((pIn->tileMode == ADDR_TM_LINEAR_GENERAL) && pIn->flags.color && (pIn->height > 1))
|
|
{
|
|
#if !ALT_TEST
|
|
// When linear_general surface is accessed in multiple lines, it requires 8 pixels in pitch
|
|
// alignment since PITCH_TILE_MAX is in unit of 8 pixels.
|
|
// It is OK if it is accessed per line.
|
|
ADDR_ASSERT((pIn->width % 8) == 0);
|
|
#endif
|
|
}
|
|
|
|
pOut->depthAlign = microTileThickness;
|
|
|
|
expPitch = HwlPreHandleBaseLvl3xPitch(pIn, expPitch);
|
|
|
|
//
|
|
// Pad pitch and height to the required granularities.
|
|
//
|
|
PadDimensions(pIn->tileMode,
|
|
pIn->bpp,
|
|
pIn->flags,
|
|
numSamples,
|
|
pOut->pTileInfo,
|
|
padDims,
|
|
pIn->mipLevel,
|
|
&expPitch, &pOut->pitchAlign,
|
|
&expHeight, pOut->heightAlign,
|
|
&expNumSlices, microTileThickness);
|
|
|
|
expPitch = HwlPostHandleBaseLvl3xPitch(pIn, expPitch);
|
|
|
|
//
|
|
// Adjust per HWL
|
|
//
|
|
|
|
UINT_64 logicalSliceSize;
|
|
|
|
logicalSliceSize = HwlGetSizeAdjustmentLinear(pIn->tileMode,
|
|
pIn->bpp,
|
|
numSamples,
|
|
pOut->baseAlign,
|
|
pOut->pitchAlign,
|
|
&expPitch,
|
|
&expHeight,
|
|
&pOut->heightAlign);
|
|
|
|
|
|
pOut->pitch = expPitch;
|
|
pOut->height = expHeight;
|
|
pOut->depth = expNumSlices;
|
|
|
|
pOut->surfSize = logicalSliceSize * expNumSlices;
|
|
|
|
pOut->tileMode = pIn->tileMode;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::ComputeSurfaceInfoMicroTiled
|
|
*
|
|
* @brief
|
|
* Compute 1D/Micro Tiled surface sizes include padded pitch, height, slices, total
|
|
* size in bytes, meanwhile alignments as well. Results are returned through output
|
|
* parameters.
|
|
*
|
|
* @return
|
|
* TRUE if no error occurs
|
|
****************************************************************************************************
|
|
*/
|
|
BOOL_32 EgBasedLib::ComputeSurfaceInfoMicroTiled(
|
|
const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] Input structure
|
|
ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut, ///< [out] Output structure
|
|
UINT_32 padDims, ///< [in] Dimensions to padd
|
|
AddrTileMode expTileMode ///< [in] Expected tile mode
|
|
) const
|
|
{
|
|
BOOL_32 valid = TRUE;
|
|
|
|
UINT_32 microTileThickness;
|
|
UINT_32 expPitch = pIn->width;
|
|
UINT_32 expHeight = pIn->height;
|
|
UINT_32 expNumSlices = pIn->numSlices;
|
|
|
|
// No 1D MSAA on real H/W, keep this for TGL
|
|
UINT_32 numSamples = pOut->numSamples;
|
|
|
|
//
|
|
// Compute the micro tile thickness.
|
|
//
|
|
microTileThickness = Thickness(expTileMode);
|
|
|
|
//
|
|
// Extra override for mip levels
|
|
//
|
|
if (pIn->mipLevel > 0)
|
|
{
|
|
//
|
|
// Reduce tiling mode from thick to thin if the number of slices is less than the
|
|
// micro tile thickness.
|
|
//
|
|
if ((expTileMode == ADDR_TM_1D_TILED_THICK) &&
|
|
(expNumSlices < ThickTileThickness))
|
|
{
|
|
expTileMode = HwlDegradeThickTileMode(ADDR_TM_1D_TILED_THICK, expNumSlices, NULL);
|
|
if (expTileMode != ADDR_TM_1D_TILED_THICK)
|
|
{
|
|
microTileThickness = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Compute the surface restrictions.
|
|
//
|
|
ComputeSurfaceAlignmentsMicroTiled(expTileMode,
|
|
pIn->bpp,
|
|
pIn->flags,
|
|
pIn->mipLevel,
|
|
numSamples,
|
|
&pOut->baseAlign,
|
|
&pOut->pitchAlign,
|
|
&pOut->heightAlign);
|
|
|
|
pOut->depthAlign = microTileThickness;
|
|
|
|
//
|
|
// Pad pitch and height to the required granularities.
|
|
// Compute surface size.
|
|
// Return parameters.
|
|
//
|
|
PadDimensions(expTileMode,
|
|
pIn->bpp,
|
|
pIn->flags,
|
|
numSamples,
|
|
pOut->pTileInfo,
|
|
padDims,
|
|
pIn->mipLevel,
|
|
&expPitch, &pOut->pitchAlign,
|
|
&expHeight, pOut->heightAlign,
|
|
&expNumSlices, microTileThickness);
|
|
|
|
//
|
|
// Get HWL specific pitch adjustment
|
|
//
|
|
UINT_64 logicalSliceSize = HwlGetSizeAdjustmentMicroTiled(microTileThickness,
|
|
pIn->bpp,
|
|
pIn->flags,
|
|
numSamples,
|
|
pOut->baseAlign,
|
|
pOut->pitchAlign,
|
|
&expPitch,
|
|
&expHeight);
|
|
|
|
|
|
pOut->pitch = expPitch;
|
|
pOut->height = expHeight;
|
|
pOut->depth = expNumSlices;
|
|
|
|
pOut->surfSize = logicalSliceSize * expNumSlices;
|
|
|
|
pOut->tileMode = expTileMode;
|
|
|
|
return valid;
|
|
}
|
|
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::ComputeSurfaceInfoMacroTiled
|
|
*
|
|
* @brief
|
|
* Compute 2D/macro tiled surface sizes include padded pitch, height, slices, total
|
|
* size in bytes, meanwhile output suitable tile mode and alignments might be changed
|
|
* in this call as well. Results are returned through output parameters.
|
|
*
|
|
* @return
|
|
* TRUE if no error occurs
|
|
****************************************************************************************************
|
|
*/
|
|
BOOL_32 EgBasedLib::ComputeSurfaceInfoMacroTiled(
|
|
const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] Input structure
|
|
ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut, ///< [out] Output structure
|
|
UINT_32 padDims, ///< [in] Dimensions to padd
|
|
AddrTileMode expTileMode ///< [in] Expected tile mode
|
|
) const
|
|
{
|
|
BOOL_32 valid = TRUE;
|
|
|
|
AddrTileMode origTileMode = expTileMode;
|
|
UINT_32 microTileThickness;
|
|
|
|
UINT_32 paddedPitch;
|
|
UINT_32 paddedHeight;
|
|
UINT_64 bytesPerSlice;
|
|
|
|
UINT_32 expPitch = pIn->width;
|
|
UINT_32 expHeight = pIn->height;
|
|
UINT_32 expNumSlices = pIn->numSlices;
|
|
|
|
UINT_32 numSamples = pOut->numSamples;
|
|
|
|
//
|
|
// Compute the surface restrictions as base
|
|
// SanityCheckMacroTiled is called in ComputeSurfaceAlignmentsMacroTiled
|
|
//
|
|
valid = ComputeSurfaceAlignmentsMacroTiled(expTileMode,
|
|
pIn->bpp,
|
|
pIn->flags,
|
|
pIn->mipLevel,
|
|
numSamples,
|
|
pOut);
|
|
|
|
if (valid)
|
|
{
|
|
//
|
|
// Compute the micro tile thickness.
|
|
//
|
|
microTileThickness = Thickness(expTileMode);
|
|
|
|
//
|
|
// Find the correct tiling mode for mip levels
|
|
//
|
|
if (pIn->mipLevel > 0)
|
|
{
|
|
//
|
|
// Try valid tile mode
|
|
//
|
|
expTileMode = ComputeSurfaceMipLevelTileMode(expTileMode,
|
|
pIn->bpp,
|
|
expPitch,
|
|
expHeight,
|
|
expNumSlices,
|
|
numSamples,
|
|
pOut->blockWidth,
|
|
pOut->blockHeight,
|
|
pOut->pTileInfo);
|
|
|
|
if (!IsMacroTiled(expTileMode)) // Downgraded to micro-tiled
|
|
{
|
|
return ComputeSurfaceInfoMicroTiled(pIn, pOut, padDims, expTileMode);
|
|
}
|
|
else if (microTileThickness != Thickness(expTileMode))
|
|
{
|
|
//
|
|
// Re-compute if thickness changed since bank-height may be changed!
|
|
//
|
|
return ComputeSurfaceInfoMacroTiled(pIn, pOut, padDims, expTileMode);
|
|
}
|
|
}
|
|
|
|
paddedPitch = expPitch;
|
|
paddedHeight = expHeight;
|
|
|
|
//
|
|
// Re-cal alignment
|
|
//
|
|
if (expTileMode != origTileMode) // Tile mode is changed but still macro-tiled
|
|
{
|
|
valid = ComputeSurfaceAlignmentsMacroTiled(expTileMode,
|
|
pIn->bpp,
|
|
pIn->flags,
|
|
pIn->mipLevel,
|
|
numSamples,
|
|
pOut);
|
|
}
|
|
|
|
//
|
|
// Do padding
|
|
//
|
|
PadDimensions(expTileMode,
|
|
pIn->bpp,
|
|
pIn->flags,
|
|
numSamples,
|
|
pOut->pTileInfo,
|
|
padDims,
|
|
pIn->mipLevel,
|
|
&paddedPitch, &pOut->pitchAlign,
|
|
&paddedHeight, pOut->heightAlign,
|
|
&expNumSlices, microTileThickness);
|
|
|
|
if (pIn->flags.qbStereo &&
|
|
(pOut->pStereoInfo != NULL))
|
|
{
|
|
UINT_32 stereoHeightAlign = HwlStereoCheckRightOffsetPadding(pOut->pTileInfo);
|
|
|
|
if (stereoHeightAlign != 0)
|
|
{
|
|
paddedHeight = PowTwoAlign(paddedHeight, stereoHeightAlign);
|
|
}
|
|
}
|
|
|
|
if ((pIn->flags.needEquation == TRUE) &&
|
|
(m_chipFamily == ADDR_CHIP_FAMILY_SI) &&
|
|
(pIn->numMipLevels > 1) &&
|
|
(pIn->mipLevel == 0))
|
|
{
|
|
BOOL_32 convertTo1D = FALSE;
|
|
|
|
ADDR_ASSERT(Thickness(expTileMode) == 1);
|
|
|
|
for (UINT_32 i = 1; i < pIn->numMipLevels; i++)
|
|
{
|
|
UINT_32 mipPitch = Max(1u, paddedPitch >> i);
|
|
UINT_32 mipHeight = Max(1u, pIn->height >> i);
|
|
UINT_32 mipSlices = pIn->flags.volume ?
|
|
Max(1u, pIn->numSlices >> i) : pIn->numSlices;
|
|
expTileMode = ComputeSurfaceMipLevelTileMode(expTileMode,
|
|
pIn->bpp,
|
|
mipPitch,
|
|
mipHeight,
|
|
mipSlices,
|
|
numSamples,
|
|
pOut->blockWidth,
|
|
pOut->blockHeight,
|
|
pOut->pTileInfo);
|
|
|
|
if (IsMacroTiled(expTileMode))
|
|
{
|
|
if (PowTwoAlign(mipPitch, pOut->blockWidth) !=
|
|
PowTwoAlign(mipPitch, pOut->pitchAlign))
|
|
{
|
|
convertTo1D = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (convertTo1D)
|
|
{
|
|
return ComputeSurfaceInfoMicroTiled(pIn, pOut, padDims, ADDR_TM_1D_TILED_THIN1);
|
|
}
|
|
}
|
|
|
|
pOut->pitch = paddedPitch;
|
|
// Put this check right here to workaround special mipmap cases which the original height
|
|
// is needed.
|
|
// The original height is pre-stored in pOut->height in PostComputeMipLevel and
|
|
// pOut->pitch is needed in HwlCheckLastMacroTiledLvl, too.
|
|
if (m_configFlags.checkLast2DLevel && (numSamples == 1)) // Don't check MSAA
|
|
{
|
|
// Set a TRUE in pOut if next Level is the first 1D sub level
|
|
HwlCheckLastMacroTiledLvl(pIn, pOut);
|
|
}
|
|
pOut->height = paddedHeight;
|
|
|
|
pOut->depth = expNumSlices;
|
|
|
|
//
|
|
// Compute the size of a slice.
|
|
//
|
|
bytesPerSlice = BITS_TO_BYTES(static_cast<UINT_64>(paddedPitch) *
|
|
paddedHeight * NextPow2(pIn->bpp) * numSamples);
|
|
|
|
pOut->surfSize = bytesPerSlice * expNumSlices;
|
|
|
|
pOut->tileMode = expTileMode;
|
|
|
|
pOut->depthAlign = microTileThickness;
|
|
|
|
} // if (valid)
|
|
|
|
return valid;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::ComputeSurfaceAlignmentsLinear
|
|
*
|
|
* @brief
|
|
* Compute linear surface alignment, calculation results are returned through
|
|
* output parameters.
|
|
*
|
|
* @return
|
|
* TRUE if no error occurs
|
|
****************************************************************************************************
|
|
*/
|
|
BOOL_32 EgBasedLib::ComputeSurfaceAlignmentsLinear(
|
|
AddrTileMode tileMode, ///< [in] tile mode
|
|
UINT_32 bpp, ///< [in] bits per pixel
|
|
ADDR_SURFACE_FLAGS flags, ///< [in] surface flags
|
|
UINT_32* pBaseAlign, ///< [out] base address alignment in bytes
|
|
UINT_32* pPitchAlign, ///< [out] pitch alignment in pixels
|
|
UINT_32* pHeightAlign ///< [out] height alignment in pixels
|
|
) const
|
|
{
|
|
BOOL_32 valid = TRUE;
|
|
|
|
switch (tileMode)
|
|
{
|
|
case ADDR_TM_LINEAR_GENERAL:
|
|
//
|
|
// The required base alignment and pitch and height granularities is to 1 element.
|
|
//
|
|
*pBaseAlign = (bpp > 8) ? bpp / 8 : 1;
|
|
*pPitchAlign = 1;
|
|
*pHeightAlign = 1;
|
|
break;
|
|
case ADDR_TM_LINEAR_ALIGNED:
|
|
//
|
|
// The required alignment for base is the pipe interleave size.
|
|
// The required granularity for pitch is hwl dependent.
|
|
// The required granularity for height is one row.
|
|
//
|
|
*pBaseAlign = m_pipeInterleaveBytes;
|
|
*pPitchAlign = HwlGetPitchAlignmentLinear(bpp, flags);
|
|
*pHeightAlign = 1;
|
|
break;
|
|
default:
|
|
*pBaseAlign = 1;
|
|
*pPitchAlign = 1;
|
|
*pHeightAlign = 1;
|
|
ADDR_UNHANDLED_CASE();
|
|
break;
|
|
}
|
|
|
|
AdjustPitchAlignment(flags, pPitchAlign);
|
|
|
|
return valid;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::ComputeSurfaceAlignmentsMicroTiled
|
|
*
|
|
* @brief
|
|
* Compute 1D tiled surface alignment, calculation results are returned through
|
|
* output parameters.
|
|
*
|
|
* @return
|
|
* TRUE if no error occurs
|
|
****************************************************************************************************
|
|
*/
|
|
BOOL_32 EgBasedLib::ComputeSurfaceAlignmentsMicroTiled(
|
|
AddrTileMode tileMode, ///< [in] tile mode
|
|
UINT_32 bpp, ///< [in] bits per pixel
|
|
ADDR_SURFACE_FLAGS flags, ///< [in] surface flags
|
|
UINT_32 mipLevel, ///< [in] mip level
|
|
UINT_32 numSamples, ///< [in] number of samples
|
|
UINT_32* pBaseAlign, ///< [out] base address alignment in bytes
|
|
UINT_32* pPitchAlign, ///< [out] pitch alignment in pixels
|
|
UINT_32* pHeightAlign ///< [out] height alignment in pixels
|
|
) const
|
|
{
|
|
BOOL_32 valid = TRUE;
|
|
|
|
//
|
|
// The required alignment for base is the pipe interleave size.
|
|
//
|
|
*pBaseAlign = m_pipeInterleaveBytes;
|
|
|
|
*pPitchAlign = HwlGetPitchAlignmentMicroTiled(tileMode, bpp, flags, numSamples);
|
|
|
|
*pHeightAlign = MicroTileHeight;
|
|
|
|
AdjustPitchAlignment(flags, pPitchAlign);
|
|
|
|
// ECR#393489
|
|
// Workaround 2 for 1D tiling - There is HW bug for Carrizo
|
|
// where it requires the following alignments for 1D tiling.
|
|
if (flags.czDispCompatible && (mipLevel == 0))
|
|
{
|
|
*pBaseAlign = PowTwoAlign(*pBaseAlign, 4096); //Base address MOD 4096 = 0
|
|
*pPitchAlign = PowTwoAlign(*pPitchAlign, 512 / (BITS_TO_BYTES(bpp))); //(8 lines * pitch * bytes per pixel) MOD 4096 = 0
|
|
}
|
|
// end Carrizo workaround for 1D tilling
|
|
|
|
return valid;
|
|
}
|
|
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::HwlReduceBankWidthHeight
|
|
*
|
|
* @brief
|
|
* Additional checks, reduce bankHeight/bankWidth if needed and possible
|
|
* tileSize*BANK_WIDTH*BANK_HEIGHT <= ROW_SIZE
|
|
*
|
|
* @return
|
|
* TRUE if no error occurs
|
|
****************************************************************************************************
|
|
*/
|
|
BOOL_32 EgBasedLib::HwlReduceBankWidthHeight(
|
|
UINT_32 tileSize, ///< [in] tile size
|
|
UINT_32 bpp, ///< [in] bits per pixel
|
|
ADDR_SURFACE_FLAGS flags, ///< [in] surface flags
|
|
UINT_32 numSamples, ///< [in] number of samples
|
|
UINT_32 bankHeightAlign, ///< [in] bank height alignment
|
|
UINT_32 pipes, ///< [in] pipes
|
|
ADDR_TILEINFO* pTileInfo ///< [in,out] bank structure.
|
|
) const
|
|
{
|
|
UINT_32 macroAspectAlign;
|
|
BOOL_32 valid = TRUE;
|
|
|
|
if (tileSize * pTileInfo->bankWidth * pTileInfo->bankHeight > m_rowSize)
|
|
{
|
|
BOOL_32 stillGreater = TRUE;
|
|
|
|
// Try reducing bankWidth first
|
|
if (stillGreater && pTileInfo->bankWidth > 1)
|
|
{
|
|
while (stillGreater && pTileInfo->bankWidth > 0)
|
|
{
|
|
pTileInfo->bankWidth >>= 1;
|
|
|
|
if (pTileInfo->bankWidth == 0)
|
|
{
|
|
pTileInfo->bankWidth = 1;
|
|
break;
|
|
}
|
|
|
|
stillGreater =
|
|
tileSize * pTileInfo->bankWidth * pTileInfo->bankHeight > m_rowSize;
|
|
}
|
|
|
|
// bankWidth is reduced above, so we need to recalculate bankHeight and ratio
|
|
bankHeightAlign = Max(1u,
|
|
m_pipeInterleaveBytes * m_bankInterleave /
|
|
(tileSize * pTileInfo->bankWidth)
|
|
);
|
|
|
|
// We cannot increase bankHeight so just assert this case.
|
|
ADDR_ASSERT((pTileInfo->bankHeight % bankHeightAlign) == 0);
|
|
|
|
if (numSamples == 1)
|
|
{
|
|
macroAspectAlign = Max(1u,
|
|
m_pipeInterleaveBytes * m_bankInterleave /
|
|
(tileSize * pipes * pTileInfo->bankWidth)
|
|
);
|
|
pTileInfo->macroAspectRatio = PowTwoAlign(pTileInfo->macroAspectRatio,
|
|
macroAspectAlign);
|
|
}
|
|
}
|
|
|
|
// Early quit bank_height degradation for "64" bit z buffer
|
|
if (flags.depth && bpp >= 64)
|
|
{
|
|
stillGreater = FALSE;
|
|
}
|
|
|
|
// Then try reducing bankHeight
|
|
if (stillGreater && pTileInfo->bankHeight > bankHeightAlign)
|
|
{
|
|
while (stillGreater && pTileInfo->bankHeight > bankHeightAlign)
|
|
{
|
|
pTileInfo->bankHeight >>= 1;
|
|
|
|
if (pTileInfo->bankHeight < bankHeightAlign)
|
|
{
|
|
pTileInfo->bankHeight = bankHeightAlign;
|
|
break;
|
|
}
|
|
|
|
stillGreater =
|
|
tileSize * pTileInfo->bankWidth * pTileInfo->bankHeight > m_rowSize;
|
|
}
|
|
}
|
|
|
|
valid = !stillGreater;
|
|
|
|
// Generate a warning if we still fail to meet this constraint
|
|
if (valid == FALSE)
|
|
{
|
|
ADDR_WARN(
|
|
0, ("TILE_SIZE(%d)*BANK_WIDTH(%d)*BANK_HEIGHT(%d) <= ROW_SIZE(%d)",
|
|
tileSize, pTileInfo->bankWidth, pTileInfo->bankHeight, m_rowSize));
|
|
}
|
|
}
|
|
|
|
return valid;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::ComputeSurfaceAlignmentsMacroTiled
|
|
*
|
|
* @brief
|
|
* Compute 2D tiled surface alignment, calculation results are returned through
|
|
* output parameters.
|
|
*
|
|
* @return
|
|
* TRUE if no error occurs
|
|
****************************************************************************************************
|
|
*/
|
|
BOOL_32 EgBasedLib::ComputeSurfaceAlignmentsMacroTiled(
|
|
AddrTileMode tileMode, ///< [in] tile mode
|
|
UINT_32 bpp, ///< [in] bits per pixel
|
|
ADDR_SURFACE_FLAGS flags, ///< [in] surface flags
|
|
UINT_32 mipLevel, ///< [in] mip level
|
|
UINT_32 numSamples, ///< [in] number of samples
|
|
ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [in,out] Surface output
|
|
) const
|
|
{
|
|
ADDR_TILEINFO* pTileInfo = pOut->pTileInfo;
|
|
|
|
BOOL_32 valid = SanityCheckMacroTiled(pTileInfo);
|
|
|
|
if (valid)
|
|
{
|
|
UINT_32 macroTileWidth;
|
|
UINT_32 macroTileHeight;
|
|
|
|
UINT_32 tileSize;
|
|
UINT_32 bankHeightAlign;
|
|
UINT_32 macroAspectAlign;
|
|
|
|
UINT_32 thickness = Thickness(tileMode);
|
|
UINT_32 pipes = HwlGetPipes(pTileInfo);
|
|
|
|
//
|
|
// Align bank height first according to latest h/w spec
|
|
//
|
|
|
|
// tile_size = MIN(tile_split, 64 * tile_thickness * element_bytes * num_samples)
|
|
tileSize = Min(pTileInfo->tileSplitBytes,
|
|
BITS_TO_BYTES(64 * thickness * bpp * numSamples));
|
|
|
|
// bank_height_align =
|
|
// MAX(1, (pipe_interleave_bytes * bank_interleave)/(tile_size*bank_width))
|
|
bankHeightAlign = Max(1u,
|
|
m_pipeInterleaveBytes * m_bankInterleave /
|
|
(tileSize * pTileInfo->bankWidth)
|
|
);
|
|
|
|
pTileInfo->bankHeight = PowTwoAlign(pTileInfo->bankHeight, bankHeightAlign);
|
|
|
|
// num_pipes * bank_width * macro_tile_aspect >=
|
|
// (pipe_interleave_size * bank_interleave) / tile_size
|
|
if (numSamples == 1)
|
|
{
|
|
// this restriction is only for mipmap (mipmap's numSamples must be 1)
|
|
macroAspectAlign = Max(1u,
|
|
m_pipeInterleaveBytes * m_bankInterleave /
|
|
(tileSize * pipes * pTileInfo->bankWidth)
|
|
);
|
|
pTileInfo->macroAspectRatio = PowTwoAlign(pTileInfo->macroAspectRatio, macroAspectAlign);
|
|
}
|
|
|
|
valid = HwlReduceBankWidthHeight(tileSize,
|
|
bpp,
|
|
flags,
|
|
numSamples,
|
|
bankHeightAlign,
|
|
pipes,
|
|
pTileInfo);
|
|
|
|
//
|
|
// The required granularity for pitch is the macro tile width.
|
|
//
|
|
macroTileWidth = MicroTileWidth * pTileInfo->bankWidth * pipes *
|
|
pTileInfo->macroAspectRatio;
|
|
|
|
pOut->pitchAlign = macroTileWidth;
|
|
pOut->blockWidth = macroTileWidth;
|
|
|
|
AdjustPitchAlignment(flags, &pOut->pitchAlign);
|
|
|
|
//
|
|
// The required granularity for height is the macro tile height.
|
|
//
|
|
macroTileHeight = MicroTileHeight * pTileInfo->bankHeight * pTileInfo->banks /
|
|
pTileInfo->macroAspectRatio;
|
|
|
|
pOut->heightAlign = macroTileHeight;
|
|
pOut->blockHeight = macroTileHeight;
|
|
|
|
//
|
|
// Compute base alignment
|
|
//
|
|
pOut->baseAlign =
|
|
pipes * pTileInfo->bankWidth * pTileInfo->banks * pTileInfo->bankHeight * tileSize;
|
|
|
|
HwlComputeSurfaceAlignmentsMacroTiled(tileMode, bpp, flags, mipLevel, numSamples, pOut);
|
|
}
|
|
|
|
return valid;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::SanityCheckMacroTiled
|
|
*
|
|
* @brief
|
|
* Check if macro-tiled parameters are valid
|
|
* @return
|
|
* TRUE if valid
|
|
****************************************************************************************************
|
|
*/
|
|
BOOL_32 EgBasedLib::SanityCheckMacroTiled(
|
|
ADDR_TILEINFO* pTileInfo ///< [in] macro-tiled parameters
|
|
) const
|
|
{
|
|
BOOL_32 valid = TRUE;
|
|
UINT_32 numPipes = HwlGetPipes(pTileInfo);
|
|
|
|
switch (pTileInfo->banks)
|
|
{
|
|
case 2: //fall through
|
|
case 4: //fall through
|
|
case 8: //fall through
|
|
case 16:
|
|
break;
|
|
default:
|
|
valid = FALSE;
|
|
break;
|
|
|
|
}
|
|
|
|
if (valid)
|
|
{
|
|
switch (pTileInfo->bankWidth)
|
|
{
|
|
case 1: //fall through
|
|
case 2: //fall through
|
|
case 4: //fall through
|
|
case 8:
|
|
break;
|
|
default:
|
|
valid = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (valid)
|
|
{
|
|
switch (pTileInfo->bankHeight)
|
|
{
|
|
case 1: //fall through
|
|
case 2: //fall through
|
|
case 4: //fall through
|
|
case 8:
|
|
break;
|
|
default:
|
|
valid = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (valid)
|
|
{
|
|
switch (pTileInfo->macroAspectRatio)
|
|
{
|
|
case 1: //fall through
|
|
case 2: //fall through
|
|
case 4: //fall through
|
|
case 8:
|
|
break;
|
|
default:
|
|
valid = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (valid)
|
|
{
|
|
if (pTileInfo->banks < pTileInfo->macroAspectRatio)
|
|
{
|
|
// This will generate macro tile height <= 1
|
|
valid = FALSE;
|
|
}
|
|
}
|
|
|
|
if (valid)
|
|
{
|
|
if (pTileInfo->tileSplitBytes > m_rowSize)
|
|
{
|
|
ADDR_WARN(0, ("tileSplitBytes is bigger than row size"));
|
|
}
|
|
}
|
|
|
|
if (valid)
|
|
{
|
|
valid = HwlSanityCheckMacroTiled(pTileInfo);
|
|
}
|
|
|
|
ADDR_ASSERT(valid == TRUE);
|
|
|
|
// Add this assert for guidance
|
|
ADDR_ASSERT(numPipes * pTileInfo->banks >= 4);
|
|
|
|
return valid;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::ComputeSurfaceMipLevelTileMode
|
|
*
|
|
* @brief
|
|
* Compute valid tile mode for surface mipmap sub-levels
|
|
*
|
|
* @return
|
|
* Suitable tile mode
|
|
****************************************************************************************************
|
|
*/
|
|
AddrTileMode EgBasedLib::ComputeSurfaceMipLevelTileMode(
|
|
AddrTileMode baseTileMode, ///< [in] base tile mode
|
|
UINT_32 bpp, ///< [in] bits per pixels
|
|
UINT_32 pitch, ///< [in] current level pitch
|
|
UINT_32 height, ///< [in] current level height
|
|
UINT_32 numSlices, ///< [in] current number of slices
|
|
UINT_32 numSamples, ///< [in] number of samples
|
|
UINT_32 pitchAlign, ///< [in] pitch alignment
|
|
UINT_32 heightAlign, ///< [in] height alignment
|
|
ADDR_TILEINFO* pTileInfo ///< [in] ptr to bank structure
|
|
) const
|
|
{
|
|
UINT_32 bytesPerTile;
|
|
|
|
AddrTileMode expTileMode = baseTileMode;
|
|
UINT_32 microTileThickness = Thickness(expTileMode);
|
|
UINT_32 interleaveSize = m_pipeInterleaveBytes * m_bankInterleave;
|
|
|
|
//
|
|
// Compute the size of a slice.
|
|
//
|
|
bytesPerTile = BITS_TO_BYTES(MicroTilePixels * microTileThickness * NextPow2(bpp) * numSamples);
|
|
|
|
//
|
|
// Reduce tiling mode from thick to thin if the number of slices is less than the
|
|
// micro tile thickness.
|
|
//
|
|
if (numSlices < microTileThickness)
|
|
{
|
|
expTileMode = HwlDegradeThickTileMode(expTileMode, numSlices, &bytesPerTile);
|
|
}
|
|
|
|
if (bytesPerTile > pTileInfo->tileSplitBytes)
|
|
{
|
|
bytesPerTile = pTileInfo->tileSplitBytes;
|
|
}
|
|
|
|
UINT_32 threshold1 =
|
|
bytesPerTile * HwlGetPipes(pTileInfo) * pTileInfo->bankWidth * pTileInfo->macroAspectRatio;
|
|
|
|
UINT_32 threshold2 =
|
|
bytesPerTile * pTileInfo->bankWidth * pTileInfo->bankHeight;
|
|
|
|
//
|
|
// Reduce the tile mode from 2D/3D to 1D in following conditions
|
|
//
|
|
switch (expTileMode)
|
|
{
|
|
case ADDR_TM_2D_TILED_THIN1: //fall through
|
|
case ADDR_TM_3D_TILED_THIN1:
|
|
case ADDR_TM_PRT_TILED_THIN1:
|
|
case ADDR_TM_PRT_2D_TILED_THIN1:
|
|
case ADDR_TM_PRT_3D_TILED_THIN1:
|
|
if ((pitch < pitchAlign) ||
|
|
(height < heightAlign) ||
|
|
(interleaveSize > threshold1) ||
|
|
(interleaveSize > threshold2))
|
|
{
|
|
expTileMode = ADDR_TM_1D_TILED_THIN1;
|
|
}
|
|
break;
|
|
case ADDR_TM_2D_TILED_THICK: //fall through
|
|
case ADDR_TM_3D_TILED_THICK:
|
|
case ADDR_TM_2D_TILED_XTHICK:
|
|
case ADDR_TM_3D_TILED_XTHICK:
|
|
case ADDR_TM_PRT_TILED_THICK:
|
|
case ADDR_TM_PRT_2D_TILED_THICK:
|
|
case ADDR_TM_PRT_3D_TILED_THICK:
|
|
if ((pitch < pitchAlign) ||
|
|
(height < heightAlign))
|
|
{
|
|
expTileMode = ADDR_TM_1D_TILED_THICK;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return expTileMode;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::HwlGetAlignmentInfoMacroTiled
|
|
* @brief
|
|
* Get alignment info for giving tile mode
|
|
* @return
|
|
* TRUE if getting alignment is OK
|
|
****************************************************************************************************
|
|
*/
|
|
BOOL_32 EgBasedLib::HwlGetAlignmentInfoMacroTiled(
|
|
const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] create surface info
|
|
UINT_32* pPitchAlign, ///< [out] pitch alignment
|
|
UINT_32* pHeightAlign, ///< [out] height alignment
|
|
UINT_32* pSizeAlign ///< [out] size alignment
|
|
) const
|
|
{
|
|
BOOL_32 valid = TRUE;
|
|
|
|
ADDR_ASSERT(IsMacroTiled(pIn->tileMode));
|
|
|
|
UINT_32 numSamples = (pIn->numFrags == 0) ? pIn->numSamples : pIn->numFrags;
|
|
|
|
ADDR_ASSERT(pIn->pTileInfo);
|
|
ADDR_TILEINFO tileInfo = *pIn->pTileInfo;
|
|
ADDR_COMPUTE_SURFACE_INFO_OUTPUT out = {0};
|
|
out.pTileInfo = &tileInfo;
|
|
|
|
if (UseTileIndex(pIn->tileIndex))
|
|
{
|
|
out.tileIndex = pIn->tileIndex;
|
|
out.macroModeIndex = TileIndexInvalid;
|
|
}
|
|
|
|
HwlSetupTileInfo(pIn->tileMode,
|
|
pIn->flags,
|
|
pIn->bpp,
|
|
pIn->width,
|
|
pIn->height,
|
|
numSamples,
|
|
&tileInfo,
|
|
&tileInfo,
|
|
pIn->tileType,
|
|
&out);
|
|
|
|
valid = ComputeSurfaceAlignmentsMacroTiled(pIn->tileMode,
|
|
pIn->bpp,
|
|
pIn->flags,
|
|
pIn->mipLevel,
|
|
numSamples,
|
|
&out);
|
|
|
|
if (valid)
|
|
{
|
|
*pPitchAlign = out.pitchAlign;
|
|
*pHeightAlign = out.heightAlign;
|
|
*pSizeAlign = out.baseAlign;
|
|
}
|
|
|
|
return valid;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::HwlDegradeThickTileMode
|
|
*
|
|
* @brief
|
|
* Degrades valid tile mode for thick modes if needed
|
|
*
|
|
* @return
|
|
* Suitable tile mode
|
|
****************************************************************************************************
|
|
*/
|
|
AddrTileMode EgBasedLib::HwlDegradeThickTileMode(
|
|
AddrTileMode baseTileMode, ///< [in] base tile mode
|
|
UINT_32 numSlices, ///< [in] current number of slices
|
|
UINT_32* pBytesPerTile ///< [in,out] pointer to bytes per slice
|
|
) const
|
|
{
|
|
ADDR_ASSERT(numSlices < Thickness(baseTileMode));
|
|
// if pBytesPerTile is NULL, this is a don't-care....
|
|
UINT_32 bytesPerTile = pBytesPerTile != NULL ? *pBytesPerTile : 64;
|
|
|
|
AddrTileMode expTileMode = baseTileMode;
|
|
switch (baseTileMode)
|
|
{
|
|
case ADDR_TM_1D_TILED_THICK:
|
|
expTileMode = ADDR_TM_1D_TILED_THIN1;
|
|
bytesPerTile >>= 2;
|
|
break;
|
|
case ADDR_TM_2D_TILED_THICK:
|
|
expTileMode = ADDR_TM_2D_TILED_THIN1;
|
|
bytesPerTile >>= 2;
|
|
break;
|
|
case ADDR_TM_3D_TILED_THICK:
|
|
expTileMode = ADDR_TM_3D_TILED_THIN1;
|
|
bytesPerTile >>= 2;
|
|
break;
|
|
case ADDR_TM_2D_TILED_XTHICK:
|
|
if (numSlices < ThickTileThickness)
|
|
{
|
|
expTileMode = ADDR_TM_2D_TILED_THIN1;
|
|
bytesPerTile >>= 3;
|
|
}
|
|
else
|
|
{
|
|
expTileMode = ADDR_TM_2D_TILED_THICK;
|
|
bytesPerTile >>= 1;
|
|
}
|
|
break;
|
|
case ADDR_TM_3D_TILED_XTHICK:
|
|
if (numSlices < ThickTileThickness)
|
|
{
|
|
expTileMode = ADDR_TM_3D_TILED_THIN1;
|
|
bytesPerTile >>= 3;
|
|
}
|
|
else
|
|
{
|
|
expTileMode = ADDR_TM_3D_TILED_THICK;
|
|
bytesPerTile >>= 1;
|
|
}
|
|
break;
|
|
default:
|
|
ADDR_ASSERT_ALWAYS();
|
|
break;
|
|
}
|
|
|
|
if (pBytesPerTile != NULL)
|
|
{
|
|
*pBytesPerTile = bytesPerTile;
|
|
}
|
|
|
|
return expTileMode;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::DispatchComputeSurfaceAddrFromCoord
|
|
*
|
|
* @brief
|
|
* Compute surface address from given coord (x, y, slice,sample)
|
|
*
|
|
* @return
|
|
* Address in bytes
|
|
****************************************************************************************************
|
|
*/
|
|
UINT_64 EgBasedLib::DispatchComputeSurfaceAddrFromCoord(
|
|
const ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn, ///< [in] input structure
|
|
ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT* pOut ///< [out] output structure
|
|
) const
|
|
{
|
|
UINT_32 x = pIn->x;
|
|
UINT_32 y = pIn->y;
|
|
UINT_32 slice = pIn->slice;
|
|
UINT_32 sample = pIn->sample;
|
|
UINT_32 bpp = pIn->bpp;
|
|
UINT_32 pitch = pIn->pitch;
|
|
UINT_32 height = pIn->height;
|
|
UINT_32 numSlices = pIn->numSlices;
|
|
UINT_32 numSamples = ((pIn->numSamples == 0) ? 1 : pIn->numSamples);
|
|
UINT_32 numFrags = ((pIn->numFrags == 0) ? numSamples : pIn->numFrags);
|
|
AddrTileMode tileMode = pIn->tileMode;
|
|
AddrTileType microTileType = pIn->tileType;
|
|
BOOL_32 ignoreSE = pIn->ignoreSE;
|
|
BOOL_32 isDepthSampleOrder = pIn->isDepth;
|
|
ADDR_TILEINFO* pTileInfo = pIn->pTileInfo;
|
|
|
|
UINT_32* pBitPosition = &pOut->bitPosition;
|
|
UINT_64 addr;
|
|
|
|
#if ADDR_AM_BUILD
|
|
UINT_32 addr5Bit = 0;
|
|
UINT_32 addr5Swizzle = pIn->addr5Swizzle;
|
|
BOOL_32 is32ByteTile = pIn->is32ByteTile;
|
|
#endif
|
|
|
|
// ADDR_DEPTH_SAMPLE_ORDER = non-disp + depth-sample-order
|
|
if (microTileType == ADDR_DEPTH_SAMPLE_ORDER)
|
|
{
|
|
isDepthSampleOrder = TRUE;
|
|
}
|
|
|
|
if (m_chipFamily >= ADDR_CHIP_FAMILY_NI)
|
|
{
|
|
if (numFrags != numSamples)
|
|
{
|
|
numSamples = numFrags;
|
|
ADDR_ASSERT(sample < numSamples);
|
|
}
|
|
|
|
/// @note
|
|
/// 128 bit/thick tiled surface doesn't support display tiling and
|
|
/// mipmap chain must have the same tileType, so please fill tileType correctly
|
|
if (IsLinear(pIn->tileMode) == FALSE)
|
|
{
|
|
if (bpp >= 128 || Thickness(tileMode) > 1)
|
|
{
|
|
ADDR_ASSERT(microTileType != ADDR_DISPLAYABLE);
|
|
}
|
|
}
|
|
}
|
|
|
|
switch (tileMode)
|
|
{
|
|
case ADDR_TM_LINEAR_GENERAL://fall through
|
|
case ADDR_TM_LINEAR_ALIGNED:
|
|
addr = ComputeSurfaceAddrFromCoordLinear(x,
|
|
y,
|
|
slice,
|
|
sample,
|
|
bpp,
|
|
pitch,
|
|
height,
|
|
numSlices,
|
|
pBitPosition);
|
|
break;
|
|
case ADDR_TM_1D_TILED_THIN1://fall through
|
|
case ADDR_TM_1D_TILED_THICK:
|
|
addr = ComputeSurfaceAddrFromCoordMicroTiled(x,
|
|
y,
|
|
slice,
|
|
sample,
|
|
bpp,
|
|
pitch,
|
|
height,
|
|
numSamples,
|
|
tileMode,
|
|
microTileType,
|
|
isDepthSampleOrder,
|
|
pBitPosition);
|
|
break;
|
|
case ADDR_TM_2D_TILED_THIN1: //fall through
|
|
case ADDR_TM_2D_TILED_THICK: //fall through
|
|
case ADDR_TM_3D_TILED_THIN1: //fall through
|
|
case ADDR_TM_3D_TILED_THICK: //fall through
|
|
case ADDR_TM_2D_TILED_XTHICK: //fall through
|
|
case ADDR_TM_3D_TILED_XTHICK: //fall through
|
|
case ADDR_TM_PRT_TILED_THIN1: //fall through
|
|
case ADDR_TM_PRT_2D_TILED_THIN1://fall through
|
|
case ADDR_TM_PRT_3D_TILED_THIN1://fall through
|
|
case ADDR_TM_PRT_TILED_THICK: //fall through
|
|
case ADDR_TM_PRT_2D_TILED_THICK://fall through
|
|
case ADDR_TM_PRT_3D_TILED_THICK:
|
|
UINT_32 pipeSwizzle;
|
|
UINT_32 bankSwizzle;
|
|
|
|
if (m_configFlags.useCombinedSwizzle)
|
|
{
|
|
ExtractBankPipeSwizzle(pIn->tileSwizzle, pIn->pTileInfo,
|
|
&bankSwizzle, &pipeSwizzle);
|
|
}
|
|
else
|
|
{
|
|
pipeSwizzle = pIn->pipeSwizzle;
|
|
bankSwizzle = pIn->bankSwizzle;
|
|
}
|
|
|
|
addr = ComputeSurfaceAddrFromCoordMacroTiled(x,
|
|
y,
|
|
slice,
|
|
sample,
|
|
bpp,
|
|
pitch,
|
|
height,
|
|
numSamples,
|
|
tileMode,
|
|
microTileType,
|
|
ignoreSE,
|
|
isDepthSampleOrder,
|
|
pipeSwizzle,
|
|
bankSwizzle,
|
|
pTileInfo,
|
|
pBitPosition);
|
|
break;
|
|
default:
|
|
addr = 0;
|
|
ADDR_ASSERT_ALWAYS();
|
|
break;
|
|
}
|
|
|
|
#if ADDR_AM_BUILD
|
|
if (m_chipFamily >= ADDR_CHIP_FAMILY_NI)
|
|
{
|
|
if (addr5Swizzle && isDepthSampleOrder && is32ByteTile)
|
|
{
|
|
UINT_32 tx = x >> 3;
|
|
UINT_32 ty = y >> 3;
|
|
UINT_32 tileBits = ((ty&0x3) << 2) | (tx&0x3);
|
|
|
|
tileBits = tileBits & addr5Swizzle;
|
|
addr5Bit = XorReduce(tileBits, 4);
|
|
|
|
addr = addr | static_cast<UINT_64>(addr5Bit << 5);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return addr;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::ComputeMacroTileEquation
|
|
*
|
|
* @brief
|
|
* Computes the address equation in macro tile
|
|
* @return
|
|
* If equation can be computed
|
|
****************************************************************************************************
|
|
*/
|
|
ADDR_E_RETURNCODE EgBasedLib::ComputeMacroTileEquation(
|
|
UINT_32 log2BytesPP, ///< [in] log2 of bytes per pixel
|
|
AddrTileMode tileMode, ///< [in] tile mode
|
|
AddrTileType microTileType, ///< [in] micro tiling type
|
|
ADDR_TILEINFO* pTileInfo, ///< [in] bank structure
|
|
ADDR_EQUATION* pEquation ///< [out] Equation for addressing in macro tile
|
|
) const
|
|
{
|
|
ADDR_E_RETURNCODE retCode;
|
|
|
|
// Element equation within a tile
|
|
retCode = ComputeMicroTileEquation(log2BytesPP, tileMode, microTileType, pEquation);
|
|
|
|
if (retCode == ADDR_OK)
|
|
{
|
|
// Tile equesiton with signle pipe bank
|
|
UINT_32 numPipes = HwlGetPipes(pTileInfo);
|
|
UINT_32 numPipeBits = Log2(numPipes);
|
|
|
|
for (UINT_32 i = 0; i < Log2(pTileInfo->bankWidth); i++)
|
|
{
|
|
pEquation->addr[pEquation->numBits].valid = 1;
|
|
pEquation->addr[pEquation->numBits].channel = 0;
|
|
pEquation->addr[pEquation->numBits].index = i + log2BytesPP + 3 + numPipeBits;
|
|
pEquation->numBits++;
|
|
}
|
|
|
|
for (UINT_32 i = 0; i < Log2(pTileInfo->bankHeight); i++)
|
|
{
|
|
pEquation->addr[pEquation->numBits].valid = 1;
|
|
pEquation->addr[pEquation->numBits].channel = 1;
|
|
pEquation->addr[pEquation->numBits].index = i + 3;
|
|
pEquation->numBits++;
|
|
}
|
|
|
|
ADDR_EQUATION equation;
|
|
memset(&equation, 0, sizeof(ADDR_EQUATION));
|
|
|
|
UINT_32 thresholdX = 32;
|
|
UINT_32 thresholdY = 32;
|
|
|
|
if (IsPrtNoRotationTileMode(tileMode))
|
|
{
|
|
UINT_32 macroTilePitch =
|
|
(MicroTileWidth * pTileInfo->bankWidth * numPipes) * pTileInfo->macroAspectRatio;
|
|
UINT_32 macroTileHeight =
|
|
(MicroTileHeight * pTileInfo->bankHeight * pTileInfo->banks) /
|
|
pTileInfo->macroAspectRatio;
|
|
thresholdX = Log2(macroTilePitch);
|
|
thresholdY = Log2(macroTileHeight);
|
|
}
|
|
|
|
// Pipe equation
|
|
retCode = ComputePipeEquation(log2BytesPP, thresholdX, thresholdY, pTileInfo, &equation);
|
|
|
|
if (retCode == ADDR_OK)
|
|
{
|
|
UINT_32 pipeBitStart = Log2(m_pipeInterleaveBytes);
|
|
|
|
if (pEquation->numBits > pipeBitStart)
|
|
{
|
|
UINT_32 numLeftShift = pEquation->numBits - pipeBitStart;
|
|
|
|
for (UINT_32 i = 0; i < numLeftShift; i++)
|
|
{
|
|
pEquation->addr[pEquation->numBits + equation.numBits - i - 1] =
|
|
pEquation->addr[pEquation->numBits - i - 1];
|
|
pEquation->xor1[pEquation->numBits + equation.numBits - i - 1] =
|
|
pEquation->xor1[pEquation->numBits - i - 1];
|
|
pEquation->xor2[pEquation->numBits + equation.numBits - i - 1] =
|
|
pEquation->xor2[pEquation->numBits - i - 1];
|
|
}
|
|
}
|
|
|
|
for (UINT_32 i = 0; i < equation.numBits; i++)
|
|
{
|
|
pEquation->addr[pipeBitStart + i] = equation.addr[i];
|
|
pEquation->xor1[pipeBitStart + i] = equation.xor1[i];
|
|
pEquation->xor2[pipeBitStart + i] = equation.xor2[i];
|
|
pEquation->numBits++;
|
|
}
|
|
|
|
// Bank equation
|
|
memset(&equation, 0, sizeof(ADDR_EQUATION));
|
|
|
|
retCode = ComputeBankEquation(log2BytesPP, thresholdX, thresholdY,
|
|
pTileInfo, &equation);
|
|
|
|
if (retCode == ADDR_OK)
|
|
{
|
|
UINT_32 bankBitStart = pipeBitStart + numPipeBits + Log2(m_bankInterleave);
|
|
|
|
if (pEquation->numBits > bankBitStart)
|
|
{
|
|
UINT_32 numLeftShift = pEquation->numBits - bankBitStart;
|
|
|
|
for (UINT_32 i = 0; i < numLeftShift; i++)
|
|
{
|
|
pEquation->addr[pEquation->numBits + equation.numBits - i - 1] =
|
|
pEquation->addr[pEquation->numBits - i - 1];
|
|
pEquation->xor1[pEquation->numBits + equation.numBits - i - 1] =
|
|
pEquation->xor1[pEquation->numBits - i - 1];
|
|
pEquation->xor2[pEquation->numBits + equation.numBits - i - 1] =
|
|
pEquation->xor2[pEquation->numBits - i - 1];
|
|
}
|
|
}
|
|
|
|
for (UINT_32 i = 0; i < equation.numBits; i++)
|
|
{
|
|
pEquation->addr[bankBitStart + i] = equation.addr[i];
|
|
pEquation->xor1[bankBitStart + i] = equation.xor1[i];
|
|
pEquation->xor2[bankBitStart + i] = equation.xor2[i];
|
|
pEquation->numBits++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return retCode;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::ComputeSurfaceAddrFromCoordMicroTiled
|
|
*
|
|
* @brief
|
|
* Computes the surface address and bit position from a
|
|
* coordinate for 2D tilied (macro tiled)
|
|
* @return
|
|
* The byte address
|
|
****************************************************************************************************
|
|
*/
|
|
UINT_64 EgBasedLib::ComputeSurfaceAddrFromCoordMacroTiled(
|
|
UINT_32 x, ///< [in] x coordinate
|
|
UINT_32 y, ///< [in] y coordinate
|
|
UINT_32 slice, ///< [in] slice index
|
|
UINT_32 sample, ///< [in] sample index
|
|
UINT_32 bpp, ///< [in] bits per pixel
|
|
UINT_32 pitch, ///< [in] surface pitch, in pixels
|
|
UINT_32 height, ///< [in] surface height, in pixels
|
|
UINT_32 numSamples, ///< [in] number of samples
|
|
AddrTileMode tileMode, ///< [in] tile mode
|
|
AddrTileType microTileType, ///< [in] micro tiling type
|
|
BOOL_32 ignoreSE, ///< [in] TRUE if shader enginers can be ignored
|
|
BOOL_32 isDepthSampleOrder, ///< [in] TRUE if it depth sample ordering is used
|
|
UINT_32 pipeSwizzle, ///< [in] pipe swizzle
|
|
UINT_32 bankSwizzle, ///< [in] bank swizzle
|
|
ADDR_TILEINFO* pTileInfo, ///< [in] bank structure
|
|
/// **All fields to be valid on entry**
|
|
UINT_32* pBitPosition ///< [out] bit position, e.g. FMT_1 will use this
|
|
) const
|
|
{
|
|
UINT_64 addr;
|
|
|
|
UINT_32 microTileBytes;
|
|
UINT_32 microTileBits;
|
|
UINT_32 sampleOffset;
|
|
UINT_32 pixelIndex;
|
|
UINT_32 pixelOffset;
|
|
UINT_32 elementOffset;
|
|
UINT_32 tileSplitSlice;
|
|
UINT_32 pipe;
|
|
UINT_32 bank;
|
|
UINT_64 sliceBytes;
|
|
UINT_64 sliceOffset;
|
|
UINT_32 macroTilePitch;
|
|
UINT_32 macroTileHeight;
|
|
UINT_32 macroTilesPerRow;
|
|
UINT_32 macroTilesPerSlice;
|
|
UINT_64 macroTileBytes;
|
|
UINT_32 macroTileIndexX;
|
|
UINT_32 macroTileIndexY;
|
|
UINT_64 macroTileOffset;
|
|
UINT_64 totalOffset;
|
|
UINT_64 pipeInterleaveMask;
|
|
UINT_64 bankInterleaveMask;
|
|
UINT_64 pipeInterleaveOffset;
|
|
UINT_32 bankInterleaveOffset;
|
|
UINT_64 offset;
|
|
UINT_32 tileRowIndex;
|
|
UINT_32 tileColumnIndex;
|
|
UINT_32 tileIndex;
|
|
UINT_32 tileOffset;
|
|
|
|
UINT_32 microTileThickness = Thickness(tileMode);
|
|
|
|
//
|
|
// Compute the number of group, pipe, and bank bits.
|
|
//
|
|
UINT_32 numPipes = HwlGetPipes(pTileInfo);
|
|
UINT_32 numPipeInterleaveBits = Log2(m_pipeInterleaveBytes);
|
|
UINT_32 numPipeBits = Log2(numPipes);
|
|
UINT_32 numBankInterleaveBits = Log2(m_bankInterleave);
|
|
UINT_32 numBankBits = Log2(pTileInfo->banks);
|
|
|
|
//
|
|
// Compute the micro tile size.
|
|
//
|
|
microTileBits = MicroTilePixels * microTileThickness * bpp * numSamples;
|
|
|
|
microTileBytes = microTileBits / 8;
|
|
//
|
|
// Compute the pixel index within the micro tile.
|
|
//
|
|
pixelIndex = ComputePixelIndexWithinMicroTile(x,
|
|
y,
|
|
slice,
|
|
bpp,
|
|
tileMode,
|
|
microTileType);
|
|
|
|
//
|
|
// Compute the sample offset and pixel offset.
|
|
//
|
|
if (isDepthSampleOrder)
|
|
{
|
|
//
|
|
// For depth surfaces, samples are stored contiguously for each element, so the sample
|
|
// offset is the sample number times the element size.
|
|
//
|
|
sampleOffset = sample * bpp;
|
|
pixelOffset = pixelIndex * bpp * numSamples;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// For color surfaces, all elements for a particular sample are stored contiguously, so
|
|
// the sample offset is the sample number times the micro tile size divided yBit the number
|
|
// of samples.
|
|
//
|
|
sampleOffset = sample * (microTileBits / numSamples);
|
|
pixelOffset = pixelIndex * bpp;
|
|
}
|
|
|
|
//
|
|
// Compute the element offset.
|
|
//
|
|
elementOffset = pixelOffset + sampleOffset;
|
|
|
|
*pBitPosition = static_cast<UINT_32>(elementOffset % 8);
|
|
|
|
elementOffset /= 8; //bit-to-byte
|
|
|
|
//
|
|
// Determine if tiles need to be split across slices.
|
|
//
|
|
// If the size of the micro tile is larger than the tile split size, then the tile will be
|
|
// split across multiple slices.
|
|
//
|
|
UINT_32 slicesPerTile = 1;
|
|
|
|
if ((microTileBytes > pTileInfo->tileSplitBytes) && (microTileThickness == 1))
|
|
{ //don't support for thick mode
|
|
|
|
//
|
|
// Compute the number of slices per tile.
|
|
//
|
|
slicesPerTile = microTileBytes / pTileInfo->tileSplitBytes;
|
|
|
|
//
|
|
// Compute the tile split slice number for use in rotating the bank.
|
|
//
|
|
tileSplitSlice = elementOffset / pTileInfo->tileSplitBytes;
|
|
|
|
//
|
|
// Adjust the element offset to account for the portion of the tile that is being moved to
|
|
// a new slice..
|
|
//
|
|
elementOffset %= pTileInfo->tileSplitBytes;
|
|
|
|
//
|
|
// Adjust the microTileBytes size to tileSplitBytes size since
|
|
// a new slice..
|
|
//
|
|
microTileBytes = pTileInfo->tileSplitBytes;
|
|
}
|
|
else
|
|
{
|
|
tileSplitSlice = 0;
|
|
}
|
|
|
|
//
|
|
// Compute macro tile pitch and height.
|
|
//
|
|
macroTilePitch =
|
|
(MicroTileWidth * pTileInfo->bankWidth * numPipes) * pTileInfo->macroAspectRatio;
|
|
macroTileHeight =
|
|
(MicroTileHeight * pTileInfo->bankHeight * pTileInfo->banks) / pTileInfo->macroAspectRatio;
|
|
|
|
//
|
|
// Compute the number of bytes per macro tile. Note: bytes of the same bank/pipe actually
|
|
//
|
|
macroTileBytes =
|
|
static_cast<UINT_64>(microTileBytes) *
|
|
(macroTilePitch / MicroTileWidth) * (macroTileHeight / MicroTileHeight) /
|
|
(numPipes * pTileInfo->banks);
|
|
|
|
//
|
|
// Compute the number of macro tiles per row.
|
|
//
|
|
macroTilesPerRow = pitch / macroTilePitch;
|
|
|
|
//
|
|
// Compute the offset to the macro tile containing the specified coordinate.
|
|
//
|
|
macroTileIndexX = x / macroTilePitch;
|
|
macroTileIndexY = y / macroTileHeight;
|
|
macroTileOffset = ((macroTileIndexY * macroTilesPerRow) + macroTileIndexX) * macroTileBytes;
|
|
|
|
//
|
|
// Compute the number of macro tiles per slice.
|
|
//
|
|
macroTilesPerSlice = macroTilesPerRow * (height / macroTileHeight);
|
|
|
|
//
|
|
// Compute the slice size.
|
|
//
|
|
sliceBytes = macroTilesPerSlice * macroTileBytes;
|
|
|
|
//
|
|
// Compute the slice offset.
|
|
//
|
|
sliceOffset = sliceBytes * (tileSplitSlice + slicesPerTile * (slice / microTileThickness));
|
|
|
|
//
|
|
// Compute tile offest
|
|
//
|
|
tileRowIndex = (y / MicroTileHeight) % pTileInfo->bankHeight;
|
|
tileColumnIndex = ((x / MicroTileWidth) / numPipes) % pTileInfo->bankWidth;
|
|
tileIndex = (tileRowIndex * pTileInfo->bankWidth) + tileColumnIndex;
|
|
tileOffset = tileIndex * microTileBytes;
|
|
|
|
//
|
|
// Combine the slice offset and macro tile offset with the pixel and sample offsets, accounting
|
|
// for the pipe and bank bits in the middle of the address.
|
|
//
|
|
totalOffset = sliceOffset + macroTileOffset + elementOffset + tileOffset;
|
|
|
|
//
|
|
// Get the pipe and bank.
|
|
//
|
|
|
|
// when the tileMode is PRT type, then adjust x and y coordinates
|
|
if (IsPrtNoRotationTileMode(tileMode))
|
|
{
|
|
x = x % macroTilePitch;
|
|
y = y % macroTileHeight;
|
|
}
|
|
|
|
pipe = ComputePipeFromCoord(x,
|
|
y,
|
|
slice,
|
|
tileMode,
|
|
pipeSwizzle,
|
|
ignoreSE,
|
|
pTileInfo);
|
|
|
|
bank = ComputeBankFromCoord(x,
|
|
y,
|
|
slice,
|
|
tileMode,
|
|
bankSwizzle,
|
|
tileSplitSlice,
|
|
pTileInfo);
|
|
|
|
|
|
//
|
|
// Split the offset to put some bits below the pipe+bank bits and some above.
|
|
//
|
|
pipeInterleaveMask = (1 << numPipeInterleaveBits) - 1;
|
|
bankInterleaveMask = (1 << numBankInterleaveBits) - 1;
|
|
pipeInterleaveOffset = totalOffset & pipeInterleaveMask;
|
|
bankInterleaveOffset = static_cast<UINT_32>((totalOffset >> numPipeInterleaveBits) &
|
|
bankInterleaveMask);
|
|
offset = totalOffset >> (numPipeInterleaveBits + numBankInterleaveBits);
|
|
|
|
//
|
|
// Assemble the address from its components.
|
|
//
|
|
addr = pipeInterleaveOffset;
|
|
// This is to remove /analyze warnings
|
|
UINT_32 pipeBits = pipe << numPipeInterleaveBits;
|
|
UINT_32 bankInterleaveBits = bankInterleaveOffset << (numPipeInterleaveBits + numPipeBits);
|
|
UINT_32 bankBits = bank << (numPipeInterleaveBits + numPipeBits +
|
|
numBankInterleaveBits);
|
|
UINT_64 offsetBits = offset << (numPipeInterleaveBits + numPipeBits +
|
|
numBankInterleaveBits + numBankBits);
|
|
|
|
addr |= pipeBits;
|
|
addr |= bankInterleaveBits;
|
|
addr |= bankBits;
|
|
addr |= offsetBits;
|
|
|
|
return addr;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::ComputeSurfaceAddrFromCoordMicroTiled
|
|
*
|
|
* @brief
|
|
* Computes the surface address and bit position from a coordinate for 1D tilied
|
|
* (micro tiled)
|
|
* @return
|
|
* The byte address
|
|
****************************************************************************************************
|
|
*/
|
|
UINT_64 EgBasedLib::ComputeSurfaceAddrFromCoordMicroTiled(
|
|
UINT_32 x, ///< [in] x coordinate
|
|
UINT_32 y, ///< [in] y coordinate
|
|
UINT_32 slice, ///< [in] slice index
|
|
UINT_32 sample, ///< [in] sample index
|
|
UINT_32 bpp, ///< [in] bits per pixel
|
|
UINT_32 pitch, ///< [in] pitch, in pixels
|
|
UINT_32 height, ///< [in] height, in pixels
|
|
UINT_32 numSamples, ///< [in] number of samples
|
|
AddrTileMode tileMode, ///< [in] tile mode
|
|
AddrTileType microTileType, ///< [in] micro tiling type
|
|
BOOL_32 isDepthSampleOrder, ///< [in] TRUE if depth sample ordering is used
|
|
UINT_32* pBitPosition ///< [out] bit position, e.g. FMT_1 will use this
|
|
) const
|
|
{
|
|
UINT_64 addr = 0;
|
|
|
|
UINT_32 microTileBytes;
|
|
UINT_64 sliceBytes;
|
|
UINT_32 microTilesPerRow;
|
|
UINT_32 microTileIndexX;
|
|
UINT_32 microTileIndexY;
|
|
UINT_32 microTileIndexZ;
|
|
UINT_64 sliceOffset;
|
|
UINT_64 microTileOffset;
|
|
UINT_32 sampleOffset;
|
|
UINT_32 pixelIndex;
|
|
UINT_32 pixelOffset;
|
|
|
|
UINT_32 microTileThickness = Thickness(tileMode);
|
|
|
|
//
|
|
// Compute the micro tile size.
|
|
//
|
|
microTileBytes = BITS_TO_BYTES(MicroTilePixels * microTileThickness * bpp * numSamples);
|
|
|
|
//
|
|
// Compute the slice size.
|
|
//
|
|
sliceBytes =
|
|
BITS_TO_BYTES(static_cast<UINT_64>(pitch) * height * microTileThickness * bpp * numSamples);
|
|
|
|
//
|
|
// Compute the number of micro tiles per row.
|
|
//
|
|
microTilesPerRow = pitch / MicroTileWidth;
|
|
|
|
//
|
|
// Compute the micro tile index.
|
|
//
|
|
microTileIndexX = x / MicroTileWidth;
|
|
microTileIndexY = y / MicroTileHeight;
|
|
microTileIndexZ = slice / microTileThickness;
|
|
|
|
//
|
|
// Compute the slice offset.
|
|
//
|
|
sliceOffset = static_cast<UINT_64>(microTileIndexZ) * sliceBytes;
|
|
|
|
//
|
|
// Compute the offset to the micro tile containing the specified coordinate.
|
|
//
|
|
microTileOffset = (static_cast<UINT_64>(microTileIndexY) * microTilesPerRow + microTileIndexX) *
|
|
microTileBytes;
|
|
|
|
//
|
|
// Compute the pixel index within the micro tile.
|
|
//
|
|
pixelIndex = ComputePixelIndexWithinMicroTile(x,
|
|
y,
|
|
slice,
|
|
bpp,
|
|
tileMode,
|
|
microTileType);
|
|
|
|
// Compute the sample offset.
|
|
//
|
|
if (isDepthSampleOrder)
|
|
{
|
|
//
|
|
// For depth surfaces, samples are stored contiguously for each element, so the sample
|
|
// offset is the sample number times the element size.
|
|
//
|
|
sampleOffset = sample * bpp;
|
|
pixelOffset = pixelIndex * bpp * numSamples;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// For color surfaces, all elements for a particular sample are stored contiguously, so
|
|
// the sample offset is the sample number times the micro tile size divided yBit the number
|
|
// of samples.
|
|
//
|
|
sampleOffset = sample * (microTileBytes*8 / numSamples);
|
|
pixelOffset = pixelIndex * bpp;
|
|
}
|
|
|
|
//
|
|
// Compute the bit position of the pixel. Each element is stored with one bit per sample.
|
|
//
|
|
|
|
UINT_32 elemOffset = sampleOffset + pixelOffset;
|
|
|
|
*pBitPosition = elemOffset % 8;
|
|
elemOffset /= 8;
|
|
|
|
//
|
|
// Combine the slice offset, micro tile offset, sample offset, and pixel offsets.
|
|
//
|
|
addr = sliceOffset + microTileOffset + elemOffset;
|
|
|
|
return addr;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::HwlComputePixelCoordFromOffset
|
|
*
|
|
* @brief
|
|
* Compute pixel coordinate from offset inside a micro tile
|
|
* @return
|
|
* N/A
|
|
****************************************************************************************************
|
|
*/
|
|
VOID EgBasedLib::HwlComputePixelCoordFromOffset(
|
|
UINT_32 offset, ///< [in] offset inside micro tile in bits
|
|
UINT_32 bpp, ///< [in] bits per pixel
|
|
UINT_32 numSamples, ///< [in] number of samples
|
|
AddrTileMode tileMode, ///< [in] tile mode
|
|
UINT_32 tileBase, ///< [in] base offset within a tile
|
|
UINT_32 compBits, ///< [in] component bits actually needed(for planar surface)
|
|
UINT_32* pX, ///< [out] x coordinate
|
|
UINT_32* pY, ///< [out] y coordinate
|
|
UINT_32* pSlice, ///< [out] slice index
|
|
UINT_32* pSample, ///< [out] sample index
|
|
AddrTileType microTileType, ///< [in] micro tiling type
|
|
BOOL_32 isDepthSampleOrder ///< [in] TRUE if depth sample order in microtile is used
|
|
) const
|
|
{
|
|
UINT_32 x = 0;
|
|
UINT_32 y = 0;
|
|
UINT_32 z = 0;
|
|
UINT_32 thickness = Thickness(tileMode);
|
|
|
|
// For planar surface, we adjust offset acoording to tile base
|
|
if ((bpp != compBits) && (compBits != 0) && isDepthSampleOrder)
|
|
{
|
|
offset -= tileBase;
|
|
|
|
ADDR_ASSERT(microTileType == ADDR_NON_DISPLAYABLE ||
|
|
microTileType == ADDR_DEPTH_SAMPLE_ORDER);
|
|
|
|
bpp = compBits;
|
|
}
|
|
|
|
UINT_32 sampleTileBits;
|
|
UINT_32 samplePixelBits;
|
|
UINT_32 pixelIndex;
|
|
|
|
if (isDepthSampleOrder)
|
|
{
|
|
samplePixelBits = bpp * numSamples;
|
|
pixelIndex = offset / samplePixelBits;
|
|
*pSample = (offset % samplePixelBits) / bpp;
|
|
}
|
|
else
|
|
{
|
|
sampleTileBits = MicroTilePixels * bpp * thickness;
|
|
*pSample = offset / sampleTileBits;
|
|
pixelIndex = (offset % sampleTileBits) / bpp;
|
|
}
|
|
|
|
if (microTileType != ADDR_THICK)
|
|
{
|
|
if (microTileType == ADDR_DISPLAYABLE) // displayable
|
|
{
|
|
switch (bpp)
|
|
{
|
|
case 8:
|
|
x = pixelIndex & 0x7;
|
|
y = Bits2Number(3, _BIT(pixelIndex,5),_BIT(pixelIndex,3),_BIT(pixelIndex,4));
|
|
break;
|
|
case 16:
|
|
x = pixelIndex & 0x7;
|
|
y = Bits2Number(3, _BIT(pixelIndex,5),_BIT(pixelIndex,4),_BIT(pixelIndex,3));
|
|
break;
|
|
case 32:
|
|
x = Bits2Number(3, _BIT(pixelIndex,3),_BIT(pixelIndex,1),_BIT(pixelIndex,0));
|
|
y = Bits2Number(3, _BIT(pixelIndex,5),_BIT(pixelIndex,4),_BIT(pixelIndex,2));
|
|
break;
|
|
case 64:
|
|
x = Bits2Number(3, _BIT(pixelIndex,3),_BIT(pixelIndex,2),_BIT(pixelIndex,0));
|
|
y = Bits2Number(3, _BIT(pixelIndex,5),_BIT(pixelIndex,4),_BIT(pixelIndex,1));
|
|
break;
|
|
case 128:
|
|
x = Bits2Number(3, _BIT(pixelIndex,3),_BIT(pixelIndex,2),_BIT(pixelIndex,1));
|
|
y = Bits2Number(3, _BIT(pixelIndex,5),_BIT(pixelIndex,4),_BIT(pixelIndex,0));
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
else if (microTileType == ADDR_NON_DISPLAYABLE || microTileType == ADDR_DEPTH_SAMPLE_ORDER)
|
|
{
|
|
x = Bits2Number(3, _BIT(pixelIndex,4),_BIT(pixelIndex,2),_BIT(pixelIndex,0));
|
|
y = Bits2Number(3, _BIT(pixelIndex,5),_BIT(pixelIndex,3),_BIT(pixelIndex,1));
|
|
}
|
|
else if (microTileType == ADDR_ROTATED)
|
|
{
|
|
/*
|
|
8-Bit Elements
|
|
element_index[5:0] = { x[2], x[0], x[1], y[2], y[1], y[0] }
|
|
|
|
16-Bit Elements
|
|
element_index[5:0] = { x[2], x[1], x[0], y[2], y[1], y[0] }
|
|
|
|
32-Bit Elements
|
|
element_index[5:0] = { x[2], x[1], y[2], x[0], y[1], y[0] }
|
|
|
|
64-Bit Elements
|
|
element_index[5:0] = { y[2], x[2], x[1], y[1], x[0], y[0] }
|
|
*/
|
|
switch(bpp)
|
|
{
|
|
case 8:
|
|
x = Bits2Number(3, _BIT(pixelIndex,5),_BIT(pixelIndex,3),_BIT(pixelIndex,4));
|
|
y = pixelIndex & 0x7;
|
|
break;
|
|
case 16:
|
|
x = Bits2Number(3, _BIT(pixelIndex,5),_BIT(pixelIndex,4),_BIT(pixelIndex,3));
|
|
y = pixelIndex & 0x7;
|
|
break;
|
|
case 32:
|
|
x = Bits2Number(3, _BIT(pixelIndex,5),_BIT(pixelIndex,4),_BIT(pixelIndex,2));
|
|
y = Bits2Number(3, _BIT(pixelIndex,3),_BIT(pixelIndex,1),_BIT(pixelIndex,0));
|
|
break;
|
|
case 64:
|
|
x = Bits2Number(3, _BIT(pixelIndex,4),_BIT(pixelIndex,3),_BIT(pixelIndex,1));
|
|
y = Bits2Number(3, _BIT(pixelIndex,5),_BIT(pixelIndex,2),_BIT(pixelIndex,0));
|
|
break;
|
|
default:
|
|
ADDR_ASSERT_ALWAYS();
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (thickness > 1) // thick
|
|
{
|
|
z = Bits2Number(3, _BIT(pixelIndex,8),_BIT(pixelIndex,7),_BIT(pixelIndex,6));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ADDR_ASSERT((m_chipFamily >= ADDR_CHIP_FAMILY_CI) && (thickness > 1));
|
|
/*
|
|
8-Bit Elements and 16-Bit Elements
|
|
element_index[7:0] = { y[2], x[2], z[1], z[0], y[1], x[1], y[0], x[0] }
|
|
|
|
32-Bit Elements
|
|
element_index[7:0] = { y[2], x[2], z[1], y[1], z[0], x[1], y[0], x[0] }
|
|
|
|
64-Bit Elements and 128-Bit Elements
|
|
element_index[7:0] = { y[2], x[2], z[1], y[1], x[1], z[0], y[0], x[0] }
|
|
|
|
The equation to compute the element index for the extra thick tile:
|
|
element_index[8] = z[2]
|
|
*/
|
|
switch (bpp)
|
|
{
|
|
case 8:
|
|
case 16: // fall-through
|
|
x = Bits2Number(3, _BIT(pixelIndex,6),_BIT(pixelIndex,2),_BIT(pixelIndex,0));
|
|
y = Bits2Number(3, _BIT(pixelIndex,7),_BIT(pixelIndex,3),_BIT(pixelIndex,1));
|
|
z = Bits2Number(2, _BIT(pixelIndex,5),_BIT(pixelIndex,4));
|
|
break;
|
|
case 32:
|
|
x = Bits2Number(3, _BIT(pixelIndex,6),_BIT(pixelIndex,2),_BIT(pixelIndex,0));
|
|
y = Bits2Number(3, _BIT(pixelIndex,7),_BIT(pixelIndex,4),_BIT(pixelIndex,1));
|
|
z = Bits2Number(2, _BIT(pixelIndex,5),_BIT(pixelIndex,3));
|
|
break;
|
|
case 64:
|
|
case 128: // fall-through
|
|
x = Bits2Number(3, _BIT(pixelIndex,6),_BIT(pixelIndex,3),_BIT(pixelIndex,0));
|
|
y = Bits2Number(3, _BIT(pixelIndex,7),_BIT(pixelIndex,4),_BIT(pixelIndex,1));
|
|
z = Bits2Number(2, _BIT(pixelIndex,5),_BIT(pixelIndex,2));
|
|
break;
|
|
default:
|
|
ADDR_ASSERT_ALWAYS();
|
|
break;
|
|
}
|
|
|
|
if (thickness == 8)
|
|
{
|
|
z += Bits2Number(3,_BIT(pixelIndex,8),0,0);
|
|
}
|
|
}
|
|
|
|
*pX = x;
|
|
*pY = y;
|
|
*pSlice += z;
|
|
}
|
|
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::DispatchComputeSurfaceCoordFromAddrDispatch
|
|
*
|
|
* @brief
|
|
* Compute (x,y,slice,sample) coordinates from surface address
|
|
* @return
|
|
* N/A
|
|
****************************************************************************************************
|
|
*/
|
|
VOID EgBasedLib::DispatchComputeSurfaceCoordFromAddr(
|
|
const ADDR_COMPUTE_SURFACE_COORDFROMADDR_INPUT* pIn, ///< [in] input structure
|
|
ADDR_COMPUTE_SURFACE_COORDFROMADDR_OUTPUT* pOut ///< [out] output structure
|
|
) const
|
|
{
|
|
UINT_64 addr = pIn->addr;
|
|
UINT_32 bitPosition = pIn->bitPosition;
|
|
UINT_32 bpp = pIn->bpp;
|
|
UINT_32 pitch = pIn->pitch;
|
|
UINT_32 height = pIn->height;
|
|
UINT_32 numSlices = pIn->numSlices;
|
|
UINT_32 numSamples = ((pIn->numSamples == 0) ? 1 : pIn->numSamples);
|
|
UINT_32 numFrags = ((pIn->numFrags == 0) ? numSamples : pIn->numFrags);
|
|
AddrTileMode tileMode = pIn->tileMode;
|
|
UINT_32 tileBase = pIn->tileBase;
|
|
UINT_32 compBits = pIn->compBits;
|
|
AddrTileType microTileType = pIn->tileType;
|
|
BOOL_32 ignoreSE = pIn->ignoreSE;
|
|
BOOL_32 isDepthSampleOrder = pIn->isDepth;
|
|
ADDR_TILEINFO* pTileInfo = pIn->pTileInfo;
|
|
|
|
UINT_32* pX = &pOut->x;
|
|
UINT_32* pY = &pOut->y;
|
|
UINT_32* pSlice = &pOut->slice;
|
|
UINT_32* pSample = &pOut->sample;
|
|
|
|
if (microTileType == ADDR_DEPTH_SAMPLE_ORDER)
|
|
{
|
|
isDepthSampleOrder = TRUE;
|
|
}
|
|
|
|
if (m_chipFamily >= ADDR_CHIP_FAMILY_NI)
|
|
{
|
|
if (numFrags != numSamples)
|
|
{
|
|
numSamples = numFrags;
|
|
}
|
|
|
|
/// @note
|
|
/// 128 bit/thick tiled surface doesn't support display tiling and
|
|
/// mipmap chain must have the same tileType, so please fill tileType correctly
|
|
if (IsLinear(pIn->tileMode) == FALSE)
|
|
{
|
|
if (bpp >= 128 || Thickness(tileMode) > 1)
|
|
{
|
|
ADDR_ASSERT(microTileType != ADDR_DISPLAYABLE);
|
|
}
|
|
}
|
|
}
|
|
|
|
switch (tileMode)
|
|
{
|
|
case ADDR_TM_LINEAR_GENERAL://fall through
|
|
case ADDR_TM_LINEAR_ALIGNED:
|
|
ComputeSurfaceCoordFromAddrLinear(addr,
|
|
bitPosition,
|
|
bpp,
|
|
pitch,
|
|
height,
|
|
numSlices,
|
|
pX,
|
|
pY,
|
|
pSlice,
|
|
pSample);
|
|
break;
|
|
case ADDR_TM_1D_TILED_THIN1://fall through
|
|
case ADDR_TM_1D_TILED_THICK:
|
|
ComputeSurfaceCoordFromAddrMicroTiled(addr,
|
|
bitPosition,
|
|
bpp,
|
|
pitch,
|
|
height,
|
|
numSamples,
|
|
tileMode,
|
|
tileBase,
|
|
compBits,
|
|
pX,
|
|
pY,
|
|
pSlice,
|
|
pSample,
|
|
microTileType,
|
|
isDepthSampleOrder);
|
|
break;
|
|
case ADDR_TM_2D_TILED_THIN1: //fall through
|
|
case ADDR_TM_2D_TILED_THICK: //fall through
|
|
case ADDR_TM_3D_TILED_THIN1: //fall through
|
|
case ADDR_TM_3D_TILED_THICK: //fall through
|
|
case ADDR_TM_2D_TILED_XTHICK: //fall through
|
|
case ADDR_TM_3D_TILED_XTHICK: //fall through
|
|
case ADDR_TM_PRT_TILED_THIN1: //fall through
|
|
case ADDR_TM_PRT_2D_TILED_THIN1://fall through
|
|
case ADDR_TM_PRT_3D_TILED_THIN1://fall through
|
|
case ADDR_TM_PRT_TILED_THICK: //fall through
|
|
case ADDR_TM_PRT_2D_TILED_THICK://fall through
|
|
case ADDR_TM_PRT_3D_TILED_THICK:
|
|
UINT_32 pipeSwizzle;
|
|
UINT_32 bankSwizzle;
|
|
|
|
if (m_configFlags.useCombinedSwizzle)
|
|
{
|
|
ExtractBankPipeSwizzle(pIn->tileSwizzle, pIn->pTileInfo,
|
|
&bankSwizzle, &pipeSwizzle);
|
|
}
|
|
else
|
|
{
|
|
pipeSwizzle = pIn->pipeSwizzle;
|
|
bankSwizzle = pIn->bankSwizzle;
|
|
}
|
|
|
|
ComputeSurfaceCoordFromAddrMacroTiled(addr,
|
|
bitPosition,
|
|
bpp,
|
|
pitch,
|
|
height,
|
|
numSamples,
|
|
tileMode,
|
|
tileBase,
|
|
compBits,
|
|
microTileType,
|
|
ignoreSE,
|
|
isDepthSampleOrder,
|
|
pipeSwizzle,
|
|
bankSwizzle,
|
|
pTileInfo,
|
|
pX,
|
|
pY,
|
|
pSlice,
|
|
pSample);
|
|
break;
|
|
default:
|
|
ADDR_ASSERT_ALWAYS();
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::ComputeSurfaceCoordFromAddrMacroTiled
|
|
*
|
|
* @brief
|
|
* Compute surface coordinates from address for macro tiled surface
|
|
* @return
|
|
* N/A
|
|
****************************************************************************************************
|
|
*/
|
|
VOID EgBasedLib::ComputeSurfaceCoordFromAddrMacroTiled(
|
|
UINT_64 addr, ///< [in] byte address
|
|
UINT_32 bitPosition, ///< [in] bit position
|
|
UINT_32 bpp, ///< [in] bits per pixel
|
|
UINT_32 pitch, ///< [in] pitch in pixels
|
|
UINT_32 height, ///< [in] height in pixels
|
|
UINT_32 numSamples, ///< [in] number of samples
|
|
AddrTileMode tileMode, ///< [in] tile mode
|
|
UINT_32 tileBase, ///< [in] tile base offset
|
|
UINT_32 compBits, ///< [in] component bits (for planar surface)
|
|
AddrTileType microTileType, ///< [in] micro tiling type
|
|
BOOL_32 ignoreSE, ///< [in] TRUE if shader engines can be ignored
|
|
BOOL_32 isDepthSampleOrder, ///< [in] TRUE if depth sample order is used
|
|
UINT_32 pipeSwizzle, ///< [in] pipe swizzle
|
|
UINT_32 bankSwizzle, ///< [in] bank swizzle
|
|
ADDR_TILEINFO* pTileInfo, ///< [in] bank structure.
|
|
/// **All fields to be valid on entry**
|
|
UINT_32* pX, ///< [out] X coord
|
|
UINT_32* pY, ///< [out] Y coord
|
|
UINT_32* pSlice, ///< [out] slice index
|
|
UINT_32* pSample ///< [out] sample index
|
|
) const
|
|
{
|
|
UINT_32 mx;
|
|
UINT_32 my;
|
|
UINT_64 tileBits;
|
|
UINT_64 macroTileBits;
|
|
UINT_32 slices;
|
|
UINT_32 tileSlices;
|
|
UINT_64 elementOffset;
|
|
UINT_64 macroTileIndex;
|
|
UINT_32 tileIndex;
|
|
UINT_64 totalOffset;
|
|
|
|
|
|
UINT_32 bank;
|
|
UINT_32 pipe;
|
|
UINT_32 groupBits = m_pipeInterleaveBytes << 3;
|
|
UINT_32 pipes = HwlGetPipes(pTileInfo);
|
|
UINT_32 banks = pTileInfo->banks;
|
|
|
|
UINT_32 bankInterleave = m_bankInterleave;
|
|
|
|
UINT_64 addrBits = BYTES_TO_BITS(addr) + bitPosition;
|
|
|
|
//
|
|
// remove bits for bank and pipe
|
|
//
|
|
totalOffset = (addrBits % groupBits) +
|
|
(((addrBits / groupBits / pipes) % bankInterleave) * groupBits) +
|
|
(((addrBits / groupBits / pipes) / bankInterleave) / banks) * groupBits * bankInterleave;
|
|
|
|
UINT_32 microTileThickness = Thickness(tileMode);
|
|
|
|
UINT_32 microTileBits = bpp * microTileThickness * MicroTilePixels * numSamples;
|
|
|
|
UINT_32 microTileBytes = BITS_TO_BYTES(microTileBits);
|
|
//
|
|
// Determine if tiles need to be split across slices.
|
|
//
|
|
// If the size of the micro tile is larger than the tile split size, then the tile will be
|
|
// split across multiple slices.
|
|
//
|
|
UINT_32 slicesPerTile = 1; //_State->TileSlices
|
|
|
|
if ((microTileBytes > pTileInfo->tileSplitBytes) && (microTileThickness == 1))
|
|
{ //don't support for thick mode
|
|
|
|
//
|
|
// Compute the number of slices per tile.
|
|
//
|
|
slicesPerTile = microTileBytes / pTileInfo->tileSplitBytes;
|
|
}
|
|
|
|
tileBits = microTileBits / slicesPerTile; // micro tile bits
|
|
|
|
// in micro tiles because not MicroTileWidth timed.
|
|
UINT_32 macroWidth = pTileInfo->bankWidth * pipes * pTileInfo->macroAspectRatio;
|
|
// in micro tiles as well
|
|
UINT_32 macroHeight = pTileInfo->bankHeight * banks / pTileInfo->macroAspectRatio;
|
|
|
|
UINT_32 pitchInMacroTiles = pitch / MicroTileWidth / macroWidth;
|
|
|
|
macroTileBits = (macroWidth * macroHeight) * tileBits / (banks * pipes);
|
|
|
|
macroTileIndex = totalOffset / macroTileBits;
|
|
|
|
// pitchMacros * height / heightMacros; macroTilesPerSlice == _State->SliceMacros
|
|
UINT_32 macroTilesPerSlice = (pitch / (macroWidth * MicroTileWidth)) * height /
|
|
(macroHeight * MicroTileWidth);
|
|
|
|
slices = static_cast<UINT_32>(macroTileIndex / macroTilesPerSlice);
|
|
|
|
*pSlice = static_cast<UINT_32>(slices / slicesPerTile * microTileThickness);
|
|
|
|
//
|
|
// calculate element offset and x[2:0], y[2:0], z[1:0] for thick
|
|
//
|
|
tileSlices = slices % slicesPerTile;
|
|
|
|
elementOffset = tileSlices * tileBits;
|
|
elementOffset += totalOffset % tileBits;
|
|
|
|
UINT_32 coordZ = 0;
|
|
|
|
HwlComputePixelCoordFromOffset(static_cast<UINT_32>(elementOffset),
|
|
bpp,
|
|
numSamples,
|
|
tileMode,
|
|
tileBase,
|
|
compBits,
|
|
pX,
|
|
pY,
|
|
&coordZ,
|
|
pSample,
|
|
microTileType,
|
|
isDepthSampleOrder);
|
|
|
|
macroTileIndex = macroTileIndex % macroTilesPerSlice;
|
|
*pY += static_cast<UINT_32>(macroTileIndex / pitchInMacroTiles * macroHeight * MicroTileHeight);
|
|
*pX += static_cast<UINT_32>(macroTileIndex % pitchInMacroTiles * macroWidth * MicroTileWidth);
|
|
|
|
*pSlice += coordZ;
|
|
|
|
tileIndex = static_cast<UINT_32>((totalOffset % macroTileBits) / tileBits);
|
|
|
|
my = (tileIndex / pTileInfo->bankWidth) % pTileInfo->bankHeight * MicroTileHeight;
|
|
mx = (tileIndex % pTileInfo->bankWidth) * pipes * MicroTileWidth;
|
|
|
|
*pY += my;
|
|
*pX += mx;
|
|
|
|
bank = ComputeBankFromAddr(addr, banks, pipes);
|
|
pipe = ComputePipeFromAddr(addr, pipes);
|
|
|
|
HwlComputeSurfaceCoord2DFromBankPipe(tileMode,
|
|
pX,
|
|
pY,
|
|
*pSlice,
|
|
bank,
|
|
pipe,
|
|
bankSwizzle,
|
|
pipeSwizzle,
|
|
tileSlices,
|
|
ignoreSE,
|
|
pTileInfo);
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::ComputeSurfaceCoord2DFromBankPipe
|
|
*
|
|
* @brief
|
|
* Compute surface x,y coordinates from bank/pipe info
|
|
* @return
|
|
* N/A
|
|
****************************************************************************************************
|
|
*/
|
|
VOID EgBasedLib::ComputeSurfaceCoord2DFromBankPipe(
|
|
AddrTileMode tileMode, ///< [in] tile mode
|
|
UINT_32 x, ///< [in] x coordinate
|
|
UINT_32 y, ///< [in] y coordinate
|
|
UINT_32 slice, ///< [in] slice index
|
|
UINT_32 bank, ///< [in] bank number
|
|
UINT_32 pipe, ///< [in] pipe number
|
|
UINT_32 bankSwizzle,///< [in] bank swizzle
|
|
UINT_32 pipeSwizzle,///< [in] pipe swizzle
|
|
UINT_32 tileSlices, ///< [in] slices in a micro tile
|
|
ADDR_TILEINFO* pTileInfo, ///< [in] bank structure. **All fields to be valid on entry**
|
|
CoordFromBankPipe* pOutput ///< [out] pointer to extracted x/y bits
|
|
) const
|
|
{
|
|
UINT_32 yBit3 = 0;
|
|
UINT_32 yBit4 = 0;
|
|
UINT_32 yBit5 = 0;
|
|
UINT_32 yBit6 = 0;
|
|
|
|
UINT_32 xBit3 = 0;
|
|
UINT_32 xBit4 = 0;
|
|
UINT_32 xBit5 = 0;
|
|
|
|
UINT_32 tileSplitRotation;
|
|
|
|
UINT_32 numPipes = HwlGetPipes(pTileInfo);
|
|
|
|
UINT_32 bankRotation = ComputeBankRotation(tileMode,
|
|
pTileInfo->banks, numPipes);
|
|
|
|
UINT_32 pipeRotation = ComputePipeRotation(tileMode, numPipes);
|
|
|
|
UINT_32 xBit = x / (MicroTileWidth * pTileInfo->bankWidth * numPipes);
|
|
UINT_32 yBit = y / (MicroTileHeight * pTileInfo->bankHeight);
|
|
|
|
//calculate the bank and pipe before rotation and swizzle
|
|
|
|
switch (tileMode)
|
|
{
|
|
case ADDR_TM_2D_TILED_THIN1: //fall through
|
|
case ADDR_TM_2D_TILED_THICK: //fall through
|
|
case ADDR_TM_2D_TILED_XTHICK: //fall through
|
|
case ADDR_TM_3D_TILED_THIN1: //fall through
|
|
case ADDR_TM_3D_TILED_THICK: //fall through
|
|
case ADDR_TM_3D_TILED_XTHICK:
|
|
tileSplitRotation = ((pTileInfo->banks / 2) + 1);
|
|
break;
|
|
default:
|
|
tileSplitRotation = 0;
|
|
break;
|
|
}
|
|
|
|
UINT_32 microTileThickness = Thickness(tileMode);
|
|
|
|
bank ^= tileSplitRotation * tileSlices;
|
|
if (pipeRotation == 0)
|
|
{
|
|
bank ^= bankRotation * (slice / microTileThickness) + bankSwizzle;
|
|
bank %= pTileInfo->banks;
|
|
pipe ^= pipeSwizzle;
|
|
}
|
|
else
|
|
{
|
|
bank ^= bankRotation * (slice / microTileThickness) / numPipes + bankSwizzle;
|
|
bank %= pTileInfo->banks;
|
|
pipe ^= pipeRotation * (slice / microTileThickness) + pipeSwizzle;
|
|
}
|
|
|
|
if (pTileInfo->macroAspectRatio == 1)
|
|
{
|
|
switch (pTileInfo->banks)
|
|
{
|
|
case 2:
|
|
yBit3 = _BIT(bank, 0) ^ _BIT(xBit,0);
|
|
break;
|
|
case 4:
|
|
yBit4 = _BIT(bank, 0) ^ _BIT(xBit,0);
|
|
yBit3 = _BIT(bank, 1) ^ _BIT(xBit,1);
|
|
break;
|
|
case 8:
|
|
yBit3 = _BIT(bank, 2) ^ _BIT(xBit,2);
|
|
yBit5 = _BIT(bank, 0) ^ _BIT(xBit,0);
|
|
yBit4 = _BIT(bank, 1) ^ _BIT(xBit,1) ^ yBit5;
|
|
break;
|
|
case 16:
|
|
yBit3 = _BIT(bank, 3) ^ _BIT(xBit, 3);
|
|
yBit4 = _BIT(bank, 2) ^ _BIT(xBit, 2);
|
|
yBit6 = _BIT(bank, 0) ^ _BIT(xBit, 0);
|
|
yBit5 = _BIT(bank, 1) ^ _BIT(xBit, 1) ^ yBit6;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
}
|
|
else if (pTileInfo->macroAspectRatio == 2)
|
|
{
|
|
switch (pTileInfo->banks)
|
|
{
|
|
case 2: //xBit3 = yBit3^b0
|
|
xBit3 = _BIT(bank, 0) ^ _BIT(yBit,0);
|
|
break;
|
|
case 4: //xBit3=yBit4^b0; yBit3=xBit4^b1
|
|
xBit3 = _BIT(bank, 0) ^ _BIT(yBit,1);
|
|
yBit3 = _BIT(bank, 1) ^ _BIT(xBit,1);
|
|
break;
|
|
case 8: //xBit4, xBit5, yBit5 are known
|
|
xBit3 = _BIT(bank, 0) ^ _BIT(yBit,2);
|
|
yBit3 = _BIT(bank, 2) ^ _BIT(xBit,2);
|
|
yBit4 = _BIT(bank, 1) ^ _BIT(xBit,1) ^ _BIT(yBit, 2);
|
|
break;
|
|
case 16://x4,x5,x6,y6 are known
|
|
xBit3 = _BIT(bank, 0) ^ _BIT(yBit, 3); //x3 = y6 ^ b0
|
|
yBit3 = _BIT(bank, 3) ^ _BIT(xBit, 3); //y3 = x6 ^ b3
|
|
yBit4 = _BIT(bank, 2) ^ _BIT(xBit, 2); //y4 = x5 ^ b2
|
|
yBit5 = _BIT(bank, 1) ^ _BIT(xBit, 1) ^ _BIT(yBit, 3); //y5=x4^y6^b1
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
else if (pTileInfo->macroAspectRatio == 4)
|
|
{
|
|
switch (pTileInfo->banks)
|
|
{
|
|
case 4: //yBit3, yBit4
|
|
xBit3 = _BIT(bank, 0) ^ _BIT(yBit,1);
|
|
xBit4 = _BIT(bank, 1) ^ _BIT(yBit,0);
|
|
break;
|
|
case 8: //xBit5, yBit4, yBit5
|
|
xBit3 = _BIT(bank, 0) ^ _BIT(yBit,2);
|
|
yBit3 = _BIT(bank, 2) ^ _BIT(xBit,2);
|
|
xBit4 = _BIT(bank, 1) ^ _BIT(yBit,1) ^ _BIT(yBit,2);
|
|
break;
|
|
case 16: //xBit5, xBit6, yBit5, yBit6
|
|
xBit3 = _BIT(bank, 0) ^ _BIT(yBit, 3);//x3 = b0 ^ y6
|
|
xBit4 = _BIT(bank, 1) ^ _BIT(yBit, 2) ^ _BIT(yBit, 3);//x4 = b1 ^ y5 ^ y6;
|
|
yBit3 = _BIT(bank, 3) ^ _BIT(xBit, 3); //y3 = b3 ^ x6;
|
|
yBit4 = _BIT(bank, 2) ^ _BIT(xBit, 2); //y4 = b2 ^ x5;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
else if (pTileInfo->macroAspectRatio == 8)
|
|
{
|
|
switch (pTileInfo->banks)
|
|
{
|
|
case 8: //yBit3, yBit4, yBit5
|
|
xBit3 = _BIT(bank, 0) ^ _BIT(yBit,2); //x3 = b0 ^ y5;
|
|
xBit4 = _BIT(bank, 1) ^ _BIT(yBit,1) ^ _BIT(yBit, 2);//x4 = b1 ^ y4 ^ y5;
|
|
xBit5 = _BIT(bank, 2) ^ _BIT(yBit,0);
|
|
break;
|
|
case 16: //xBit6, yBit4, yBit5, yBit6
|
|
xBit3 = _BIT(bank, 0) ^ _BIT(yBit, 3);//x3 = y6 ^ b0
|
|
xBit4 = _BIT(bank, 1) ^ _BIT(yBit, 2) ^ _BIT(yBit, 3);//x4 = y5 ^ y6 ^ b1
|
|
xBit5 = _BIT(bank, 2) ^ _BIT(yBit, 1);//x5 = y4 ^ b2
|
|
yBit3 = _BIT(bank, 3) ^ _BIT(xBit, 3); //y3 = x6 ^ b3
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
pOutput->xBits = xBit;
|
|
pOutput->yBits = yBit;
|
|
|
|
pOutput->xBit3 = xBit3;
|
|
pOutput->xBit4 = xBit4;
|
|
pOutput->xBit5 = xBit5;
|
|
pOutput->yBit3 = yBit3;
|
|
pOutput->yBit4 = yBit4;
|
|
pOutput->yBit5 = yBit5;
|
|
pOutput->yBit6 = yBit6;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::HwlExtractBankPipeSwizzle
|
|
* @brief
|
|
* Entry of EgBasedLib ExtractBankPipeSwizzle
|
|
* @return
|
|
* ADDR_E_RETURNCODE
|
|
****************************************************************************************************
|
|
*/
|
|
ADDR_E_RETURNCODE EgBasedLib::HwlExtractBankPipeSwizzle(
|
|
const ADDR_EXTRACT_BANKPIPE_SWIZZLE_INPUT* pIn, ///< [in] input structure
|
|
ADDR_EXTRACT_BANKPIPE_SWIZZLE_OUTPUT* pOut ///< [out] output structure
|
|
) const
|
|
{
|
|
ExtractBankPipeSwizzle(pIn->base256b,
|
|
pIn->pTileInfo,
|
|
&pOut->bankSwizzle,
|
|
&pOut->pipeSwizzle);
|
|
|
|
return ADDR_OK;
|
|
}
|
|
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::HwlCombineBankPipeSwizzle
|
|
* @brief
|
|
* Combine bank/pipe swizzle
|
|
* @return
|
|
* ADDR_E_RETURNCODE
|
|
****************************************************************************************************
|
|
*/
|
|
ADDR_E_RETURNCODE EgBasedLib::HwlCombineBankPipeSwizzle(
|
|
UINT_32 bankSwizzle, ///< [in] bank swizzle
|
|
UINT_32 pipeSwizzle, ///< [in] pipe swizzle
|
|
ADDR_TILEINFO* pTileInfo, ///< [in] tile info
|
|
UINT_64 baseAddr, ///< [in] base address
|
|
UINT_32* pTileSwizzle ///< [out] combined swizzle
|
|
) const
|
|
{
|
|
ADDR_E_RETURNCODE retCode = ADDR_OK;
|
|
|
|
if (pTileSwizzle)
|
|
{
|
|
*pTileSwizzle = GetBankPipeSwizzle(bankSwizzle, pipeSwizzle, baseAddr, pTileInfo);
|
|
}
|
|
else
|
|
{
|
|
retCode = ADDR_INVALIDPARAMS;
|
|
}
|
|
|
|
return retCode;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::HwlComputeBaseSwizzle
|
|
* @brief
|
|
* Compute base swizzle
|
|
* @return
|
|
* ADDR_E_RETURNCODE
|
|
****************************************************************************************************
|
|
*/
|
|
ADDR_E_RETURNCODE EgBasedLib::HwlComputeBaseSwizzle(
|
|
const ADDR_COMPUTE_BASE_SWIZZLE_INPUT* pIn,
|
|
ADDR_COMPUTE_BASE_SWIZZLE_OUTPUT* pOut
|
|
) const
|
|
{
|
|
UINT_32 bankSwizzle = 0;
|
|
UINT_32 pipeSwizzle = 0;
|
|
ADDR_TILEINFO* pTileInfo = pIn->pTileInfo;
|
|
|
|
ADDR_ASSERT(IsMacroTiled(pIn->tileMode));
|
|
ADDR_ASSERT(pIn->pTileInfo);
|
|
|
|
/// This is a legacy misreading of h/w doc, use it as it doesn't hurt.
|
|
static const UINT_8 bankRotationArray[4][16] = {
|
|
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // ADDR_SURF_2_BANK
|
|
{ 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // ADDR_SURF_4_BANK
|
|
{ 0, 3, 6, 1, 4, 7, 2, 5, 0, 0, 0, 0, 0, 0, 0, 0 }, // ADDR_SURF_8_BANK
|
|
{ 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9 }, // ADDR_SURF_16_BANK
|
|
};
|
|
|
|
UINT_32 banks = pTileInfo ? pTileInfo->banks : 2;
|
|
UINT_32 hwNumBanks;
|
|
|
|
// Uses less bank swizzle bits
|
|
if (pIn->option.reduceBankBit && banks > 2)
|
|
{
|
|
banks >>= 1;
|
|
}
|
|
|
|
switch (banks)
|
|
{
|
|
case 2:
|
|
hwNumBanks = 0;
|
|
break;
|
|
case 4:
|
|
hwNumBanks = 1;
|
|
break;
|
|
case 8:
|
|
hwNumBanks = 2;
|
|
break;
|
|
case 16:
|
|
hwNumBanks = 3;
|
|
break;
|
|
default:
|
|
ADDR_ASSERT_ALWAYS();
|
|
hwNumBanks = 0;
|
|
break;
|
|
}
|
|
|
|
if (pIn->option.genOption == ADDR_SWIZZLE_GEN_LINEAR)
|
|
{
|
|
bankSwizzle = pIn->surfIndex & (banks - 1);
|
|
}
|
|
else // (pIn->option.genOption == ADDR_SWIZZLE_GEN_DEFAULT)
|
|
{
|
|
bankSwizzle = bankRotationArray[hwNumBanks][pIn->surfIndex & (banks - 1)];
|
|
}
|
|
|
|
if (IsMacro3dTiled(pIn->tileMode))
|
|
{
|
|
pipeSwizzle = pIn->surfIndex & (HwlGetPipes(pTileInfo) - 1);
|
|
}
|
|
|
|
return HwlCombineBankPipeSwizzle(bankSwizzle, pipeSwizzle, pTileInfo, 0, &pOut->tileSwizzle);
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::ExtractBankPipeSwizzle
|
|
* @brief
|
|
* Extract bank/pipe swizzle from base256b
|
|
* @return
|
|
* N/A
|
|
****************************************************************************************************
|
|
*/
|
|
VOID EgBasedLib::ExtractBankPipeSwizzle(
|
|
UINT_32 base256b, ///< [in] input base256b register value
|
|
ADDR_TILEINFO* pTileInfo, ///< [in] 2D tile parameters. Client must provide all data
|
|
UINT_32* pBankSwizzle, ///< [out] bank swizzle
|
|
UINT_32* pPipeSwizzle ///< [out] pipe swizzle
|
|
) const
|
|
{
|
|
UINT_32 bankSwizzle = 0;
|
|
UINT_32 pipeSwizzle = 0;
|
|
|
|
if (base256b != 0)
|
|
{
|
|
UINT_32 numPipes = HwlGetPipes(pTileInfo);
|
|
UINT_32 bankBits = QLog2(pTileInfo->banks);
|
|
UINT_32 pipeBits = QLog2(numPipes);
|
|
UINT_32 groupBytes = m_pipeInterleaveBytes;
|
|
UINT_32 bankInterleave = m_bankInterleave;
|
|
|
|
pipeSwizzle =
|
|
(base256b / (groupBytes >> 8)) & ((1<<pipeBits)-1);
|
|
|
|
bankSwizzle =
|
|
(base256b / (groupBytes >> 8) / numPipes / bankInterleave) & ((1 << bankBits) - 1);
|
|
}
|
|
|
|
*pPipeSwizzle = pipeSwizzle;
|
|
*pBankSwizzle = bankSwizzle;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::GetBankPipeSwizzle
|
|
* @brief
|
|
* Combine bank/pipe swizzle
|
|
* @return
|
|
* Base256b bits (only filled bank/pipe bits)
|
|
****************************************************************************************************
|
|
*/
|
|
UINT_32 EgBasedLib::GetBankPipeSwizzle(
|
|
UINT_32 bankSwizzle, ///< [in] bank swizzle
|
|
UINT_32 pipeSwizzle, ///< [in] pipe swizzle
|
|
UINT_64 baseAddr, ///< [in] base address
|
|
ADDR_TILEINFO* pTileInfo ///< [in] tile info
|
|
) const
|
|
{
|
|
UINT_32 pipeBits = QLog2(HwlGetPipes(pTileInfo));
|
|
UINT_32 bankInterleaveBits = QLog2(m_bankInterleave);
|
|
UINT_32 tileSwizzle = pipeSwizzle + ((bankSwizzle << bankInterleaveBits) << pipeBits);
|
|
|
|
baseAddr ^= tileSwizzle * m_pipeInterleaveBytes;
|
|
baseAddr >>= 8;
|
|
|
|
return static_cast<UINT_32>(baseAddr);
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::ComputeSliceTileSwizzle
|
|
* @brief
|
|
* Compute cubemap/3d texture faces/slices tile swizzle
|
|
* @return
|
|
* Tile swizzle
|
|
****************************************************************************************************
|
|
*/
|
|
UINT_32 EgBasedLib::ComputeSliceTileSwizzle(
|
|
AddrTileMode tileMode, ///< [in] Tile mode
|
|
UINT_32 baseSwizzle, ///< [in] Base swizzle
|
|
UINT_32 slice, ///< [in] Slice index, Cubemap face index, 0 means +X
|
|
UINT_64 baseAddr, ///< [in] Base address
|
|
ADDR_TILEINFO* pTileInfo ///< [in] Bank structure
|
|
) const
|
|
{
|
|
UINT_32 tileSwizzle = 0;
|
|
|
|
if (IsMacroTiled(tileMode)) // Swizzle only for macro tile mode
|
|
{
|
|
UINT_32 firstSlice = slice / Thickness(tileMode);
|
|
|
|
UINT_32 numPipes = HwlGetPipes(pTileInfo);
|
|
UINT_32 numBanks = pTileInfo->banks;
|
|
|
|
UINT_32 pipeRotation;
|
|
UINT_32 bankRotation;
|
|
|
|
UINT_32 bankSwizzle = 0;
|
|
UINT_32 pipeSwizzle = 0;
|
|
|
|
pipeRotation = ComputePipeRotation(tileMode, numPipes);
|
|
bankRotation = ComputeBankRotation(tileMode, numBanks, numPipes);
|
|
|
|
if (baseSwizzle != 0)
|
|
{
|
|
ExtractBankPipeSwizzle(baseSwizzle,
|
|
pTileInfo,
|
|
&bankSwizzle,
|
|
&pipeSwizzle);
|
|
}
|
|
|
|
if (pipeRotation == 0) //2D mode
|
|
{
|
|
bankSwizzle += firstSlice * bankRotation;
|
|
bankSwizzle %= numBanks;
|
|
}
|
|
else //3D mode
|
|
{
|
|
pipeSwizzle += firstSlice * pipeRotation;
|
|
pipeSwizzle %= numPipes;
|
|
bankSwizzle += firstSlice * bankRotation / numPipes;
|
|
bankSwizzle %= numBanks;
|
|
}
|
|
|
|
tileSwizzle = GetBankPipeSwizzle(bankSwizzle,
|
|
pipeSwizzle,
|
|
baseAddr,
|
|
pTileInfo);
|
|
}
|
|
|
|
return tileSwizzle;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::HwlComputeQbStereoRightSwizzle
|
|
*
|
|
* @brief
|
|
* Compute right eye swizzle
|
|
* @return
|
|
* swizzle
|
|
****************************************************************************************************
|
|
*/
|
|
UINT_32 EgBasedLib::HwlComputeQbStereoRightSwizzle(
|
|
ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pInfo ///< [in] Surface info, must be valid
|
|
) const
|
|
{
|
|
UINT_32 bankBits = 0;
|
|
UINT_32 swizzle = 0;
|
|
|
|
// The assumption is default swizzle for left eye is 0
|
|
if (IsMacroTiled(pInfo->tileMode) && pInfo->pStereoInfo && pInfo->pTileInfo)
|
|
{
|
|
bankBits = ComputeBankFromCoord(0, pInfo->height, 0,
|
|
pInfo->tileMode, 0, 0, pInfo->pTileInfo);
|
|
|
|
if (bankBits)
|
|
{
|
|
HwlCombineBankPipeSwizzle(bankBits, 0, pInfo->pTileInfo, 0, &swizzle);
|
|
}
|
|
}
|
|
|
|
return swizzle;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::ComputeBankFromCoord
|
|
*
|
|
* @brief
|
|
* Compute bank number from coordinates
|
|
* @return
|
|
* Bank number
|
|
****************************************************************************************************
|
|
*/
|
|
UINT_32 EgBasedLib::ComputeBankFromCoord(
|
|
UINT_32 x, ///< [in] x coordinate
|
|
UINT_32 y, ///< [in] y coordinate
|
|
UINT_32 slice, ///< [in] slice index
|
|
AddrTileMode tileMode, ///< [in] tile mode
|
|
UINT_32 bankSwizzle, ///< [in] bank swizzle
|
|
UINT_32 tileSplitSlice, ///< [in] If the size of the pixel offset is larger than the
|
|
/// tile split size, then the pixel will be moved to a separate
|
|
/// slice. This value equals pixelOffset / tileSplitBytes
|
|
/// in this case. Otherwise this is 0.
|
|
ADDR_TILEINFO* pTileInfo ///< [in] tile info
|
|
) const
|
|
{
|
|
UINT_32 pipes = HwlGetPipes(pTileInfo);
|
|
UINT_32 bankBit0 = 0;
|
|
UINT_32 bankBit1 = 0;
|
|
UINT_32 bankBit2 = 0;
|
|
UINT_32 bankBit3 = 0;
|
|
UINT_32 sliceRotation;
|
|
UINT_32 tileSplitRotation;
|
|
UINT_32 bank;
|
|
UINT_32 numBanks = pTileInfo->banks;
|
|
UINT_32 bankWidth = pTileInfo->bankWidth;
|
|
UINT_32 bankHeight = pTileInfo->bankHeight;
|
|
|
|
UINT_32 tx = x / MicroTileWidth / (bankWidth * pipes);
|
|
UINT_32 ty = y / MicroTileHeight / bankHeight;
|
|
|
|
UINT_32 x3 = _BIT(tx,0);
|
|
UINT_32 x4 = _BIT(tx,1);
|
|
UINT_32 x5 = _BIT(tx,2);
|
|
UINT_32 x6 = _BIT(tx,3);
|
|
UINT_32 y3 = _BIT(ty,0);
|
|
UINT_32 y4 = _BIT(ty,1);
|
|
UINT_32 y5 = _BIT(ty,2);
|
|
UINT_32 y6 = _BIT(ty,3);
|
|
|
|
switch (numBanks)
|
|
{
|
|
case 16:
|
|
bankBit0 = x3 ^ y6;
|
|
bankBit1 = x4 ^ y5 ^ y6;
|
|
bankBit2 = x5 ^ y4;
|
|
bankBit3 = x6 ^ y3;
|
|
break;
|
|
case 8:
|
|
bankBit0 = x3 ^ y5;
|
|
bankBit1 = x4 ^ y4 ^ y5;
|
|
bankBit2 = x5 ^ y3;
|
|
break;
|
|
case 4:
|
|
bankBit0 = x3 ^ y4;
|
|
bankBit1 = x4 ^ y3;
|
|
break;
|
|
case 2:
|
|
bankBit0 = x3 ^ y3;
|
|
break;
|
|
default:
|
|
ADDR_ASSERT_ALWAYS();
|
|
break;
|
|
}
|
|
|
|
bank = bankBit0 | (bankBit1 << 1) | (bankBit2 << 2) | (bankBit3 << 3);
|
|
|
|
//Bits2Number(4, bankBit3, bankBit2, bankBit1, bankBit0);
|
|
|
|
bank = HwlPreAdjustBank((x / MicroTileWidth), bank, pTileInfo);
|
|
//
|
|
// Compute bank rotation for the slice.
|
|
//
|
|
UINT_32 microTileThickness = Thickness(tileMode);
|
|
|
|
switch (tileMode)
|
|
{
|
|
case ADDR_TM_2D_TILED_THIN1: // fall through
|
|
case ADDR_TM_2D_TILED_THICK: // fall through
|
|
case ADDR_TM_2D_TILED_XTHICK:
|
|
sliceRotation = ((numBanks / 2) - 1) * (slice / microTileThickness);
|
|
break;
|
|
case ADDR_TM_3D_TILED_THIN1: // fall through
|
|
case ADDR_TM_3D_TILED_THICK: // fall through
|
|
case ADDR_TM_3D_TILED_XTHICK:
|
|
sliceRotation =
|
|
Max(1u, (pipes / 2) - 1) * (slice / microTileThickness) / pipes;
|
|
break;
|
|
default:
|
|
sliceRotation = 0;
|
|
break;
|
|
}
|
|
|
|
|
|
//
|
|
// Compute bank rotation for the tile split slice.
|
|
//
|
|
// The sample slice will be non-zero if samples must be split across multiple slices.
|
|
// This situation arises when the micro tile size multiplied yBit the number of samples exceeds
|
|
// the split size (set in GB_ADDR_CONFIG).
|
|
//
|
|
switch (tileMode)
|
|
{
|
|
case ADDR_TM_2D_TILED_THIN1: //fall through
|
|
case ADDR_TM_3D_TILED_THIN1: //fall through
|
|
case ADDR_TM_PRT_2D_TILED_THIN1: //fall through
|
|
case ADDR_TM_PRT_3D_TILED_THIN1: //fall through
|
|
tileSplitRotation = ((numBanks / 2) + 1) * tileSplitSlice;
|
|
break;
|
|
default:
|
|
tileSplitRotation = 0;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Apply bank rotation for the slice and tile split slice.
|
|
//
|
|
bank ^= bankSwizzle + sliceRotation;
|
|
bank ^= tileSplitRotation;
|
|
|
|
bank &= (numBanks - 1);
|
|
|
|
return bank;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::ComputeBankFromAddr
|
|
*
|
|
* @brief
|
|
* Compute the bank number from an address
|
|
* @return
|
|
* Bank number
|
|
****************************************************************************************************
|
|
*/
|
|
UINT_32 EgBasedLib::ComputeBankFromAddr(
|
|
UINT_64 addr, ///< [in] address
|
|
UINT_32 numBanks, ///< [in] number of banks
|
|
UINT_32 numPipes ///< [in] number of pipes
|
|
) const
|
|
{
|
|
UINT_32 bank;
|
|
|
|
//
|
|
// The LSBs of the address are arranged as follows:
|
|
// bank | bankInterleave | pipe | pipeInterleave
|
|
//
|
|
// To get the bank number, shift off the pipe interleave, pipe, and bank interlave bits and
|
|
// mask the bank bits.
|
|
//
|
|
bank = static_cast<UINT_32>(
|
|
(addr >> Log2(m_pipeInterleaveBytes * numPipes * m_bankInterleave)) &
|
|
(numBanks - 1)
|
|
);
|
|
|
|
return bank;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::ComputePipeRotation
|
|
*
|
|
* @brief
|
|
* Compute pipe rotation value
|
|
* @return
|
|
* Pipe rotation
|
|
****************************************************************************************************
|
|
*/
|
|
UINT_32 EgBasedLib::ComputePipeRotation(
|
|
AddrTileMode tileMode, ///< [in] tile mode
|
|
UINT_32 numPipes ///< [in] number of pipes
|
|
) const
|
|
{
|
|
UINT_32 rotation;
|
|
|
|
switch (tileMode)
|
|
{
|
|
case ADDR_TM_3D_TILED_THIN1: //fall through
|
|
case ADDR_TM_3D_TILED_THICK: //fall through
|
|
case ADDR_TM_3D_TILED_XTHICK: //fall through
|
|
case ADDR_TM_PRT_3D_TILED_THIN1: //fall through
|
|
case ADDR_TM_PRT_3D_TILED_THICK:
|
|
rotation = (numPipes < 4) ? 1 : (numPipes / 2 - 1);
|
|
break;
|
|
default:
|
|
rotation = 0;
|
|
}
|
|
|
|
return rotation;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::ComputeBankRotation
|
|
*
|
|
* @brief
|
|
* Compute bank rotation value
|
|
* @return
|
|
* Bank rotation
|
|
****************************************************************************************************
|
|
*/
|
|
UINT_32 EgBasedLib::ComputeBankRotation(
|
|
AddrTileMode tileMode, ///< [in] tile mode
|
|
UINT_32 numBanks, ///< [in] number of banks
|
|
UINT_32 numPipes ///< [in] number of pipes
|
|
) const
|
|
{
|
|
UINT_32 rotation;
|
|
|
|
switch (tileMode)
|
|
{
|
|
case ADDR_TM_2D_TILED_THIN1: // fall through
|
|
case ADDR_TM_2D_TILED_THICK: // fall through
|
|
case ADDR_TM_2D_TILED_XTHICK:
|
|
case ADDR_TM_PRT_2D_TILED_THIN1:
|
|
case ADDR_TM_PRT_2D_TILED_THICK:
|
|
// Rotate banks per Z-slice yBit 1 for 4-bank or 3 for 8-bank
|
|
rotation = numBanks / 2 - 1;
|
|
break;
|
|
case ADDR_TM_3D_TILED_THIN1: // fall through
|
|
case ADDR_TM_3D_TILED_THICK: // fall through
|
|
case ADDR_TM_3D_TILED_XTHICK:
|
|
case ADDR_TM_PRT_3D_TILED_THIN1:
|
|
case ADDR_TM_PRT_3D_TILED_THICK:
|
|
rotation = (numPipes < 4) ? 1 : (numPipes / 2 - 1); // rotate pipes & banks
|
|
break;
|
|
default:
|
|
rotation = 0;
|
|
}
|
|
|
|
return rotation;
|
|
}
|
|
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::ComputeHtileBytes
|
|
*
|
|
* @brief
|
|
* Compute htile size in bytes
|
|
*
|
|
* @return
|
|
* Htile size in bytes
|
|
****************************************************************************************************
|
|
*/
|
|
UINT_64 EgBasedLib::ComputeHtileBytes(
|
|
UINT_32 pitch, ///< [in] pitch
|
|
UINT_32 height, ///< [in] height
|
|
UINT_32 bpp, ///< [in] bits per pixel
|
|
BOOL_32 isLinear, ///< [in] if it is linear mode
|
|
UINT_32 numSlices, ///< [in] number of slices
|
|
UINT_64* sliceBytes, ///< [out] bytes per slice
|
|
UINT_32 baseAlign ///< [in] base alignments
|
|
) const
|
|
{
|
|
UINT_64 surfBytes;
|
|
|
|
const UINT_64 HtileCacheLineSize = BITS_TO_BYTES(HtileCacheBits);
|
|
|
|
*sliceBytes = BITS_TO_BYTES(static_cast<UINT_64>(pitch) * height * bpp / 64);
|
|
|
|
if (m_configFlags.useHtileSliceAlign)
|
|
{
|
|
// Align the sliceSize to htilecachelinesize * pipes at first
|
|
*sliceBytes = PowTwoAlign(*sliceBytes, HtileCacheLineSize * m_pipes);
|
|
surfBytes = *sliceBytes * numSlices;
|
|
}
|
|
else
|
|
{
|
|
// Align the surfSize to htilecachelinesize * pipes at last
|
|
surfBytes = *sliceBytes * numSlices;
|
|
surfBytes = PowTwoAlign(surfBytes, HtileCacheLineSize * m_pipes);
|
|
}
|
|
|
|
return surfBytes;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::DispatchComputeFmaskInfo
|
|
*
|
|
* @brief
|
|
* Compute fmask sizes include padded pitch, height, slices, total size in bytes,
|
|
* meanwhile output suitable tile mode and alignments as well. Results are returned
|
|
* through output parameters.
|
|
*
|
|
* @return
|
|
* ADDR_E_RETURNCODE
|
|
****************************************************************************************************
|
|
*/
|
|
ADDR_E_RETURNCODE EgBasedLib::DispatchComputeFmaskInfo(
|
|
const ADDR_COMPUTE_FMASK_INFO_INPUT* pIn, ///< [in] input structure
|
|
ADDR_COMPUTE_FMASK_INFO_OUTPUT* pOut) ///< [out] output structure
|
|
{
|
|
ADDR_E_RETURNCODE retCode = ADDR_OK;
|
|
|
|
ADDR_COMPUTE_SURFACE_INFO_INPUT surfIn = {0};
|
|
ADDR_COMPUTE_SURFACE_INFO_OUTPUT surfOut = {0};
|
|
|
|
// Setup input structure
|
|
surfIn.tileMode = pIn->tileMode;
|
|
surfIn.width = pIn->pitch;
|
|
surfIn.height = pIn->height;
|
|
surfIn.numSlices = pIn->numSlices;
|
|
surfIn.pTileInfo = pIn->pTileInfo;
|
|
surfIn.tileType = ADDR_NON_DISPLAYABLE;
|
|
surfIn.flags.fmask = 1;
|
|
|
|
// Setup output structure
|
|
surfOut.pTileInfo = pOut->pTileInfo;
|
|
|
|
// Setup hwl specific fields
|
|
HwlFmaskPreThunkSurfInfo(pIn, pOut, &surfIn, &surfOut);
|
|
|
|
surfIn.bpp = HwlComputeFmaskBits(pIn, &surfIn.numSamples);
|
|
|
|
// ComputeSurfaceInfo needs numSamples in surfOut as surface routines need adjusted numSamples
|
|
surfOut.numSamples = surfIn.numSamples;
|
|
|
|
retCode = HwlComputeSurfaceInfo(&surfIn, &surfOut);
|
|
|
|
// Save bpp field for surface dump support
|
|
surfOut.bpp = surfIn.bpp;
|
|
|
|
if (retCode == ADDR_OK)
|
|
{
|
|
pOut->bpp = surfOut.bpp;
|
|
pOut->pitch = surfOut.pitch;
|
|
pOut->height = surfOut.height;
|
|
pOut->numSlices = surfOut.depth;
|
|
pOut->fmaskBytes = surfOut.surfSize;
|
|
pOut->baseAlign = surfOut.baseAlign;
|
|
pOut->pitchAlign = surfOut.pitchAlign;
|
|
pOut->heightAlign = surfOut.heightAlign;
|
|
|
|
if (surfOut.depth > 1)
|
|
{
|
|
// For fmask, expNumSlices is stored in depth.
|
|
pOut->sliceSize = surfOut.surfSize / surfOut.depth;
|
|
}
|
|
else
|
|
{
|
|
pOut->sliceSize = surfOut.surfSize;
|
|
}
|
|
|
|
// Save numSamples field for surface dump support
|
|
pOut->numSamples = surfOut.numSamples;
|
|
|
|
HwlFmaskPostThunkSurfInfo(&surfOut, pOut);
|
|
}
|
|
|
|
return retCode;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::HwlFmaskSurfaceInfo
|
|
* @brief
|
|
* Entry of EgBasedLib ComputeFmaskInfo
|
|
* @return
|
|
* ADDR_E_RETURNCODE
|
|
****************************************************************************************************
|
|
*/
|
|
ADDR_E_RETURNCODE EgBasedLib::HwlComputeFmaskInfo(
|
|
const ADDR_COMPUTE_FMASK_INFO_INPUT* pIn, ///< [in] input structure
|
|
ADDR_COMPUTE_FMASK_INFO_OUTPUT* pOut ///< [out] output structure
|
|
)
|
|
{
|
|
ADDR_E_RETURNCODE retCode = ADDR_OK;
|
|
|
|
ADDR_TILEINFO tileInfo = {0};
|
|
|
|
// Use internal tile info if pOut does not have a valid pTileInfo
|
|
if (pOut->pTileInfo == NULL)
|
|
{
|
|
pOut->pTileInfo = &tileInfo;
|
|
}
|
|
|
|
retCode = DispatchComputeFmaskInfo(pIn, pOut);
|
|
|
|
if (retCode == ADDR_OK)
|
|
{
|
|
pOut->tileIndex =
|
|
HwlPostCheckTileIndex(pOut->pTileInfo, pIn->tileMode, ADDR_NON_DISPLAYABLE,
|
|
pOut->tileIndex);
|
|
}
|
|
|
|
// Resets pTileInfo to NULL if the internal tile info is used
|
|
if (pOut->pTileInfo == &tileInfo)
|
|
{
|
|
pOut->pTileInfo = NULL;
|
|
}
|
|
|
|
return retCode;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::HwlComputeFmaskAddrFromCoord
|
|
* @brief
|
|
* Entry of EgBasedLib ComputeFmaskAddrFromCoord
|
|
* @return
|
|
* ADDR_E_RETURNCODE
|
|
****************************************************************************************************
|
|
*/
|
|
ADDR_E_RETURNCODE EgBasedLib::HwlComputeFmaskAddrFromCoord(
|
|
const ADDR_COMPUTE_FMASK_ADDRFROMCOORD_INPUT* pIn, ///< [in] input structure
|
|
ADDR_COMPUTE_FMASK_ADDRFROMCOORD_OUTPUT* pOut ///< [out] output structure
|
|
) const
|
|
{
|
|
ADDR_E_RETURNCODE retCode = ADDR_OK;
|
|
|
|
#if ADDR_AM_BUILD
|
|
if ((pIn->x > pIn->pitch) ||
|
|
(pIn->y > pIn->height) ||
|
|
(pIn->numSamples > m_maxSamples) ||
|
|
(pIn->sample >= m_maxSamples))
|
|
{
|
|
retCode = ADDR_INVALIDPARAMS;
|
|
}
|
|
else
|
|
{
|
|
pOut->addr = DispatchComputeFmaskAddrFromCoord(pIn, pOut);
|
|
}
|
|
#endif
|
|
|
|
return retCode;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::HwlComputeFmaskCoordFromAddr
|
|
* @brief
|
|
* Entry of EgBasedLib ComputeFmaskCoordFromAddr
|
|
* @return
|
|
* ADDR_E_RETURNCODE
|
|
****************************************************************************************************
|
|
*/
|
|
ADDR_E_RETURNCODE EgBasedLib::HwlComputeFmaskCoordFromAddr(
|
|
const ADDR_COMPUTE_FMASK_COORDFROMADDR_INPUT* pIn, ///< [in] input structure
|
|
ADDR_COMPUTE_FMASK_COORDFROMADDR_OUTPUT* pOut ///< [out] output structure
|
|
) const
|
|
{
|
|
ADDR_E_RETURNCODE retCode = ADDR_OK;
|
|
|
|
#if ADDR_AM_BUILD
|
|
if ((pIn->bitPosition >= 8) ||
|
|
(pIn->numSamples > m_maxSamples))
|
|
{
|
|
retCode = ADDR_INVALIDPARAMS;
|
|
}
|
|
else
|
|
{
|
|
DispatchComputeFmaskCoordFromAddr(pIn, pOut);
|
|
}
|
|
#endif
|
|
|
|
return retCode;
|
|
}
|
|
|
|
#if ADDR_AM_BUILD
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::DispatchComputeFmaskAddrFromCoord
|
|
*
|
|
* @brief
|
|
* Computes the FMASK address and bit position from a coordinate.
|
|
* @return
|
|
* The byte address
|
|
****************************************************************************************************
|
|
*/
|
|
UINT_64 EgBasedLib::DispatchComputeFmaskAddrFromCoord(
|
|
const ADDR_COMPUTE_FMASK_ADDRFROMCOORD_INPUT* pIn, ///< [in] input structure
|
|
ADDR_COMPUTE_FMASK_ADDRFROMCOORD_OUTPUT* pOut ///< [out] output structure
|
|
) const
|
|
{
|
|
UINT_32 x = pIn->x;
|
|
UINT_32 y = pIn->y;
|
|
UINT_32 slice = pIn->slice;
|
|
UINT_32 sample = pIn->sample;
|
|
UINT_32 plane = pIn->plane;
|
|
UINT_32 pitch = pIn->pitch;
|
|
UINT_32 height = pIn->height;
|
|
UINT_32 numSamples = pIn->numSamples;
|
|
AddrTileMode tileMode = pIn->tileMode;
|
|
BOOL_32 ignoreSE = pIn->ignoreSE;
|
|
ADDR_TILEINFO* pTileInfo = pIn->pTileInfo;
|
|
BOOL_32 resolved = pIn->resolved;
|
|
|
|
UINT_32* pBitPosition = &pOut->bitPosition;
|
|
UINT_64 addr = 0;
|
|
|
|
ADDR_ASSERT(numSamples > 1);
|
|
ADDR_ASSERT(Thickness(tileMode) == 1);
|
|
|
|
switch (tileMode)
|
|
{
|
|
case ADDR_TM_1D_TILED_THIN1:
|
|
addr = ComputeFmaskAddrFromCoordMicroTiled(x,
|
|
y,
|
|
slice,
|
|
sample,
|
|
plane,
|
|
pitch,
|
|
height,
|
|
numSamples,
|
|
tileMode,
|
|
resolved,
|
|
pBitPosition);
|
|
break;
|
|
case ADDR_TM_2D_TILED_THIN1: //fall through
|
|
case ADDR_TM_3D_TILED_THIN1:
|
|
UINT_32 pipeSwizzle;
|
|
UINT_32 bankSwizzle;
|
|
|
|
if (m_configFlags.useCombinedSwizzle)
|
|
{
|
|
ExtractBankPipeSwizzle(pIn->tileSwizzle, pIn->pTileInfo,
|
|
&bankSwizzle, &pipeSwizzle);
|
|
}
|
|
else
|
|
{
|
|
pipeSwizzle = pIn->pipeSwizzle;
|
|
bankSwizzle = pIn->bankSwizzle;
|
|
}
|
|
|
|
addr = ComputeFmaskAddrFromCoordMacroTiled(x,
|
|
y,
|
|
slice,
|
|
sample,
|
|
plane,
|
|
pitch,
|
|
height,
|
|
numSamples,
|
|
tileMode,
|
|
pipeSwizzle,
|
|
bankSwizzle,
|
|
ignoreSE,
|
|
pTileInfo,
|
|
resolved,
|
|
pBitPosition);
|
|
break;
|
|
default:
|
|
*pBitPosition = 0;
|
|
break;
|
|
}
|
|
|
|
return addr;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::ComputeFmaskAddrFromCoordMicroTiled
|
|
*
|
|
* @brief
|
|
* Computes the FMASK address and bit position from a coordinate for 1D tilied (micro
|
|
* tiled)
|
|
* @return
|
|
* The byte address
|
|
****************************************************************************************************
|
|
*/
|
|
UINT_64 EgBasedLib::ComputeFmaskAddrFromCoordMicroTiled(
|
|
UINT_32 x, ///< [in] x coordinate
|
|
UINT_32 y, ///< [in] y coordinate
|
|
UINT_32 slice, ///< [in] slice index
|
|
UINT_32 sample, ///< [in] sample number
|
|
UINT_32 plane, ///< [in] plane number
|
|
UINT_32 pitch, ///< [in] surface pitch in pixels
|
|
UINT_32 height, ///< [in] surface height in pixels
|
|
UINT_32 numSamples, ///< [in] number of samples
|
|
AddrTileMode tileMode, ///< [in] tile mode
|
|
BOOL_32 resolved, ///< [in] TRUE if this is for resolved fmask
|
|
UINT_32* pBitPosition ///< [out] pointer to returned bit position
|
|
) const
|
|
{
|
|
UINT_64 addr = 0;
|
|
UINT_32 effectiveBpp;
|
|
UINT_32 effectiveSamples;
|
|
|
|
//
|
|
// 2xAA use the same layout as 4xAA
|
|
//
|
|
if (numSamples == 2)
|
|
{
|
|
numSamples = 4;
|
|
}
|
|
|
|
//
|
|
// Compute the number of planes.
|
|
//
|
|
if (resolved == FALSE)
|
|
{
|
|
effectiveSamples = ComputeFmaskNumPlanesFromNumSamples(numSamples);
|
|
effectiveBpp = numSamples;
|
|
|
|
//
|
|
// Compute the address just like a color surface with numSamples bits per element and
|
|
// numPlanes samples.
|
|
//
|
|
addr = ComputeSurfaceAddrFromCoordMicroTiled(x,
|
|
y,
|
|
slice,
|
|
plane, // sample
|
|
effectiveBpp,
|
|
pitch,
|
|
height,
|
|
effectiveSamples,
|
|
tileMode,
|
|
ADDR_NON_DISPLAYABLE,
|
|
FALSE,
|
|
pBitPosition);
|
|
|
|
//
|
|
// Compute the real bit position. Each (sample, plane) is stored with one bit per sample.
|
|
//
|
|
|
|
//
|
|
// Compute the pixel index with in the micro tile
|
|
//
|
|
UINT_32 pixelIndex = ComputePixelIndexWithinMicroTile(x % 8,
|
|
y % 8,
|
|
slice,
|
|
1,
|
|
tileMode,
|
|
ADDR_NON_DISPLAYABLE);
|
|
|
|
*pBitPosition = ((pixelIndex * numSamples) + sample) & (BITS_PER_BYTE-1);
|
|
|
|
UINT_64 bitAddr = BYTES_TO_BITS(addr) + *pBitPosition;
|
|
|
|
addr = bitAddr / 8;
|
|
}
|
|
else
|
|
{
|
|
effectiveBpp = ComputeFmaskResolvedBppFromNumSamples(numSamples);
|
|
effectiveSamples = 1;
|
|
|
|
//
|
|
// Compute the address just like a color surface with numSamples bits per element and
|
|
// numPlanes samples.
|
|
//
|
|
addr = ComputeSurfaceAddrFromCoordMicroTiled(x,
|
|
y,
|
|
slice,
|
|
sample,
|
|
effectiveBpp,
|
|
pitch,
|
|
height,
|
|
effectiveSamples,
|
|
tileMode,
|
|
ADDR_NON_DISPLAYABLE,
|
|
TRUE,
|
|
pBitPosition);
|
|
}
|
|
|
|
return addr;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::ComputeFmaskAddrFromCoordMacroTiled
|
|
*
|
|
* @brief
|
|
* Computes the FMASK address and bit position from a coordinate for 2D tilied (macro
|
|
* tiled)
|
|
* @return
|
|
* The byte address
|
|
****************************************************************************************************
|
|
*/
|
|
UINT_64 EgBasedLib::ComputeFmaskAddrFromCoordMacroTiled(
|
|
UINT_32 x, ///< [in] x coordinate
|
|
UINT_32 y, ///< [in] y coordinate
|
|
UINT_32 slice, ///< [in] slice index
|
|
UINT_32 sample, ///< [in] sample number
|
|
UINT_32 plane, ///< [in] plane number
|
|
UINT_32 pitch, ///< [in] surface pitch in pixels
|
|
UINT_32 height, ///< [in] surface height in pixels
|
|
UINT_32 numSamples, ///< [in] number of samples
|
|
AddrTileMode tileMode, ///< [in] tile mode
|
|
UINT_32 pipeSwizzle, ///< [in] pipe swizzle
|
|
UINT_32 bankSwizzle, ///< [in] bank swizzle
|
|
BOOL_32 ignoreSE, ///< [in] TRUE if ignore shader engine
|
|
ADDR_TILEINFO* pTileInfo, ///< [in] bank structure.**All fields to be valid on entry**
|
|
BOOL_32 resolved, ///< [in] TRUE if this is for resolved fmask
|
|
UINT_32* pBitPosition ///< [out] pointer to returned bit position
|
|
) const
|
|
{
|
|
UINT_64 addr = 0;
|
|
UINT_32 effectiveBpp;
|
|
UINT_32 effectiveSamples;
|
|
|
|
//
|
|
// 2xAA use the same layout as 4xAA
|
|
//
|
|
if (numSamples == 2)
|
|
{
|
|
numSamples = 4;
|
|
}
|
|
|
|
//
|
|
// Compute the number of planes.
|
|
//
|
|
if (resolved == FALSE)
|
|
{
|
|
effectiveSamples = ComputeFmaskNumPlanesFromNumSamples(numSamples);
|
|
effectiveBpp = numSamples;
|
|
|
|
//
|
|
// Compute the address just like a color surface with numSamples bits per element and
|
|
// numPlanes samples.
|
|
//
|
|
addr = ComputeSurfaceAddrFromCoordMacroTiled(x,
|
|
y,
|
|
slice,
|
|
plane, // sample
|
|
effectiveBpp,
|
|
pitch,
|
|
height,
|
|
effectiveSamples,
|
|
tileMode,
|
|
ADDR_NON_DISPLAYABLE,// isdisp
|
|
ignoreSE,// ignore_shader
|
|
FALSE,// depth_sample_order
|
|
pipeSwizzle,
|
|
bankSwizzle,
|
|
pTileInfo,
|
|
pBitPosition);
|
|
|
|
//
|
|
// Compute the real bit position. Each (sample, plane) is stored with one bit per sample.
|
|
//
|
|
|
|
|
|
//
|
|
// Compute the pixel index with in the micro tile
|
|
//
|
|
UINT_32 pixelIndex = ComputePixelIndexWithinMicroTile(x ,
|
|
y ,
|
|
slice,
|
|
effectiveBpp,
|
|
tileMode,
|
|
ADDR_NON_DISPLAYABLE);
|
|
|
|
*pBitPosition = ((pixelIndex * numSamples) + sample) & (BITS_PER_BYTE-1);
|
|
|
|
UINT_64 bitAddr = BYTES_TO_BITS(addr) + *pBitPosition;
|
|
|
|
addr = bitAddr / 8;
|
|
|
|
}
|
|
else
|
|
{
|
|
effectiveBpp = ComputeFmaskResolvedBppFromNumSamples(numSamples);
|
|
effectiveSamples = 1;
|
|
|
|
//
|
|
// Compute the address just like a color surface with numSamples bits per element and
|
|
// numPlanes samples.
|
|
//
|
|
addr = ComputeSurfaceAddrFromCoordMacroTiled(x,
|
|
y,
|
|
slice,
|
|
sample,
|
|
effectiveBpp,
|
|
pitch,
|
|
height,
|
|
effectiveSamples,
|
|
tileMode,
|
|
ADDR_NON_DISPLAYABLE,
|
|
ignoreSE,
|
|
TRUE,
|
|
pipeSwizzle,
|
|
bankSwizzle,
|
|
pTileInfo,
|
|
pBitPosition);
|
|
}
|
|
|
|
return addr;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::ComputeFmaskCoordFromAddrMicroTiled
|
|
*
|
|
* @brief
|
|
* Compute (x,y,slice,sample,plane) coordinates from fmask address
|
|
* @return
|
|
* N/A
|
|
*
|
|
****************************************************************************************************
|
|
*/
|
|
VOID EgBasedLib::ComputeFmaskCoordFromAddrMicroTiled(
|
|
UINT_64 addr, ///< [in] byte address
|
|
UINT_32 bitPosition,///< [in] bit position
|
|
UINT_32 pitch, ///< [in] pitch in pixels
|
|
UINT_32 height, ///< [in] height in pixels
|
|
UINT_32 numSamples, ///< [in] number of samples (of color buffer)
|
|
AddrTileMode tileMode, ///< [in] tile mode
|
|
BOOL_32 resolved, ///< [in] TRUE if it is resolved fmask
|
|
UINT_32* pX, ///< [out] X coord
|
|
UINT_32* pY, ///< [out] Y coord
|
|
UINT_32* pSlice, ///< [out] slice index
|
|
UINT_32* pSample, ///< [out] sample index
|
|
UINT_32* pPlane ///< [out] plane index
|
|
) const
|
|
{
|
|
UINT_32 effectiveBpp;
|
|
UINT_32 effectiveSamples;
|
|
|
|
// 2xAA use the same layout as 4xAA
|
|
if (numSamples == 2)
|
|
{
|
|
numSamples = 4;
|
|
}
|
|
|
|
if (resolved == FALSE)
|
|
{
|
|
effectiveSamples = ComputeFmaskNumPlanesFromNumSamples(numSamples);
|
|
effectiveBpp = numSamples;
|
|
|
|
ComputeSurfaceCoordFromAddrMicroTiled(addr,
|
|
bitPosition,
|
|
effectiveBpp,
|
|
pitch,
|
|
height,
|
|
effectiveSamples,
|
|
tileMode,
|
|
0, // tileBase
|
|
0, // compBits
|
|
pX,
|
|
pY,
|
|
pSlice,
|
|
pPlane,
|
|
ADDR_NON_DISPLAYABLE, // microTileType
|
|
FALSE // isDepthSampleOrder
|
|
);
|
|
|
|
|
|
if ( pSample )
|
|
{
|
|
*pSample = bitPosition % numSamples;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
effectiveBpp = ComputeFmaskResolvedBppFromNumSamples(numSamples);
|
|
effectiveSamples = 1;
|
|
|
|
ComputeSurfaceCoordFromAddrMicroTiled(addr,
|
|
bitPosition,
|
|
effectiveBpp,
|
|
pitch,
|
|
height,
|
|
effectiveSamples,
|
|
tileMode,
|
|
0, // tileBase
|
|
0, // compBits
|
|
pX,
|
|
pY,
|
|
pSlice,
|
|
pSample,
|
|
ADDR_NON_DISPLAYABLE, // microTileType
|
|
TRUE // isDepthSampleOrder
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::ComputeFmaskCoordFromAddrMacroTiled
|
|
*
|
|
* @brief
|
|
* Compute (x,y,slice,sample,plane) coordinates from
|
|
* fmask address
|
|
* @return
|
|
* N/A
|
|
*
|
|
****************************************************************************************************
|
|
*/
|
|
VOID EgBasedLib::ComputeFmaskCoordFromAddrMacroTiled(
|
|
UINT_64 addr, ///< [in] byte address
|
|
UINT_32 bitPosition,///< [in] bit position
|
|
UINT_32 pitch, ///< [in] pitch in pixels
|
|
UINT_32 height, ///< [in] height in pixels
|
|
UINT_32 numSamples, ///< [in] number of samples (of color buffer)
|
|
AddrTileMode tileMode, ///< [in] tile mode
|
|
UINT_32 pipeSwizzle,///< [in] pipe swizzle
|
|
UINT_32 bankSwizzle,///< [in] bank swizzle
|
|
BOOL_32 ignoreSE, ///< [in] TRUE if ignore shader engine
|
|
ADDR_TILEINFO* pTileInfo, ///< [in] bank structure. **All fields to be valid on entry**
|
|
BOOL_32 resolved, ///< [in] TRUE if it is resolved fmask
|
|
UINT_32* pX, ///< [out] X coord
|
|
UINT_32* pY, ///< [out] Y coord
|
|
UINT_32* pSlice, ///< [out] slice index
|
|
UINT_32* pSample, ///< [out] sample index
|
|
UINT_32* pPlane ///< [out] plane index
|
|
) const
|
|
{
|
|
UINT_32 effectiveBpp;
|
|
UINT_32 effectiveSamples;
|
|
|
|
// 2xAA use the same layout as 4xAA
|
|
if (numSamples == 2)
|
|
{
|
|
numSamples = 4;
|
|
}
|
|
|
|
//
|
|
// Compute the number of planes.
|
|
//
|
|
if (resolved == FALSE)
|
|
{
|
|
effectiveSamples = ComputeFmaskNumPlanesFromNumSamples(numSamples);
|
|
effectiveBpp = numSamples;
|
|
|
|
ComputeSurfaceCoordFromAddrMacroTiled(addr,
|
|
bitPosition,
|
|
effectiveBpp,
|
|
pitch,
|
|
height,
|
|
effectiveSamples,
|
|
tileMode,
|
|
0, // No tileBase
|
|
0, // No compBits
|
|
ADDR_NON_DISPLAYABLE,
|
|
ignoreSE,
|
|
FALSE,
|
|
pipeSwizzle,
|
|
bankSwizzle,
|
|
pTileInfo,
|
|
pX,
|
|
pY,
|
|
pSlice,
|
|
pPlane);
|
|
|
|
if (pSample)
|
|
{
|
|
*pSample = bitPosition % numSamples;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
effectiveBpp = ComputeFmaskResolvedBppFromNumSamples(numSamples);
|
|
effectiveSamples = 1;
|
|
|
|
ComputeSurfaceCoordFromAddrMacroTiled(addr,
|
|
bitPosition,
|
|
effectiveBpp,
|
|
pitch,
|
|
height,
|
|
effectiveSamples,
|
|
tileMode,
|
|
0, // No tileBase
|
|
0, // No compBits
|
|
ADDR_NON_DISPLAYABLE,
|
|
ignoreSE,
|
|
TRUE,
|
|
pipeSwizzle,
|
|
bankSwizzle,
|
|
pTileInfo,
|
|
pX,
|
|
pY,
|
|
pSlice,
|
|
pSample);
|
|
}
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::DispatchComputeFmaskCoordFromAddr
|
|
*
|
|
* @brief
|
|
* Compute (x,y,slice,sample,plane) coordinates from
|
|
* fmask address
|
|
* @return
|
|
* N/A
|
|
*
|
|
****************************************************************************************************
|
|
*/
|
|
VOID EgBasedLib::DispatchComputeFmaskCoordFromAddr(
|
|
const ADDR_COMPUTE_FMASK_COORDFROMADDR_INPUT* pIn, ///< [in] input structure
|
|
ADDR_COMPUTE_FMASK_COORDFROMADDR_OUTPUT* pOut ///< [out] output structure
|
|
) const
|
|
{
|
|
UINT_64 addr = pIn->addr;
|
|
UINT_32 bitPosition = pIn->bitPosition;
|
|
UINT_32 pitch = pIn->pitch;
|
|
UINT_32 height = pIn->height;
|
|
UINT_32 numSamples = pIn->numSamples;
|
|
AddrTileMode tileMode = pIn->tileMode;
|
|
BOOL_32 ignoreSE = pIn->ignoreSE;
|
|
ADDR_TILEINFO* pTileInfo = pIn->pTileInfo;
|
|
BOOL_32 resolved = pIn->resolved;
|
|
|
|
UINT_32* pX = &pOut->x;
|
|
UINT_32* pY = &pOut->y;
|
|
UINT_32* pSlice = &pOut->slice;
|
|
UINT_32* pSample = &pOut->sample;
|
|
UINT_32* pPlane = &pOut->plane;
|
|
|
|
switch (tileMode)
|
|
{
|
|
case ADDR_TM_1D_TILED_THIN1:
|
|
ComputeFmaskCoordFromAddrMicroTiled(addr,
|
|
bitPosition,
|
|
pitch,
|
|
height,
|
|
numSamples,
|
|
tileMode,
|
|
resolved,
|
|
pX,
|
|
pY,
|
|
pSlice,
|
|
pSample,
|
|
pPlane);
|
|
break;
|
|
case ADDR_TM_2D_TILED_THIN1://fall through
|
|
case ADDR_TM_3D_TILED_THIN1:
|
|
UINT_32 pipeSwizzle;
|
|
UINT_32 bankSwizzle;
|
|
|
|
if (m_configFlags.useCombinedSwizzle)
|
|
{
|
|
ExtractBankPipeSwizzle(pIn->tileSwizzle, pIn->pTileInfo,
|
|
&bankSwizzle, &pipeSwizzle);
|
|
}
|
|
else
|
|
{
|
|
pipeSwizzle = pIn->pipeSwizzle;
|
|
bankSwizzle = pIn->bankSwizzle;
|
|
}
|
|
|
|
ComputeFmaskCoordFromAddrMacroTiled(addr,
|
|
bitPosition,
|
|
pitch,
|
|
height,
|
|
numSamples,
|
|
tileMode,
|
|
pipeSwizzle,
|
|
bankSwizzle,
|
|
ignoreSE,
|
|
pTileInfo,
|
|
resolved,
|
|
pX,
|
|
pY,
|
|
pSlice,
|
|
pSample,
|
|
pPlane);
|
|
break;
|
|
default:
|
|
ADDR_ASSERT_ALWAYS();
|
|
break;
|
|
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::ComputeFmaskNumPlanesFromNumSamples
|
|
*
|
|
* @brief
|
|
* Compute fmask number of planes from number of samples
|
|
*
|
|
* @return
|
|
* Number of planes
|
|
****************************************************************************************************
|
|
*/
|
|
UINT_32 EgBasedLib::ComputeFmaskNumPlanesFromNumSamples(
|
|
UINT_32 numSamples) ///< [in] number of samples
|
|
{
|
|
UINT_32 numPlanes;
|
|
|
|
//
|
|
// FMASK is stored such that each micro tile is composed of elements containing N bits, where
|
|
// N is the number of samples. There is a micro tile for each bit in the FMASK address, and
|
|
// micro tiles for each address bit, sometimes referred to as a plane, are stored sequentially.
|
|
// The FMASK for a 2-sample surface looks like a general surface with 2 bits per element.
|
|
// The FMASK for a 4-sample surface looks like a general surface with 4 bits per element and
|
|
// 2 samples. The FMASK for an 8-sample surface looks like a general surface with 8 bits per
|
|
// element and 4 samples. R6xx and R7xx only stored 3 planes for 8-sample FMASK surfaces.
|
|
// This was changed for R8xx to simplify the logic in the CB.
|
|
//
|
|
switch (numSamples)
|
|
{
|
|
case 2:
|
|
numPlanes = 1;
|
|
break;
|
|
case 4:
|
|
numPlanes = 2;
|
|
break;
|
|
case 8:
|
|
numPlanes = 4;
|
|
break;
|
|
default:
|
|
ADDR_UNHANDLED_CASE();
|
|
numPlanes = 0;
|
|
break;
|
|
}
|
|
return numPlanes;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::ComputeFmaskResolvedBppFromNumSamples
|
|
*
|
|
* @brief
|
|
* Compute resolved fmask effective bpp based on number of samples
|
|
*
|
|
* @return
|
|
* bpp
|
|
****************************************************************************************************
|
|
*/
|
|
UINT_32 EgBasedLib::ComputeFmaskResolvedBppFromNumSamples(
|
|
UINT_32 numSamples) ///< number of samples
|
|
{
|
|
UINT_32 bpp;
|
|
|
|
//
|
|
// Resolved FMASK surfaces are generated yBit the CB and read yBit the texture unit
|
|
// so that the texture unit can read compressed multi-sample color data.
|
|
// These surfaces store each index value packed per element.
|
|
// Each element contains at least num_samples * log2(num_samples) bits.
|
|
// Resolved FMASK surfaces are addressed as follows:
|
|
// 2-sample Addressed similarly to a color surface with 8 bits per element and 1 sample.
|
|
// 4-sample Addressed similarly to a color surface with 8 bits per element and 1 sample.
|
|
// 8-sample Addressed similarly to a color surface with 32 bits per element and 1 sample.
|
|
|
|
switch (numSamples)
|
|
{
|
|
case 2:
|
|
bpp = 8;
|
|
break;
|
|
case 4:
|
|
bpp = 8;
|
|
break;
|
|
case 8:
|
|
bpp = 32;
|
|
break;
|
|
default:
|
|
ADDR_UNHANDLED_CASE();
|
|
bpp = 0;
|
|
break;
|
|
}
|
|
return bpp;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::IsTileInfoAllZero
|
|
*
|
|
* @brief
|
|
* Return TRUE if all field are zero
|
|
* @note
|
|
* Since NULL input is consider to be all zero
|
|
****************************************************************************************************
|
|
*/
|
|
BOOL_32 EgBasedLib::IsTileInfoAllZero(
|
|
ADDR_TILEINFO* pTileInfo)
|
|
{
|
|
BOOL_32 allZero = TRUE;
|
|
|
|
if (pTileInfo)
|
|
{
|
|
if ((pTileInfo->banks != 0) ||
|
|
(pTileInfo->bankWidth != 0) ||
|
|
(pTileInfo->bankHeight != 0) ||
|
|
(pTileInfo->macroAspectRatio != 0) ||
|
|
(pTileInfo->tileSplitBytes != 0) ||
|
|
(pTileInfo->pipeConfig != 0)
|
|
)
|
|
{
|
|
allZero = FALSE;
|
|
}
|
|
}
|
|
|
|
return allZero;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::HwlTileInfoEqual
|
|
*
|
|
* @brief
|
|
* Return TRUE if all field are equal
|
|
* @note
|
|
* Only takes care of current HWL's data
|
|
****************************************************************************************************
|
|
*/
|
|
BOOL_32 EgBasedLib::HwlTileInfoEqual(
|
|
const ADDR_TILEINFO* pLeft, ///<[in] Left compare operand
|
|
const ADDR_TILEINFO* pRight ///<[in] Right compare operand
|
|
) const
|
|
{
|
|
BOOL_32 equal = FALSE;
|
|
|
|
if (pLeft->banks == pRight->banks &&
|
|
pLeft->bankWidth == pRight->bankWidth &&
|
|
pLeft->bankHeight == pRight->bankHeight &&
|
|
pLeft->macroAspectRatio == pRight->macroAspectRatio &&
|
|
pLeft->tileSplitBytes == pRight->tileSplitBytes)
|
|
{
|
|
equal = TRUE;
|
|
}
|
|
|
|
return equal;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::HwlConvertTileInfoToHW
|
|
* @brief
|
|
* Entry of EgBasedLib ConvertTileInfoToHW
|
|
* @return
|
|
* ADDR_E_RETURNCODE
|
|
****************************************************************************************************
|
|
*/
|
|
ADDR_E_RETURNCODE EgBasedLib::HwlConvertTileInfoToHW(
|
|
const ADDR_CONVERT_TILEINFOTOHW_INPUT* pIn, ///< [in] input structure
|
|
ADDR_CONVERT_TILEINFOTOHW_OUTPUT* pOut ///< [out] output structure
|
|
) const
|
|
{
|
|
ADDR_E_RETURNCODE retCode = ADDR_OK;
|
|
|
|
ADDR_TILEINFO *pTileInfoIn = pIn->pTileInfo;
|
|
ADDR_TILEINFO *pTileInfoOut = pOut->pTileInfo;
|
|
|
|
if ((pTileInfoIn != NULL) && (pTileInfoOut != NULL))
|
|
{
|
|
if (pIn->reverse == FALSE)
|
|
{
|
|
switch (pTileInfoIn->banks)
|
|
{
|
|
case 2:
|
|
pTileInfoOut->banks = 0;
|
|
break;
|
|
case 4:
|
|
pTileInfoOut->banks = 1;
|
|
break;
|
|
case 8:
|
|
pTileInfoOut->banks = 2;
|
|
break;
|
|
case 16:
|
|
pTileInfoOut->banks = 3;
|
|
break;
|
|
default:
|
|
ADDR_ASSERT_ALWAYS();
|
|
retCode = ADDR_INVALIDPARAMS;
|
|
pTileInfoOut->banks = 0;
|
|
break;
|
|
}
|
|
|
|
switch (pTileInfoIn->bankWidth)
|
|
{
|
|
case 1:
|
|
pTileInfoOut->bankWidth = 0;
|
|
break;
|
|
case 2:
|
|
pTileInfoOut->bankWidth = 1;
|
|
break;
|
|
case 4:
|
|
pTileInfoOut->bankWidth = 2;
|
|
break;
|
|
case 8:
|
|
pTileInfoOut->bankWidth = 3;
|
|
break;
|
|
default:
|
|
ADDR_ASSERT_ALWAYS();
|
|
retCode = ADDR_INVALIDPARAMS;
|
|
pTileInfoOut->bankWidth = 0;
|
|
break;
|
|
}
|
|
|
|
switch (pTileInfoIn->bankHeight)
|
|
{
|
|
case 1:
|
|
pTileInfoOut->bankHeight = 0;
|
|
break;
|
|
case 2:
|
|
pTileInfoOut->bankHeight = 1;
|
|
break;
|
|
case 4:
|
|
pTileInfoOut->bankHeight = 2;
|
|
break;
|
|
case 8:
|
|
pTileInfoOut->bankHeight = 3;
|
|
break;
|
|
default:
|
|
ADDR_ASSERT_ALWAYS();
|
|
retCode = ADDR_INVALIDPARAMS;
|
|
pTileInfoOut->bankHeight = 0;
|
|
break;
|
|
}
|
|
|
|
switch (pTileInfoIn->macroAspectRatio)
|
|
{
|
|
case 1:
|
|
pTileInfoOut->macroAspectRatio = 0;
|
|
break;
|
|
case 2:
|
|
pTileInfoOut->macroAspectRatio = 1;
|
|
break;
|
|
case 4:
|
|
pTileInfoOut->macroAspectRatio = 2;
|
|
break;
|
|
case 8:
|
|
pTileInfoOut->macroAspectRatio = 3;
|
|
break;
|
|
default:
|
|
ADDR_ASSERT_ALWAYS();
|
|
retCode = ADDR_INVALIDPARAMS;
|
|
pTileInfoOut->macroAspectRatio = 0;
|
|
break;
|
|
}
|
|
|
|
switch (pTileInfoIn->tileSplitBytes)
|
|
{
|
|
case 64:
|
|
pTileInfoOut->tileSplitBytes = 0;
|
|
break;
|
|
case 128:
|
|
pTileInfoOut->tileSplitBytes = 1;
|
|
break;
|
|
case 256:
|
|
pTileInfoOut->tileSplitBytes = 2;
|
|
break;
|
|
case 512:
|
|
pTileInfoOut->tileSplitBytes = 3;
|
|
break;
|
|
case 1024:
|
|
pTileInfoOut->tileSplitBytes = 4;
|
|
break;
|
|
case 2048:
|
|
pTileInfoOut->tileSplitBytes = 5;
|
|
break;
|
|
case 4096:
|
|
pTileInfoOut->tileSplitBytes = 6;
|
|
break;
|
|
default:
|
|
ADDR_ASSERT_ALWAYS();
|
|
retCode = ADDR_INVALIDPARAMS;
|
|
pTileInfoOut->tileSplitBytes = 0;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (pTileInfoIn->banks)
|
|
{
|
|
case 0:
|
|
pTileInfoOut->banks = 2;
|
|
break;
|
|
case 1:
|
|
pTileInfoOut->banks = 4;
|
|
break;
|
|
case 2:
|
|
pTileInfoOut->banks = 8;
|
|
break;
|
|
case 3:
|
|
pTileInfoOut->banks = 16;
|
|
break;
|
|
default:
|
|
ADDR_ASSERT_ALWAYS();
|
|
retCode = ADDR_INVALIDPARAMS;
|
|
pTileInfoOut->banks = 2;
|
|
break;
|
|
}
|
|
|
|
switch (pTileInfoIn->bankWidth)
|
|
{
|
|
case 0:
|
|
pTileInfoOut->bankWidth = 1;
|
|
break;
|
|
case 1:
|
|
pTileInfoOut->bankWidth = 2;
|
|
break;
|
|
case 2:
|
|
pTileInfoOut->bankWidth = 4;
|
|
break;
|
|
case 3:
|
|
pTileInfoOut->bankWidth = 8;
|
|
break;
|
|
default:
|
|
ADDR_ASSERT_ALWAYS();
|
|
retCode = ADDR_INVALIDPARAMS;
|
|
pTileInfoOut->bankWidth = 1;
|
|
break;
|
|
}
|
|
|
|
switch (pTileInfoIn->bankHeight)
|
|
{
|
|
case 0:
|
|
pTileInfoOut->bankHeight = 1;
|
|
break;
|
|
case 1:
|
|
pTileInfoOut->bankHeight = 2;
|
|
break;
|
|
case 2:
|
|
pTileInfoOut->bankHeight = 4;
|
|
break;
|
|
case 3:
|
|
pTileInfoOut->bankHeight = 8;
|
|
break;
|
|
default:
|
|
ADDR_ASSERT_ALWAYS();
|
|
retCode = ADDR_INVALIDPARAMS;
|
|
pTileInfoOut->bankHeight = 1;
|
|
break;
|
|
}
|
|
|
|
switch (pTileInfoIn->macroAspectRatio)
|
|
{
|
|
case 0:
|
|
pTileInfoOut->macroAspectRatio = 1;
|
|
break;
|
|
case 1:
|
|
pTileInfoOut->macroAspectRatio = 2;
|
|
break;
|
|
case 2:
|
|
pTileInfoOut->macroAspectRatio = 4;
|
|
break;
|
|
case 3:
|
|
pTileInfoOut->macroAspectRatio = 8;
|
|
break;
|
|
default:
|
|
ADDR_ASSERT_ALWAYS();
|
|
retCode = ADDR_INVALIDPARAMS;
|
|
pTileInfoOut->macroAspectRatio = 1;
|
|
break;
|
|
}
|
|
|
|
switch (pTileInfoIn->tileSplitBytes)
|
|
{
|
|
case 0:
|
|
pTileInfoOut->tileSplitBytes = 64;
|
|
break;
|
|
case 1:
|
|
pTileInfoOut->tileSplitBytes = 128;
|
|
break;
|
|
case 2:
|
|
pTileInfoOut->tileSplitBytes = 256;
|
|
break;
|
|
case 3:
|
|
pTileInfoOut->tileSplitBytes = 512;
|
|
break;
|
|
case 4:
|
|
pTileInfoOut->tileSplitBytes = 1024;
|
|
break;
|
|
case 5:
|
|
pTileInfoOut->tileSplitBytes = 2048;
|
|
break;
|
|
case 6:
|
|
pTileInfoOut->tileSplitBytes = 4096;
|
|
break;
|
|
default:
|
|
ADDR_ASSERT_ALWAYS();
|
|
retCode = ADDR_INVALIDPARAMS;
|
|
pTileInfoOut->tileSplitBytes = 64;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (pTileInfoIn != pTileInfoOut)
|
|
{
|
|
pTileInfoOut->pipeConfig = pTileInfoIn->pipeConfig;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ADDR_ASSERT_ALWAYS();
|
|
retCode = ADDR_INVALIDPARAMS;
|
|
}
|
|
|
|
return retCode;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::HwlComputeSurfaceInfo
|
|
* @brief
|
|
* Entry of EgBasedLib ComputeSurfaceInfo
|
|
* @return
|
|
* ADDR_E_RETURNCODE
|
|
****************************************************************************************************
|
|
*/
|
|
ADDR_E_RETURNCODE EgBasedLib::HwlComputeSurfaceInfo(
|
|
const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] input structure
|
|
ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [out] output structure
|
|
) const
|
|
{
|
|
ADDR_E_RETURNCODE retCode = ADDR_OK;
|
|
|
|
if (pIn->numSamples < pIn->numFrags)
|
|
{
|
|
retCode = ADDR_INVALIDPARAMS;
|
|
}
|
|
|
|
ADDR_TILEINFO tileInfo = {0};
|
|
|
|
if (retCode == ADDR_OK)
|
|
{
|
|
// Uses internal tile info if pOut does not have a valid pTileInfo
|
|
if (pOut->pTileInfo == NULL)
|
|
{
|
|
pOut->pTileInfo = &tileInfo;
|
|
}
|
|
|
|
if (DispatchComputeSurfaceInfo(pIn, pOut) == FALSE)
|
|
{
|
|
retCode = ADDR_INVALIDPARAMS;
|
|
}
|
|
|
|
// In case client uses tile info as input and would like to calculate a correct size and
|
|
// alignment together with tile info as output when the tile info is not suppose to have any
|
|
// matching indices in tile mode tables.
|
|
if (pIn->flags.skipIndicesOutput == FALSE)
|
|
{
|
|
// Returns an index
|
|
pOut->tileIndex = HwlPostCheckTileIndex(pOut->pTileInfo,
|
|
pOut->tileMode,
|
|
pOut->tileType,
|
|
pOut->tileIndex);
|
|
|
|
if (IsMacroTiled(pOut->tileMode) && (pOut->macroModeIndex == TileIndexInvalid))
|
|
{
|
|
pOut->macroModeIndex = HwlComputeMacroModeIndex(pOut->tileIndex,
|
|
pIn->flags,
|
|
pIn->bpp,
|
|
pIn->numSamples,
|
|
pOut->pTileInfo);
|
|
}
|
|
}
|
|
|
|
// Resets pTileInfo to NULL if the internal tile info is used
|
|
if (pOut->pTileInfo == &tileInfo)
|
|
{
|
|
#if DEBUG
|
|
// Client does not pass in a valid pTileInfo
|
|
if (IsMacroTiled(pOut->tileMode))
|
|
{
|
|
// If a valid index is returned, then no pTileInfo is okay
|
|
ADDR_ASSERT((m_configFlags.useTileIndex == FALSE) ||
|
|
(pOut->tileIndex != TileIndexInvalid));
|
|
|
|
if (IsTileInfoAllZero(pIn->pTileInfo) == FALSE)
|
|
{
|
|
// The initial value of pIn->pTileInfo is copied to tileInfo
|
|
// We do not expect any of these value to be changed nor any 0 of inputs
|
|
ADDR_ASSERT(tileInfo.banks == pIn->pTileInfo->banks);
|
|
ADDR_ASSERT(tileInfo.bankWidth == pIn->pTileInfo->bankWidth);
|
|
ADDR_ASSERT(tileInfo.bankHeight == pIn->pTileInfo->bankHeight);
|
|
ADDR_ASSERT(tileInfo.macroAspectRatio == pIn->pTileInfo->macroAspectRatio);
|
|
ADDR_ASSERT(tileInfo.tileSplitBytes == pIn->pTileInfo->tileSplitBytes);
|
|
}
|
|
}
|
|
#endif
|
|
pOut->pTileInfo = NULL;
|
|
}
|
|
}
|
|
|
|
return retCode;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::HwlComputeSurfaceAddrFromCoord
|
|
* @brief
|
|
* Entry of EgBasedLib ComputeSurfaceAddrFromCoord
|
|
* @return
|
|
* ADDR_E_RETURNCODE
|
|
****************************************************************************************************
|
|
*/
|
|
ADDR_E_RETURNCODE EgBasedLib::HwlComputeSurfaceAddrFromCoord(
|
|
const ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn, ///< [in] input structure
|
|
ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT* pOut ///< [out] output structure
|
|
) const
|
|
{
|
|
ADDR_E_RETURNCODE retCode = ADDR_OK;
|
|
|
|
if (
|
|
#if !ALT_TEST // Overflow test needs this out-of-boundary coord
|
|
(pIn->x > pIn->pitch) ||
|
|
(pIn->y > pIn->height) ||
|
|
#endif
|
|
(pIn->numSamples > m_maxSamples))
|
|
{
|
|
retCode = ADDR_INVALIDPARAMS;
|
|
}
|
|
else
|
|
{
|
|
pOut->addr = DispatchComputeSurfaceAddrFromCoord(pIn, pOut);
|
|
}
|
|
|
|
return retCode;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::HwlComputeSurfaceCoordFromAddr
|
|
* @brief
|
|
* Entry of EgBasedLib ComputeSurfaceCoordFromAddr
|
|
* @return
|
|
* ADDR_E_RETURNCODE
|
|
****************************************************************************************************
|
|
*/
|
|
ADDR_E_RETURNCODE EgBasedLib::HwlComputeSurfaceCoordFromAddr(
|
|
const ADDR_COMPUTE_SURFACE_COORDFROMADDR_INPUT* pIn, ///< [in] input structure
|
|
ADDR_COMPUTE_SURFACE_COORDFROMADDR_OUTPUT* pOut ///< [out] output structure
|
|
) const
|
|
{
|
|
ADDR_E_RETURNCODE retCode = ADDR_OK;
|
|
|
|
if ((pIn->bitPosition >= 8) ||
|
|
(pIn->numSamples > m_maxSamples))
|
|
{
|
|
retCode = ADDR_INVALIDPARAMS;
|
|
}
|
|
else
|
|
{
|
|
DispatchComputeSurfaceCoordFromAddr(pIn, pOut);
|
|
}
|
|
return retCode;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::HwlComputeSliceTileSwizzle
|
|
* @brief
|
|
* Entry of EgBasedLib ComputeSurfaceCoordFromAddr
|
|
* @return
|
|
* ADDR_E_RETURNCODE
|
|
****************************************************************************************************
|
|
*/
|
|
ADDR_E_RETURNCODE EgBasedLib::HwlComputeSliceTileSwizzle(
|
|
const ADDR_COMPUTE_SLICESWIZZLE_INPUT* pIn, ///< [in] input structure
|
|
ADDR_COMPUTE_SLICESWIZZLE_OUTPUT* pOut ///< [out] output structure
|
|
) const
|
|
{
|
|
ADDR_E_RETURNCODE retCode = ADDR_OK;
|
|
|
|
if (pIn->pTileInfo && (pIn->pTileInfo->banks > 0))
|
|
{
|
|
|
|
pOut->tileSwizzle = ComputeSliceTileSwizzle(pIn->tileMode,
|
|
pIn->baseSwizzle,
|
|
pIn->slice,
|
|
pIn->baseAddr,
|
|
pIn->pTileInfo);
|
|
}
|
|
else
|
|
{
|
|
retCode = ADDR_INVALIDPARAMS;
|
|
}
|
|
|
|
return retCode;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::HwlComputeHtileBpp
|
|
*
|
|
* @brief
|
|
* Compute htile bpp
|
|
*
|
|
* @return
|
|
* Htile bpp
|
|
****************************************************************************************************
|
|
*/
|
|
UINT_32 EgBasedLib::HwlComputeHtileBpp(
|
|
BOOL_32 isWidth8, ///< [in] TRUE if block width is 8
|
|
BOOL_32 isHeight8 ///< [in] TRUE if block height is 8
|
|
) const
|
|
{
|
|
// only support 8x8 mode
|
|
ADDR_ASSERT(isWidth8 && isHeight8);
|
|
return 32;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::HwlComputeHtileBaseAlign
|
|
*
|
|
* @brief
|
|
* Compute htile base alignment
|
|
*
|
|
* @return
|
|
* Htile base alignment
|
|
****************************************************************************************************
|
|
*/
|
|
UINT_32 EgBasedLib::HwlComputeHtileBaseAlign(
|
|
BOOL_32 isTcCompatible, ///< [in] if TC compatible
|
|
BOOL_32 isLinear, ///< [in] if it is linear mode
|
|
ADDR_TILEINFO* pTileInfo ///< [in] Tile info
|
|
) const
|
|
{
|
|
UINT_32 baseAlign = m_pipeInterleaveBytes * HwlGetPipes(pTileInfo);
|
|
|
|
if (isTcCompatible)
|
|
{
|
|
ADDR_ASSERT(pTileInfo != NULL);
|
|
if (pTileInfo)
|
|
{
|
|
baseAlign *= pTileInfo->banks;
|
|
}
|
|
}
|
|
|
|
return baseAlign;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::HwlGetPitchAlignmentMicroTiled
|
|
*
|
|
* @brief
|
|
* Compute 1D tiled surface pitch alignment, calculation results are returned through
|
|
* output parameters.
|
|
*
|
|
* @return
|
|
* pitch alignment
|
|
****************************************************************************************************
|
|
*/
|
|
UINT_32 EgBasedLib::HwlGetPitchAlignmentMicroTiled(
|
|
AddrTileMode tileMode, ///< [in] tile mode
|
|
UINT_32 bpp, ///< [in] bits per pixel
|
|
ADDR_SURFACE_FLAGS flags, ///< [in] surface flags
|
|
UINT_32 numSamples ///< [in] number of samples
|
|
) const
|
|
{
|
|
UINT_32 pitchAlign;
|
|
|
|
UINT_32 microTileThickness = Thickness(tileMode);
|
|
|
|
UINT_32 pixelsPerMicroTile;
|
|
UINT_32 pixelsPerPipeInterleave;
|
|
UINT_32 microTilesPerPipeInterleave;
|
|
|
|
//
|
|
// Special workaround for depth/stencil buffer, use 8 bpp to meet larger requirement for
|
|
// stencil buffer since pitch alignment is related to bpp.
|
|
// For a depth only buffer do not set this.
|
|
//
|
|
// Note: this actually does not work for mipmap but mipmap depth texture is not really
|
|
// sampled with mipmap.
|
|
//
|
|
if (flags.depth && (flags.noStencil == FALSE))
|
|
{
|
|
bpp = 8;
|
|
}
|
|
|
|
pixelsPerMicroTile = MicroTilePixels * microTileThickness;
|
|
pixelsPerPipeInterleave = BYTES_TO_BITS(m_pipeInterleaveBytes) / (bpp * numSamples);
|
|
microTilesPerPipeInterleave = pixelsPerPipeInterleave / pixelsPerMicroTile;
|
|
|
|
pitchAlign = Max(MicroTileWidth, microTilesPerPipeInterleave * MicroTileWidth);
|
|
|
|
return pitchAlign;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::HwlGetSizeAdjustmentMicroTiled
|
|
*
|
|
* @brief
|
|
* Adjust 1D tiled surface pitch and slice size
|
|
*
|
|
* @return
|
|
* Logical slice size in bytes
|
|
****************************************************************************************************
|
|
*/
|
|
UINT_64 EgBasedLib::HwlGetSizeAdjustmentMicroTiled(
|
|
UINT_32 thickness, ///< [in] thickness
|
|
UINT_32 bpp, ///< [in] bits per pixel
|
|
ADDR_SURFACE_FLAGS flags, ///< [in] surface flags
|
|
UINT_32 numSamples, ///< [in] number of samples
|
|
UINT_32 baseAlign, ///< [in] base alignment
|
|
UINT_32 pitchAlign, ///< [in] pitch alignment
|
|
UINT_32* pPitch, ///< [in,out] pointer to pitch
|
|
UINT_32* pHeight ///< [in,out] pointer to height
|
|
) const
|
|
{
|
|
UINT_64 logicalSliceSize;
|
|
UINT_64 physicalSliceSize;
|
|
|
|
UINT_32 pitch = *pPitch;
|
|
UINT_32 height = *pHeight;
|
|
|
|
// Logical slice: pitch * height * bpp * numSamples (no 1D MSAA so actually numSamples == 1)
|
|
logicalSliceSize = BITS_TO_BYTES(static_cast<UINT_64>(pitch) * height * bpp * numSamples);
|
|
|
|
// Physical slice: multiplied by thickness
|
|
physicalSliceSize = logicalSliceSize * thickness;
|
|
|
|
//
|
|
// R800 will always pad physical slice size to baseAlign which is pipe_interleave_bytes
|
|
//
|
|
ADDR_ASSERT((physicalSliceSize % baseAlign) == 0);
|
|
|
|
return logicalSliceSize;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************************
|
|
* EgBasedLib::HwlStereoCheckRightOffsetPadding
|
|
*
|
|
* @brief
|
|
* check if the height needs extra padding for stereo right eye offset, to avoid swizzling
|
|
*
|
|
* @return
|
|
* TRUE is the extra padding is needed
|
|
*
|
|
****************************************************************************************************
|
|
*/
|
|
UINT_32 EgBasedLib::HwlStereoCheckRightOffsetPadding(
|
|
ADDR_TILEINFO* pTileInfo ///< Tiling info
|
|
) const
|
|
{
|
|
UINT_32 stereoHeightAlign = 0;
|
|
|
|
if (pTileInfo->macroAspectRatio > 2)
|
|
{
|
|
// Since 3D rendering treats right eye surface starting from y == "eye height" while
|
|
// display engine treats it to be 0, so the bank bits may be different.
|
|
// Additional padding in height is required to make sure it's possible
|
|
// to achieve synonym by adjusting bank swizzle of right eye surface.
|
|
|
|
static const UINT_32 StereoAspectRatio = 2;
|
|
stereoHeightAlign = pTileInfo->banks *
|
|
pTileInfo->bankHeight *
|
|
MicroTileHeight /
|
|
StereoAspectRatio;
|
|
}
|
|
|
|
return stereoHeightAlign;
|
|
}
|
|
|
|
} // V1
|
|
} // Addr
|