2 * Copyright © 2014 Advanced Micro Devices, Inc.
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
14 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
15 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
16 * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS
17 * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 * USE OR OTHER DEALINGS IN THE SOFTWARE.
22 * The above copyright notice and this permission notice (including the
23 * next paragraph) shall be included in all copies or substantial portions
28 ****************************************************************************************************
30 * @brief Contains the implementation for the CiLib class.
31 ****************************************************************************************************
34 #include "ciaddrlib.h"
36 #include "si_gb_reg.h"
38 #include "si_ci_vi_merged_enum.h"
41 #include "amdgpu_id.h"
48 ////////////////////////////////////////////////////////////////////////////////////////////////////
49 ////////////////////////////////////////////////////////////////////////////////////////////////////
55 ****************************************************************************************************
59 * Creates an CiLib object.
62 * Returns an CiLib object pointer.
63 ****************************************************************************************************
65 Lib
* CiHwlInit(const Client
* pClient
)
67 return V1::CiLib::CreateObj(pClient
);
74 ****************************************************************************************************
78 * Gets a mask of "width"
81 ****************************************************************************************************
84 UINT_32 width
) ///< Width of bits
88 if (width
>= sizeof(UINT_64
)*8)
94 return (((UINT_64
) 1) << width
) - 1;
100 ****************************************************************************************************
104 * Gets bits within a range of [msb, lsb]
107 ****************************************************************************************************
109 static UINT_64
GetBits(
110 UINT_64 bits
, ///< Source bits
111 UINT_32 msb
, ///< Most signicant bit
112 UINT_32 lsb
) ///< Least signicant bit
118 ret
= (bits
>> lsb
) & (Mask(1 + msb
- lsb
));
124 ****************************************************************************************************
128 * Removes bits within the range of [msb, lsb]
131 ****************************************************************************************************
133 static UINT_64
RemoveBits(
134 UINT_64 bits
, ///< Source bits
135 UINT_32 msb
, ///< Most signicant bit
136 UINT_32 lsb
) ///< Least signicant bit
142 ret
= GetBits(bits
, lsb
- 1, 0) // low bits
143 | (GetBits(bits
, 8 * sizeof(bits
) - 1, msb
+ 1) << lsb
); //high bits
149 ****************************************************************************************************
153 * Inserts new bits into the range of [msb, lsb]
156 ****************************************************************************************************
158 static UINT_64
InsertBits(
159 UINT_64 bits
, ///< Source bits
160 UINT_64 newBits
, ///< New bits to be inserted
161 UINT_32 msb
, ///< Most signicant bit
162 UINT_32 lsb
) ///< Least signicant bit
168 ret
= GetBits(bits
, lsb
- 1, 0) // old low bitss
169 | (GetBits(newBits
, msb
- lsb
, 0) << lsb
) //new bits
170 | (GetBits(bits
, 8 * sizeof(bits
) - 1, lsb
) << (msb
+ 1)); //old high bits
176 ****************************************************************************************************
182 ****************************************************************************************************
184 CiLib::CiLib(const Client
* pClient
)
187 m_noOfMacroEntries(0),
188 m_allowNonDispThickModes(FALSE
)
190 m_class
= CI_ADDRLIB
;
191 memset(&m_settings
, 0, sizeof(m_settings
));
195 ****************************************************************************************************
200 ****************************************************************************************************
207 ****************************************************************************************************
208 * CiLib::HwlComputeDccInfo
211 * Compute DCC key size, base alignment
214 ****************************************************************************************************
216 ADDR_E_RETURNCODE
CiLib::HwlComputeDccInfo(
217 const ADDR_COMPUTE_DCCINFO_INPUT
* pIn
,
218 ADDR_COMPUTE_DCCINFO_OUTPUT
* pOut
) const
220 ADDR_E_RETURNCODE returnCode
= ADDR_OK
;
222 if (m_settings
.isVolcanicIslands
&& IsMacroTiled(pIn
->tileMode
))
224 UINT_64 dccFastClearSize
= pIn
->colorSurfSize
>> 8;
226 ADDR_ASSERT(0 == (pIn
->colorSurfSize
& 0xff));
228 if (pIn
->numSamples
> 1)
230 UINT_32 tileSizePerSample
= BITS_TO_BYTES(pIn
->bpp
* MicroTileWidth
* MicroTileHeight
);
231 UINT_32 samplesPerSplit
= pIn
->tileInfo
.tileSplitBytes
/ tileSizePerSample
;
233 if (samplesPerSplit
< pIn
->numSamples
)
235 UINT_32 numSplits
= pIn
->numSamples
/ samplesPerSplit
;
236 UINT_32 fastClearBaseAlign
= HwlGetPipes(&pIn
->tileInfo
) * m_pipeInterleaveBytes
;
238 ADDR_ASSERT(IsPow2(fastClearBaseAlign
));
240 dccFastClearSize
/= numSplits
;
242 if (0 != (dccFastClearSize
& (fastClearBaseAlign
- 1)))
244 // Disable dcc fast clear
245 // if key size of fisrt sample split is not pipe*interleave aligned
246 dccFastClearSize
= 0;
251 pOut
->dccRamSize
= pIn
->colorSurfSize
>> 8;
252 pOut
->dccRamBaseAlign
= pIn
->tileInfo
.banks
*
253 HwlGetPipes(&pIn
->tileInfo
) *
254 m_pipeInterleaveBytes
;
255 pOut
->dccFastClearSize
= dccFastClearSize
;
256 pOut
->dccRamSizeAligned
= TRUE
;
258 ADDR_ASSERT(IsPow2(pOut
->dccRamBaseAlign
));
260 if (0 == (pOut
->dccRamSize
& (pOut
->dccRamBaseAlign
- 1)))
262 pOut
->subLvlCompressible
= TRUE
;
266 UINT_64 dccRamSizeAlign
= HwlGetPipes(&pIn
->tileInfo
) * m_pipeInterleaveBytes
;
268 if (pOut
->dccRamSize
== pOut
->dccFastClearSize
)
270 pOut
->dccFastClearSize
= PowTwoAlign(pOut
->dccRamSize
, dccRamSizeAlign
);
272 if ((pOut
->dccRamSize
& (dccRamSizeAlign
- 1)) != 0)
274 pOut
->dccRamSizeAligned
= FALSE
;
276 pOut
->dccRamSize
= PowTwoAlign(pOut
->dccRamSize
, dccRamSizeAlign
);
277 pOut
->subLvlCompressible
= FALSE
;
282 returnCode
= ADDR_NOTSUPPORTED
;
289 ****************************************************************************************************
290 * CiLib::HwlComputeCmaskAddrFromCoord
293 * Compute tc compatible Cmask address from fmask ram address
297 ****************************************************************************************************
299 ADDR_E_RETURNCODE
CiLib::HwlComputeCmaskAddrFromCoord(
300 const ADDR_COMPUTE_CMASK_ADDRFROMCOORD_INPUT
* pIn
, ///< [in] fmask addr/bpp/tile input
301 ADDR_COMPUTE_CMASK_ADDRFROMCOORD_OUTPUT
* pOut
///< [out] cmask address
304 ADDR_E_RETURNCODE returnCode
= ADDR_NOTSUPPORTED
;
306 if ((m_settings
.isVolcanicIslands
== TRUE
) &&
307 (pIn
->flags
.tcCompatible
== TRUE
))
309 UINT_32 numOfPipes
= HwlGetPipes(pIn
->pTileInfo
);
310 UINT_32 numOfBanks
= pIn
->pTileInfo
->banks
;
311 UINT_64 fmaskAddress
= pIn
->fmaskAddr
;
312 UINT_32 elemBits
= pIn
->bpp
;
313 UINT_32 blockByte
= 64 * elemBits
/ 8;
314 UINT_64 metaNibbleAddress
= HwlComputeMetadataNibbleAddress(fmaskAddress
,
320 m_pipeInterleaveBytes
,
324 pOut
->addr
= (metaNibbleAddress
>> 1);
325 pOut
->bitPosition
= (metaNibbleAddress
% 2) ? 4 : 0;
326 returnCode
= ADDR_OK
;
333 ****************************************************************************************************
334 * CiLib::HwlComputeHtileAddrFromCoord
337 * Compute tc compatible Htile address from depth/stencil address
341 ****************************************************************************************************
343 ADDR_E_RETURNCODE
CiLib::HwlComputeHtileAddrFromCoord(
344 const ADDR_COMPUTE_HTILE_ADDRFROMCOORD_INPUT
* pIn
, ///< [in] depth/stencil addr/bpp/tile input
345 ADDR_COMPUTE_HTILE_ADDRFROMCOORD_OUTPUT
* pOut
///< [out] htile address
348 ADDR_E_RETURNCODE returnCode
= ADDR_NOTSUPPORTED
;
350 if ((m_settings
.isVolcanicIslands
== TRUE
) &&
351 (pIn
->flags
.tcCompatible
== TRUE
))
353 UINT_32 numOfPipes
= HwlGetPipes(pIn
->pTileInfo
);
354 UINT_32 numOfBanks
= pIn
->pTileInfo
->banks
;
355 UINT_64 zStencilAddr
= pIn
->zStencilAddr
;
356 UINT_32 elemBits
= pIn
->bpp
;
357 UINT_32 blockByte
= 64 * elemBits
/ 8;
358 UINT_64 metaNibbleAddress
= HwlComputeMetadataNibbleAddress(zStencilAddr
,
364 m_pipeInterleaveBytes
,
368 pOut
->addr
= (metaNibbleAddress
>> 1);
369 pOut
->bitPosition
= 0;
370 returnCode
= ADDR_OK
;
377 ****************************************************************************************************
378 * CiLib::HwlConvertChipFamily
381 * Convert familyID defined in atiid.h to ChipFamily and set m_chipFamily/m_chipRevision
384 ****************************************************************************************************
386 ChipFamily
CiLib::HwlConvertChipFamily(
387 UINT_32 uChipFamily
, ///< [in] chip family defined in atiih.h
388 UINT_32 uChipRevision
) ///< [in] chip revision defined in "asic_family"_id.h
390 ChipFamily family
= ADDR_CHIP_FAMILY_CI
;
395 m_settings
.isSeaIsland
= 1;
396 m_settings
.isBonaire
= ASICREV_IS_BONAIRE_M(uChipRevision
);
397 m_settings
.isHawaii
= ASICREV_IS_HAWAII_P(uChipRevision
);
400 m_settings
.isKaveri
= 1;
401 m_settings
.isSpectre
= ASICREV_IS_SPECTRE(uChipRevision
);
402 m_settings
.isSpooky
= ASICREV_IS_SPOOKY(uChipRevision
);
403 m_settings
.isKalindi
= ASICREV_IS_KALINDI(uChipRevision
);
406 m_settings
.isVolcanicIslands
= 1;
407 m_settings
.isIceland
= ASICREV_IS_ICELAND_M(uChipRevision
);
408 m_settings
.isTonga
= ASICREV_IS_TONGA_P(uChipRevision
);
409 m_settings
.isFiji
= ASICREV_IS_FIJI_P(uChipRevision
);
410 m_settings
.isPolaris10
= ASICREV_IS_POLARIS10_P(uChipRevision
);
411 m_settings
.isPolaris11
= ASICREV_IS_POLARIS11_M(uChipRevision
);
412 m_settings
.isPolaris12
= ASICREV_IS_POLARIS12_V(uChipRevision
);
413 family
= ADDR_CHIP_FAMILY_VI
;
416 m_settings
.isCarrizo
= 1;
417 m_settings
.isVolcanicIslands
= 1;
418 family
= ADDR_CHIP_FAMILY_VI
;
421 ADDR_ASSERT(!"This should be a unexpected Fusion");
429 ****************************************************************************************************
430 * CiLib::HwlInitGlobalParams
433 * Initializes global parameters
436 * TRUE if all settings are valid
438 ****************************************************************************************************
440 BOOL_32
CiLib::HwlInitGlobalParams(
441 const ADDR_CREATE_INPUT
* pCreateIn
) ///< [in] create input
443 BOOL_32 valid
= TRUE
;
445 const ADDR_REGISTER_VALUE
* pRegValue
= &pCreateIn
->regValue
;
447 valid
= DecodeGbRegs(pRegValue
);
449 // The following assignments for m_pipes is only for fail-safe, InitTileSettingTable should
450 // read the correct pipes from tile mode table
451 if (m_settings
.isHawaii
)
453 // Hawaii has 16-pipe, see GFXIP_Config_Summary.xls
456 else if (m_settings
.isBonaire
|| m_settings
.isSpectre
)
460 else // Treat other KV asics to be 2-pipe
466 // Move this to VI code path once created
467 if (m_settings
.isTonga
|| m_settings
.isPolaris10
)
471 else if (m_settings
.isIceland
)
475 else if (m_settings
.isFiji
)
479 else if (m_settings
.isPolaris11
|| m_settings
.isPolaris12
)
486 valid
= InitTileSettingTable(pRegValue
->pTileConfig
, pRegValue
->noOfEntries
);
490 valid
= InitMacroTileCfgTable(pRegValue
->pMacroTileConfig
, pRegValue
->noOfMacroEntries
);
502 ****************************************************************************************************
503 * CiLib::HwlPostCheckTileIndex
506 * Map a tile setting to index if curIndex is invalid, otherwise check if curIndex matches
507 * tile mode/type/info and change the index if needed
510 ****************************************************************************************************
512 INT_32
CiLib::HwlPostCheckTileIndex(
513 const ADDR_TILEINFO
* pInfo
, ///< [in] Tile Info
514 AddrTileMode mode
, ///< [in] Tile mode
515 AddrTileType type
, ///< [in] Tile type
516 INT curIndex
///< [in] Current index assigned in HwlSetupTileInfo
519 INT_32 index
= curIndex
;
521 if (mode
== ADDR_TM_LINEAR_GENERAL
)
523 index
= TileIndexLinearGeneral
;
527 BOOL_32 macroTiled
= IsMacroTiled(mode
);
529 // We need to find a new index if either of them is true
530 // 1. curIndex is invalid
531 // 2. tile mode is changed
532 // 3. tile info does not match for macro tiled
533 if ((index
== TileIndexInvalid
) ||
534 (mode
!= m_tileTable
[index
].mode
) ||
535 (macroTiled
&& pInfo
->pipeConfig
!= m_tileTable
[index
].info
.pipeConfig
))
537 for (index
= 0; index
< static_cast<INT_32
>(m_noOfEntries
); index
++)
541 // macro tile modes need all to match
542 if ((pInfo
->pipeConfig
== m_tileTable
[index
].info
.pipeConfig
) &&
543 (mode
== m_tileTable
[index
].mode
) &&
544 (type
== m_tileTable
[index
].type
))
546 // tileSplitBytes stored in m_tileTable is only valid for depth entries
547 if (type
== ADDR_DEPTH_SAMPLE_ORDER
)
549 if (Min(m_tileTable
[index
].info
.tileSplitBytes
,
550 m_rowSize
) == pInfo
->tileSplitBytes
)
555 else // other entries are determined by other 3 fields
561 else if (mode
== ADDR_TM_LINEAR_ALIGNED
)
563 // linear mode only needs tile mode to match
564 if (mode
== m_tileTable
[index
].mode
)
571 // micro tile modes only need tile mode and tile type to match
572 if (mode
== m_tileTable
[index
].mode
&&
573 type
== m_tileTable
[index
].type
)
582 ADDR_ASSERT(index
< static_cast<INT_32
>(m_noOfEntries
));
584 if (index
>= static_cast<INT_32
>(m_noOfEntries
))
586 index
= TileIndexInvalid
;
593 ****************************************************************************************************
594 * CiLib::HwlSetupTileCfg
597 * Map tile index to tile setting.
600 ****************************************************************************************************
602 ADDR_E_RETURNCODE
CiLib::HwlSetupTileCfg(
603 UINT_32 bpp
, ///< [in] Bits per pixel
604 INT_32 index
, ///< [in] Tile index
605 INT_32 macroModeIndex
, ///< [in] Index in macro tile mode table(CI)
606 ADDR_TILEINFO
* pInfo
, ///< [out] Tile Info
607 AddrTileMode
* pMode
, ///< [out] Tile mode
608 AddrTileType
* pType
///< [out] Tile type
611 ADDR_E_RETURNCODE returnCode
= ADDR_OK
;
613 // Global flag to control usage of tileIndex
614 if (UseTileIndex(index
))
616 if (index
== TileIndexLinearGeneral
)
619 pInfo
->bankWidth
= 1;
620 pInfo
->bankHeight
= 1;
621 pInfo
->macroAspectRatio
= 1;
622 pInfo
->tileSplitBytes
= 64;
623 pInfo
->pipeConfig
= ADDR_PIPECFG_P2
;
625 else if (static_cast<UINT_32
>(index
) >= m_noOfEntries
)
627 returnCode
= ADDR_INVALIDPARAMS
;
631 const TileConfig
* pCfgTable
= GetTileSetting(index
);
635 if (IsMacroTiled(pCfgTable
->mode
))
637 ADDR_ASSERT((macroModeIndex
!= TileIndexInvalid
) &&
638 (macroModeIndex
!= TileIndexNoMacroIndex
));
642 *pInfo
= m_macroTileTable
[macroModeIndex
];
644 if (pCfgTable
->type
== ADDR_DEPTH_SAMPLE_ORDER
)
646 tileSplit
= pCfgTable
->info
.tileSplitBytes
;
652 UINT_32 thickness
= Thickness(pCfgTable
->mode
);
653 UINT_32 tileBytes1x
= BITS_TO_BYTES(bpp
* MicroTilePixels
* thickness
);
654 // Non-depth entries store a split factor
655 UINT_32 sampleSplit
= m_tileTable
[index
].info
.tileSplitBytes
;
656 tileSplit
= Max(256u, sampleSplit
* tileBytes1x
);
660 // Return tileBytes instead if not enough info
661 tileSplit
= pInfo
->tileSplitBytes
;
666 pInfo
->tileSplitBytes
= Min(m_rowSize
, tileSplit
);
668 pInfo
->pipeConfig
= pCfgTable
->info
.pipeConfig
;
670 else // 1D and linear modes, we return default value stored in table
672 *pInfo
= pCfgTable
->info
;
678 *pMode
= pCfgTable
->mode
;
683 *pType
= pCfgTable
->type
;
692 ****************************************************************************************************
693 * CiLib::HwlComputeSurfaceInfo
696 * Entry of CI's ComputeSurfaceInfo
699 ****************************************************************************************************
701 ADDR_E_RETURNCODE
CiLib::HwlComputeSurfaceInfo(
702 const ADDR_COMPUTE_SURFACE_INFO_INPUT
* pIn
, ///< [in] input structure
703 ADDR_COMPUTE_SURFACE_INFO_OUTPUT
* pOut
///< [out] output structure
706 // If tileIndex is invalid, force macroModeIndex to be invalid, too
707 if (pIn
->tileIndex
== TileIndexInvalid
)
709 pOut
->macroModeIndex
= TileIndexInvalid
;
712 ADDR_E_RETURNCODE retCode
= SiLib::HwlComputeSurfaceInfo(pIn
, pOut
);
715 if ((pIn
->mipLevel
> 0) &&
716 (pOut
->tcCompatible
== TRUE
) &&
717 (pOut
->tileMode
!= pIn
->tileMode
) &&
718 (m_settings
.isVolcanicIslands
== TRUE
))
720 CheckTcCompatibility(pOut
->pTileInfo
, pIn
->bpp
, pOut
->tileMode
, pOut
->tileType
, pOut
);
723 if (pOut
->macroModeIndex
== TileIndexNoMacroIndex
)
725 pOut
->macroModeIndex
= TileIndexInvalid
;
728 if ((pIn
->flags
.matchStencilTileCfg
== TRUE
) &&
729 (pIn
->flags
.depth
== TRUE
))
731 pOut
->stencilTileIdx
= TileIndexInvalid
;
733 if ((MinDepth2DThinIndex
<= pOut
->tileIndex
) &&
734 (MaxDepth2DThinIndex
>= pOut
->tileIndex
))
736 BOOL_32 depthStencil2DTileConfigMatch
= DepthStencilTileCfgMatch(pIn
, pOut
);
738 if ((depthStencil2DTileConfigMatch
== FALSE
) &&
739 (pOut
->tcCompatible
== TRUE
))
741 pOut
->macroModeIndex
= TileIndexInvalid
;
743 ADDR_COMPUTE_SURFACE_INFO_INPUT localIn
= *pIn
;
744 localIn
.tileIndex
= TileIndexInvalid
;
745 localIn
.pTileInfo
= NULL
;
746 localIn
.flags
.tcCompatible
= FALSE
;
748 SiLib::HwlComputeSurfaceInfo(&localIn
, pOut
);
750 ADDR_ASSERT((MinDepth2DThinIndex
<= pOut
->tileIndex
) && (MaxDepth2DThinIndex
>= pOut
->tileIndex
));
752 depthStencil2DTileConfigMatch
= DepthStencilTileCfgMatch(pIn
, pOut
);
755 if ((depthStencil2DTileConfigMatch
== FALSE
) &&
756 (pIn
->numSamples
<= 1))
758 pOut
->macroModeIndex
= TileIndexInvalid
;
760 ADDR_COMPUTE_SURFACE_INFO_INPUT localIn
= *pIn
;
761 localIn
.tileMode
= ADDR_TM_1D_TILED_THIN1
;
762 localIn
.tileIndex
= TileIndexInvalid
;
763 localIn
.pTileInfo
= NULL
;
765 retCode
= SiLib::HwlComputeSurfaceInfo(&localIn
, pOut
);
769 if (pOut
->tileIndex
== Depth1DThinIndex
)
771 pOut
->stencilTileIdx
= Depth1DThinIndex
;
779 ****************************************************************************************************
780 * CiLib::HwlFmaskSurfaceInfo
782 * Entry of r800's ComputeFmaskInfo
785 ****************************************************************************************************
787 ADDR_E_RETURNCODE
CiLib::HwlComputeFmaskInfo(
788 const ADDR_COMPUTE_FMASK_INFO_INPUT
* pIn
, ///< [in] input structure
789 ADDR_COMPUTE_FMASK_INFO_OUTPUT
* pOut
///< [out] output structure
792 ADDR_E_RETURNCODE retCode
= ADDR_OK
;
794 ADDR_TILEINFO tileInfo
= {0};
795 ADDR_COMPUTE_FMASK_INFO_INPUT fmaskIn
;
798 AddrTileMode tileMode
= pIn
->tileMode
;
800 // Use internal tile info if pOut does not have a valid pTileInfo
801 if (pOut
->pTileInfo
== NULL
)
803 pOut
->pTileInfo
= &tileInfo
;
806 ADDR_ASSERT(tileMode
== ADDR_TM_2D_TILED_THIN1
||
807 tileMode
== ADDR_TM_3D_TILED_THIN1
||
808 tileMode
== ADDR_TM_PRT_TILED_THIN1
||
809 tileMode
== ADDR_TM_PRT_2D_TILED_THIN1
||
810 tileMode
== ADDR_TM_PRT_3D_TILED_THIN1
);
812 ADDR_ASSERT(m_tileTable
[14].mode
== ADDR_TM_2D_TILED_THIN1
);
813 ADDR_ASSERT(m_tileTable
[15].mode
== ADDR_TM_3D_TILED_THIN1
);
815 // The only valid tile modes for fmask are 2D_THIN1 and 3D_THIN1 plus non-displayable
816 INT_32 tileIndex
= tileMode
== ADDR_TM_2D_TILED_THIN1
? 14 : 15;
817 ADDR_SURFACE_FLAGS flags
= {{0}};
820 INT_32 macroModeIndex
= TileIndexInvalid
;
822 UINT_32 numSamples
= pIn
->numSamples
;
823 UINT_32 numFrags
= pIn
->numFrags
== 0 ? numSamples
: pIn
->numFrags
;
825 UINT_32 bpp
= QLog2(numFrags
);
827 // EQAA needs one more bit
828 if (numSamples
> numFrags
)
838 bpp
= Max(8u, bpp
* numSamples
);
840 macroModeIndex
= HwlComputeMacroModeIndex(tileIndex
, flags
, bpp
, numSamples
, pOut
->pTileInfo
);
842 fmaskIn
.tileIndex
= tileIndex
;
843 fmaskIn
.pTileInfo
= pOut
->pTileInfo
;
844 pOut
->macroModeIndex
= macroModeIndex
;
845 pOut
->tileIndex
= tileIndex
;
847 retCode
= DispatchComputeFmaskInfo(&fmaskIn
, pOut
);
849 if (retCode
== ADDR_OK
)
852 HwlPostCheckTileIndex(pOut
->pTileInfo
, pIn
->tileMode
, ADDR_NON_DISPLAYABLE
,
856 // Resets pTileInfo to NULL if the internal tile info is used
857 if (pOut
->pTileInfo
== &tileInfo
)
859 pOut
->pTileInfo
= NULL
;
866 ****************************************************************************************************
867 * CiLib::HwlFmaskPreThunkSurfInfo
870 * Some preparation before thunking a ComputeSurfaceInfo call for Fmask
873 ****************************************************************************************************
875 VOID
CiLib::HwlFmaskPreThunkSurfInfo(
876 const ADDR_COMPUTE_FMASK_INFO_INPUT
* pFmaskIn
, ///< [in] Input of fmask info
877 const ADDR_COMPUTE_FMASK_INFO_OUTPUT
* pFmaskOut
, ///< [in] Output of fmask info
878 ADDR_COMPUTE_SURFACE_INFO_INPUT
* pSurfIn
, ///< [out] Input of thunked surface info
879 ADDR_COMPUTE_SURFACE_INFO_OUTPUT
* pSurfOut
///< [out] Output of thunked surface info
882 pSurfIn
->tileIndex
= pFmaskIn
->tileIndex
;
883 pSurfOut
->macroModeIndex
= pFmaskOut
->macroModeIndex
;
887 ****************************************************************************************************
888 * CiLib::HwlFmaskPostThunkSurfInfo
891 * Copy hwl extra field after calling thunked ComputeSurfaceInfo
894 ****************************************************************************************************
896 VOID
CiLib::HwlFmaskPostThunkSurfInfo(
897 const ADDR_COMPUTE_SURFACE_INFO_OUTPUT
* pSurfOut
, ///< [in] Output of surface info
898 ADDR_COMPUTE_FMASK_INFO_OUTPUT
* pFmaskOut
///< [out] Output of fmask info
901 pFmaskOut
->tileIndex
= pSurfOut
->tileIndex
;
902 pFmaskOut
->macroModeIndex
= pSurfOut
->macroModeIndex
;
906 ****************************************************************************************************
907 * CiLib::HwlDegradeThickTileMode
910 * Degrades valid tile mode for thick modes if needed
914 ****************************************************************************************************
916 AddrTileMode
CiLib::HwlDegradeThickTileMode(
917 AddrTileMode baseTileMode
, ///< [in] base tile mode
918 UINT_32 numSlices
, ///< [in] current number of slices
919 UINT_32
* pBytesPerTile
///< [in,out] pointer to bytes per slice
926 ****************************************************************************************************
927 * CiLib::HwlOptimizeTileMode
930 * Optimize tile mode on CI
935 ****************************************************************************************************
937 VOID
CiLib::HwlOptimizeTileMode(
938 ADDR_COMPUTE_SURFACE_INFO_INPUT
* pInOut
///< [in,out] input output structure
941 AddrTileMode tileMode
= pInOut
->tileMode
;
943 // Override 2D/3D macro tile mode to PRT_* tile mode if
944 // client driver requests this surface is equation compatible
945 if (IsMacroTiled(tileMode
) == TRUE
)
947 if ((pInOut
->flags
.needEquation
== TRUE
) &&
948 (pInOut
->numSamples
<= 1) &&
949 (IsPrtTileMode(tileMode
) == FALSE
))
951 if ((pInOut
->numSlices
> 1) && ((pInOut
->maxBaseAlign
== 0) || (pInOut
->maxBaseAlign
>= Block64K
)))
953 UINT_32 thickness
= Thickness(tileMode
);
957 tileMode
= ADDR_TM_PRT_TILED_THIN1
;
961 static const UINT_32 PrtTileBytes
= 0x10000;
962 // First prt thick tile index in the tile mode table
963 static const UINT_32 PrtThickTileIndex
= 22;
964 ADDR_TILEINFO tileInfo
= {0};
966 HwlComputeMacroModeIndex(PrtThickTileIndex
,
972 UINT_32 macroTileBytes
= ((pInOut
->bpp
) >> 3) * 64 * pInOut
->numSamples
*
973 thickness
* HwlGetPipes(&tileInfo
) *
974 tileInfo
.banks
* tileInfo
.bankWidth
*
977 if (macroTileBytes
<= PrtTileBytes
)
979 tileMode
= ADDR_TM_PRT_TILED_THICK
;
983 tileMode
= ADDR_TM_PRT_TILED_THIN1
;
989 if (pInOut
->maxBaseAlign
!= 0)
991 pInOut
->flags
.dccPipeWorkaround
= FALSE
;
995 if (tileMode
!= pInOut
->tileMode
)
997 pInOut
->tileMode
= tileMode
;
1002 ****************************************************************************************************
1003 * CiLib::HwlOverrideTileMode
1006 * Override THICK to THIN, for specific formats on CI
1011 ****************************************************************************************************
1013 VOID
CiLib::HwlOverrideTileMode(
1014 ADDR_COMPUTE_SURFACE_INFO_INPUT
* pInOut
///< [in,out] input output structure
1017 AddrTileMode tileMode
= pInOut
->tileMode
;
1018 AddrTileType tileType
= pInOut
->tileType
;
1020 // currently, all CI/VI family do not
1021 // support ADDR_TM_PRT_2D_TILED_THICK,ADDR_TM_PRT_3D_TILED_THICK and
1022 // ADDR_TM_PRT_2D_TILED_THIN1, ADDR_TM_PRT_3D_TILED_THIN1
1025 case ADDR_TM_PRT_2D_TILED_THICK
:
1026 case ADDR_TM_PRT_3D_TILED_THICK
:
1027 tileMode
= ADDR_TM_PRT_TILED_THICK
;
1029 case ADDR_TM_PRT_2D_TILED_THIN1
:
1030 case ADDR_TM_PRT_3D_TILED_THIN1
:
1031 tileMode
= ADDR_TM_PRT_TILED_THIN1
;
1037 // UBTS#404321, we do not need such overriding, as THICK+THICK entries removed from the tile-mode table
1038 if (!m_settings
.isBonaire
)
1040 UINT_32 thickness
= Thickness(tileMode
);
1042 // tile_thickness = (array_mode == XTHICK) ? 8 : ((array_mode == THICK) ? 4 : 1)
1045 switch (pInOut
->format
)
1047 // see //gfxip/gcB/devel/cds/src/verif/tc/models/csim/tcp.cpp
1048 // tcpError("Thick micro tiling is not supported for format...
1049 case ADDR_FMT_X24_8_32_FLOAT
:
1050 case ADDR_FMT_32_AS_8
:
1051 case ADDR_FMT_32_AS_8_8
:
1052 case ADDR_FMT_32_AS_32_32_32_32
:
1055 case ADDR_FMT_GB_GR
:
1056 case ADDR_FMT_BG_RG
:
1057 case ADDR_FMT_1_REVERSED
:
1068 case ADDR_TM_1D_TILED_THICK
:
1069 tileMode
= ADDR_TM_1D_TILED_THIN1
;
1072 case ADDR_TM_2D_TILED_XTHICK
:
1073 case ADDR_TM_2D_TILED_THICK
:
1074 tileMode
= ADDR_TM_2D_TILED_THIN1
;
1077 case ADDR_TM_3D_TILED_XTHICK
:
1078 case ADDR_TM_3D_TILED_THICK
:
1079 tileMode
= ADDR_TM_3D_TILED_THIN1
;
1082 case ADDR_TM_PRT_TILED_THICK
:
1083 tileMode
= ADDR_TM_PRT_TILED_THIN1
;
1086 case ADDR_TM_PRT_2D_TILED_THICK
:
1087 tileMode
= ADDR_TM_PRT_2D_TILED_THIN1
;
1090 case ADDR_TM_PRT_3D_TILED_THICK
:
1091 tileMode
= ADDR_TM_PRT_3D_TILED_THIN1
;
1099 // Switch tile type from thick to thin
1100 if (tileMode
!= pInOut
->tileMode
)
1102 // see tileIndex: 13-18
1103 tileType
= ADDR_NON_DISPLAYABLE
;
1113 if (tileMode
!= pInOut
->tileMode
)
1115 pInOut
->tileMode
= tileMode
;
1116 pInOut
->tileType
= tileType
;
1121 ****************************************************************************************************
1122 * CiLib::HwlSelectTileMode
1125 * Select tile modes.
1130 ****************************************************************************************************
1132 VOID
CiLib::HwlSelectTileMode(
1133 ADDR_COMPUTE_SURFACE_INFO_INPUT
* pInOut
///< [in,out] input output structure
1136 AddrTileMode tileMode
;
1137 AddrTileType tileType
;
1139 if (pInOut
->flags
.rotateDisplay
)
1141 tileMode
= ADDR_TM_2D_TILED_THIN1
;
1142 tileType
= ADDR_ROTATED
;
1144 else if (pInOut
->flags
.volume
)
1146 BOOL_32 bThin
= (m_settings
.isBonaire
== TRUE
) ||
1147 ((m_allowNonDispThickModes
== TRUE
) && (pInOut
->flags
.color
== TRUE
));
1149 if (pInOut
->numSlices
>= 8)
1151 tileMode
= ADDR_TM_2D_TILED_XTHICK
;
1152 tileType
= (bThin
== TRUE
) ? ADDR_NON_DISPLAYABLE
: ADDR_THICK
;
1154 else if (pInOut
->numSlices
>= 4)
1156 tileMode
= ADDR_TM_2D_TILED_THICK
;
1157 tileType
= (bThin
== TRUE
) ? ADDR_NON_DISPLAYABLE
: ADDR_THICK
;
1161 tileMode
= ADDR_TM_2D_TILED_THIN1
;
1162 tileType
= ADDR_NON_DISPLAYABLE
;
1167 tileMode
= ADDR_TM_2D_TILED_THIN1
;
1169 if (pInOut
->flags
.depth
|| pInOut
->flags
.stencil
)
1171 tileType
= ADDR_DEPTH_SAMPLE_ORDER
;
1173 else if ((pInOut
->bpp
<= 32) ||
1174 (pInOut
->flags
.display
== TRUE
) ||
1175 (pInOut
->flags
.overlay
== TRUE
))
1177 tileType
= ADDR_DISPLAYABLE
;
1181 tileType
= ADDR_NON_DISPLAYABLE
;
1185 if (pInOut
->flags
.prt
)
1187 if (Thickness(tileMode
) > 1)
1189 tileMode
= ADDR_TM_PRT_TILED_THICK
;
1190 tileType
= (m_settings
.isBonaire
== TRUE
) ? ADDR_NON_DISPLAYABLE
: ADDR_THICK
;
1194 tileMode
= ADDR_TM_PRT_TILED_THIN1
;
1198 pInOut
->tileMode
= tileMode
;
1199 pInOut
->tileType
= tileType
;
1201 if ((pInOut
->flags
.dccCompatible
== FALSE
) &&
1202 (pInOut
->flags
.tcCompatible
== FALSE
))
1204 pInOut
->flags
.opt4Space
= TRUE
;
1205 pInOut
->maxBaseAlign
= Block64K
;
1208 // Optimize tile mode if possible
1209 OptimizeTileMode(pInOut
);
1211 HwlOverrideTileMode(pInOut
);
1215 ****************************************************************************************************
1216 * CiLib::HwlSetPrtTileMode
1219 * Set PRT tile mode.
1224 ****************************************************************************************************
1226 VOID
CiLib::HwlSetPrtTileMode(
1227 ADDR_COMPUTE_SURFACE_INFO_INPUT
* pInOut
///< [in,out] input output structure
1230 AddrTileMode tileMode
= pInOut
->tileMode
;
1231 AddrTileType tileType
= pInOut
->tileType
;
1233 if (Thickness(tileMode
) > 1)
1235 tileMode
= ADDR_TM_PRT_TILED_THICK
;
1236 tileType
= (m_settings
.isBonaire
== TRUE
) ? ADDR_NON_DISPLAYABLE
: ADDR_THICK
;
1240 tileMode
= ADDR_TM_PRT_TILED_THIN1
;
1241 tileType
= (tileType
== ADDR_THICK
) ? ADDR_NON_DISPLAYABLE
: tileType
;
1244 pInOut
->tileMode
= tileMode
;
1245 pInOut
->tileType
= tileType
;
1249 ****************************************************************************************************
1250 * CiLib::HwlSetupTileInfo
1253 * Setup default value of tile info for SI
1254 ****************************************************************************************************
1256 VOID
CiLib::HwlSetupTileInfo(
1257 AddrTileMode tileMode
, ///< [in] Tile mode
1258 ADDR_SURFACE_FLAGS flags
, ///< [in] Surface type flags
1259 UINT_32 bpp
, ///< [in] Bits per pixel
1260 UINT_32 pitch
, ///< [in] Pitch in pixels
1261 UINT_32 height
, ///< [in] Height in pixels
1262 UINT_32 numSamples
, ///< [in] Number of samples
1263 ADDR_TILEINFO
* pTileInfoIn
, ///< [in] Tile info input: NULL for default
1264 ADDR_TILEINFO
* pTileInfoOut
, ///< [out] Tile info output
1265 AddrTileType inTileType
, ///< [in] Tile type
1266 ADDR_COMPUTE_SURFACE_INFO_OUTPUT
* pOut
///< [out] Output
1269 UINT_32 thickness
= Thickness(tileMode
);
1270 ADDR_TILEINFO
* pTileInfo
= pTileInfoOut
;
1271 INT index
= TileIndexInvalid
;
1272 INT macroModeIndex
= TileIndexInvalid
;
1275 if (IsLinear(tileMode
) == FALSE
)
1277 // Thick tile modes must use thick micro tile mode but Bonaire does not support due to
1278 // old derived netlists (UBTS 404321)
1281 if (m_settings
.isBonaire
)
1283 inTileType
= ADDR_NON_DISPLAYABLE
;
1285 else if ((m_allowNonDispThickModes
== FALSE
) ||
1286 (inTileType
!= ADDR_NON_DISPLAYABLE
) ||
1287 // There is no PRT_THICK + THIN entry in tile mode table except Bonaire
1288 (IsPrtTileMode(tileMode
) == TRUE
))
1290 inTileType
= ADDR_THICK
;
1293 // 128 bpp tiling must be non-displayable.
1294 // Fmask reuse color buffer's entry but bank-height field can be from another entry
1295 // To simplify the logic, fmask entry should be picked from non-displayable ones
1296 else if (bpp
== 128 || flags
.fmask
)
1298 inTileType
= ADDR_NON_DISPLAYABLE
;
1300 // These two modes only have non-disp entries though they can be other micro tile modes
1301 else if (tileMode
== ADDR_TM_3D_TILED_THIN1
|| tileMode
== ADDR_TM_PRT_3D_TILED_THIN1
)
1303 inTileType
= ADDR_NON_DISPLAYABLE
;
1306 if (flags
.depth
|| flags
.stencil
)
1308 inTileType
= ADDR_DEPTH_SAMPLE_ORDER
;
1312 // tcCompatible flag is only meaningful for gfx8.
1313 if (m_settings
.isVolcanicIslands
== FALSE
)
1315 flags
.tcCompatible
= FALSE
;
1318 if (IsTileInfoAllZero(pTileInfo
))
1320 // See table entries 0-4
1321 if (flags
.depth
|| flags
.stencil
)
1323 // tileSize = thickness * bpp * numSamples * 8 * 8 / 8
1324 UINT_32 tileSize
= thickness
* bpp
* numSamples
* 8;
1326 // Turn off tc compatible if row_size is smaller than tile size (tile split occurs).
1327 if (m_rowSize
< tileSize
)
1329 flags
.tcCompatible
= FALSE
;
1332 if (flags
.nonSplit
| flags
.tcCompatible
| flags
.needEquation
)
1334 // Texture readable depth surface should not be split
1356 // Depth and stencil need to use the same index, thus the pre-defined tile_split
1357 // can meet the requirement to choose the same macro mode index
1358 // uncompressed depth/stencil are not supported for now
1377 // See table entries 5-6
1378 if (inTileType
== ADDR_DEPTH_SAMPLE_ORDER
)
1382 case ADDR_TM_1D_TILED_THIN1
:
1385 case ADDR_TM_PRT_TILED_THIN1
:
1393 // See table entries 8-12
1394 if (inTileType
== ADDR_DISPLAYABLE
)
1398 case ADDR_TM_1D_TILED_THIN1
:
1401 case ADDR_TM_2D_TILED_THIN1
:
1404 case ADDR_TM_PRT_TILED_THIN1
:
1412 // See table entries 13-18
1413 if (inTileType
== ADDR_NON_DISPLAYABLE
)
1417 case ADDR_TM_1D_TILED_THIN1
:
1420 case ADDR_TM_2D_TILED_THIN1
:
1423 case ADDR_TM_3D_TILED_THIN1
:
1426 case ADDR_TM_PRT_TILED_THIN1
:
1434 // See table entries 19-26
1439 case ADDR_TM_1D_TILED_THICK
:
1440 // special check for bonaire, for the compatablity between old KMD and new UMD
1441 index
= ((inTileType
== ADDR_THICK
) || m_settings
.isBonaire
) ? 19 : 18;
1443 case ADDR_TM_2D_TILED_THICK
:
1444 // special check for bonaire, for the compatablity between old KMD and new UMD
1445 index
= ((inTileType
== ADDR_THICK
) || m_settings
.isBonaire
) ? 20 : 24;
1447 case ADDR_TM_3D_TILED_THICK
:
1450 case ADDR_TM_PRT_TILED_THICK
:
1453 case ADDR_TM_2D_TILED_XTHICK
:
1456 case ADDR_TM_3D_TILED_XTHICK
:
1464 // See table entries 27-30
1465 if (inTileType
== ADDR_ROTATED
)
1469 case ADDR_TM_1D_TILED_THIN1
:
1472 case ADDR_TM_2D_TILED_THIN1
:
1475 case ADDR_TM_PRT_TILED_THIN1
:
1478 case ADDR_TM_PRT_2D_TILED_THIN1
:
1488 ADDR_ASSERT((index
+ 1) < static_cast<INT_32
>(m_noOfEntries
));
1489 // Only do this when tile mode table is updated.
1490 if (((tileMode
== ADDR_TM_PRT_TILED_THIN1
) || (tileMode
== ADDR_TM_PRT_TILED_THICK
)) &&
1491 (m_tileTable
[index
+ 1].mode
== tileMode
))
1493 static const UINT_32 PrtTileBytes
= 0x10000;
1494 ADDR_TILEINFO tileInfo
= {0};
1496 HwlComputeMacroModeIndex(index
, flags
, bpp
, numSamples
, &tileInfo
);
1498 UINT_32 macroTileBytes
= (bpp
>> 3) * 64 * numSamples
* thickness
*
1499 HwlGetPipes(&tileInfo
) * tileInfo
.banks
*
1500 tileInfo
.bankWidth
* tileInfo
.bankHeight
;
1502 if (macroTileBytes
!= PrtTileBytes
)
1504 // Switching to next tile mode entry to make sure macro tile size is 64KB
1507 tileInfo
.pipeConfig
= m_tileTable
[index
].info
.pipeConfig
;
1509 macroTileBytes
= (bpp
>> 3) * 64 * numSamples
* thickness
*
1510 HwlGetPipes(&tileInfo
) * tileInfo
.banks
*
1511 tileInfo
.bankWidth
* tileInfo
.bankHeight
;
1513 ADDR_ASSERT(macroTileBytes
== PrtTileBytes
);
1515 flags
.tcCompatible
= FALSE
;
1516 pOut
->dccUnsupport
= TRUE
;
1523 // A pre-filled tile info is ready
1524 index
= pOut
->tileIndex
;
1525 macroModeIndex
= pOut
->macroModeIndex
;
1527 // pass tile type back for post tile index compute
1528 pOut
->tileType
= inTileType
;
1530 if (flags
.depth
|| flags
.stencil
)
1532 // tileSize = thickness * bpp * numSamples * 8 * 8 / 8
1533 UINT_32 tileSize
= thickness
* bpp
* numSamples
* 8;
1535 // Turn off tc compatible if row_size is smaller than tile size (tile split occurs).
1536 if (m_rowSize
< tileSize
)
1538 flags
.tcCompatible
= FALSE
;
1542 UINT_32 numPipes
= GetPipePerSurf(pTileInfo
->pipeConfig
);
1544 if (m_pipes
!= numPipes
)
1546 pOut
->dccUnsupport
= TRUE
;
1550 // We only need to set up tile info if there is a valid index but macroModeIndex is invalid
1551 if ((index
!= TileIndexInvalid
) && (macroModeIndex
== TileIndexInvalid
))
1553 macroModeIndex
= HwlComputeMacroModeIndex(index
, flags
, bpp
, numSamples
, pTileInfo
);
1555 // Copy to pOut->tileType/tileIndex/macroModeIndex
1556 pOut
->tileIndex
= index
;
1557 pOut
->tileType
= m_tileTable
[index
].type
; // Or inTileType, the samea
1558 pOut
->macroModeIndex
= macroModeIndex
;
1560 else if (tileMode
== ADDR_TM_LINEAR_GENERAL
)
1562 pOut
->tileIndex
= TileIndexLinearGeneral
;
1564 // Copy linear-aligned entry??
1565 *pTileInfo
= m_tileTable
[8].info
;
1567 else if (tileMode
== ADDR_TM_LINEAR_ALIGNED
)
1569 pOut
->tileIndex
= 8;
1570 *pTileInfo
= m_tileTable
[8].info
;
1573 if (flags
.tcCompatible
)
1575 CheckTcCompatibility(pTileInfo
, bpp
, tileMode
, inTileType
, pOut
);
1578 pOut
->tcCompatible
= flags
.tcCompatible
;
1582 ****************************************************************************************************
1583 * CiLib::ReadGbTileMode
1586 * Convert GB_TILE_MODE HW value to ADDR_TILE_CONFIG.
1587 ****************************************************************************************************
1589 VOID
CiLib::ReadGbTileMode(
1590 UINT_32 regValue
, ///< [in] GB_TILE_MODE register
1591 TileConfig
* pCfg
///< [out] output structure
1594 GB_TILE_MODE gbTileMode
;
1595 gbTileMode
.val
= regValue
;
1597 pCfg
->type
= static_cast<AddrTileType
>(gbTileMode
.f
.micro_tile_mode_new
);
1598 pCfg
->info
.pipeConfig
= static_cast<AddrPipeCfg
>(gbTileMode
.f
.pipe_config
+ 1);
1600 if (pCfg
->type
== ADDR_DEPTH_SAMPLE_ORDER
)
1602 pCfg
->info
.tileSplitBytes
= 64 << gbTileMode
.f
.tile_split
;
1606 pCfg
->info
.tileSplitBytes
= 1 << gbTileMode
.f
.sample_split
;
1609 UINT_32 regArrayMode
= gbTileMode
.f
.array_mode
;
1611 pCfg
->mode
= static_cast<AddrTileMode
>(regArrayMode
);
1613 switch (regArrayMode
)
1616 pCfg
->mode
= ADDR_TM_PRT_TILED_THIN1
;
1619 pCfg
->mode
= ADDR_TM_PRT_2D_TILED_THIN1
;
1622 pCfg
->mode
= ADDR_TM_2D_TILED_XTHICK
;
1625 pCfg
->mode
= ADDR_TM_PRT_TILED_THICK
;
1628 pCfg
->mode
= ADDR_TM_PRT_2D_TILED_THICK
;
1631 pCfg
->mode
= ADDR_TM_PRT_3D_TILED_THIN1
;
1634 pCfg
->mode
= ADDR_TM_3D_TILED_XTHICK
;
1637 pCfg
->mode
= ADDR_TM_PRT_3D_TILED_THICK
;
1643 // Fail-safe code for these always convert tile info, as the non-macro modes
1644 // return the entry of tile mode table directly without looking up macro mode table
1645 if (!IsMacroTiled(pCfg
->mode
))
1647 pCfg
->info
.banks
= 2;
1648 pCfg
->info
.bankWidth
= 1;
1649 pCfg
->info
.bankHeight
= 1;
1650 pCfg
->info
.macroAspectRatio
= 1;
1651 pCfg
->info
.tileSplitBytes
= 64;
1656 ****************************************************************************************************
1657 * CiLib::InitTileSettingTable
1660 * Initialize the ADDR_TILE_CONFIG table.
1662 * TRUE if tile table is correctly initialized
1663 ****************************************************************************************************
1665 BOOL_32
CiLib::InitTileSettingTable(
1666 const UINT_32
* pCfg
, ///< [in] Pointer to table of tile configs
1667 UINT_32 noOfEntries
///< [in] Numbe of entries in the table above
1670 BOOL_32 initOk
= TRUE
;
1672 ADDR_ASSERT(noOfEntries
<= TileTableSize
);
1674 memset(m_tileTable
, 0, sizeof(m_tileTable
));
1676 if (noOfEntries
!= 0)
1678 m_noOfEntries
= noOfEntries
;
1682 m_noOfEntries
= TileTableSize
;
1685 if (pCfg
) // From Client
1687 for (UINT_32 i
= 0; i
< m_noOfEntries
; i
++)
1689 ReadGbTileMode(*(pCfg
+ i
), &m_tileTable
[i
]);
1694 ADDR_ASSERT_ALWAYS();
1700 ADDR_ASSERT(m_tileTable
[TILEINDEX_LINEAR_ALIGNED
].mode
== ADDR_TM_LINEAR_ALIGNED
);
1702 if (m_settings
.isBonaire
== FALSE
)
1704 // Check if entry 18 is "thick+thin" combination
1705 if ((m_tileTable
[18].mode
== ADDR_TM_1D_TILED_THICK
) &&
1706 (m_tileTable
[18].type
== ADDR_NON_DISPLAYABLE
))
1708 m_allowNonDispThickModes
= TRUE
;
1709 ADDR_ASSERT(m_tileTable
[24].mode
== ADDR_TM_2D_TILED_THICK
);
1714 m_allowNonDispThickModes
= TRUE
;
1717 // Assume the first entry is always programmed with full pipes
1718 m_pipes
= HwlGetPipes(&m_tileTable
[0].info
);
1725 ****************************************************************************************************
1726 * CiLib::ReadGbMacroTileCfg
1729 * Convert GB_MACRO_TILE_CFG HW value to ADDR_TILE_CONFIG.
1730 ****************************************************************************************************
1732 VOID
CiLib::ReadGbMacroTileCfg(
1733 UINT_32 regValue
, ///< [in] GB_MACRO_TILE_MODE register
1734 ADDR_TILEINFO
* pCfg
///< [out] output structure
1737 GB_MACROTILE_MODE gbTileMode
;
1738 gbTileMode
.val
= regValue
;
1740 pCfg
->bankHeight
= 1 << gbTileMode
.f
.bank_height
;
1741 pCfg
->bankWidth
= 1 << gbTileMode
.f
.bank_width
;
1742 pCfg
->banks
= 1 << (gbTileMode
.f
.num_banks
+ 1);
1743 pCfg
->macroAspectRatio
= 1 << gbTileMode
.f
.macro_tile_aspect
;
1747 ****************************************************************************************************
1748 * CiLib::InitMacroTileCfgTable
1751 * Initialize the ADDR_MACRO_TILE_CONFIG table.
1753 * TRUE if macro tile table is correctly initialized
1754 ****************************************************************************************************
1756 BOOL_32
CiLib::InitMacroTileCfgTable(
1757 const UINT_32
* pCfg
, ///< [in] Pointer to table of tile configs
1758 UINT_32 noOfMacroEntries
///< [in] Numbe of entries in the table above
1761 BOOL_32 initOk
= TRUE
;
1763 ADDR_ASSERT(noOfMacroEntries
<= MacroTileTableSize
);
1765 memset(m_macroTileTable
, 0, sizeof(m_macroTileTable
));
1767 if (noOfMacroEntries
!= 0)
1769 m_noOfMacroEntries
= noOfMacroEntries
;
1773 m_noOfMacroEntries
= MacroTileTableSize
;
1776 if (pCfg
) // From Client
1778 for (UINT_32 i
= 0; i
< m_noOfMacroEntries
; i
++)
1780 ReadGbMacroTileCfg(*(pCfg
+ i
), &m_macroTileTable
[i
]);
1782 m_macroTileTable
[i
].tileSplitBytes
= 64 << (i
% 8);
1787 ADDR_ASSERT_ALWAYS();
1794 ****************************************************************************************************
1795 * CiLib::HwlComputeMacroModeIndex
1798 * Computes macro tile mode index
1800 * TRUE if macro tile table is correctly initialized
1801 ****************************************************************************************************
1803 INT_32
CiLib::HwlComputeMacroModeIndex(
1804 INT_32 tileIndex
, ///< [in] Tile mode index
1805 ADDR_SURFACE_FLAGS flags
, ///< [in] Surface flags
1806 UINT_32 bpp
, ///< [in] Bit per pixel
1807 UINT_32 numSamples
, ///< [in] Number of samples
1808 ADDR_TILEINFO
* pTileInfo
, ///< [out] Pointer to ADDR_TILEINFO
1809 AddrTileMode
* pTileMode
, ///< [out] Pointer to AddrTileMode
1810 AddrTileType
* pTileType
///< [out] Pointer to AddrTileType
1813 INT_32 macroModeIndex
= TileIndexInvalid
;
1815 AddrTileMode tileMode
= m_tileTable
[tileIndex
].mode
;
1816 AddrTileType tileType
= m_tileTable
[tileIndex
].type
;
1817 UINT_32 thickness
= Thickness(tileMode
);
1819 if (!IsMacroTiled(tileMode
))
1821 *pTileInfo
= m_tileTable
[tileIndex
].info
;
1822 macroModeIndex
= TileIndexNoMacroIndex
;
1826 UINT_32 tileBytes1x
= BITS_TO_BYTES(bpp
* MicroTilePixels
* thickness
);
1829 if (m_tileTable
[tileIndex
].type
== ADDR_DEPTH_SAMPLE_ORDER
)
1831 // Depth entries store real tileSplitBytes
1832 tileSplit
= m_tileTable
[tileIndex
].info
.tileSplitBytes
;
1836 // Non-depth entries store a split factor
1837 UINT_32 sampleSplit
= m_tileTable
[tileIndex
].info
.tileSplitBytes
;
1838 UINT_32 colorTileSplit
= Max(256u, sampleSplit
* tileBytes1x
);
1840 tileSplit
= colorTileSplit
;
1843 UINT_32 tileSplitC
= Min(m_rowSize
, tileSplit
);
1848 tileBytes
= Min(tileSplitC
, tileBytes1x
);
1852 tileBytes
= Min(tileSplitC
, numSamples
* tileBytes1x
);
1860 macroModeIndex
= Log2(tileBytes
/ 64);
1862 if (flags
.prt
|| IsPrtTileMode(tileMode
))
1864 macroModeIndex
+= PrtMacroModeOffset
;
1865 *pTileInfo
= m_macroTileTable
[macroModeIndex
];
1869 *pTileInfo
= m_macroTileTable
[macroModeIndex
];
1872 pTileInfo
->pipeConfig
= m_tileTable
[tileIndex
].info
.pipeConfig
;
1874 pTileInfo
->tileSplitBytes
= tileSplitC
;
1877 if (NULL
!= pTileMode
)
1879 *pTileMode
= tileMode
;
1882 if (NULL
!= pTileType
)
1884 *pTileType
= tileType
;
1887 return macroModeIndex
;
1891 ****************************************************************************************************
1892 * CiLib::HwlComputeTileDataWidthAndHeightLinear
1895 * Compute the squared cache shape for per-tile data (CMASK and HTILE) for linear layout
1898 * MacroWidth and macroHeight are measured in pixels
1899 ****************************************************************************************************
1901 VOID
CiLib::HwlComputeTileDataWidthAndHeightLinear(
1902 UINT_32
* pMacroWidth
, ///< [out] macro tile width
1903 UINT_32
* pMacroHeight
, ///< [out] macro tile height
1904 UINT_32 bpp
, ///< [in] bits per pixel
1905 ADDR_TILEINFO
* pTileInfo
///< [in] tile info
1908 ADDR_ASSERT(pTileInfo
!= NULL
);
1912 switch (pTileInfo
->pipeConfig
)
1914 case ADDR_PIPECFG_P16_32x32_8x16
:
1915 case ADDR_PIPECFG_P16_32x32_16x16
:
1916 case ADDR_PIPECFG_P8_32x64_32x32
:
1917 case ADDR_PIPECFG_P8_32x32_16x32
:
1918 case ADDR_PIPECFG_P8_32x32_16x16
:
1919 case ADDR_PIPECFG_P8_32x32_8x16
:
1920 case ADDR_PIPECFG_P4_32x32
:
1928 *pMacroWidth
= numTiles
* MicroTileWidth
;
1929 *pMacroHeight
= numTiles
* MicroTileHeight
;
1933 ****************************************************************************************************
1934 * CiLib::HwlComputeMetadataNibbleAddress
1937 * calculate meta data address based on input information
1940 * uncompressedDataByteAddress - address of a pixel in color surface
1941 * dataBaseByteAddress - base address of color surface
1942 * metadataBaseByteAddress - base address of meta ram
1943 * metadataBitSize - meta key size, 8 for DCC, 4 for cmask
1944 * elementBitSize - element size of color surface
1945 * blockByteSize - compression block size, 256 for DCC
1946 * pipeInterleaveBytes - pipe interleave size
1947 * numOfPipes - number of pipes
1948 * numOfBanks - number of banks
1949 * numOfSamplesPerSplit - number of samples per tile split
1951 * meta data nibble address (nibble address is used to support DCC compatible cmask)
1953 ****************************************************************************************************
1955 UINT_64
CiLib::HwlComputeMetadataNibbleAddress(
1956 UINT_64 uncompressedDataByteAddress
,
1957 UINT_64 dataBaseByteAddress
,
1958 UINT_64 metadataBaseByteAddress
,
1959 UINT_32 metadataBitSize
,
1960 UINT_32 elementBitSize
,
1961 UINT_32 blockByteSize
,
1962 UINT_32 pipeInterleaveBytes
,
1965 UINT_32 numOfSamplesPerSplit
) const
1967 ///--------------------------------------------------------------------------------------------
1968 /// Get pipe interleave, bank and pipe bits
1969 ///--------------------------------------------------------------------------------------------
1970 UINT_32 pipeInterleaveBits
= Log2(pipeInterleaveBytes
);
1971 UINT_32 pipeBits
= Log2(numOfPipes
);
1972 UINT_32 bankBits
= Log2(numOfBanks
);
1974 ///--------------------------------------------------------------------------------------------
1975 /// Clear pipe and bank swizzles
1976 ///--------------------------------------------------------------------------------------------
1977 UINT_32 dataMacrotileBits
= pipeInterleaveBits
+ pipeBits
+ bankBits
;
1978 UINT_32 metadataMacrotileBits
= pipeInterleaveBits
+ pipeBits
+ bankBits
;
1980 UINT_64 dataMacrotileClearMask
= ~((1L << dataMacrotileBits
) - 1);
1981 UINT_64 metadataMacrotileClearMask
= ~((1L << metadataMacrotileBits
) - 1);
1983 UINT_64 dataBaseByteAddressNoSwizzle
= dataBaseByteAddress
& dataMacrotileClearMask
;
1984 UINT_64 metadataBaseByteAddressNoSwizzle
= metadataBaseByteAddress
& metadataMacrotileClearMask
;
1986 ///--------------------------------------------------------------------------------------------
1987 /// Modify metadata base before adding in so that when final address is divided by data ratio,
1988 /// the base address returns to where it should be
1989 ///--------------------------------------------------------------------------------------------
1990 ADDR_ASSERT((0 != metadataBitSize
));
1991 UINT_64 metadataBaseShifted
= metadataBaseByteAddressNoSwizzle
* blockByteSize
* 8 /
1993 UINT_64 offset
= uncompressedDataByteAddress
-
1994 dataBaseByteAddressNoSwizzle
+
1995 metadataBaseShifted
;
1997 ///--------------------------------------------------------------------------------------------
1998 /// Save bank data bits
1999 ///--------------------------------------------------------------------------------------------
2000 UINT_32 lsb
= pipeBits
+ pipeInterleaveBits
;
2001 UINT_32 msb
= bankBits
- 1 + lsb
;
2003 UINT_64 bankDataBits
= GetBits(offset
, msb
, lsb
);
2005 ///--------------------------------------------------------------------------------------------
2006 /// Save pipe data bits
2007 ///--------------------------------------------------------------------------------------------
2008 lsb
= pipeInterleaveBits
;
2009 msb
= pipeBits
- 1 + lsb
;
2011 UINT_64 pipeDataBits
= GetBits(offset
, msb
, lsb
);
2013 ///--------------------------------------------------------------------------------------------
2014 /// Remove pipe and bank bits
2015 ///--------------------------------------------------------------------------------------------
2016 lsb
= pipeInterleaveBits
;
2017 msb
= dataMacrotileBits
- 1;
2019 UINT_64 offsetWithoutPipeBankBits
= RemoveBits(offset
, msb
, lsb
);
2021 ADDR_ASSERT((0 != blockByteSize
));
2022 UINT_64 blockInBankpipe
= offsetWithoutPipeBankBits
/ blockByteSize
;
2024 UINT_32 tileSize
= 8 * 8 * elementBitSize
/8 * numOfSamplesPerSplit
;
2025 UINT_32 blocksInTile
= tileSize
/ blockByteSize
;
2027 if (0 == blocksInTile
)
2033 lsb
= Log2(blocksInTile
);
2035 msb
= bankBits
- 1 + lsb
;
2037 UINT_64 blockInBankpipeWithBankBits
= InsertBits(blockInBankpipe
, bankDataBits
, msb
, lsb
);
2039 /// NOTE *2 because we are converting to Nibble address in this step
2040 UINT_64 metaAddressInPipe
= blockInBankpipeWithBankBits
* 2 * metadataBitSize
/ 8;
2043 ///--------------------------------------------------------------------------------------------
2044 /// Reinsert pipe bits back into the final address
2045 ///--------------------------------------------------------------------------------------------
2046 lsb
= pipeInterleaveBits
+ 1; ///<+1 due to Nibble address now gives interleave bits extra lsb.
2047 msb
= pipeBits
- 1 + lsb
;
2048 UINT_64 metadataAddress
= InsertBits(metaAddressInPipe
, pipeDataBits
, msb
, lsb
);
2050 return metadataAddress
;
2054 ****************************************************************************************************
2055 * CiLib::HwlComputeSurfaceAlignmentsMacroTiled
2058 * Hardware layer function to compute alignment request for macro tile mode
2060 ****************************************************************************************************
2062 VOID
CiLib::HwlComputeSurfaceAlignmentsMacroTiled(
2063 AddrTileMode tileMode
, ///< [in] tile mode
2064 UINT_32 bpp
, ///< [in] bits per pixel
2065 ADDR_SURFACE_FLAGS flags
, ///< [in] surface flags
2066 UINT_32 mipLevel
, ///< [in] mip level
2067 UINT_32 numSamples
, ///< [in] number of samples
2068 ADDR_COMPUTE_SURFACE_INFO_OUTPUT
* pOut
///< [in,out] Surface output
2071 // This is to workaround a H/W limitation that DCC doesn't work when pipe config is switched to
2072 // P4. In theory, all asics that have such switching should be patched but we now only know what
2074 if ((m_settings
.isFiji
== TRUE
) &&
2075 (flags
.dccPipeWorkaround
== TRUE
) &&
2076 (flags
.prt
== FALSE
) &&
2078 (tileMode
== ADDR_TM_PRT_TILED_THIN1
) &&
2079 (pOut
->dccUnsupport
== TRUE
))
2081 pOut
->pitchAlign
= PowTwoAlign(pOut
->pitchAlign
, 256);
2082 // In case the client still requests DCC usage.
2083 pOut
->dccUnsupport
= FALSE
;
2088 ****************************************************************************************************
2089 * CiLib::HwlPadDimensions
2092 * Helper function to pad dimensions
2094 ****************************************************************************************************
2096 VOID
CiLib::HwlPadDimensions(
2097 AddrTileMode tileMode
, ///< [in] tile mode
2098 UINT_32 bpp
, ///< [in] bits per pixel
2099 ADDR_SURFACE_FLAGS flags
, ///< [in] surface flags
2100 UINT_32 numSamples
, ///< [in] number of samples
2101 ADDR_TILEINFO
* pTileInfo
, ///< [in] tile info
2102 UINT_32 mipLevel
, ///< [in] mip level
2103 UINT_32
* pPitch
, ///< [in,out] pitch in pixels
2104 UINT_32
* pPitchAlign
, ///< [in,out] pitch alignment
2105 UINT_32 height
, ///< [in] height in pixels
2106 UINT_32 heightAlign
///< [in] height alignment
2109 if ((m_settings
.isVolcanicIslands
== TRUE
) &&
2110 (flags
.dccCompatible
== TRUE
) &&
2113 (IsMacroTiled(tileMode
) == TRUE
))
2115 UINT_32 tileSizePerSample
= BITS_TO_BYTES(bpp
* MicroTileWidth
* MicroTileHeight
);
2116 UINT_32 samplesPerSplit
= pTileInfo
->tileSplitBytes
/ tileSizePerSample
;
2118 if (samplesPerSplit
< numSamples
)
2120 UINT_32 dccFastClearByteAlign
= HwlGetPipes(pTileInfo
) * m_pipeInterleaveBytes
* 256;
2121 UINT_32 bytesPerSplit
= BITS_TO_BYTES((*pPitch
) * height
* bpp
* samplesPerSplit
);
2123 ADDR_ASSERT(IsPow2(dccFastClearByteAlign
));
2125 if (0 != (bytesPerSplit
& (dccFastClearByteAlign
- 1)))
2127 UINT_32 dccFastClearPixelAlign
= dccFastClearByteAlign
/
2128 BITS_TO_BYTES(bpp
) /
2130 UINT_32 macroTilePixelAlign
= (*pPitchAlign
) * heightAlign
;
2132 if ((dccFastClearPixelAlign
>= macroTilePixelAlign
) &&
2133 ((dccFastClearPixelAlign
% macroTilePixelAlign
) == 0))
2135 UINT_32 dccFastClearPitchAlignInMacroTile
=
2136 dccFastClearPixelAlign
/ macroTilePixelAlign
;
2137 UINT_32 heightInMacroTile
= height
/ heightAlign
;
2139 while ((heightInMacroTile
> 1) &&
2140 ((heightInMacroTile
% 2) == 0) &&
2141 (dccFastClearPitchAlignInMacroTile
> 1) &&
2142 ((dccFastClearPitchAlignInMacroTile
% 2) == 0))
2144 heightInMacroTile
>>= 1;
2145 dccFastClearPitchAlignInMacroTile
>>= 1;
2148 UINT_32 dccFastClearPitchAlignInPixels
=
2149 (*pPitchAlign
) * dccFastClearPitchAlignInMacroTile
;
2151 if (IsPow2(dccFastClearPitchAlignInPixels
))
2153 *pPitch
= PowTwoAlign((*pPitch
), dccFastClearPitchAlignInPixels
);
2157 *pPitch
+= (dccFastClearPitchAlignInPixels
- 1);
2158 *pPitch
/= dccFastClearPitchAlignInPixels
;
2159 *pPitch
*= dccFastClearPitchAlignInPixels
;
2162 *pPitchAlign
= dccFastClearPitchAlignInPixels
;
2170 ****************************************************************************************************
2171 * CiLib::HwlGetMaxAlignments
2174 * Gets maximum alignments
2177 ****************************************************************************************************
2179 ADDR_E_RETURNCODE
CiLib::HwlGetMaxAlignments(
2180 ADDR_GET_MAX_ALINGMENTS_OUTPUT
* pOut
///< [out] output structure
2183 const UINT_32 pipes
= HwlGetPipes(&m_tileTable
[0].info
);
2185 // Initial size is 64 KiB for PRT.
2186 UINT_64 maxBaseAlign
= 64 * 1024;
2188 for (UINT_32 i
= 0; i
< m_noOfMacroEntries
; i
++)
2190 // The maximum tile size is 16 byte-per-pixel and either 8-sample or 8-slice.
2191 UINT_32 tileSize
= m_macroTileTable
[i
].tileSplitBytes
;
2193 UINT_64 baseAlign
= tileSize
* pipes
* m_macroTileTable
[i
].banks
*
2194 m_macroTileTable
[i
].bankWidth
* m_macroTileTable
[i
].bankHeight
;
2196 if (baseAlign
> maxBaseAlign
)
2198 maxBaseAlign
= baseAlign
;
2204 pOut
->baseAlign
= maxBaseAlign
;
2211 ****************************************************************************************************
2212 * CiLib::DepthStencilTileCfgMatch
2215 * Try to find a tile index for stencil which makes its tile config parameters matches to depth
2217 * TRUE if such tile index for stencil can be found
2218 ****************************************************************************************************
2220 BOOL_32
CiLib::DepthStencilTileCfgMatch(
2221 const ADDR_COMPUTE_SURFACE_INFO_INPUT
* pIn
, ///< [in] input structure
2222 ADDR_COMPUTE_SURFACE_INFO_OUTPUT
* pOut
///< [out] output structure
2225 BOOL_32 depthStencil2DTileConfigMatch
= FALSE
;
2227 for (INT_32 stencilTileIndex
= MinDepth2DThinIndex
;
2228 stencilTileIndex
<= MaxDepth2DThinIndex
;
2231 ADDR_TILEINFO tileInfo
= {0};
2232 INT_32 stencilMacroIndex
= HwlComputeMacroModeIndex(stencilTileIndex
,
2238 if (stencilMacroIndex
!= TileIndexNoMacroIndex
)
2240 if ((m_macroTileTable
[stencilMacroIndex
].banks
==
2241 m_macroTileTable
[pOut
->macroModeIndex
].banks
) &&
2242 (m_macroTileTable
[stencilMacroIndex
].bankWidth
==
2243 m_macroTileTable
[pOut
->macroModeIndex
].bankWidth
) &&
2244 (m_macroTileTable
[stencilMacroIndex
].bankHeight
==
2245 m_macroTileTable
[pOut
->macroModeIndex
].bankHeight
) &&
2246 (m_macroTileTable
[stencilMacroIndex
].macroAspectRatio
==
2247 m_macroTileTable
[pOut
->macroModeIndex
].macroAspectRatio
) &&
2248 (m_macroTileTable
[stencilMacroIndex
].pipeConfig
==
2249 m_macroTileTable
[pOut
->macroModeIndex
].pipeConfig
))
2251 if ((pOut
->tcCompatible
== FALSE
) ||
2252 (tileInfo
.tileSplitBytes
>= MicroTileWidth
* MicroTileHeight
* pIn
->numSamples
))
2254 depthStencil2DTileConfigMatch
= TRUE
;
2255 pOut
->stencilTileIdx
= stencilTileIndex
;
2262 ADDR_ASSERT_ALWAYS();
2266 return depthStencil2DTileConfigMatch
;
2270 ****************************************************************************************************
2271 * CiLib::DepthStencilTileCfgMatch
2274 * Turn off TcCompatible if requirement is not met
2277 ****************************************************************************************************
2279 VOID
CiLib::CheckTcCompatibility(
2280 const ADDR_TILEINFO
* pTileInfo
, ///< [in] input tile info
2281 UINT_32 bpp
, ///< [in] Bits per pixel
2282 AddrTileMode tileMode
, ///< [in] input tile mode
2283 AddrTileType tileType
, ///< [in] input tile type
2284 ADDR_COMPUTE_SURFACE_INFO_OUTPUT
* pOut
///< [out] out structure
2287 if (IsMacroTiled(tileMode
))
2289 if (tileType
!= ADDR_DEPTH_SAMPLE_ORDER
)
2291 // Turn off tcCompatible for color surface if tileSplit happens. Depth/stencil
2292 // tileSplit case was handled at tileIndex selecting time.
2293 INT_32 tileIndex
= pOut
->tileIndex
;
2295 if ((tileIndex
== TileIndexInvalid
) && (IsTileInfoAllZero(pTileInfo
) == FALSE
))
2297 tileIndex
= HwlPostCheckTileIndex(pTileInfo
, tileMode
, tileType
, tileIndex
);
2300 if (tileIndex
!= TileIndexInvalid
)
2302 UINT_32 thickness
= Thickness(tileMode
);
2304 ADDR_ASSERT(static_cast<UINT_32
>(tileIndex
) < TileTableSize
);
2305 // Non-depth entries store a split factor
2306 UINT_32 sampleSplit
= m_tileTable
[tileIndex
].info
.tileSplitBytes
;
2307 UINT_32 tileBytes1x
= BITS_TO_BYTES(bpp
* MicroTilePixels
* thickness
);
2308 UINT_32 colorTileSplit
= Max(256u, sampleSplit
* tileBytes1x
);
2310 if (m_rowSize
< colorTileSplit
)
2312 pOut
->tcCompatible
= FALSE
;
2319 // Client should not enable tc compatible for linear and 1D tile modes.
2320 pOut
->tcCompatible
= FALSE
;