// Also Mip 1+ needs an element pitch of 32 bits so we do not need this workaround
// but we use this flag to skip RestoreSurfaceInfo below
- if ((elemMode == ADDR_EXPANDED) &&
- (expandX > 1))
+ if ((elemMode == ADDR_EXPANDED) && (expandX > 1))
{
- ADDR_ASSERT(localIn.tileMode == ADDR_TM_LINEAR_ALIGNED || localIn.height == 1);
+ ADDR_ASSERT(IsLinear(localIn.tileMode));
}
GetElemLib()->AdjustSurfaceInfo(elemMode,
if (returnCode == ADDR_OK)
{
+ localIn.flags.dccPipeWorkaround = localIn.flags.dccCompatible;
+
if (localIn.tileMode == ADDR_TM_UNKNOWN)
{
// HWL layer may override tile mode if necessary
// HWL layer may override tile mode if necessary
HwlOverrideTileMode(&localIn);
- AddrTileMode tileMode = localIn.tileMode;
-
// Optimize tile mode if possible
- if (OptimizeTileMode(&localIn, &tileMode))
- {
- localIn.tileMode = tileMode;
- }
+ OptimizeTileMode(&localIn);
}
}
if (localIn.format != ADDR_FMT_INVALID)
{
//
- // 96 bits surface of level 1+ requires element pitch of 32 bits instead
- // In hwl function we skip multiplication of 3 then we should skip division of 3
- // We keep pitch that represents 32 bit element instead of 96 bits since we
- // will get an odd number if divided by 3.
+ // Note: For 96 bit surface, the pixelPitch returned might be an odd number, but it
+ // is okay to program texture pitch as HW's mip calculator would multiply 3 first,
+ // then do the appropriate paddings (linear alignment requirement and possible the
+ // nearest power-of-two for mipmaps), which results in the original pitch.
//
- if (!((expandX == 3) && (localIn.mipLevel > 0)))
- {
-
- GetElemLib()->RestoreSurfaceInfo(elemMode,
- expandX,
- expandY,
- &localIn.bpp,
- &pOut->pixelPitch,
- &pOut->pixelHeight);
- }
+ GetElemLib()->RestoreSurfaceInfo(elemMode,
+ expandX,
+ expandY,
+ &localIn.bpp,
+ &pOut->pixelPitch,
+ &pOut->pixelHeight);
}
if (localIn.flags.qbStereo)
if (returnCode == ADDR_OK)
{
- pOut->bpp = ComputeHtileInfo(pIn->flags,
- pIn->pitch,
- pIn->height,
- pIn->numSlices,
- pIn->isLinear,
- isWidth8,
- isHeight8,
- pIn->pTileInfo,
- &pOut->pitch,
- &pOut->height,
- &pOut->htileBytes,
- &pOut->macroWidth,
- &pOut->macroHeight,
- &pOut->sliceSize,
- &pOut->baseAlign);
+ if (pIn->flags.tcCompatible)
+ {
+ const UINT_32 sliceSize = pIn->pitch * pIn->height * 4 / (8 * 8);
+ const UINT_32 align = HwlGetPipes(pIn->pTileInfo) * pIn->pTileInfo->banks * m_pipeInterleaveBytes;
+
+ if (pIn->numSlices > 1)
+ {
+ const UINT_32 surfBytes = (sliceSize * pIn->numSlices);
+
+ pOut->sliceSize = sliceSize;
+ pOut->htileBytes = pIn->flags.skipTcCompatSizeAlign ?
+ surfBytes : PowTwoAlign(surfBytes, align);
+ pOut->sliceInterleaved = ((sliceSize % align) != 0) ? TRUE : FALSE;
+ }
+ else
+ {
+ pOut->sliceSize = pIn->flags.skipTcCompatSizeAlign ?
+ sliceSize : PowTwoAlign(sliceSize, align);
+ pOut->htileBytes = pOut->sliceSize;
+ pOut->sliceInterleaved = FALSE;
+ }
+
+ pOut->nextMipLevelCompressible = ((sliceSize % align) == 0) ? TRUE : FALSE;
+
+ pOut->pitch = pIn->pitch;
+ pOut->height = pIn->height;
+ pOut->baseAlign = align;
+ pOut->macroWidth = 0;
+ pOut->macroHeight = 0;
+ pOut->bpp = 32;
+ }
+ else
+ {
+ pOut->bpp = ComputeHtileInfo(pIn->flags,
+ pIn->pitch,
+ pIn->height,
+ pIn->numSlices,
+ pIn->isLinear,
+ isWidth8,
+ isHeight8,
+ pIn->pTileInfo,
+ &pOut->pitch,
+ &pOut->height,
+ &pOut->htileBytes,
+ &pOut->macroWidth,
+ &pOut->macroHeight,
+ &pOut->sliceSize,
+ &pOut->baseAlign);
+ }
}
}
{
UINT_32 pipe;
UINT_32 numPipes;
+ UINT_32 numGroupBits;
+ (void)numGroupBits;
UINT_32 numPipeBits;
UINT_32 macroTilePitch;
UINT_32 macroTileHeight;
//
// Compute the number of group and pipe bits.
//
+ numGroupBits = Log2(m_pipeInterleaveBytes);
numPipeBits = Log2(numPipes);
UINT_32 groupBits = 8 * m_pipeInterleaveBytes;
ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn ///< [in,out] Input structure
) const
{
+ // Check if HWL has handled
+ BOOL_32 hwlHandled = FALSE;
+ (void)hwlHandled;
+
if (ElemLib::IsBlockCompressed(pIn->format))
{
if (pIn->mipLevel == 0)
}
}
- HwlComputeMipLevel(pIn);
+ hwlHandled = HwlComputeMipLevel(pIn);
+}
+
+/**
+****************************************************************************************************
+* Lib::DegradeTo1D
+*
+* @brief
+* Check if surface can be degraded to 1D
+* @return
+* TRUE if degraded
+****************************************************************************************************
+*/
+BOOL_32 Lib::DegradeTo1D(
+ UINT_32 width, ///< surface width
+ UINT_32 height, ///< surface height
+ UINT_32 macroTilePitchAlign, ///< macro tile pitch align
+ UINT_32 macroTileHeightAlign ///< macro tile height align
+ )
+{
+ BOOL_32 degrade = ((width < macroTilePitchAlign) || (height < macroTileHeightAlign));
+
+ // Check whether 2D tiling still has too much footprint
+ if (degrade == FALSE)
+ {
+ // Only check width and height as slices are aligned to thickness
+ UINT_64 unalignedSize = width * height;
+
+ UINT_32 alignedPitch = PowTwoAlign(width, macroTilePitchAlign);
+ UINT_32 alignedHeight = PowTwoAlign(height, macroTileHeightAlign);
+ UINT_64 alignedSize = alignedPitch * alignedHeight;
+
+ // alignedSize > 1.5 * unalignedSize
+ if (2 * alignedSize > 3 * unalignedSize)
+ {
+ degrade = TRUE;
+ }
+ }
+
+ return degrade;
}
/**
* @brief
* Check if base level's tile mode can be optimized (degraded)
* @return
-* TRUE if degraded, also returns degraded tile mode (unchanged if not degraded)
+* N/A
****************************************************************************************************
*/
-BOOL_32 Lib::OptimizeTileMode(
- const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] Input structure for surface info
- AddrTileMode* pTileMode ///< [out] Degraded tile mode
+VOID Lib::OptimizeTileMode(
+ ADDR_COMPUTE_SURFACE_INFO_INPUT* pInOut ///< [in, out] structure for surface info
) const
{
- AddrTileMode tileMode = pIn->tileMode;
- UINT_32 thickness = Thickness(tileMode);
+ AddrTileMode tileMode = pInOut->tileMode;
+
+ BOOL_32 doOpt = (pInOut->flags.opt4Space == TRUE) ||
+ (pInOut->flags.minimizeAlignment == TRUE) ||
+ (pInOut->maxBaseAlign != 0);
+
+ BOOL_32 convertToPrt = FALSE;
// Optimization can only be done on level 0 and samples <= 1
- if ((pIn->flags.opt4Space == TRUE) &&
- (pIn->mipLevel == 0) &&
- (pIn->numSamples <= 1) &&
- (pIn->flags.display == FALSE) &&
+ if ((doOpt == TRUE) &&
+ (pInOut->mipLevel == 0) &&
(IsPrtTileMode(tileMode) == FALSE) &&
- (pIn->flags.prt == FALSE))
+ (pInOut->flags.prt == FALSE))
{
- // Check if linear mode is optimal
- if ((pIn->height == 1) &&
- (IsLinear(tileMode) == FALSE) &&
- (ElemLib::IsBlockCompressed(pIn->format) == FALSE) &&
- (pIn->flags.depth == FALSE) &&
- (pIn->flags.stencil == FALSE) &&
- (m_configFlags.disableLinearOpt == FALSE) &&
- (pIn->flags.disableLinearOpt == FALSE))
+ UINT_32 width = pInOut->width;
+ UINT_32 height = pInOut->height;
+ UINT_32 thickness = Thickness(tileMode);
+ BOOL_32 macroTiledOK = TRUE;
+ UINT_32 macroWidthAlign = 0;
+ UINT_32 macroHeightAlign = 0;
+ UINT_32 macroSizeAlign = 0;
+
+ if (IsMacroTiled(tileMode))
{
- tileMode = ADDR_TM_LINEAR_ALIGNED;
+ macroTiledOK = HwlGetAlignmentInfoMacroTiled(pInOut,
+ ¯oWidthAlign,
+ ¯oHeightAlign,
+ ¯oSizeAlign);
}
- else if (IsMacroTiled(tileMode))
+
+ if (macroTiledOK)
{
- if (HwlDegradeBaseLevel(pIn))
+ if ((pInOut->flags.display == FALSE) &&
+ (pInOut->flags.opt4Space == TRUE) &&
+ (pInOut->numSamples <= 1))
{
- tileMode = (thickness == 1) ? ADDR_TM_1D_TILED_THIN1 : ADDR_TM_1D_TILED_THICK;
+ // Check if linear mode is optimal
+ if ((pInOut->height == 1) &&
+ (IsLinear(tileMode) == FALSE) &&
+ (ElemLib::IsBlockCompressed(pInOut->format) == FALSE) &&
+ (pInOut->flags.depth == FALSE) &&
+ (pInOut->flags.stencil == FALSE) &&
+ (m_configFlags.disableLinearOpt == FALSE) &&
+ (pInOut->flags.disableLinearOpt == FALSE))
+ {
+ tileMode = ADDR_TM_LINEAR_ALIGNED;
+ }
+ else if (IsMacroTiled(tileMode) && (pInOut->flags.tcCompatible == FALSE))
+ {
+ if (DegradeTo1D(width, height, macroWidthAlign, macroHeightAlign))
+ {
+ tileMode = (thickness == 1) ?
+ ADDR_TM_1D_TILED_THIN1 : ADDR_TM_1D_TILED_THICK;
+ }
+ else if (thickness > 1)
+ {
+ // As in the following HwlComputeSurfaceInfo, thick modes may be degraded to
+ // thinner modes, we should re-evaluate whether the corresponding
+ // thinner modes should be degraded. If so, we choose 1D thick mode instead.
+ tileMode = DegradeLargeThickTile(pInOut->tileMode, pInOut->bpp);
+
+ if (tileMode != pInOut->tileMode)
+ {
+ // Get thickness again after large thick degrade
+ thickness = Thickness(tileMode);
+
+ ADDR_COMPUTE_SURFACE_INFO_INPUT input = *pInOut;
+ input.tileMode = tileMode;
+
+ macroTiledOK = HwlGetAlignmentInfoMacroTiled(&input,
+ ¯oWidthAlign,
+ ¯oHeightAlign,
+ ¯oSizeAlign);
+
+ if (macroTiledOK &&
+ DegradeTo1D(width, height, macroWidthAlign, macroHeightAlign))
+ {
+ tileMode = ADDR_TM_1D_TILED_THICK;
+ }
+ }
+ }
+ }
}
- else if (thickness > 1)
+
+ if (macroTiledOK)
{
- // As in the following HwlComputeSurfaceInfo, thick modes may be degraded to
- // thinner modes, we should re-evaluate whether the corresponding thinner modes
- // need to be degraded. If so, we choose 1D thick mode instead.
- tileMode = DegradeLargeThickTile(pIn->tileMode, pIn->bpp);
- if (tileMode != pIn->tileMode)
+ if ((pInOut->flags.minimizeAlignment == TRUE) &&
+ (pInOut->numSamples <= 1) &&
+ (IsMacroTiled(tileMode) == TRUE))
{
- ADDR_COMPUTE_SURFACE_INFO_INPUT input = *pIn;
- input.tileMode = tileMode;
- if (HwlDegradeBaseLevel(&input))
+ UINT_32 macroSize = PowTwoAlign(width, macroWidthAlign) *
+ PowTwoAlign(height, macroHeightAlign);
+ UINT_32 microSize = PowTwoAlign(width, MicroTileWidth) *
+ PowTwoAlign(height, MicroTileHeight);
+
+ if (macroSize > microSize)
{
- tileMode = ADDR_TM_1D_TILED_THICK;
+ tileMode = (thickness == 1) ?
+ ADDR_TM_1D_TILED_THIN1 : ADDR_TM_1D_TILED_THICK;
+ }
+ }
+
+ if ((pInOut->maxBaseAlign != 0) &&
+ (IsMacroTiled(tileMode) == TRUE))
+ {
+ if (macroSizeAlign > pInOut->maxBaseAlign)
+ {
+ if (pInOut->numSamples > 1)
+ {
+ ADDR_ASSERT(pInOut->maxBaseAlign >= Block64K);
+
+ convertToPrt = TRUE;
+ }
+ else if (pInOut->maxBaseAlign < Block64K)
+ {
+ tileMode = (thickness == 1) ?
+ ADDR_TM_1D_TILED_THIN1 : ADDR_TM_1D_TILED_THICK;
+ }
+ else
+ {
+ convertToPrt = TRUE;
+ }
}
}
}
}
}
- BOOL_32 optimized = (tileMode != pIn->tileMode);
- if (optimized)
+ if (convertToPrt)
{
- *pTileMode = tileMode;
+ if ((pInOut->flags.matchStencilTileCfg == TRUE) && (pInOut->numSamples <= 1))
+ {
+ pInOut->tileMode = ADDR_TM_1D_TILED_THIN1;
+ }
+ else
+ {
+ HwlSetPrtTileMode(pInOut);
+ }
}
- return optimized;
+ else if (tileMode != pInOut->tileMode)
+ {
+ pInOut->tileMode = tileMode;
+ }
+
+ HwlOptimizeTileMode(pInOut);
}
/**
* @brief
* Get quad buffer stereo information
* @return
-* TRUE if no error
+* N/A
****************************************************************************************************
*/
-BOOL_32 Lib::ComputeQbStereoInfo(
+VOID Lib::ComputeQbStereoInfo(
ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [in,out] updated pOut+pStereoInfo
) const
{
- BOOL_32 success = FALSE;
-
- if (pOut->pStereoInfo)
- {
- ADDR_ASSERT(pOut->bpp >= 8);
- ADDR_ASSERT((pOut->surfSize % pOut->baseAlign) == 0);
+ ADDR_ASSERT(pOut->bpp >= 8);
+ ADDR_ASSERT((pOut->surfSize % pOut->baseAlign) == 0);
- // Save original height
- pOut->pStereoInfo->eyeHeight = pOut->height;
+ // Save original height
+ pOut->pStereoInfo->eyeHeight = pOut->height;
- // Right offset
- pOut->pStereoInfo->rightOffset = static_cast<UINT_32>(pOut->surfSize);
+ // Right offset
+ pOut->pStereoInfo->rightOffset = static_cast<UINT_32>(pOut->surfSize);
- pOut->pStereoInfo->rightSwizzle = HwlComputeQbStereoRightSwizzle(pOut);
- // Double height
- pOut->height <<= 1;
- pOut->pixelHeight <<= 1;
+ pOut->pStereoInfo->rightSwizzle = HwlComputeQbStereoRightSwizzle(pOut);
+ // Double height
+ pOut->height <<= 1;
+ pOut->pixelHeight <<= 1;
- // Double size
- pOut->surfSize <<= 1;
+ // Double size
+ pOut->surfSize <<= 1;
- // Right start address meets the base align since it is guaranteed by AddrLib1
-
- // 1D surface on SI may break this rule, but we can force it to meet by checking .qbStereo.
- success = TRUE;
- }
+ // Right start address meets the base align since it is guaranteed by AddrLib1
- return success;
+ // 1D surface on SI may break this rule, but we can force it to meet by checking .qbStereo.
}