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