1 /*
2 * Copyright © 2007-2019 Advanced Micro Devices, Inc.
3 * All Rights Reserved.
4 *
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:
12 *
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.
21 *
22 * The above copyright notice and this permission notice (including the
23 * next paragraph) shall be included in all copies or substantial portions
24 * of the Software.
25 */
26
27 /**
28 ****************************************************************************************************
29 * @file ciaddrlib.cpp
30 * @brief Contains the implementation for the CiLib class.
31 ****************************************************************************************************
32 */
33
34 #include "ciaddrlib.h"
35
36 #include "si_gb_reg.h"
37
38 #include "amdgpu_asic_addr.h"
39
40 ////////////////////////////////////////////////////////////////////////////////////////////////////
41 ////////////////////////////////////////////////////////////////////////////////////////////////////
42
43 namespace Addr
44 {
45
46 /**
47 ****************************************************************************************************
48 * CiHwlInit
49 *
50 * @brief
51 * Creates an CiLib object.
52 *
53 * @return
54 * Returns an CiLib object pointer.
55 ****************************************************************************************************
56 */
CiHwlInit(const Client * pClient)57 Lib* CiHwlInit(const Client* pClient)
58 {
59 return V1::CiLib::CreateObj(pClient);
60 }
61
62 namespace V1
63 {
64
65 /**
66 ****************************************************************************************************
67 * Mask
68 *
69 * @brief
70 * Gets a mask of "width"
71 * @return
72 * Bit mask
73 ****************************************************************************************************
74 */
Mask(UINT_32 width)75 static UINT_64 Mask(
76 UINT_32 width) ///< Width of bits
77 {
78 UINT_64 ret;
79
80 if (width >= sizeof(UINT_64)*8)
81 {
82 ret = ~((UINT_64) 0);
83 }
84 else
85 {
86 return (((UINT_64) 1) << width) - 1;
87 }
88 return ret;
89 }
90
91 /**
92 ****************************************************************************************************
93 * GetBits
94 *
95 * @brief
96 * Gets bits within a range of [msb, lsb]
97 * @return
98 * Bits of this range
99 ****************************************************************************************************
100 */
GetBits(UINT_64 bits,UINT_32 msb,UINT_32 lsb)101 static UINT_64 GetBits(
102 UINT_64 bits, ///< Source bits
103 UINT_32 msb, ///< Most signicant bit
104 UINT_32 lsb) ///< Least signicant bit
105 {
106 UINT_64 ret = 0;
107
108 if (msb >= lsb)
109 {
110 ret = (bits >> lsb) & (Mask(1 + msb - lsb));
111 }
112 return ret;
113 }
114
115 /**
116 ****************************************************************************************************
117 * RemoveBits
118 *
119 * @brief
120 * Removes bits within the range of [msb, lsb]
121 * @return
122 * Modified bits
123 ****************************************************************************************************
124 */
RemoveBits(UINT_64 bits,UINT_32 msb,UINT_32 lsb)125 static UINT_64 RemoveBits(
126 UINT_64 bits, ///< Source bits
127 UINT_32 msb, ///< Most signicant bit
128 UINT_32 lsb) ///< Least signicant bit
129 {
130 UINT_64 ret = bits;
131
132 if (msb >= lsb)
133 {
134 ret = GetBits(bits, lsb - 1, 0) // low bits
135 | (GetBits(bits, 8 * sizeof(bits) - 1, msb + 1) << lsb); //high bits
136 }
137 return ret;
138 }
139
140 /**
141 ****************************************************************************************************
142 * InsertBits
143 *
144 * @brief
145 * Inserts new bits into the range of [msb, lsb]
146 * @return
147 * Modified bits
148 ****************************************************************************************************
149 */
InsertBits(UINT_64 bits,UINT_64 newBits,UINT_32 msb,UINT_32 lsb)150 static UINT_64 InsertBits(
151 UINT_64 bits, ///< Source bits
152 UINT_64 newBits, ///< New bits to be inserted
153 UINT_32 msb, ///< Most signicant bit
154 UINT_32 lsb) ///< Least signicant bit
155 {
156 UINT_64 ret = bits;
157
158 if (msb >= lsb)
159 {
160 ret = GetBits(bits, lsb - 1, 0) // old low bitss
161 | (GetBits(newBits, msb - lsb, 0) << lsb) //new bits
162 | (GetBits(bits, 8 * sizeof(bits) - 1, lsb) << (msb + 1)); //old high bits
163 }
164 return ret;
165 }
166
167 /**
168 ****************************************************************************************************
169 * CiLib::CiLib
170 *
171 * @brief
172 * Constructor
173 *
174 ****************************************************************************************************
175 */
CiLib(const Client * pClient)176 CiLib::CiLib(const Client* pClient)
177 :
178 SiLib(pClient),
179 m_noOfMacroEntries(0),
180 m_allowNonDispThickModes(FALSE)
181 {
182 }
183
184 /**
185 ****************************************************************************************************
186 * CiLib::~CiLib
187 *
188 * @brief
189 * Destructor
190 ****************************************************************************************************
191 */
~CiLib()192 CiLib::~CiLib()
193 {
194 }
195
196 /**
197 ****************************************************************************************************
198 * CiLib::HwlComputeDccInfo
199 *
200 * @brief
201 * Compute DCC key size, base alignment
202 * @return
203 * ADDR_E_RETURNCODE
204 ****************************************************************************************************
205 */
HwlComputeDccInfo(const ADDR_COMPUTE_DCCINFO_INPUT * pIn,ADDR_COMPUTE_DCCINFO_OUTPUT * pOut) const206 ADDR_E_RETURNCODE CiLib::HwlComputeDccInfo(
207 const ADDR_COMPUTE_DCCINFO_INPUT* pIn,
208 ADDR_COMPUTE_DCCINFO_OUTPUT* pOut) const
209 {
210 ADDR_E_RETURNCODE returnCode = ADDR_OK;
211
212 if (SupportDccAndTcCompatibility() && IsMacroTiled(pIn->tileMode))
213 {
214 UINT_64 dccFastClearSize = pIn->colorSurfSize >> 8;
215
216 ADDR_ASSERT(0 == (pIn->colorSurfSize & 0xff));
217
218 if (pIn->numSamples > 1)
219 {
220 UINT_32 tileSizePerSample = BITS_TO_BYTES(pIn->bpp * MicroTileWidth * MicroTileHeight);
221 UINT_32 samplesPerSplit = pIn->tileInfo.tileSplitBytes / tileSizePerSample;
222
223 if (samplesPerSplit < pIn->numSamples)
224 {
225 UINT_32 numSplits = pIn->numSamples / samplesPerSplit;
226 UINT_32 fastClearBaseAlign = HwlGetPipes(&pIn->tileInfo) * m_pipeInterleaveBytes;
227
228 ADDR_ASSERT(IsPow2(fastClearBaseAlign));
229
230 dccFastClearSize /= numSplits;
231
232 if (0 != (dccFastClearSize & (fastClearBaseAlign - 1)))
233 {
234 // Disable dcc fast clear
235 // if key size of fisrt sample split is not pipe*interleave aligned
236 dccFastClearSize = 0;
237 }
238 }
239 }
240
241 pOut->dccRamSize = pIn->colorSurfSize >> 8;
242 pOut->dccRamBaseAlign = pIn->tileInfo.banks *
243 HwlGetPipes(&pIn->tileInfo) *
244 m_pipeInterleaveBytes;
245 pOut->dccFastClearSize = dccFastClearSize;
246 pOut->dccRamSizeAligned = TRUE;
247
248 ADDR_ASSERT(IsPow2(pOut->dccRamBaseAlign));
249
250 if (0 == (pOut->dccRamSize & (pOut->dccRamBaseAlign - 1)))
251 {
252 pOut->subLvlCompressible = TRUE;
253 }
254 else
255 {
256 UINT_64 dccRamSizeAlign = HwlGetPipes(&pIn->tileInfo) * m_pipeInterleaveBytes;
257
258 if (pOut->dccRamSize == pOut->dccFastClearSize)
259 {
260 pOut->dccFastClearSize = PowTwoAlign(pOut->dccRamSize, dccRamSizeAlign);
261 }
262 if ((pOut->dccRamSize & (dccRamSizeAlign - 1)) != 0)
263 {
264 pOut->dccRamSizeAligned = FALSE;
265 }
266 pOut->dccRamSize = PowTwoAlign(pOut->dccRamSize, dccRamSizeAlign);
267 pOut->subLvlCompressible = FALSE;
268 }
269 }
270 else
271 {
272 returnCode = ADDR_NOTSUPPORTED;
273 }
274
275 return returnCode;
276 }
277
278 /**
279 ****************************************************************************************************
280 * CiLib::HwlComputeCmaskAddrFromCoord
281 *
282 * @brief
283 * Compute tc compatible Cmask address from fmask ram address
284 *
285 * @return
286 * ADDR_E_RETURNCODE
287 ****************************************************************************************************
288 */
HwlComputeCmaskAddrFromCoord(const ADDR_COMPUTE_CMASK_ADDRFROMCOORD_INPUT * pIn,ADDR_COMPUTE_CMASK_ADDRFROMCOORD_OUTPUT * pOut) const289 ADDR_E_RETURNCODE CiLib::HwlComputeCmaskAddrFromCoord(
290 const ADDR_COMPUTE_CMASK_ADDRFROMCOORD_INPUT* pIn, ///< [in] fmask addr/bpp/tile input
291 ADDR_COMPUTE_CMASK_ADDRFROMCOORD_OUTPUT* pOut ///< [out] cmask address
292 ) const
293 {
294 ADDR_E_RETURNCODE returnCode = ADDR_NOTSUPPORTED;
295
296 if ((SupportDccAndTcCompatibility() == TRUE) &&
297 (pIn->flags.tcCompatible == TRUE))
298 {
299 UINT_32 numOfPipes = HwlGetPipes(pIn->pTileInfo);
300 UINT_32 numOfBanks = pIn->pTileInfo->banks;
301 UINT_64 fmaskAddress = pIn->fmaskAddr;
302 UINT_32 elemBits = pIn->bpp;
303 UINT_32 blockByte = 64 * elemBits / 8;
304 UINT_64 metaNibbleAddress = HwlComputeMetadataNibbleAddress(fmaskAddress,
305 0,
306 0,
307 4, // cmask 4 bits
308 elemBits,
309 blockByte,
310 m_pipeInterleaveBytes,
311 numOfPipes,
312 numOfBanks,
313 1);
314 pOut->addr = (metaNibbleAddress >> 1);
315 pOut->bitPosition = (metaNibbleAddress % 2) ? 4 : 0;
316 returnCode = ADDR_OK;
317 }
318
319 return returnCode;
320 }
321
322 /**
323 ****************************************************************************************************
324 * CiLib::HwlComputeHtileAddrFromCoord
325 *
326 * @brief
327 * Compute tc compatible Htile address from depth/stencil address
328 *
329 * @return
330 * ADDR_E_RETURNCODE
331 ****************************************************************************************************
332 */
HwlComputeHtileAddrFromCoord(const ADDR_COMPUTE_HTILE_ADDRFROMCOORD_INPUT * pIn,ADDR_COMPUTE_HTILE_ADDRFROMCOORD_OUTPUT * pOut) const333 ADDR_E_RETURNCODE CiLib::HwlComputeHtileAddrFromCoord(
334 const ADDR_COMPUTE_HTILE_ADDRFROMCOORD_INPUT* pIn, ///< [in] depth/stencil addr/bpp/tile input
335 ADDR_COMPUTE_HTILE_ADDRFROMCOORD_OUTPUT* pOut ///< [out] htile address
336 ) const
337 {
338 ADDR_E_RETURNCODE returnCode = ADDR_NOTSUPPORTED;
339
340 if ((SupportDccAndTcCompatibility() == TRUE) &&
341 (pIn->flags.tcCompatible == TRUE))
342 {
343 UINT_32 numOfPipes = HwlGetPipes(pIn->pTileInfo);
344 UINT_32 numOfBanks = pIn->pTileInfo->banks;
345 UINT_64 zStencilAddr = pIn->zStencilAddr;
346 UINT_32 elemBits = pIn->bpp;
347 UINT_32 blockByte = 64 * elemBits / 8;
348 UINT_64 metaNibbleAddress = HwlComputeMetadataNibbleAddress(zStencilAddr,
349 0,
350 0,
351 32, // htile 32 bits
352 elemBits,
353 blockByte,
354 m_pipeInterleaveBytes,
355 numOfPipes,
356 numOfBanks,
357 1);
358 pOut->addr = (metaNibbleAddress >> 1);
359 pOut->bitPosition = 0;
360 returnCode = ADDR_OK;
361 }
362
363 return returnCode;
364 }
365
366 /**
367 ****************************************************************************************************
368 * CiLib::HwlConvertChipFamily
369 *
370 * @brief
371 * Convert familyID defined in atiid.h to ChipFamily and set m_chipFamily/m_chipRevision
372 * @return
373 * ChipFamily
374 ****************************************************************************************************
375 */
HwlConvertChipFamily(UINT_32 uChipFamily,UINT_32 uChipRevision)376 ChipFamily CiLib::HwlConvertChipFamily(
377 UINT_32 uChipFamily, ///< [in] chip family defined in atiih.h
378 UINT_32 uChipRevision) ///< [in] chip revision defined in "asic_family"_id.h
379 {
380 ChipFamily family = ADDR_CHIP_FAMILY_CI;
381
382 switch (uChipFamily)
383 {
384 case FAMILY_CI:
385 m_settings.isSeaIsland = 1;
386 m_settings.isBonaire = ASICREV_IS_BONAIRE_M(uChipRevision);
387 m_settings.isHawaii = ASICREV_IS_HAWAII_P(uChipRevision);
388 break;
389 case FAMILY_KV:
390 m_settings.isKaveri = 1;
391 m_settings.isSpectre = ASICREV_IS_SPECTRE(uChipRevision);
392 m_settings.isSpooky = ASICREV_IS_SPOOKY(uChipRevision);
393 m_settings.isKalindi = ASICREV_IS_KALINDI(uChipRevision);
394 break;
395 case FAMILY_VI:
396 m_settings.isVolcanicIslands = 1;
397 m_settings.isIceland = ASICREV_IS_ICELAND_M(uChipRevision);
398 m_settings.isTonga = ASICREV_IS_TONGA_P(uChipRevision);
399 m_settings.isFiji = ASICREV_IS_FIJI_P(uChipRevision);
400 m_settings.isPolaris10 = ASICREV_IS_POLARIS10_P(uChipRevision);
401 m_settings.isPolaris11 = ASICREV_IS_POLARIS11_M(uChipRevision);
402 m_settings.isPolaris12 = ASICREV_IS_POLARIS12_V(uChipRevision);
403 m_settings.isVegaM = ASICREV_IS_VEGAM_P(uChipRevision);
404 family = ADDR_CHIP_FAMILY_VI;
405 break;
406 case FAMILY_CZ:
407 m_settings.isCarrizo = 1;
408 m_settings.isVolcanicIslands = 1;
409 family = ADDR_CHIP_FAMILY_VI;
410 break;
411 default:
412 ADDR_ASSERT(!"No Chip found");
413 break;
414 }
415
416 return family;
417 }
418
419 /**
420 ****************************************************************************************************
421 * CiLib::HwlInitGlobalParams
422 *
423 * @brief
424 * Initializes global parameters
425 *
426 * @return
427 * TRUE if all settings are valid
428 *
429 ****************************************************************************************************
430 */
HwlInitGlobalParams(const ADDR_CREATE_INPUT * pCreateIn)431 BOOL_32 CiLib::HwlInitGlobalParams(
432 const ADDR_CREATE_INPUT* pCreateIn) ///< [in] create input
433 {
434 BOOL_32 valid = TRUE;
435
436 const ADDR_REGISTER_VALUE* pRegValue = &pCreateIn->regValue;
437
438 valid = DecodeGbRegs(pRegValue);
439
440 // The following assignments for m_pipes is only for fail-safe, InitTileSettingTable should
441 // read the correct pipes from tile mode table
442 if (m_settings.isHawaii)
443 {
444 m_pipes = 16;
445 }
446 else if (m_settings.isBonaire || m_settings.isSpectre)
447 {
448 m_pipes = 4;
449 }
450 else // Treat other KV asics to be 2-pipe
451 {
452 m_pipes = 2;
453 }
454
455 // @todo: VI
456 // Move this to VI code path once created
457 if (m_settings.isTonga || m_settings.isPolaris10)
458 {
459 m_pipes = 8;
460 }
461 else if (m_settings.isIceland)
462 {
463 m_pipes = 2;
464 }
465 else if (m_settings.isFiji)
466 {
467 m_pipes = 16;
468 }
469 else if (m_settings.isPolaris11 || m_settings.isPolaris12)
470 {
471 m_pipes = 4;
472 }
473 else if (m_settings.isVegaM)
474 {
475 m_pipes = 16;
476 }
477
478 if (valid)
479 {
480 valid = InitTileSettingTable(pRegValue->pTileConfig, pRegValue->noOfEntries);
481 }
482 if (valid)
483 {
484 valid = InitMacroTileCfgTable(pRegValue->pMacroTileConfig, pRegValue->noOfMacroEntries);
485 }
486
487 if (valid)
488 {
489 InitEquationTable();
490 }
491
492 return valid;
493 }
494
495 /**
496 ****************************************************************************************************
497 * CiLib::HwlPostCheckTileIndex
498 *
499 * @brief
500 * Map a tile setting to index if curIndex is invalid, otherwise check if curIndex matches
501 * tile mode/type/info and change the index if needed
502 * @return
503 * Tile index.
504 ****************************************************************************************************
505 */
HwlPostCheckTileIndex(const ADDR_TILEINFO * pInfo,AddrTileMode mode,AddrTileType type,INT curIndex) const506 INT_32 CiLib::HwlPostCheckTileIndex(
507 const ADDR_TILEINFO* pInfo, ///< [in] Tile Info
508 AddrTileMode mode, ///< [in] Tile mode
509 AddrTileType type, ///< [in] Tile type
510 INT curIndex ///< [in] Current index assigned in HwlSetupTileInfo
511 ) const
512 {
513 INT_32 index = curIndex;
514
515 if (mode == ADDR_TM_LINEAR_GENERAL)
516 {
517 index = TileIndexLinearGeneral;
518 }
519 else
520 {
521 BOOL_32 macroTiled = IsMacroTiled(mode);
522
523 // We need to find a new index if either of them is true
524 // 1. curIndex is invalid
525 // 2. tile mode is changed
526 // 3. tile info does not match for macro tiled
527 if ((index == TileIndexInvalid) ||
528 (mode != m_tileTable[index].mode) ||
529 (macroTiled && pInfo->pipeConfig != m_tileTable[index].info.pipeConfig))
530 {
531 for (index = 0; index < static_cast<INT_32>(m_noOfEntries); index++)
532 {
533 if (macroTiled)
534 {
535 // macro tile modes need all to match
536 if ((pInfo->pipeConfig == m_tileTable[index].info.pipeConfig) &&
537 (mode == m_tileTable[index].mode) &&
538 (type == m_tileTable[index].type))
539 {
540 // tileSplitBytes stored in m_tileTable is only valid for depth entries
541 if (type == ADDR_DEPTH_SAMPLE_ORDER)
542 {
543 if (Min(m_tileTable[index].info.tileSplitBytes,
544 m_rowSize) == pInfo->tileSplitBytes)
545 {
546 break;
547 }
548 }
549 else // other entries are determined by other 3 fields
550 {
551 break;
552 }
553 }
554 }
555 else if (mode == ADDR_TM_LINEAR_ALIGNED)
556 {
557 // linear mode only needs tile mode to match
558 if (mode == m_tileTable[index].mode)
559 {
560 break;
561 }
562 }
563 else
564 {
565 // micro tile modes only need tile mode and tile type to match
566 if (mode == m_tileTable[index].mode &&
567 type == m_tileTable[index].type)
568 {
569 break;
570 }
571 }
572 }
573 }
574 }
575
576 ADDR_ASSERT(index < static_cast<INT_32>(m_noOfEntries));
577
578 if (index >= static_cast<INT_32>(m_noOfEntries))
579 {
580 index = TileIndexInvalid;
581 }
582
583 return index;
584 }
585
586 /**
587 ****************************************************************************************************
588 * CiLib::HwlSetupTileCfg
589 *
590 * @brief
591 * Map tile index to tile setting.
592 * @return
593 * ADDR_E_RETURNCODE
594 ****************************************************************************************************
595 */
HwlSetupTileCfg(UINT_32 bpp,INT_32 index,INT_32 macroModeIndex,ADDR_TILEINFO * pInfo,AddrTileMode * pMode,AddrTileType * pType) const596 ADDR_E_RETURNCODE CiLib::HwlSetupTileCfg(
597 UINT_32 bpp, ///< Bits per pixel
598 INT_32 index, ///< Tile index
599 INT_32 macroModeIndex, ///< Index in macro tile mode table(CI)
600 ADDR_TILEINFO* pInfo, ///< [out] Tile Info
601 AddrTileMode* pMode, ///< [out] Tile mode
602 AddrTileType* pType ///< [out] Tile type
603 ) const
604 {
605 ADDR_E_RETURNCODE returnCode = ADDR_OK;
606
607 // Global flag to control usage of tileIndex
608 if (UseTileIndex(index))
609 {
610 if (index == TileIndexLinearGeneral)
611 {
612 pInfo->banks = 2;
613 pInfo->bankWidth = 1;
614 pInfo->bankHeight = 1;
615 pInfo->macroAspectRatio = 1;
616 pInfo->tileSplitBytes = 64;
617 pInfo->pipeConfig = ADDR_PIPECFG_P2;
618 }
619 else if (static_cast<UINT_32>(index) >= m_noOfEntries)
620 {
621 returnCode = ADDR_INVALIDPARAMS;
622 }
623 else
624 {
625 const TileConfig* pCfgTable = GetTileSetting(index);
626
627 if (pInfo != NULL)
628 {
629 if (IsMacroTiled(pCfgTable->mode))
630 {
631 ADDR_ASSERT((macroModeIndex != TileIndexInvalid) &&
632 (macroModeIndex != TileIndexNoMacroIndex));
633
634 UINT_32 tileSplit;
635
636 *pInfo = m_macroTileTable[macroModeIndex];
637
638 if (pCfgTable->type == ADDR_DEPTH_SAMPLE_ORDER)
639 {
640 tileSplit = pCfgTable->info.tileSplitBytes;
641 }
642 else
643 {
644 if (bpp > 0)
645 {
646 UINT_32 thickness = Thickness(pCfgTable->mode);
647 UINT_32 tileBytes1x = BITS_TO_BYTES(bpp * MicroTilePixels * thickness);
648 // Non-depth entries store a split factor
649 UINT_32 sampleSplit = m_tileTable[index].info.tileSplitBytes;
650 tileSplit = Max(256u, sampleSplit * tileBytes1x);
651 }
652 else
653 {
654 // Return tileBytes instead if not enough info
655 tileSplit = pInfo->tileSplitBytes;
656 }
657 }
658
659 // Clamp to row_size
660 pInfo->tileSplitBytes = Min(m_rowSize, tileSplit);
661
662 pInfo->pipeConfig = pCfgTable->info.pipeConfig;
663 }
664 else // 1D and linear modes, we return default value stored in table
665 {
666 *pInfo = pCfgTable->info;
667 }
668 }
669
670 if (pMode != NULL)
671 {
672 *pMode = pCfgTable->mode;
673 }
674
675 if (pType != NULL)
676 {
677 *pType = pCfgTable->type;
678 }
679 }
680 }
681
682 return returnCode;
683 }
684
685 /**
686 ****************************************************************************************************
687 * CiLib::HwlComputeSurfaceInfo
688 *
689 * @brief
690 * Entry of CI's ComputeSurfaceInfo
691 * @return
692 * ADDR_E_RETURNCODE
693 ****************************************************************************************************
694 */
HwlComputeSurfaceInfo(const ADDR_COMPUTE_SURFACE_INFO_INPUT * pIn,ADDR_COMPUTE_SURFACE_INFO_OUTPUT * pOut) const695 ADDR_E_RETURNCODE CiLib::HwlComputeSurfaceInfo(
696 const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] input structure
697 ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [out] output structure
698 ) const
699 {
700 // If tileIndex is invalid, force macroModeIndex to be invalid, too
701 if (pIn->tileIndex == TileIndexInvalid)
702 {
703 pOut->macroModeIndex = TileIndexInvalid;
704 }
705
706 ADDR_E_RETURNCODE retCode = SiLib::HwlComputeSurfaceInfo(pIn, pOut);
707
708 if ((pIn->mipLevel > 0) &&
709 (pOut->tcCompatible == TRUE) &&
710 (pOut->tileMode != pIn->tileMode) &&
711 (SupportDccAndTcCompatibility() == TRUE))
712 {
713 pOut->tcCompatible = CheckTcCompatibility(pOut->pTileInfo, pIn->bpp, pOut->tileMode, pOut->tileType, pOut);
714 }
715
716 if (pOut->macroModeIndex == TileIndexNoMacroIndex)
717 {
718 pOut->macroModeIndex = TileIndexInvalid;
719 }
720
721 if ((pIn->flags.matchStencilTileCfg == TRUE) &&
722 (pIn->flags.depth == TRUE))
723 {
724 pOut->stencilTileIdx = TileIndexInvalid;
725
726 if ((MinDepth2DThinIndex <= pOut->tileIndex) &&
727 (MaxDepth2DThinIndex >= pOut->tileIndex))
728 {
729 BOOL_32 depthStencil2DTileConfigMatch = DepthStencilTileCfgMatch(pIn, pOut);
730
731 if ((depthStencil2DTileConfigMatch == FALSE) &&
732 (pOut->tcCompatible == TRUE))
733 {
734 pOut->macroModeIndex = TileIndexInvalid;
735
736 ADDR_COMPUTE_SURFACE_INFO_INPUT localIn = *pIn;
737 localIn.tileIndex = TileIndexInvalid;
738 localIn.pTileInfo = NULL;
739 localIn.flags.tcCompatible = FALSE;
740
741 SiLib::HwlComputeSurfaceInfo(&localIn, pOut);
742
743 ADDR_ASSERT((MinDepth2DThinIndex <= pOut->tileIndex) && (MaxDepth2DThinIndex >= pOut->tileIndex));
744
745 depthStencil2DTileConfigMatch = DepthStencilTileCfgMatch(pIn, pOut);
746 }
747
748 if ((depthStencil2DTileConfigMatch == FALSE) &&
749 (pIn->numSamples <= 1))
750 {
751 pOut->macroModeIndex = TileIndexInvalid;
752
753 ADDR_COMPUTE_SURFACE_INFO_INPUT localIn = *pIn;
754 localIn.tileMode = ADDR_TM_1D_TILED_THIN1;
755 localIn.tileIndex = TileIndexInvalid;
756 localIn.pTileInfo = NULL;
757
758 retCode = SiLib::HwlComputeSurfaceInfo(&localIn, pOut);
759 }
760 }
761
762 if (pOut->tileIndex == Depth1DThinIndex)
763 {
764 pOut->stencilTileIdx = Depth1DThinIndex;
765 }
766 }
767
768 return retCode;
769 }
770
771 /**
772 ****************************************************************************************************
773 * CiLib::HwlFmaskSurfaceInfo
774 * @brief
775 * Entry of r800's ComputeFmaskInfo
776 * @return
777 * ADDR_E_RETURNCODE
778 ****************************************************************************************************
779 */
HwlComputeFmaskInfo(const ADDR_COMPUTE_FMASK_INFO_INPUT * pIn,ADDR_COMPUTE_FMASK_INFO_OUTPUT * pOut)780 ADDR_E_RETURNCODE CiLib::HwlComputeFmaskInfo(
781 const ADDR_COMPUTE_FMASK_INFO_INPUT* pIn, ///< [in] input structure
782 ADDR_COMPUTE_FMASK_INFO_OUTPUT* pOut ///< [out] output structure
783 )
784 {
785 ADDR_E_RETURNCODE retCode = ADDR_OK;
786
787 ADDR_TILEINFO tileInfo = {0};
788 ADDR_COMPUTE_FMASK_INFO_INPUT fmaskIn;
789 fmaskIn = *pIn;
790
791 AddrTileMode tileMode = pIn->tileMode;
792
793 // Use internal tile info if pOut does not have a valid pTileInfo
794 if (pOut->pTileInfo == NULL)
795 {
796 pOut->pTileInfo = &tileInfo;
797 }
798
799 ADDR_ASSERT(tileMode == ADDR_TM_2D_TILED_THIN1 ||
800 tileMode == ADDR_TM_3D_TILED_THIN1 ||
801 tileMode == ADDR_TM_PRT_TILED_THIN1 ||
802 tileMode == ADDR_TM_PRT_2D_TILED_THIN1 ||
803 tileMode == ADDR_TM_PRT_3D_TILED_THIN1);
804
805 ADDR_ASSERT(m_tileTable[14].mode == ADDR_TM_2D_TILED_THIN1);
806 ADDR_ASSERT(m_tileTable[15].mode == ADDR_TM_3D_TILED_THIN1);
807
808 // The only valid tile modes for fmask are 2D_THIN1 and 3D_THIN1 plus non-displayable
809 INT_32 tileIndex = tileMode == ADDR_TM_2D_TILED_THIN1 ? 14 : 15;
810 ADDR_SURFACE_FLAGS flags = {{0}};
811 flags.fmask = 1;
812
813 INT_32 macroModeIndex = TileIndexInvalid;
814
815 UINT_32 numSamples = pIn->numSamples;
816 UINT_32 numFrags = pIn->numFrags == 0 ? numSamples : pIn->numFrags;
817
818 UINT_32 bpp = QLog2(numFrags);
819
820 // EQAA needs one more bit
821 if (numSamples > numFrags)
822 {
823 bpp++;
824 }
825
826 if (bpp == 3)
827 {
828 bpp = 4;
829 }
830
831 bpp = Max(8u, bpp * numSamples);
832
833 macroModeIndex = HwlComputeMacroModeIndex(tileIndex, flags, bpp, numSamples, pOut->pTileInfo);
834
835 fmaskIn.tileIndex = tileIndex;
836 fmaskIn.pTileInfo = pOut->pTileInfo;
837 pOut->macroModeIndex = macroModeIndex;
838 pOut->tileIndex = tileIndex;
839
840 retCode = DispatchComputeFmaskInfo(&fmaskIn, pOut);
841
842 if (retCode == ADDR_OK)
843 {
844 pOut->tileIndex =
845 HwlPostCheckTileIndex(pOut->pTileInfo, pIn->tileMode, ADDR_NON_DISPLAYABLE,
846 pOut->tileIndex);
847 }
848
849 // Resets pTileInfo to NULL if the internal tile info is used
850 if (pOut->pTileInfo == &tileInfo)
851 {
852 pOut->pTileInfo = NULL;
853 }
854
855 return retCode;
856 }
857
858 /**
859 ****************************************************************************************************
860 * CiLib::HwlFmaskPreThunkSurfInfo
861 *
862 * @brief
863 * Some preparation before thunking a ComputeSurfaceInfo call for Fmask
864 * @return
865 * ADDR_E_RETURNCODE
866 ****************************************************************************************************
867 */
HwlFmaskPreThunkSurfInfo(const ADDR_COMPUTE_FMASK_INFO_INPUT * pFmaskIn,const ADDR_COMPUTE_FMASK_INFO_OUTPUT * pFmaskOut,ADDR_COMPUTE_SURFACE_INFO_INPUT * pSurfIn,ADDR_COMPUTE_SURFACE_INFO_OUTPUT * pSurfOut) const868 VOID CiLib::HwlFmaskPreThunkSurfInfo(
869 const ADDR_COMPUTE_FMASK_INFO_INPUT* pFmaskIn, ///< [in] Input of fmask info
870 const ADDR_COMPUTE_FMASK_INFO_OUTPUT* pFmaskOut, ///< [in] Output of fmask info
871 ADDR_COMPUTE_SURFACE_INFO_INPUT* pSurfIn, ///< [out] Input of thunked surface info
872 ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pSurfOut ///< [out] Output of thunked surface info
873 ) const
874 {
875 pSurfIn->tileIndex = pFmaskIn->tileIndex;
876 pSurfOut->macroModeIndex = pFmaskOut->macroModeIndex;
877 }
878
879 /**
880 ****************************************************************************************************
881 * CiLib::HwlFmaskPostThunkSurfInfo
882 *
883 * @brief
884 * Copy hwl extra field after calling thunked ComputeSurfaceInfo
885 * @return
886 * ADDR_E_RETURNCODE
887 ****************************************************************************************************
888 */
HwlFmaskPostThunkSurfInfo(const ADDR_COMPUTE_SURFACE_INFO_OUTPUT * pSurfOut,ADDR_COMPUTE_FMASK_INFO_OUTPUT * pFmaskOut) const889 VOID CiLib::HwlFmaskPostThunkSurfInfo(
890 const ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pSurfOut, ///< [in] Output of surface info
891 ADDR_COMPUTE_FMASK_INFO_OUTPUT* pFmaskOut ///< [out] Output of fmask info
892 ) const
893 {
894 pFmaskOut->tileIndex = pSurfOut->tileIndex;
895 pFmaskOut->macroModeIndex = pSurfOut->macroModeIndex;
896 }
897
898 /**
899 ****************************************************************************************************
900 * CiLib::HwlDegradeThickTileMode
901 *
902 * @brief
903 * Degrades valid tile mode for thick modes if needed
904 *
905 * @return
906 * Suitable tile mode
907 ****************************************************************************************************
908 */
HwlDegradeThickTileMode(AddrTileMode baseTileMode,UINT_32 numSlices,UINT_32 * pBytesPerTile) const909 AddrTileMode CiLib::HwlDegradeThickTileMode(
910 AddrTileMode baseTileMode, ///< [in] base tile mode
911 UINT_32 numSlices, ///< [in] current number of slices
912 UINT_32* pBytesPerTile ///< [in,out] pointer to bytes per slice
913 ) const
914 {
915 return baseTileMode;
916 }
917
918 /**
919 ****************************************************************************************************
920 * CiLib::HwlOptimizeTileMode
921 *
922 * @brief
923 * Optimize tile mode on CI
924 *
925 * @return
926 * N/A
927 *
928 ****************************************************************************************************
929 */
HwlOptimizeTileMode(ADDR_COMPUTE_SURFACE_INFO_INPUT * pInOut) const930 VOID CiLib::HwlOptimizeTileMode(
931 ADDR_COMPUTE_SURFACE_INFO_INPUT* pInOut ///< [in,out] input output structure
932 ) const
933 {
934 AddrTileMode tileMode = pInOut->tileMode;
935
936 // Override 2D/3D macro tile mode to PRT_* tile mode if
937 // client driver requests this surface is equation compatible
938 if (IsMacroTiled(tileMode) == TRUE)
939 {
940 if ((pInOut->flags.needEquation == TRUE) &&
941 (pInOut->numSamples <= 1) &&
942 (IsPrtTileMode(tileMode) == FALSE))
943 {
944 if ((pInOut->numSlices > 1) && ((pInOut->maxBaseAlign == 0) || (pInOut->maxBaseAlign >= Block64K)))
945 {
946 UINT_32 thickness = Thickness(tileMode);
947
948 if (thickness == 1)
949 {
950 tileMode = ADDR_TM_PRT_TILED_THIN1;
951 }
952 else
953 {
954 static const UINT_32 PrtTileBytes = 0x10000;
955 // First prt thick tile index in the tile mode table
956 static const UINT_32 PrtThickTileIndex = 22;
957 ADDR_TILEINFO tileInfo = {0};
958
959 HwlComputeMacroModeIndex(PrtThickTileIndex,
960 pInOut->flags,
961 pInOut->bpp,
962 pInOut->numSamples,
963 &tileInfo);
964
965 UINT_32 macroTileBytes = ((pInOut->bpp) >> 3) * 64 * pInOut->numSamples *
966 thickness * HwlGetPipes(&tileInfo) *
967 tileInfo.banks * tileInfo.bankWidth *
968 tileInfo.bankHeight;
969
970 if (macroTileBytes <= PrtTileBytes)
971 {
972 tileMode = ADDR_TM_PRT_TILED_THICK;
973 }
974 else
975 {
976 tileMode = ADDR_TM_PRT_TILED_THIN1;
977 }
978 }
979 }
980 }
981
982 if (pInOut->maxBaseAlign != 0)
983 {
984 pInOut->flags.dccPipeWorkaround = FALSE;
985 }
986 }
987
988 if (tileMode != pInOut->tileMode)
989 {
990 pInOut->tileMode = tileMode;
991 }
992 }
993
994 /**
995 ****************************************************************************************************
996 * CiLib::HwlOverrideTileMode
997 *
998 * @brief
999 * Override THICK to THIN, for specific formats on CI
1000 *
1001 * @return
1002 * N/A
1003 *
1004 ****************************************************************************************************
1005 */
HwlOverrideTileMode(ADDR_COMPUTE_SURFACE_INFO_INPUT * pInOut) const1006 VOID CiLib::HwlOverrideTileMode(
1007 ADDR_COMPUTE_SURFACE_INFO_INPUT* pInOut ///< [in,out] input output structure
1008 ) const
1009 {
1010 AddrTileMode tileMode = pInOut->tileMode;
1011 AddrTileType tileType = pInOut->tileType;
1012
1013 // currently, all CI/VI family do not
1014 // support ADDR_TM_PRT_2D_TILED_THICK,ADDR_TM_PRT_3D_TILED_THICK and
1015 // ADDR_TM_PRT_2D_TILED_THIN1, ADDR_TM_PRT_3D_TILED_THIN1
1016 switch (tileMode)
1017 {
1018 case ADDR_TM_PRT_2D_TILED_THICK:
1019 case ADDR_TM_PRT_3D_TILED_THICK:
1020 tileMode = ADDR_TM_PRT_TILED_THICK;
1021 break;
1022 case ADDR_TM_PRT_2D_TILED_THIN1:
1023 case ADDR_TM_PRT_3D_TILED_THIN1:
1024 tileMode = ADDR_TM_PRT_TILED_THIN1;
1025 break;
1026 default:
1027 break;
1028 }
1029
1030 // UBTS#404321, we do not need such overriding, as THICK+THICK entries removed from the tile-mode table
1031 if (!m_settings.isBonaire)
1032 {
1033 UINT_32 thickness = Thickness(tileMode);
1034
1035 // tile_thickness = (array_mode == XTHICK) ? 8 : ((array_mode == THICK) ? 4 : 1)
1036 if (thickness > 1)
1037 {
1038 switch (pInOut->format)
1039 {
1040 // tcpError("Thick micro tiling is not supported for format...
1041 case ADDR_FMT_X24_8_32_FLOAT:
1042 case ADDR_FMT_32_AS_8:
1043 case ADDR_FMT_32_AS_8_8:
1044 case ADDR_FMT_32_AS_32_32_32_32:
1045
1046 // packed formats
1047 case ADDR_FMT_GB_GR:
1048 case ADDR_FMT_BG_RG:
1049 case ADDR_FMT_1_REVERSED:
1050 case ADDR_FMT_1:
1051 case ADDR_FMT_BC1:
1052 case ADDR_FMT_BC2:
1053 case ADDR_FMT_BC3:
1054 case ADDR_FMT_BC4:
1055 case ADDR_FMT_BC5:
1056 case ADDR_FMT_BC6:
1057 case ADDR_FMT_BC7:
1058 switch (tileMode)
1059 {
1060 case ADDR_TM_1D_TILED_THICK:
1061 tileMode = ADDR_TM_1D_TILED_THIN1;
1062 break;
1063
1064 case ADDR_TM_2D_TILED_XTHICK:
1065 case ADDR_TM_2D_TILED_THICK:
1066 tileMode = ADDR_TM_2D_TILED_THIN1;
1067 break;
1068
1069 case ADDR_TM_3D_TILED_XTHICK:
1070 case ADDR_TM_3D_TILED_THICK:
1071 tileMode = ADDR_TM_3D_TILED_THIN1;
1072 break;
1073
1074 case ADDR_TM_PRT_TILED_THICK:
1075 tileMode = ADDR_TM_PRT_TILED_THIN1;
1076 break;
1077
1078 case ADDR_TM_PRT_2D_TILED_THICK:
1079 tileMode = ADDR_TM_PRT_2D_TILED_THIN1;
1080 break;
1081
1082 case ADDR_TM_PRT_3D_TILED_THICK:
1083 tileMode = ADDR_TM_PRT_3D_TILED_THIN1;
1084 break;
1085
1086 default:
1087 break;
1088
1089 }
1090
1091 // Switch tile type from thick to thin
1092 if (tileMode != pInOut->tileMode)
1093 {
1094 // see tileIndex: 13-18
1095 tileType = ADDR_NON_DISPLAYABLE;
1096 }
1097
1098 break;
1099 default:
1100 break;
1101 }
1102 }
1103 }
1104
1105 if (tileMode != pInOut->tileMode)
1106 {
1107 pInOut->tileMode = tileMode;
1108 pInOut->tileType = tileType;
1109 }
1110 }
1111
1112 /**
1113 ****************************************************************************************************
1114 * CiLib::HwlSelectTileMode
1115 *
1116 * @brief
1117 * Select tile modes.
1118 *
1119 * @return
1120 * N/A
1121 *
1122 ****************************************************************************************************
1123 */
HwlSelectTileMode(ADDR_COMPUTE_SURFACE_INFO_INPUT * pInOut) const1124 VOID CiLib::HwlSelectTileMode(
1125 ADDR_COMPUTE_SURFACE_INFO_INPUT* pInOut ///< [in,out] input output structure
1126 ) const
1127 {
1128 AddrTileMode tileMode;
1129 AddrTileType tileType;
1130
1131 if (pInOut->flags.rotateDisplay)
1132 {
1133 tileMode = ADDR_TM_2D_TILED_THIN1;
1134 tileType = ADDR_ROTATED;
1135 }
1136 else if (pInOut->flags.volume)
1137 {
1138 BOOL_32 bThin = (m_settings.isBonaire == TRUE) ||
1139 ((m_allowNonDispThickModes == TRUE) && (pInOut->flags.color == TRUE));
1140
1141 if (pInOut->numSlices >= 8)
1142 {
1143 tileMode = ADDR_TM_2D_TILED_XTHICK;
1144 tileType = (bThin == TRUE) ? ADDR_NON_DISPLAYABLE : ADDR_THICK;
1145 }
1146 else if (pInOut->numSlices >= 4)
1147 {
1148 tileMode = ADDR_TM_2D_TILED_THICK;
1149 tileType = (bThin == TRUE) ? ADDR_NON_DISPLAYABLE : ADDR_THICK;
1150 }
1151 else
1152 {
1153 tileMode = ADDR_TM_2D_TILED_THIN1;
1154 tileType = ADDR_NON_DISPLAYABLE;
1155 }
1156 }
1157 else
1158 {
1159 tileMode = ADDR_TM_2D_TILED_THIN1;
1160
1161 if (pInOut->flags.depth || pInOut->flags.stencil)
1162 {
1163 tileType = ADDR_DEPTH_SAMPLE_ORDER;
1164 }
1165 else if ((pInOut->bpp <= 32) ||
1166 (pInOut->flags.display == TRUE) ||
1167 (pInOut->flags.overlay == TRUE))
1168 {
1169 tileType = ADDR_DISPLAYABLE;
1170 }
1171 else
1172 {
1173 tileType = ADDR_NON_DISPLAYABLE;
1174 }
1175 }
1176
1177 if (pInOut->flags.prt)
1178 {
1179 if (Thickness(tileMode) > 1)
1180 {
1181 tileMode = ADDR_TM_PRT_TILED_THICK;
1182 tileType = (m_settings.isBonaire == TRUE) ? ADDR_NON_DISPLAYABLE : ADDR_THICK;
1183 }
1184 else
1185 {
1186 tileMode = ADDR_TM_PRT_TILED_THIN1;
1187 }
1188 }
1189
1190 pInOut->tileMode = tileMode;
1191 pInOut->tileType = tileType;
1192
1193 if ((pInOut->flags.dccCompatible == FALSE) &&
1194 (pInOut->flags.tcCompatible == FALSE))
1195 {
1196 pInOut->flags.opt4Space = TRUE;
1197 pInOut->maxBaseAlign = Block64K;
1198 }
1199
1200 // Optimize tile mode if possible
1201 OptimizeTileMode(pInOut);
1202
1203 HwlOverrideTileMode(pInOut);
1204 }
1205
1206 /**
1207 ****************************************************************************************************
1208 * CiLib::HwlSetPrtTileMode
1209 *
1210 * @brief
1211 * Set PRT tile mode.
1212 *
1213 * @return
1214 * N/A
1215 *
1216 ****************************************************************************************************
1217 */
HwlSetPrtTileMode(ADDR_COMPUTE_SURFACE_INFO_INPUT * pInOut) const1218 VOID CiLib::HwlSetPrtTileMode(
1219 ADDR_COMPUTE_SURFACE_INFO_INPUT* pInOut ///< [in,out] input output structure
1220 ) const
1221 {
1222 AddrTileMode tileMode = pInOut->tileMode;
1223 AddrTileType tileType = pInOut->tileType;
1224
1225 if (Thickness(tileMode) > 1)
1226 {
1227 tileMode = ADDR_TM_PRT_TILED_THICK;
1228 tileType = (m_settings.isBonaire == TRUE) ? ADDR_NON_DISPLAYABLE : ADDR_THICK;
1229 }
1230 else
1231 {
1232 tileMode = ADDR_TM_PRT_TILED_THIN1;
1233 tileType = (tileType == ADDR_THICK) ? ADDR_NON_DISPLAYABLE : tileType;
1234 }
1235
1236 pInOut->tileMode = tileMode;
1237 pInOut->tileType = tileType;
1238 }
1239
1240 /**
1241 ****************************************************************************************************
1242 * CiLib::HwlSetupTileInfo
1243 *
1244 * @brief
1245 * Setup default value of tile info for SI
1246 ****************************************************************************************************
1247 */
HwlSetupTileInfo(AddrTileMode tileMode,ADDR_SURFACE_FLAGS flags,UINT_32 bpp,UINT_32 pitch,UINT_32 height,UINT_32 numSamples,ADDR_TILEINFO * pTileInfoIn,ADDR_TILEINFO * pTileInfoOut,AddrTileType inTileType,ADDR_COMPUTE_SURFACE_INFO_OUTPUT * pOut) const1248 VOID CiLib::HwlSetupTileInfo(
1249 AddrTileMode tileMode, ///< [in] Tile mode
1250 ADDR_SURFACE_FLAGS flags, ///< [in] Surface type flags
1251 UINT_32 bpp, ///< [in] Bits per pixel
1252 UINT_32 pitch, ///< [in] Pitch in pixels
1253 UINT_32 height, ///< [in] Height in pixels
1254 UINT_32 numSamples, ///< [in] Number of samples
1255 ADDR_TILEINFO* pTileInfoIn, ///< [in] Tile info input: NULL for default
1256 ADDR_TILEINFO* pTileInfoOut, ///< [out] Tile info output
1257 AddrTileType inTileType, ///< [in] Tile type
1258 ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [out] Output
1259 ) const
1260 {
1261 UINT_32 thickness = Thickness(tileMode);
1262 ADDR_TILEINFO* pTileInfo = pTileInfoOut;
1263 INT index = TileIndexInvalid;
1264 INT macroModeIndex = TileIndexInvalid;
1265
1266 // Fail-safe code
1267 if (IsLinear(tileMode) == FALSE)
1268 {
1269 // Thick tile modes must use thick micro tile mode but Bonaire does not support due to
1270 // old derived netlists (UBTS 404321)
1271 if (thickness > 1)
1272 {
1273 if (m_settings.isBonaire)
1274 {
1275 inTileType = ADDR_NON_DISPLAYABLE;
1276 }
1277 else if ((m_allowNonDispThickModes == FALSE) ||
1278 (inTileType != ADDR_NON_DISPLAYABLE) ||
1279 // There is no PRT_THICK + THIN entry in tile mode table except Bonaire
1280 (IsPrtTileMode(tileMode) == TRUE))
1281 {
1282 inTileType = ADDR_THICK;
1283 }
1284 }
1285 // 128 bpp tiling must be non-displayable.
1286 // Fmask reuse color buffer's entry but bank-height field can be from another entry
1287 // To simplify the logic, fmask entry should be picked from non-displayable ones
1288 else if (bpp == 128 || flags.fmask)
1289 {
1290 inTileType = ADDR_NON_DISPLAYABLE;
1291 }
1292 // These two modes only have non-disp entries though they can be other micro tile modes
1293 else if (tileMode == ADDR_TM_3D_TILED_THIN1 || tileMode == ADDR_TM_PRT_3D_TILED_THIN1)
1294 {
1295 inTileType = ADDR_NON_DISPLAYABLE;
1296 }
1297
1298 if (flags.depth || flags.stencil)
1299 {
1300 inTileType = ADDR_DEPTH_SAMPLE_ORDER;
1301 }
1302 }
1303
1304 // tcCompatible flag is only meaningful for gfx8.
1305 if (SupportDccAndTcCompatibility() == FALSE)
1306 {
1307 flags.tcCompatible = FALSE;
1308 }
1309
1310 if (IsTileInfoAllZero(pTileInfo))
1311 {
1312 // See table entries 0-4
1313 if (flags.depth || flags.stencil)
1314 {
1315 // tileSize = thickness * bpp * numSamples * 8 * 8 / 8
1316 UINT_32 tileSize = thickness * bpp * numSamples * 8;
1317
1318 // Turn off tc compatible if row_size is smaller than tile size (tile split occurs).
1319 if (m_rowSize < tileSize)
1320 {
1321 flags.tcCompatible = FALSE;
1322 }
1323
1324 if (flags.nonSplit | flags.tcCompatible | flags.needEquation)
1325 {
1326 // Texture readable depth surface should not be split
1327 switch (tileSize)
1328 {
1329 case 64:
1330 index = 0;
1331 break;
1332 case 128:
1333 index = 1;
1334 break;
1335 case 256:
1336 index = 2;
1337 break;
1338 case 512:
1339 index = 3;
1340 break;
1341 default:
1342 index = 4;
1343 break;
1344 }
1345 }
1346 else
1347 {
1348 // Depth and stencil need to use the same index, thus the pre-defined tile_split
1349 // can meet the requirement to choose the same macro mode index
1350 // uncompressed depth/stencil are not supported for now
1351 switch (numSamples)
1352 {
1353 case 1:
1354 index = 0;
1355 break;
1356 case 2:
1357 case 4:
1358 index = 1;
1359 break;
1360 case 8:
1361 index = 2;
1362 break;
1363 default:
1364 break;
1365 }
1366 }
1367 }
1368
1369 // See table entries 5-6
1370 if (inTileType == ADDR_DEPTH_SAMPLE_ORDER)
1371 {
1372 switch (tileMode)
1373 {
1374 case ADDR_TM_1D_TILED_THIN1:
1375 index = 5;
1376 break;
1377 case ADDR_TM_PRT_TILED_THIN1:
1378 index = 6;
1379 break;
1380 default:
1381 break;
1382 }
1383 }
1384
1385 // See table entries 8-12
1386 if (inTileType == ADDR_DISPLAYABLE)
1387 {
1388 switch (tileMode)
1389 {
1390 case ADDR_TM_1D_TILED_THIN1:
1391 index = 9;
1392 break;
1393 case ADDR_TM_2D_TILED_THIN1:
1394 index = 10;
1395 break;
1396 case ADDR_TM_PRT_TILED_THIN1:
1397 index = 11;
1398 break;
1399 default:
1400 break;
1401 }
1402 }
1403
1404 // See table entries 13-18
1405 if (inTileType == ADDR_NON_DISPLAYABLE)
1406 {
1407 switch (tileMode)
1408 {
1409 case ADDR_TM_1D_TILED_THIN1:
1410 index = 13;
1411 break;
1412 case ADDR_TM_2D_TILED_THIN1:
1413 index = 14;
1414 break;
1415 case ADDR_TM_3D_TILED_THIN1:
1416 index = 15;
1417 break;
1418 case ADDR_TM_PRT_TILED_THIN1:
1419 index = 16;
1420 break;
1421 default:
1422 break;
1423 }
1424 }
1425
1426 // See table entries 19-26
1427 if (thickness > 1)
1428 {
1429 switch (tileMode)
1430 {
1431 case ADDR_TM_1D_TILED_THICK:
1432 // special check for bonaire, for the compatablity between old KMD and new UMD
1433 index = ((inTileType == ADDR_THICK) || m_settings.isBonaire) ? 19 : 18;
1434 break;
1435 case ADDR_TM_2D_TILED_THICK:
1436 // special check for bonaire, for the compatablity between old KMD and new UMD
1437 index = ((inTileType == ADDR_THICK) || m_settings.isBonaire) ? 20 : 24;
1438 break;
1439 case ADDR_TM_3D_TILED_THICK:
1440 index = 21;
1441 break;
1442 case ADDR_TM_PRT_TILED_THICK:
1443 index = 22;
1444 break;
1445 case ADDR_TM_2D_TILED_XTHICK:
1446 index = 25;
1447 break;
1448 case ADDR_TM_3D_TILED_XTHICK:
1449 index = 26;
1450 break;
1451 default:
1452 break;
1453 }
1454 }
1455
1456 // See table entries 27-30
1457 if (inTileType == ADDR_ROTATED)
1458 {
1459 switch (tileMode)
1460 {
1461 case ADDR_TM_1D_TILED_THIN1:
1462 index = 27;
1463 break;
1464 case ADDR_TM_2D_TILED_THIN1:
1465 index = 28;
1466 break;
1467 case ADDR_TM_PRT_TILED_THIN1:
1468 index = 29;
1469 break;
1470 case ADDR_TM_PRT_2D_TILED_THIN1:
1471 index = 30;
1472 break;
1473 default:
1474 break;
1475 }
1476 }
1477
1478 if (m_pipes >= 8)
1479 {
1480 ADDR_ASSERT((index + 1) < static_cast<INT_32>(m_noOfEntries));
1481 // Only do this when tile mode table is updated.
1482 if (((tileMode == ADDR_TM_PRT_TILED_THIN1) || (tileMode == ADDR_TM_PRT_TILED_THICK)) &&
1483 (m_tileTable[index + 1].mode == tileMode))
1484 {
1485 static const UINT_32 PrtTileBytes = 0x10000;
1486 ADDR_TILEINFO tileInfo = {0};
1487
1488 HwlComputeMacroModeIndex(index, flags, bpp, numSamples, &tileInfo);
1489
1490 UINT_32 macroTileBytes = (bpp >> 3) * 64 * numSamples * thickness *
1491 HwlGetPipes(&tileInfo) * tileInfo.banks *
1492 tileInfo.bankWidth * tileInfo.bankHeight;
1493
1494 if (macroTileBytes != PrtTileBytes)
1495 {
1496 // Switching to next tile mode entry to make sure macro tile size is 64KB
1497 index += 1;
1498
1499 tileInfo.pipeConfig = m_tileTable[index].info.pipeConfig;
1500
1501 macroTileBytes = (bpp >> 3) * 64 * numSamples * thickness *
1502 HwlGetPipes(&tileInfo) * tileInfo.banks *
1503 tileInfo.bankWidth * tileInfo.bankHeight;
1504
1505 ADDR_ASSERT(macroTileBytes == PrtTileBytes);
1506
1507 flags.tcCompatible = FALSE;
1508 pOut->dccUnsupport = TRUE;
1509 }
1510 }
1511 }
1512 }
1513 else
1514 {
1515 // A pre-filled tile info is ready
1516 index = pOut->tileIndex;
1517 macroModeIndex = pOut->macroModeIndex;
1518
1519 // pass tile type back for post tile index compute
1520 pOut->tileType = inTileType;
1521
1522 if (flags.depth || flags.stencil)
1523 {
1524 // tileSize = thickness * bpp * numSamples * 8 * 8 / 8
1525 UINT_32 tileSize = thickness * bpp * numSamples * 8;
1526
1527 // Turn off tc compatible if row_size is smaller than tile size (tile split occurs).
1528 if (m_rowSize < tileSize)
1529 {
1530 flags.tcCompatible = FALSE;
1531 }
1532 }
1533
1534 UINT_32 numPipes = GetPipePerSurf(pTileInfo->pipeConfig);
1535
1536 if (m_pipes != numPipes)
1537 {
1538 pOut->dccUnsupport = TRUE;
1539 }
1540 }
1541
1542 // We only need to set up tile info if there is a valid index but macroModeIndex is invalid
1543 if ((index != TileIndexInvalid) && (macroModeIndex == TileIndexInvalid))
1544 {
1545 macroModeIndex = HwlComputeMacroModeIndex(index, flags, bpp, numSamples, pTileInfo);
1546
1547 // Copy to pOut->tileType/tileIndex/macroModeIndex
1548 pOut->tileIndex = index;
1549 pOut->tileType = m_tileTable[index].type; // Or inTileType, the samea
1550 pOut->macroModeIndex = macroModeIndex;
1551 }
1552 else if (tileMode == ADDR_TM_LINEAR_GENERAL)
1553 {
1554 pOut->tileIndex = TileIndexLinearGeneral;
1555
1556 // Copy linear-aligned entry??
1557 *pTileInfo = m_tileTable[8].info;
1558 }
1559 else if (tileMode == ADDR_TM_LINEAR_ALIGNED)
1560 {
1561 pOut->tileIndex = 8;
1562 *pTileInfo = m_tileTable[8].info;
1563 }
1564
1565 if (flags.tcCompatible)
1566 {
1567 flags.tcCompatible = CheckTcCompatibility(pTileInfo, bpp, tileMode, inTileType, pOut);
1568 }
1569
1570 pOut->tcCompatible = flags.tcCompatible;
1571 }
1572
1573 /**
1574 ****************************************************************************************************
1575 * CiLib::ReadGbTileMode
1576 *
1577 * @brief
1578 * Convert GB_TILE_MODE HW value to ADDR_TILE_CONFIG.
1579 ****************************************************************************************************
1580 */
ReadGbTileMode(UINT_32 regValue,TileConfig * pCfg) const1581 VOID CiLib::ReadGbTileMode(
1582 UINT_32 regValue, ///< [in] GB_TILE_MODE register
1583 TileConfig* pCfg ///< [out] output structure
1584 ) const
1585 {
1586 GB_TILE_MODE gbTileMode;
1587 gbTileMode.val = regValue;
1588
1589 pCfg->type = static_cast<AddrTileType>(gbTileMode.f.micro_tile_mode_new);
1590 if (AltTilingEnabled() == TRUE)
1591 {
1592 pCfg->info.pipeConfig = static_cast<AddrPipeCfg>(gbTileMode.f.alt_pipe_config + 1);
1593 }
1594 else
1595 {
1596 pCfg->info.pipeConfig = static_cast<AddrPipeCfg>(gbTileMode.f.pipe_config + 1);
1597 }
1598
1599 if (pCfg->type == ADDR_DEPTH_SAMPLE_ORDER)
1600 {
1601 pCfg->info.tileSplitBytes = 64 << gbTileMode.f.tile_split;
1602 }
1603 else
1604 {
1605 pCfg->info.tileSplitBytes = 1 << gbTileMode.f.sample_split;
1606 }
1607
1608 UINT_32 regArrayMode = gbTileMode.f.array_mode;
1609
1610 pCfg->mode = static_cast<AddrTileMode>(regArrayMode);
1611
1612 switch (regArrayMode)
1613 {
1614 case 5:
1615 pCfg->mode = ADDR_TM_PRT_TILED_THIN1;
1616 break;
1617 case 6:
1618 pCfg->mode = ADDR_TM_PRT_2D_TILED_THIN1;
1619 break;
1620 case 8:
1621 pCfg->mode = ADDR_TM_2D_TILED_XTHICK;
1622 break;
1623 case 9:
1624 pCfg->mode = ADDR_TM_PRT_TILED_THICK;
1625 break;
1626 case 0xa:
1627 pCfg->mode = ADDR_TM_PRT_2D_TILED_THICK;
1628 break;
1629 case 0xb:
1630 pCfg->mode = ADDR_TM_PRT_3D_TILED_THIN1;
1631 break;
1632 case 0xe:
1633 pCfg->mode = ADDR_TM_3D_TILED_XTHICK;
1634 break;
1635 case 0xf:
1636 pCfg->mode = ADDR_TM_PRT_3D_TILED_THICK;
1637 break;
1638 default:
1639 break;
1640 }
1641
1642 // Fail-safe code for these always convert tile info, as the non-macro modes
1643 // return the entry of tile mode table directly without looking up macro mode table
1644 if (!IsMacroTiled(pCfg->mode))
1645 {
1646 pCfg->info.banks = 2;
1647 pCfg->info.bankWidth = 1;
1648 pCfg->info.bankHeight = 1;
1649 pCfg->info.macroAspectRatio = 1;
1650 pCfg->info.tileSplitBytes = 64;
1651 }
1652 }
1653
1654 /**
1655 ****************************************************************************************************
1656 * CiLib::InitTileSettingTable
1657 *
1658 * @brief
1659 * Initialize the ADDR_TILE_CONFIG table.
1660 * @return
1661 * TRUE if tile table is correctly initialized
1662 ****************************************************************************************************
1663 */
InitTileSettingTable(const UINT_32 * pCfg,UINT_32 noOfEntries)1664 BOOL_32 CiLib::InitTileSettingTable(
1665 const UINT_32* pCfg, ///< [in] Pointer to table of tile configs
1666 UINT_32 noOfEntries ///< [in] Numbe of entries in the table above
1667 )
1668 {
1669 BOOL_32 initOk = TRUE;
1670
1671 ADDR_ASSERT(noOfEntries <= TileTableSize);
1672
1673 memset(m_tileTable, 0, sizeof(m_tileTable));
1674
1675 if (noOfEntries != 0)
1676 {
1677 m_noOfEntries = noOfEntries;
1678 }
1679 else
1680 {
1681 m_noOfEntries = TileTableSize;
1682 }
1683
1684 if (pCfg) // From Client
1685 {
1686 for (UINT_32 i = 0; i < m_noOfEntries; i++)
1687 {
1688 ReadGbTileMode(*(pCfg + i), &m_tileTable[i]);
1689 }
1690 }
1691 else
1692 {
1693 ADDR_ASSERT_ALWAYS();
1694 initOk = FALSE;
1695 }
1696
1697 if (initOk)
1698 {
1699 ADDR_ASSERT(m_tileTable[TILEINDEX_LINEAR_ALIGNED].mode == ADDR_TM_LINEAR_ALIGNED);
1700
1701 if (m_settings.isBonaire == FALSE)
1702 {
1703 // Check if entry 18 is "thick+thin" combination
1704 if ((m_tileTable[18].mode == ADDR_TM_1D_TILED_THICK) &&
1705 (m_tileTable[18].type == ADDR_NON_DISPLAYABLE))
1706 {
1707 m_allowNonDispThickModes = TRUE;
1708 ADDR_ASSERT(m_tileTable[24].mode == ADDR_TM_2D_TILED_THICK);
1709 }
1710 }
1711 else
1712 {
1713 m_allowNonDispThickModes = TRUE;
1714 }
1715
1716 // Assume the first entry is always programmed with full pipes
1717 m_pipes = HwlGetPipes(&m_tileTable[0].info);
1718 }
1719
1720 return initOk;
1721 }
1722
1723 /**
1724 ****************************************************************************************************
1725 * CiLib::ReadGbMacroTileCfg
1726 *
1727 * @brief
1728 * Convert GB_MACRO_TILE_CFG HW value to ADDR_TILE_CONFIG.
1729 ****************************************************************************************************
1730 */
ReadGbMacroTileCfg(UINT_32 regValue,ADDR_TILEINFO * pCfg) const1731 VOID CiLib::ReadGbMacroTileCfg(
1732 UINT_32 regValue, ///< [in] GB_MACRO_TILE_MODE register
1733 ADDR_TILEINFO* pCfg ///< [out] output structure
1734 ) const
1735 {
1736 GB_MACROTILE_MODE gbTileMode;
1737 gbTileMode.val = regValue;
1738
1739 if (AltTilingEnabled() == TRUE)
1740 {
1741 pCfg->bankHeight = 1 << gbTileMode.f.alt_bank_height;
1742 pCfg->banks = 1 << (gbTileMode.f.alt_num_banks + 1);
1743 pCfg->macroAspectRatio = 1 << gbTileMode.f.alt_macro_tile_aspect;
1744 }
1745 else
1746 {
1747 pCfg->bankHeight = 1 << gbTileMode.f.bank_height;
1748 pCfg->banks = 1 << (gbTileMode.f.num_banks + 1);
1749 pCfg->macroAspectRatio = 1 << gbTileMode.f.macro_tile_aspect;
1750 }
1751 pCfg->bankWidth = 1 << gbTileMode.f.bank_width;
1752 }
1753
1754 /**
1755 ****************************************************************************************************
1756 * CiLib::InitMacroTileCfgTable
1757 *
1758 * @brief
1759 * Initialize the ADDR_MACRO_TILE_CONFIG table.
1760 * @return
1761 * TRUE if macro tile table is correctly initialized
1762 ****************************************************************************************************
1763 */
InitMacroTileCfgTable(const UINT_32 * pCfg,UINT_32 noOfMacroEntries)1764 BOOL_32 CiLib::InitMacroTileCfgTable(
1765 const UINT_32* pCfg, ///< [in] Pointer to table of tile configs
1766 UINT_32 noOfMacroEntries ///< [in] Numbe of entries in the table above
1767 )
1768 {
1769 BOOL_32 initOk = TRUE;
1770
1771 ADDR_ASSERT(noOfMacroEntries <= MacroTileTableSize);
1772
1773 memset(m_macroTileTable, 0, sizeof(m_macroTileTable));
1774
1775 if (noOfMacroEntries != 0)
1776 {
1777 m_noOfMacroEntries = noOfMacroEntries;
1778 }
1779 else
1780 {
1781 m_noOfMacroEntries = MacroTileTableSize;
1782 }
1783
1784 if (pCfg) // From Client
1785 {
1786 for (UINT_32 i = 0; i < m_noOfMacroEntries; i++)
1787 {
1788 ReadGbMacroTileCfg(*(pCfg + i), &m_macroTileTable[i]);
1789
1790 m_macroTileTable[i].tileSplitBytes = 64 << (i % 8);
1791 }
1792 }
1793 else
1794 {
1795 ADDR_ASSERT_ALWAYS();
1796 initOk = FALSE;
1797 }
1798 return initOk;
1799 }
1800
1801 /**
1802 ****************************************************************************************************
1803 * CiLib::HwlComputeMacroModeIndex
1804 *
1805 * @brief
1806 * Computes macro tile mode index
1807 * @return
1808 * TRUE if macro tile table is correctly initialized
1809 ****************************************************************************************************
1810 */
HwlComputeMacroModeIndex(INT_32 tileIndex,ADDR_SURFACE_FLAGS flags,UINT_32 bpp,UINT_32 numSamples,ADDR_TILEINFO * pTileInfo,AddrTileMode * pTileMode,AddrTileType * pTileType) const1811 INT_32 CiLib::HwlComputeMacroModeIndex(
1812 INT_32 tileIndex, ///< [in] Tile mode index
1813 ADDR_SURFACE_FLAGS flags, ///< [in] Surface flags
1814 UINT_32 bpp, ///< [in] Bit per pixel
1815 UINT_32 numSamples, ///< [in] Number of samples
1816 ADDR_TILEINFO* pTileInfo, ///< [out] Pointer to ADDR_TILEINFO
1817 AddrTileMode* pTileMode, ///< [out] Pointer to AddrTileMode
1818 AddrTileType* pTileType ///< [out] Pointer to AddrTileType
1819 ) const
1820 {
1821 INT_32 macroModeIndex = TileIndexInvalid;
1822
1823 AddrTileMode tileMode = m_tileTable[tileIndex].mode;
1824 AddrTileType tileType = m_tileTable[tileIndex].type;
1825 UINT_32 thickness = Thickness(tileMode);
1826
1827 if (!IsMacroTiled(tileMode))
1828 {
1829 *pTileInfo = m_tileTable[tileIndex].info;
1830 macroModeIndex = TileIndexNoMacroIndex;
1831 }
1832 else
1833 {
1834 UINT_32 tileBytes1x = BITS_TO_BYTES(bpp * MicroTilePixels * thickness);
1835 UINT_32 tileSplit;
1836
1837 if (m_tileTable[tileIndex].type == ADDR_DEPTH_SAMPLE_ORDER)
1838 {
1839 // Depth entries store real tileSplitBytes
1840 tileSplit = m_tileTable[tileIndex].info.tileSplitBytes;
1841 }
1842 else
1843 {
1844 // Non-depth entries store a split factor
1845 UINT_32 sampleSplit = m_tileTable[tileIndex].info.tileSplitBytes;
1846 UINT_32 colorTileSplit = Max(256u, sampleSplit * tileBytes1x);
1847
1848 tileSplit = colorTileSplit;
1849 }
1850
1851 UINT_32 tileSplitC = Min(m_rowSize, tileSplit);
1852 UINT_32 tileBytes;
1853
1854 if (flags.fmask)
1855 {
1856 tileBytes = Min(tileSplitC, tileBytes1x);
1857 }
1858 else
1859 {
1860 tileBytes = Min(tileSplitC, numSamples * tileBytes1x);
1861 }
1862
1863 if (tileBytes < 64)
1864 {
1865 tileBytes = 64;
1866 }
1867
1868 macroModeIndex = Log2(tileBytes / 64);
1869
1870 if (flags.prt || IsPrtTileMode(tileMode))
1871 {
1872 macroModeIndex += PrtMacroModeOffset;
1873 *pTileInfo = m_macroTileTable[macroModeIndex];
1874 }
1875 else
1876 {
1877 *pTileInfo = m_macroTileTable[macroModeIndex];
1878 }
1879
1880 pTileInfo->pipeConfig = m_tileTable[tileIndex].info.pipeConfig;
1881
1882 pTileInfo->tileSplitBytes = tileSplitC;
1883 }
1884
1885 if (NULL != pTileMode)
1886 {
1887 *pTileMode = tileMode;
1888 }
1889
1890 if (NULL != pTileType)
1891 {
1892 *pTileType = tileType;
1893 }
1894
1895 return macroModeIndex;
1896 }
1897
1898 /**
1899 ****************************************************************************************************
1900 * CiLib::HwlComputeTileDataWidthAndHeightLinear
1901 *
1902 * @brief
1903 * Compute the squared cache shape for per-tile data (CMASK and HTILE) for linear layout
1904 *
1905 * @note
1906 * MacroWidth and macroHeight are measured in pixels
1907 ****************************************************************************************************
1908 */
HwlComputeTileDataWidthAndHeightLinear(UINT_32 * pMacroWidth,UINT_32 * pMacroHeight,UINT_32 bpp,ADDR_TILEINFO * pTileInfo) const1909 VOID CiLib::HwlComputeTileDataWidthAndHeightLinear(
1910 UINT_32* pMacroWidth, ///< [out] macro tile width
1911 UINT_32* pMacroHeight, ///< [out] macro tile height
1912 UINT_32 bpp, ///< [in] bits per pixel
1913 ADDR_TILEINFO* pTileInfo ///< [in] tile info
1914 ) const
1915 {
1916 ADDR_ASSERT(pTileInfo != NULL);
1917
1918 UINT_32 numTiles;
1919
1920 switch (pTileInfo->pipeConfig)
1921 {
1922 case ADDR_PIPECFG_P16_32x32_8x16:
1923 case ADDR_PIPECFG_P16_32x32_16x16:
1924 case ADDR_PIPECFG_P8_32x64_32x32:
1925 case ADDR_PIPECFG_P8_32x32_16x32:
1926 case ADDR_PIPECFG_P8_32x32_16x16:
1927 case ADDR_PIPECFG_P8_32x32_8x16:
1928 case ADDR_PIPECFG_P4_32x32:
1929 numTiles = 8;
1930 break;
1931 default:
1932 numTiles = 4;
1933 break;
1934 }
1935
1936 *pMacroWidth = numTiles * MicroTileWidth;
1937 *pMacroHeight = numTiles * MicroTileHeight;
1938 }
1939
1940 /**
1941 ****************************************************************************************************
1942 * CiLib::HwlComputeMetadataNibbleAddress
1943 *
1944 * @brief
1945 * calculate meta data address based on input information
1946 *
1947 * ¶meter
1948 * uncompressedDataByteAddress - address of a pixel in color surface
1949 * dataBaseByteAddress - base address of color surface
1950 * metadataBaseByteAddress - base address of meta ram
1951 * metadataBitSize - meta key size, 8 for DCC, 4 for cmask
1952 * elementBitSize - element size of color surface
1953 * blockByteSize - compression block size, 256 for DCC
1954 * pipeInterleaveBytes - pipe interleave size
1955 * numOfPipes - number of pipes
1956 * numOfBanks - number of banks
1957 * numOfSamplesPerSplit - number of samples per tile split
1958 * @return
1959 * meta data nibble address (nibble address is used to support DCC compatible cmask)
1960 *
1961 ****************************************************************************************************
1962 */
HwlComputeMetadataNibbleAddress(UINT_64 uncompressedDataByteAddress,UINT_64 dataBaseByteAddress,UINT_64 metadataBaseByteAddress,UINT_32 metadataBitSize,UINT_32 elementBitSize,UINT_32 blockByteSize,UINT_32 pipeInterleaveBytes,UINT_32 numOfPipes,UINT_32 numOfBanks,UINT_32 numOfSamplesPerSplit) const1963 UINT_64 CiLib::HwlComputeMetadataNibbleAddress(
1964 UINT_64 uncompressedDataByteAddress,
1965 UINT_64 dataBaseByteAddress,
1966 UINT_64 metadataBaseByteAddress,
1967 UINT_32 metadataBitSize,
1968 UINT_32 elementBitSize,
1969 UINT_32 blockByteSize,
1970 UINT_32 pipeInterleaveBytes,
1971 UINT_32 numOfPipes,
1972 UINT_32 numOfBanks,
1973 UINT_32 numOfSamplesPerSplit) const
1974 {
1975 ///--------------------------------------------------------------------------------------------
1976 /// Get pipe interleave, bank and pipe bits
1977 ///--------------------------------------------------------------------------------------------
1978 UINT_32 pipeInterleaveBits = Log2(pipeInterleaveBytes);
1979 UINT_32 pipeBits = Log2(numOfPipes);
1980 UINT_32 bankBits = Log2(numOfBanks);
1981
1982 ///--------------------------------------------------------------------------------------------
1983 /// Clear pipe and bank swizzles
1984 ///--------------------------------------------------------------------------------------------
1985 UINT_32 dataMacrotileBits = pipeInterleaveBits + pipeBits + bankBits;
1986 UINT_32 metadataMacrotileBits = pipeInterleaveBits + pipeBits + bankBits;
1987
1988 UINT_64 dataMacrotileClearMask = ~((1L << dataMacrotileBits) - 1);
1989 UINT_64 metadataMacrotileClearMask = ~((1L << metadataMacrotileBits) - 1);
1990
1991 UINT_64 dataBaseByteAddressNoSwizzle = dataBaseByteAddress & dataMacrotileClearMask;
1992 UINT_64 metadataBaseByteAddressNoSwizzle = metadataBaseByteAddress & metadataMacrotileClearMask;
1993
1994 ///--------------------------------------------------------------------------------------------
1995 /// Modify metadata base before adding in so that when final address is divided by data ratio,
1996 /// the base address returns to where it should be
1997 ///--------------------------------------------------------------------------------------------
1998 ADDR_ASSERT((0 != metadataBitSize));
1999 UINT_64 metadataBaseShifted = metadataBaseByteAddressNoSwizzle * blockByteSize * 8 /
2000 metadataBitSize;
2001 UINT_64 offset = uncompressedDataByteAddress -
2002 dataBaseByteAddressNoSwizzle +
2003 metadataBaseShifted;
2004
2005 ///--------------------------------------------------------------------------------------------
2006 /// Save bank data bits
2007 ///--------------------------------------------------------------------------------------------
2008 UINT_32 lsb = pipeBits + pipeInterleaveBits;
2009 UINT_32 msb = bankBits - 1 + lsb;
2010
2011 UINT_64 bankDataBits = GetBits(offset, msb, lsb);
2012
2013 ///--------------------------------------------------------------------------------------------
2014 /// Save pipe data bits
2015 ///--------------------------------------------------------------------------------------------
2016 lsb = pipeInterleaveBits;
2017 msb = pipeBits - 1 + lsb;
2018
2019 UINT_64 pipeDataBits = GetBits(offset, msb, lsb);
2020
2021 ///--------------------------------------------------------------------------------------------
2022 /// Remove pipe and bank bits
2023 ///--------------------------------------------------------------------------------------------
2024 lsb = pipeInterleaveBits;
2025 msb = dataMacrotileBits - 1;
2026
2027 UINT_64 offsetWithoutPipeBankBits = RemoveBits(offset, msb, lsb);
2028
2029 ADDR_ASSERT((0 != blockByteSize));
2030 UINT_64 blockInBankpipe = offsetWithoutPipeBankBits / blockByteSize;
2031
2032 UINT_32 tileSize = 8 * 8 * elementBitSize/8 * numOfSamplesPerSplit;
2033 UINT_32 blocksInTile = tileSize / blockByteSize;
2034
2035 if (0 == blocksInTile)
2036 {
2037 lsb = 0;
2038 }
2039 else
2040 {
2041 lsb = Log2(blocksInTile);
2042 }
2043 msb = bankBits - 1 + lsb;
2044
2045 UINT_64 blockInBankpipeWithBankBits = InsertBits(blockInBankpipe, bankDataBits, msb, lsb);
2046
2047 /// NOTE *2 because we are converting to Nibble address in this step
2048 UINT_64 metaAddressInPipe = blockInBankpipeWithBankBits * 2 * metadataBitSize / 8;
2049
2050
2051 ///--------------------------------------------------------------------------------------------
2052 /// Reinsert pipe bits back into the final address
2053 ///--------------------------------------------------------------------------------------------
2054 lsb = pipeInterleaveBits + 1; ///<+1 due to Nibble address now gives interleave bits extra lsb.
2055 msb = pipeBits - 1 + lsb;
2056 UINT_64 metadataAddress = InsertBits(metaAddressInPipe, pipeDataBits, msb, lsb);
2057
2058 return metadataAddress;
2059 }
2060
2061 /**
2062 ****************************************************************************************************
2063 * CiLib::HwlComputeSurfaceAlignmentsMacroTiled
2064 *
2065 * @brief
2066 * Hardware layer function to compute alignment request for macro tile mode
2067 *
2068 ****************************************************************************************************
2069 */
HwlComputeSurfaceAlignmentsMacroTiled(AddrTileMode tileMode,UINT_32 bpp,ADDR_SURFACE_FLAGS flags,UINT_32 mipLevel,UINT_32 numSamples,ADDR_COMPUTE_SURFACE_INFO_OUTPUT * pOut) const2070 VOID CiLib::HwlComputeSurfaceAlignmentsMacroTiled(
2071 AddrTileMode tileMode, ///< [in] tile mode
2072 UINT_32 bpp, ///< [in] bits per pixel
2073 ADDR_SURFACE_FLAGS flags, ///< [in] surface flags
2074 UINT_32 mipLevel, ///< [in] mip level
2075 UINT_32 numSamples, ///< [in] number of samples
2076 ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [in,out] Surface output
2077 ) const
2078 {
2079 // This is to workaround a H/W limitation that DCC doesn't work when pipe config is switched to
2080 // P4. In theory, all asics that have such switching should be patched but we now only know what
2081 // to pad for Fiji.
2082 if ((m_settings.isFiji == TRUE) &&
2083 (flags.dccPipeWorkaround == TRUE) &&
2084 (flags.prt == FALSE) &&
2085 (mipLevel == 0) &&
2086 (tileMode == ADDR_TM_PRT_TILED_THIN1) &&
2087 (pOut->dccUnsupport == TRUE))
2088 {
2089 pOut->pitchAlign = PowTwoAlign(pOut->pitchAlign, 256);
2090 // In case the client still requests DCC usage.
2091 pOut->dccUnsupport = FALSE;
2092 }
2093 }
2094
2095 /**
2096 ****************************************************************************************************
2097 * CiLib::HwlPadDimensions
2098 *
2099 * @brief
2100 * Helper function to pad dimensions
2101 *
2102 ****************************************************************************************************
2103 */
HwlPadDimensions(AddrTileMode tileMode,UINT_32 bpp,ADDR_SURFACE_FLAGS flags,UINT_32 numSamples,ADDR_TILEINFO * pTileInfo,UINT_32 mipLevel,UINT_32 * pPitch,UINT_32 * pPitchAlign,UINT_32 height,UINT_32 heightAlign) const2104 VOID CiLib::HwlPadDimensions(
2105 AddrTileMode tileMode, ///< [in] tile mode
2106 UINT_32 bpp, ///< [in] bits per pixel
2107 ADDR_SURFACE_FLAGS flags, ///< [in] surface flags
2108 UINT_32 numSamples, ///< [in] number of samples
2109 ADDR_TILEINFO* pTileInfo, ///< [in] tile info
2110 UINT_32 mipLevel, ///< [in] mip level
2111 UINT_32* pPitch, ///< [in,out] pitch in pixels
2112 UINT_32* pPitchAlign, ///< [in,out] pitch alignment
2113 UINT_32 height, ///< [in] height in pixels
2114 UINT_32 heightAlign ///< [in] height alignment
2115 ) const
2116 {
2117 if ((SupportDccAndTcCompatibility() == TRUE) &&
2118 (flags.dccCompatible == TRUE) &&
2119 (numSamples > 1) &&
2120 (mipLevel == 0) &&
2121 (IsMacroTiled(tileMode) == TRUE))
2122 {
2123 UINT_32 tileSizePerSample = BITS_TO_BYTES(bpp * MicroTileWidth * MicroTileHeight);
2124 UINT_32 samplesPerSplit = pTileInfo->tileSplitBytes / tileSizePerSample;
2125
2126 if (samplesPerSplit < numSamples)
2127 {
2128 UINT_32 dccFastClearByteAlign = HwlGetPipes(pTileInfo) * m_pipeInterleaveBytes * 256;
2129 UINT_32 bytesPerSplit = BITS_TO_BYTES((*pPitch) * height * bpp * samplesPerSplit);
2130
2131 ADDR_ASSERT(IsPow2(dccFastClearByteAlign));
2132
2133 if (0 != (bytesPerSplit & (dccFastClearByteAlign - 1)))
2134 {
2135 UINT_32 dccFastClearPixelAlign = dccFastClearByteAlign /
2136 BITS_TO_BYTES(bpp) /
2137 samplesPerSplit;
2138 UINT_32 macroTilePixelAlign = (*pPitchAlign) * heightAlign;
2139
2140 if ((dccFastClearPixelAlign >= macroTilePixelAlign) &&
2141 ((dccFastClearPixelAlign % macroTilePixelAlign) == 0))
2142 {
2143 UINT_32 dccFastClearPitchAlignInMacroTile =
2144 dccFastClearPixelAlign / macroTilePixelAlign;
2145 UINT_32 heightInMacroTile = height / heightAlign;
2146
2147 while ((heightInMacroTile > 1) &&
2148 ((heightInMacroTile % 2) == 0) &&
2149 (dccFastClearPitchAlignInMacroTile > 1) &&
2150 ((dccFastClearPitchAlignInMacroTile % 2) == 0))
2151 {
2152 heightInMacroTile >>= 1;
2153 dccFastClearPitchAlignInMacroTile >>= 1;
2154 }
2155
2156 UINT_32 dccFastClearPitchAlignInPixels =
2157 (*pPitchAlign) * dccFastClearPitchAlignInMacroTile;
2158
2159 if (IsPow2(dccFastClearPitchAlignInPixels))
2160 {
2161 *pPitch = PowTwoAlign((*pPitch), dccFastClearPitchAlignInPixels);
2162 }
2163 else
2164 {
2165 *pPitch += (dccFastClearPitchAlignInPixels - 1);
2166 *pPitch /= dccFastClearPitchAlignInPixels;
2167 *pPitch *= dccFastClearPitchAlignInPixels;
2168 }
2169
2170 *pPitchAlign = dccFastClearPitchAlignInPixels;
2171 }
2172 }
2173 }
2174 }
2175 }
2176
2177 /**
2178 ****************************************************************************************************
2179 * CiLib::HwlComputeMaxBaseAlignments
2180 *
2181 * @brief
2182 * Gets maximum alignments
2183 * @return
2184 * maximum alignments
2185 ****************************************************************************************************
2186 */
HwlComputeMaxBaseAlignments() const2187 UINT_32 CiLib::HwlComputeMaxBaseAlignments() const
2188 {
2189 const UINT_32 pipes = HwlGetPipes(&m_tileTable[0].info);
2190
2191 // Initial size is 64 KiB for PRT.
2192 UINT_32 maxBaseAlign = 64 * 1024;
2193
2194 for (UINT_32 i = 0; i < m_noOfMacroEntries; i++)
2195 {
2196 // The maximum tile size is 16 byte-per-pixel and either 8-sample or 8-slice.
2197 UINT_32 tileSize = m_macroTileTable[i].tileSplitBytes;
2198
2199 UINT_32 baseAlign = tileSize * pipes * m_macroTileTable[i].banks *
2200 m_macroTileTable[i].bankWidth * m_macroTileTable[i].bankHeight;
2201
2202 if (baseAlign > maxBaseAlign)
2203 {
2204 maxBaseAlign = baseAlign;
2205 }
2206 }
2207
2208 return maxBaseAlign;
2209 }
2210
2211 /**
2212 ****************************************************************************************************
2213 * CiLib::HwlComputeMaxMetaBaseAlignments
2214 *
2215 * @brief
2216 * Gets maximum alignments for metadata
2217 * @return
2218 * maximum alignments for metadata
2219 ****************************************************************************************************
2220 */
HwlComputeMaxMetaBaseAlignments() const2221 UINT_32 CiLib::HwlComputeMaxMetaBaseAlignments() const
2222 {
2223 UINT_32 maxBank = 1;
2224
2225 for (UINT_32 i = 0; i < m_noOfMacroEntries; i++)
2226 {
2227 if (SupportDccAndTcCompatibility() && IsMacroTiled(m_tileTable[i].mode))
2228 {
2229 maxBank = Max(maxBank, m_macroTileTable[i].banks);
2230 }
2231 }
2232
2233 return SiLib::HwlComputeMaxMetaBaseAlignments() * maxBank;
2234 }
2235
2236 /**
2237 ****************************************************************************************************
2238 * CiLib::DepthStencilTileCfgMatch
2239 *
2240 * @brief
2241 * Try to find a tile index for stencil which makes its tile config parameters matches to depth
2242 * @return
2243 * TRUE if such tile index for stencil can be found
2244 ****************************************************************************************************
2245 */
DepthStencilTileCfgMatch(const ADDR_COMPUTE_SURFACE_INFO_INPUT * pIn,ADDR_COMPUTE_SURFACE_INFO_OUTPUT * pOut) const2246 BOOL_32 CiLib::DepthStencilTileCfgMatch(
2247 const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] input structure
2248 ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [out] output structure
2249 ) const
2250 {
2251 BOOL_32 depthStencil2DTileConfigMatch = FALSE;
2252
2253 for (INT_32 stencilTileIndex = MinDepth2DThinIndex;
2254 stencilTileIndex <= MaxDepth2DThinIndex;
2255 stencilTileIndex++)
2256 {
2257 ADDR_TILEINFO tileInfo = {0};
2258 INT_32 stencilMacroIndex = HwlComputeMacroModeIndex(stencilTileIndex,
2259 pIn->flags,
2260 8,
2261 pIn->numSamples,
2262 &tileInfo);
2263
2264 if (stencilMacroIndex != TileIndexNoMacroIndex)
2265 {
2266 if ((m_macroTileTable[stencilMacroIndex].banks ==
2267 m_macroTileTable[pOut->macroModeIndex].banks) &&
2268 (m_macroTileTable[stencilMacroIndex].bankWidth ==
2269 m_macroTileTable[pOut->macroModeIndex].bankWidth) &&
2270 (m_macroTileTable[stencilMacroIndex].bankHeight ==
2271 m_macroTileTable[pOut->macroModeIndex].bankHeight) &&
2272 (m_macroTileTable[stencilMacroIndex].macroAspectRatio ==
2273 m_macroTileTable[pOut->macroModeIndex].macroAspectRatio) &&
2274 (m_macroTileTable[stencilMacroIndex].pipeConfig ==
2275 m_macroTileTable[pOut->macroModeIndex].pipeConfig))
2276 {
2277 if ((pOut->tcCompatible == FALSE) ||
2278 (tileInfo.tileSplitBytes >= MicroTileWidth * MicroTileHeight * pIn->numSamples))
2279 {
2280 depthStencil2DTileConfigMatch = TRUE;
2281 pOut->stencilTileIdx = stencilTileIndex;
2282 break;
2283 }
2284 }
2285 }
2286 else
2287 {
2288 ADDR_ASSERT_ALWAYS();
2289 }
2290 }
2291
2292 return depthStencil2DTileConfigMatch;
2293 }
2294
2295 /**
2296 ****************************************************************************************************
2297 * CiLib::DepthStencilTileCfgMatch
2298 *
2299 * @brief
2300 * Check if tc compatibility is available
2301 * @return
2302 * If tc compatibility is not available
2303 ****************************************************************************************************
2304 */
CheckTcCompatibility(const ADDR_TILEINFO * pTileInfo,UINT_32 bpp,AddrTileMode tileMode,AddrTileType tileType,const ADDR_COMPUTE_SURFACE_INFO_OUTPUT * pOut) const2305 BOOL_32 CiLib::CheckTcCompatibility(
2306 const ADDR_TILEINFO* pTileInfo, ///< [in] input tile info
2307 UINT_32 bpp, ///< [in] Bits per pixel
2308 AddrTileMode tileMode, ///< [in] input tile mode
2309 AddrTileType tileType, ///< [in] input tile type
2310 const ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [in] output surf info
2311 ) const
2312 {
2313 BOOL_32 tcCompatible = TRUE;
2314
2315 if (IsMacroTiled(tileMode))
2316 {
2317 if (tileType != ADDR_DEPTH_SAMPLE_ORDER)
2318 {
2319 // Turn off tcCompatible for color surface if tileSplit happens. Depth/stencil
2320 // tileSplit case was handled at tileIndex selecting time.
2321 INT_32 tileIndex = pOut->tileIndex;
2322
2323 if ((tileIndex == TileIndexInvalid) && (IsTileInfoAllZero(pTileInfo) == FALSE))
2324 {
2325 tileIndex = HwlPostCheckTileIndex(pTileInfo, tileMode, tileType, tileIndex);
2326 }
2327
2328 if (tileIndex != TileIndexInvalid)
2329 {
2330 UINT_32 thickness = Thickness(tileMode);
2331
2332 ADDR_ASSERT(static_cast<UINT_32>(tileIndex) < TileTableSize);
2333 // Non-depth entries store a split factor
2334 UINT_32 sampleSplit = m_tileTable[tileIndex].info.tileSplitBytes;
2335 UINT_32 tileBytes1x = BITS_TO_BYTES(bpp * MicroTilePixels * thickness);
2336 UINT_32 colorTileSplit = Max(256u, sampleSplit * tileBytes1x);
2337
2338 if (m_rowSize < colorTileSplit)
2339 {
2340 tcCompatible = FALSE;
2341 }
2342 }
2343 }
2344 }
2345 else
2346 {
2347 // Client should not enable tc compatible for linear and 1D tile modes.
2348 tcCompatible = FALSE;
2349 }
2350
2351 return tcCompatible;
2352 }
2353
2354 } // V1
2355 } // Addr
2356