xref: /aosp_15_r20/external/mesa3d/src/amd/addrlib/src/core/addrlib.cpp (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2 ************************************************************************************************************************
3 *
4 *  Copyright (C) 2007-2022 Advanced Micro Devices, Inc.  All rights reserved.
5 *  SPDX-License-Identifier: MIT
6 *
7 ***********************************************************************************************************************/
8 
9 /**
10 ****************************************************************************************************
11 * @file  addrlib.cpp
12 * @brief Contains the implementation for the Addr::Lib class.
13 ****************************************************************************************************
14 */
15 
16 #include "addrinterface.h"
17 #include "addrlib.h"
18 #include "addrcommon.h"
19 
20 #if defined(__APPLE__)
21 
div64_32(UINT_64 n,UINT_32 base)22 UINT_32 div64_32(UINT_64 n, UINT_32 base)
23 {
24     UINT_64 rem = n;
25     UINT_64 b = base;
26     UINT_64 res, d = 1;
27     UINT_32 high = rem >> 32;
28 
29     res = 0;
30     if (high >= base)
31     {
32         high /= base;
33         res = (UINT_64) high << 32;
34         rem -= (UINT_64) (high * base) << 32;
35     }
36 
37     while (((INT_64)b > 0) && (b < rem))
38     {
39         b = b + b;
40         d = d + d;
41     }
42 
43     do
44     {
45         if (rem >= b)
46         {
47             rem -= b;
48             res += d;
49         }
50         b >>= 1;
51         d >>= 1;
52     } while (d);
53 
54     n = res;
55     return rem;
56 }
57 
58 extern "C"
__umoddi3(UINT_64 n,UINT_32 base)59 UINT_32 __umoddi3(UINT_64 n, UINT_32 base)
60 {
61     return div64_32(n, base);
62 }
63 
64 #endif // __APPLE__
65 
66 namespace Addr
67 {
68 
69 ////////////////////////////////////////////////////////////////////////////////////////////////////
70 //                               Constructor/Destructor
71 ////////////////////////////////////////////////////////////////////////////////////////////////////
72 
73 /**
74 ****************************************************************************************************
75 *   Lib::Lib
76 *
77 *   @brief
78 *       Constructor for the AddrLib class
79 *
80 ****************************************************************************************************
81 */
Lib()82 Lib::Lib() :
83     m_chipFamily(ADDR_CHIP_FAMILY_IVLD),
84     m_chipRevision(0),
85     m_version(ADDRLIB_VERSION),
86     m_pipes(0),
87     m_banks(0),
88     m_pipeInterleaveBytes(0),
89     m_rowSize(0),
90     m_minPitchAlignPixels(1),
91     m_maxSamples(8),
92     m_maxBaseAlign(0),
93     m_maxMetaBaseAlign(0),
94     m_pElemLib(NULL)
95 {
96     m_configFlags.value = 0;
97 }
98 
99 /**
100 ****************************************************************************************************
101 *   Lib::Lib
102 *
103 *   @brief
104 *       Constructor for the AddrLib class with hClient as parameter
105 *
106 ****************************************************************************************************
107 */
Lib(const Client * pClient)108 Lib::Lib(const Client* pClient) :
109     Object(pClient),
110     m_chipFamily(ADDR_CHIP_FAMILY_IVLD),
111     m_chipRevision(0),
112     m_version(ADDRLIB_VERSION),
113     m_pipes(0),
114     m_banks(0),
115     m_pipeInterleaveBytes(0),
116     m_rowSize(0),
117     m_minPitchAlignPixels(1),
118     m_maxSamples(8),
119     m_maxBaseAlign(0),
120     m_maxMetaBaseAlign(0),
121     m_pElemLib(NULL)
122 {
123     m_configFlags.value = 0;
124 }
125 
126 /**
127 ****************************************************************************************************
128 *   Lib::~AddrLib
129 *
130 *   @brief
131 *       Destructor for the AddrLib class
132 *
133 ****************************************************************************************************
134 */
~Lib()135 Lib::~Lib()
136 {
137     if (m_pElemLib)
138     {
139         delete m_pElemLib;
140         m_pElemLib = NULL;
141     }
142 }
143 
144 
145 ////////////////////////////////////////////////////////////////////////////////////////////////////
146 //                               Initialization/Helper
147 ////////////////////////////////////////////////////////////////////////////////////////////////////
148 
149 /**
150 ****************************************************************************************************
151 *   Lib::Create
152 *
153 *   @brief
154 *       Creates and initializes AddrLib object.
155 *
156 *   @return
157 *       ADDR_E_RETURNCODE
158 ****************************************************************************************************
159 */
Create(const ADDR_CREATE_INPUT * pCreateIn,ADDR_CREATE_OUTPUT * pCreateOut)160 ADDR_E_RETURNCODE Lib::Create(
161     const ADDR_CREATE_INPUT* pCreateIn,     ///< [in] pointer to ADDR_CREATE_INPUT
162     ADDR_CREATE_OUTPUT*      pCreateOut)    ///< [out] pointer to ADDR_CREATE_OUTPUT
163 {
164     Lib* pLib = NULL;
165     ADDR_E_RETURNCODE returnCode = ADDR_OK;
166 
167     if (pCreateIn->createFlags.fillSizeFields == TRUE)
168     {
169         if ((pCreateIn->size != sizeof(ADDR_CREATE_INPUT)) ||
170             (pCreateOut->size != sizeof(ADDR_CREATE_OUTPUT)))
171         {
172             returnCode = ADDR_PARAMSIZEMISMATCH;
173         }
174     }
175 
176 #if DEBUG
177     ApplyDebugPrinters(pCreateIn->callbacks.debugPrint, pCreateIn->hClient);
178 #endif
179 
180     if ((returnCode == ADDR_OK)                    &&
181         (pCreateIn->callbacks.allocSysMem != NULL) &&
182         (pCreateIn->callbacks.freeSysMem != NULL))
183     {
184         Client client = {
185             pCreateIn->hClient,
186             pCreateIn->callbacks
187         };
188 
189         switch (pCreateIn->chipEngine)
190         {
191             case CIASICIDGFXENGINE_SOUTHERNISLAND:
192                 switch (pCreateIn->chipFamily)
193                 {
194                     case FAMILY_SI:
195                         pLib = SiHwlInit(&client);
196                         break;
197                     case FAMILY_CI:
198                     case FAMILY_KV: // CI based fusion
199                     case FAMILY_VI:
200                     case FAMILY_CZ: // VI based fusion
201                         pLib = CiHwlInit(&client);
202                         break;
203                     default:
204                         ADDR_ASSERT_ALWAYS();
205                         break;
206                 }
207                 break;
208             case CIASICIDGFXENGINE_ARCTICISLAND:
209                 switch (pCreateIn->chipFamily)
210                 {
211                     case FAMILY_AI:
212                     case FAMILY_RV:
213                         pLib = Gfx9HwlInit(&client);
214                         break;
215                     case FAMILY_NV:
216                     case FAMILY_VGH:
217                     case FAMILY_RMB:
218                     case FAMILY_RPL:
219                     case FAMILY_MDN:
220                         pLib = Gfx10HwlInit(&client);
221                         break;
222                     case FAMILY_NV3:
223                     case FAMILY_GFX1150:
224                     case FAMILY_GFX1103:
225                         pLib = Gfx11HwlInit(&client);
226                         break;
227                     case FAMILY_GFX12:
228                         pLib = Gfx12HwlInit(&client);
229                         break;
230                     default:
231                         ADDR_ASSERT_ALWAYS();
232                         break;
233                 }
234                 break;
235             default:
236                 ADDR_ASSERT_ALWAYS();
237                 break;
238         }
239     }
240 
241     if(pLib == NULL)
242     {
243         returnCode = ADDR_OUTOFMEMORY;
244     }
245     if (pLib != NULL)
246     {
247         BOOL_32 initValid;
248 
249         // Pass createFlags to configFlags first since these flags may be overwritten
250         pLib->m_configFlags.noCubeMipSlicesPad  = pCreateIn->createFlags.noCubeMipSlicesPad;
251         pLib->m_configFlags.fillSizeFields      = pCreateIn->createFlags.fillSizeFields;
252         pLib->m_configFlags.useTileIndex        = pCreateIn->createFlags.useTileIndex;
253         pLib->m_configFlags.useCombinedSwizzle  = pCreateIn->createFlags.useCombinedSwizzle;
254         pLib->m_configFlags.checkLast2DLevel    = pCreateIn->createFlags.checkLast2DLevel;
255         pLib->m_configFlags.useHtileSliceAlign  = pCreateIn->createFlags.useHtileSliceAlign;
256         pLib->m_configFlags.allowLargeThickTile = pCreateIn->createFlags.allowLargeThickTile;
257         pLib->m_configFlags.forceDccAndTcCompat = pCreateIn->createFlags.forceDccAndTcCompat;
258         pLib->m_configFlags.nonPower2MemConfig  = pCreateIn->createFlags.nonPower2MemConfig;
259         pLib->m_configFlags.enableAltTiling     = pCreateIn->createFlags.enableAltTiling;
260         pLib->m_configFlags.disableLinearOpt    = FALSE;
261 
262         pLib->SetChipFamily(pCreateIn->chipFamily, pCreateIn->chipRevision);
263 
264         pLib->SetMinPitchAlignPixels(pCreateIn->minPitchAlignPixels);
265 
266         // Global parameters initialized and remaining configFlags bits are set as well
267         initValid = pLib->HwlInitGlobalParams(pCreateIn);
268 
269         if (initValid)
270         {
271             pLib->m_pElemLib = ElemLib::Create(pLib);
272         }
273         else
274         {
275             pLib->m_pElemLib = NULL; // Don't go on allocating element lib
276             returnCode = ADDR_INVALIDGBREGVALUES;
277         }
278 
279         if (pLib->m_pElemLib == NULL)
280         {
281             delete pLib;
282             pLib = NULL;
283             returnCode = ADDR_OUTOFMEMORY;
284             ADDR_ASSERT_ALWAYS();
285         }
286         else
287         {
288             pLib->m_pElemLib->SetConfigFlags(pLib->m_configFlags);
289         }
290     }
291 
292     pCreateOut->hLib = pLib;
293 
294     if ((pLib != NULL) &&
295         (returnCode == ADDR_OK))
296     {
297         pCreateOut->numEquations =
298             pLib->HwlGetEquationTableInfo(&pCreateOut->pEquationTable);
299 
300         pLib->SetMaxAlignments();
301 
302     }
303 
304     return returnCode;
305 }
306 
307 /**
308 ****************************************************************************************************
309 *   Lib::SetChipFamily
310 *
311 *   @brief
312 *       Convert familyID defined in atiid.h to ChipFamily and set m_chipFamily/m_chipRevision
313 *   @return
314 *      N/A
315 ****************************************************************************************************
316 */
SetChipFamily(UINT_32 uChipFamily,UINT_32 uChipRevision)317 VOID Lib::SetChipFamily(
318     UINT_32 uChipFamily,        ///< [in] chip family defined in atiih.h
319     UINT_32 uChipRevision)      ///< [in] chip revision defined in "asic_family"_id.h
320 {
321     ChipFamily family = HwlConvertChipFamily(uChipFamily, uChipRevision);
322 
323     ADDR_ASSERT(family != ADDR_CHIP_FAMILY_IVLD);
324 
325     m_chipFamily   = family;
326     m_chipRevision = uChipRevision;
327 }
328 
329 /**
330 ****************************************************************************************************
331 *   Lib::SetMinPitchAlignPixels
332 *
333 *   @brief
334 *       Set m_minPitchAlignPixels with input param
335 *
336 *   @return
337 *      N/A
338 ****************************************************************************************************
339 */
SetMinPitchAlignPixels(UINT_32 minPitchAlignPixels)340 VOID Lib::SetMinPitchAlignPixels(
341     UINT_32 minPitchAlignPixels)    ///< [in] minmum pitch alignment in pixels
342 {
343     m_minPitchAlignPixels = (minPitchAlignPixels == 0) ? 1 : minPitchAlignPixels;
344 }
345 
346 /**
347 ****************************************************************************************************
348 *   Lib::SetMaxAlignments
349 *
350 *   @brief
351 *       Set max alignments
352 *
353 *   @return
354 *      N/A
355 ****************************************************************************************************
356 */
SetMaxAlignments()357 VOID Lib::SetMaxAlignments()
358 {
359     m_maxBaseAlign     = HwlComputeMaxBaseAlignments();
360     m_maxMetaBaseAlign = HwlComputeMaxMetaBaseAlignments();
361 }
362 
363 /**
364 ****************************************************************************************************
365 *   Lib::GetLib
366 *
367 *   @brief
368 *       Get AddrLib pointer
369 *
370 *   @return
371 *      An AddrLib class pointer
372 ****************************************************************************************************
373 */
GetLib(ADDR_HANDLE hLib)374 Lib* Lib::GetLib(
375     ADDR_HANDLE hLib)   ///< [in] handle of ADDR_HANDLE
376 {
377     Lib* pLib = static_cast<Addr::Lib*>(hLib);
378 #if DEBUG
379     if (pLib != NULL)
380     {
381         pLib->SetDebugPrinters();
382     }
383 #endif
384     return pLib;
385 }
386 
387 /**
388 ****************************************************************************************************
389 *   Lib::GetMaxAlignments
390 *
391 *   @brief
392 *       Gets maximum alignments for data surface (include FMask)
393 *
394 *   @return
395 *       ADDR_E_RETURNCODE
396 ****************************************************************************************************
397 */
GetMaxAlignments(ADDR_GET_MAX_ALIGNMENTS_OUTPUT * pOut) const398 ADDR_E_RETURNCODE Lib::GetMaxAlignments(
399     ADDR_GET_MAX_ALIGNMENTS_OUTPUT* pOut    ///< [out] output structure
400     ) const
401 {
402     ADDR_E_RETURNCODE returnCode = ADDR_OK;
403 
404     if (GetFillSizeFieldsFlags() == TRUE)
405     {
406         if (pOut->size != sizeof(ADDR_GET_MAX_ALIGNMENTS_OUTPUT))
407         {
408             returnCode = ADDR_PARAMSIZEMISMATCH;
409         }
410     }
411 
412     if (returnCode == ADDR_OK)
413     {
414         if (m_maxBaseAlign != 0)
415         {
416             pOut->baseAlign = m_maxBaseAlign;
417         }
418         else
419         {
420             returnCode = ADDR_NOTIMPLEMENTED;
421         }
422     }
423 
424     return returnCode;
425 }
426 
427 /**
428 ****************************************************************************************************
429 *   Lib::GetMaxMetaAlignments
430 *
431 *   @brief
432 *       Gets maximum alignments for metadata (CMask, DCC and HTile)
433 *
434 *   @return
435 *       ADDR_E_RETURNCODE
436 ****************************************************************************************************
437 */
GetMaxMetaAlignments(ADDR_GET_MAX_ALIGNMENTS_OUTPUT * pOut) const438 ADDR_E_RETURNCODE Lib::GetMaxMetaAlignments(
439     ADDR_GET_MAX_ALIGNMENTS_OUTPUT* pOut    ///< [out] output structure
440     ) const
441 {
442     ADDR_E_RETURNCODE returnCode = ADDR_OK;
443 
444     if (GetFillSizeFieldsFlags() == TRUE)
445     {
446         if (pOut->size != sizeof(ADDR_GET_MAX_ALIGNMENTS_OUTPUT))
447         {
448             returnCode = ADDR_PARAMSIZEMISMATCH;
449         }
450     }
451 
452     if (returnCode == ADDR_OK)
453     {
454         if (m_maxMetaBaseAlign != 0)
455         {
456             pOut->baseAlign = m_maxMetaBaseAlign;
457         }
458         else
459         {
460             returnCode = ADDR_NOTIMPLEMENTED;
461         }
462     }
463 
464     return returnCode;
465 }
466 
467 /**
468 ****************************************************************************************************
469 *   Lib::Bits2Number
470 *
471 *   @brief
472 *       Cat a array of binary bit to a number
473 *
474 *   @return
475 *       The number combined with the array of bits
476 ****************************************************************************************************
477 */
Bits2Number(UINT_32 bitNum,...)478 UINT_32 Lib::Bits2Number(
479     UINT_32 bitNum,     ///< [in] how many bits
480     ...)                ///< [in] varaible bits value starting from MSB
481 {
482     UINT_32 number = 0;
483     UINT_32 i;
484     va_list bits_ptr;
485 
486     va_start(bits_ptr, bitNum);
487 
488     for(i = 0; i < bitNum; i++)
489     {
490         number |= va_arg(bits_ptr, UINT_32);
491         number <<= 1;
492     }
493 
494     number >>= 1;
495 
496     va_end(bits_ptr);
497 
498     return number;
499 }
500 
501 
502 ////////////////////////////////////////////////////////////////////////////////////////////////////
503 //                               Element lib
504 ////////////////////////////////////////////////////////////////////////////////////////////////////
505 
506 
507 /**
508 ****************************************************************************************************
509 *   Lib::Flt32ToColorPixel
510 *
511 *   @brief
512 *       Convert a FLT_32 value to a depth/stencil pixel value
513 *   @return
514 *       ADDR_E_RETURNCODE
515 ****************************************************************************************************
516 */
Flt32ToDepthPixel(const ELEM_FLT32TODEPTHPIXEL_INPUT * pIn,ELEM_FLT32TODEPTHPIXEL_OUTPUT * pOut) const517 ADDR_E_RETURNCODE Lib::Flt32ToDepthPixel(
518     const ELEM_FLT32TODEPTHPIXEL_INPUT* pIn,
519     ELEM_FLT32TODEPTHPIXEL_OUTPUT* pOut) const
520 {
521     ADDR_E_RETURNCODE returnCode = ADDR_OK;
522 
523     if (GetFillSizeFieldsFlags() == TRUE)
524     {
525         if ((pIn->size != sizeof(ELEM_FLT32TODEPTHPIXEL_INPUT)) ||
526             (pOut->size != sizeof(ELEM_FLT32TODEPTHPIXEL_OUTPUT)))
527         {
528             returnCode = ADDR_PARAMSIZEMISMATCH;
529         }
530     }
531 
532     if (returnCode == ADDR_OK)
533     {
534         GetElemLib()->Flt32ToDepthPixel(pIn->format, pIn->comps, pOut->pPixel);
535 
536         UINT_32 depthBase = 0;
537         UINT_32 stencilBase = 0;
538         UINT_32 depthBits = 0;
539         UINT_32 stencilBits = 0;
540 
541         switch (pIn->format)
542         {
543             case ADDR_DEPTH_16:
544                 depthBits = 16;
545                 break;
546             case ADDR_DEPTH_X8_24:
547             case ADDR_DEPTH_8_24:
548             case ADDR_DEPTH_X8_24_FLOAT:
549             case ADDR_DEPTH_8_24_FLOAT:
550                 depthBase = 8;
551                 depthBits = 24;
552                 stencilBits = 8;
553                 break;
554             case ADDR_DEPTH_32_FLOAT:
555                 depthBits = 32;
556                 break;
557             case ADDR_DEPTH_X24_8_32_FLOAT:
558                 depthBase = 8;
559                 depthBits = 32;
560                 stencilBits = 8;
561                 break;
562             default:
563                 break;
564         }
565 
566         // Overwrite base since R800 has no "tileBase"
567         if (GetElemLib()->IsDepthStencilTilePlanar() == FALSE)
568         {
569             depthBase = 0;
570             stencilBase = 0;
571         }
572 
573         depthBase *= 64;
574         stencilBase *= 64;
575 
576         pOut->stencilBase = stencilBase;
577         pOut->depthBase = depthBase;
578         pOut->depthBits = depthBits;
579         pOut->stencilBits = stencilBits;
580     }
581 
582     return returnCode;
583 }
584 
585 /**
586 ****************************************************************************************************
587 *   Lib::Flt32ToColorPixel
588 *
589 *   @brief
590 *       Convert a FLT_32 value to a red/green/blue/alpha pixel value
591 *   @return
592 *       ADDR_E_RETURNCODE
593 ****************************************************************************************************
594 */
Flt32ToColorPixel(const ELEM_FLT32TOCOLORPIXEL_INPUT * pIn,ELEM_FLT32TOCOLORPIXEL_OUTPUT * pOut) const595 ADDR_E_RETURNCODE Lib::Flt32ToColorPixel(
596     const ELEM_FLT32TOCOLORPIXEL_INPUT* pIn,
597     ELEM_FLT32TOCOLORPIXEL_OUTPUT* pOut) const
598 {
599     ADDR_E_RETURNCODE returnCode = ADDR_OK;
600 
601     if (GetFillSizeFieldsFlags() == TRUE)
602     {
603         if ((pIn->size != sizeof(ELEM_FLT32TOCOLORPIXEL_INPUT)) ||
604             (pOut->size != sizeof(ELEM_FLT32TOCOLORPIXEL_OUTPUT)))
605         {
606             returnCode = ADDR_PARAMSIZEMISMATCH;
607         }
608     }
609 
610     if (returnCode == ADDR_OK)
611     {
612         GetElemLib()->Flt32ToColorPixel(pIn->format,
613                                         pIn->surfNum,
614                                         pIn->surfSwap,
615                                         pIn->comps,
616                                         pOut->pPixel);
617     }
618 
619     return returnCode;
620 }
621 
622 
623 /**
624 ****************************************************************************************************
625 *   Lib::GetExportNorm
626 *
627 *   @brief
628 *       Check one format can be EXPORT_NUM
629 *   @return
630 *       TRUE if EXPORT_NORM can be used
631 ****************************************************************************************************
632 */
GetExportNorm(const ELEM_GETEXPORTNORM_INPUT * pIn) const633 BOOL_32 Lib::GetExportNorm(
634     const ELEM_GETEXPORTNORM_INPUT* pIn) const
635 {
636     ADDR_E_RETURNCODE returnCode = ADDR_OK;
637 
638     BOOL_32 enabled = FALSE;
639 
640     if (GetFillSizeFieldsFlags() == TRUE)
641     {
642         if (pIn->size != sizeof(ELEM_GETEXPORTNORM_INPUT))
643         {
644             returnCode = ADDR_PARAMSIZEMISMATCH;
645         }
646     }
647 
648     if (returnCode == ADDR_OK)
649     {
650         enabled = GetElemLib()->PixGetExportNorm(pIn->format, pIn->num, pIn->swap);
651     }
652 
653     return enabled;
654 }
655 
656 /**
657 ****************************************************************************************************
658 *   Lib::GetBpe
659 *
660 *   @brief
661 *       Get bits-per-element for specified format
662 *   @return
663 *       bits-per-element of specified format
664 ****************************************************************************************************
665 */
GetBpe(AddrFormat format) const666 UINT_32 Lib::GetBpe(AddrFormat format) const
667 {
668     return GetElemLib()->GetBitsPerPixel(format);
669 }
670 
671 } // Addr
672