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