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 ((returnCode == ADDR_OK) &&
177 (pCreateIn->callbacks.allocSysMem != NULL) &&
178 (pCreateIn->callbacks.freeSysMem != NULL))
179 {
180 Client client = {
181 pCreateIn->hClient,
182 pCreateIn->callbacks
183 };
184
185 switch (pCreateIn->chipEngine)
186 {
187 case CIASICIDGFXENGINE_SOUTHERNISLAND:
188 switch (pCreateIn->chipFamily)
189 {
190 case FAMILY_SI:
191 pLib = SiHwlInit(&client);
192 break;
193 case FAMILY_VI:
194 case FAMILY_CZ: // VI based fusion
195 case FAMILY_CI:
196 case FAMILY_KV: // CI based fusion
197 pLib = CiHwlInit(&client);
198 break;
199 default:
200 ADDR_ASSERT_ALWAYS();
201 break;
202 }
203 break;
204 case CIASICIDGFXENGINE_ARCTICISLAND:
205 switch (pCreateIn->chipFamily)
206 {
207 case FAMILY_AI:
208 case FAMILY_RV:
209 pLib = Gfx9HwlInit(&client);
210 break;
211 case FAMILY_NV:
212 case FAMILY_VGH:
213 case FAMILY_RMB:
214 case FAMILY_RPL:
215 case FAMILY_MDN:
216 pLib = Gfx10HwlInit(&client);
217 break;
218 case FAMILY_NV3:
219 case FAMILY_GFX1103:
220 case FAMILY_GFX1150:
221 pLib = Gfx11HwlInit(&client);
222 break;
223 default:
224 ADDR_ASSERT_ALWAYS();
225 break;
226 }
227 break;
228 default:
229 ADDR_ASSERT_ALWAYS();
230 break;
231 }
232 }
233
234 if (pLib != NULL)
235 {
236 BOOL_32 initValid;
237
238 // Pass createFlags to configFlags first since these flags may be overwritten
239 pLib->m_configFlags.noCubeMipSlicesPad = pCreateIn->createFlags.noCubeMipSlicesPad;
240 pLib->m_configFlags.fillSizeFields = pCreateIn->createFlags.fillSizeFields;
241 pLib->m_configFlags.useTileIndex = pCreateIn->createFlags.useTileIndex;
242 pLib->m_configFlags.useCombinedSwizzle = pCreateIn->createFlags.useCombinedSwizzle;
243 pLib->m_configFlags.checkLast2DLevel = pCreateIn->createFlags.checkLast2DLevel;
244 pLib->m_configFlags.useHtileSliceAlign = pCreateIn->createFlags.useHtileSliceAlign;
245 pLib->m_configFlags.allowLargeThickTile = pCreateIn->createFlags.allowLargeThickTile;
246 pLib->m_configFlags.forceDccAndTcCompat = pCreateIn->createFlags.forceDccAndTcCompat;
247 pLib->m_configFlags.nonPower2MemConfig = pCreateIn->createFlags.nonPower2MemConfig;
248 pLib->m_configFlags.enableAltTiling = pCreateIn->createFlags.enableAltTiling;
249 pLib->m_configFlags.disableLinearOpt = FALSE;
250
251 pLib->SetChipFamily(pCreateIn->chipFamily, pCreateIn->chipRevision);
252
253 pLib->SetMinPitchAlignPixels(pCreateIn->minPitchAlignPixels);
254
255 // Global parameters initialized and remaining configFlags bits are set as well
256 initValid = pLib->HwlInitGlobalParams(pCreateIn);
257
258 if (initValid)
259 {
260 pLib->m_pElemLib = ElemLib::Create(pLib);
261 }
262 else
263 {
264 pLib->m_pElemLib = NULL; // Don't go on allocating element lib
265 returnCode = ADDR_INVALIDGBREGVALUES;
266 }
267
268 if (pLib->m_pElemLib == NULL)
269 {
270 delete pLib;
271 pLib = NULL;
272 ADDR_ASSERT_ALWAYS();
273 }
274 else
275 {
276 pLib->m_pElemLib->SetConfigFlags(pLib->m_configFlags);
277 }
278 }
279
280 pCreateOut->hLib = pLib;
281
282 if ((pLib != NULL) &&
283 (returnCode == ADDR_OK))
284 {
285 pCreateOut->numEquations =
286 pLib->HwlGetEquationTableInfo(&pCreateOut->pEquationTable);
287
288 pLib->SetMaxAlignments();
289
290 }
291 else if ((pLib == NULL) &&
292 (returnCode == ADDR_OK))
293 {
294 // Unknown failures, we return the general error code
295 returnCode = ADDR_ERROR;
296 }
297
298 return returnCode;
299 }
300
301 /**
302 ****************************************************************************************************
303 * Lib::SetChipFamily
304 *
305 * @brief
306 * Convert familyID defined in atiid.h to ChipFamily and set m_chipFamily/m_chipRevision
307 * @return
308 * N/A
309 ****************************************************************************************************
310 */
SetChipFamily(UINT_32 uChipFamily,UINT_32 uChipRevision)311 VOID Lib::SetChipFamily(
312 UINT_32 uChipFamily, ///< [in] chip family defined in atiih.h
313 UINT_32 uChipRevision) ///< [in] chip revision defined in "asic_family"_id.h
314 {
315 ChipFamily family = HwlConvertChipFamily(uChipFamily, uChipRevision);
316
317 ADDR_ASSERT(family != ADDR_CHIP_FAMILY_IVLD);
318
319 m_chipFamily = family;
320 m_chipRevision = uChipRevision;
321 }
322
323 /**
324 ****************************************************************************************************
325 * Lib::SetMinPitchAlignPixels
326 *
327 * @brief
328 * Set m_minPitchAlignPixels with input param
329 *
330 * @return
331 * N/A
332 ****************************************************************************************************
333 */
SetMinPitchAlignPixels(UINT_32 minPitchAlignPixels)334 VOID Lib::SetMinPitchAlignPixels(
335 UINT_32 minPitchAlignPixels) ///< [in] minmum pitch alignment in pixels
336 {
337 m_minPitchAlignPixels = (minPitchAlignPixels == 0) ? 1 : minPitchAlignPixels;
338 }
339
340 /**
341 ****************************************************************************************************
342 * Lib::SetMaxAlignments
343 *
344 * @brief
345 * Set max alignments
346 *
347 * @return
348 * N/A
349 ****************************************************************************************************
350 */
SetMaxAlignments()351 VOID Lib::SetMaxAlignments()
352 {
353 m_maxBaseAlign = HwlComputeMaxBaseAlignments();
354 m_maxMetaBaseAlign = HwlComputeMaxMetaBaseAlignments();
355 }
356
357 /**
358 ****************************************************************************************************
359 * Lib::GetLib
360 *
361 * @brief
362 * Get AddrLib pointer
363 *
364 * @return
365 * An AddrLib class pointer
366 ****************************************************************************************************
367 */
GetLib(ADDR_HANDLE hLib)368 Lib* Lib::GetLib(
369 ADDR_HANDLE hLib) ///< [in] handle of ADDR_HANDLE
370 {
371 return static_cast<Addr::Lib*>(hLib);
372 }
373
374 /**
375 ****************************************************************************************************
376 * Lib::GetMaxAlignments
377 *
378 * @brief
379 * Gets maximum alignments for data surface (include FMask)
380 *
381 * @return
382 * ADDR_E_RETURNCODE
383 ****************************************************************************************************
384 */
GetMaxAlignments(ADDR_GET_MAX_ALIGNMENTS_OUTPUT * pOut) const385 ADDR_E_RETURNCODE Lib::GetMaxAlignments(
386 ADDR_GET_MAX_ALIGNMENTS_OUTPUT* pOut ///< [out] output structure
387 ) const
388 {
389 ADDR_E_RETURNCODE returnCode = ADDR_OK;
390
391 if (GetFillSizeFieldsFlags() == TRUE)
392 {
393 if (pOut->size != sizeof(ADDR_GET_MAX_ALIGNMENTS_OUTPUT))
394 {
395 returnCode = ADDR_PARAMSIZEMISMATCH;
396 }
397 }
398
399 if (returnCode == ADDR_OK)
400 {
401 if (m_maxBaseAlign != 0)
402 {
403 pOut->baseAlign = m_maxBaseAlign;
404 }
405 else
406 {
407 returnCode = ADDR_NOTIMPLEMENTED;
408 }
409 }
410
411 return returnCode;
412 }
413
414 /**
415 ****************************************************************************************************
416 * Lib::GetMaxMetaAlignments
417 *
418 * @brief
419 * Gets maximum alignments for metadata (CMask, DCC and HTile)
420 *
421 * @return
422 * ADDR_E_RETURNCODE
423 ****************************************************************************************************
424 */
GetMaxMetaAlignments(ADDR_GET_MAX_ALIGNMENTS_OUTPUT * pOut) const425 ADDR_E_RETURNCODE Lib::GetMaxMetaAlignments(
426 ADDR_GET_MAX_ALIGNMENTS_OUTPUT* pOut ///< [out] output structure
427 ) const
428 {
429 ADDR_E_RETURNCODE returnCode = ADDR_OK;
430
431 if (GetFillSizeFieldsFlags() == TRUE)
432 {
433 if (pOut->size != sizeof(ADDR_GET_MAX_ALIGNMENTS_OUTPUT))
434 {
435 returnCode = ADDR_PARAMSIZEMISMATCH;
436 }
437 }
438
439 if (returnCode == ADDR_OK)
440 {
441 if (m_maxMetaBaseAlign != 0)
442 {
443 pOut->baseAlign = m_maxMetaBaseAlign;
444 }
445 else
446 {
447 returnCode = ADDR_NOTIMPLEMENTED;
448 }
449 }
450
451 return returnCode;
452 }
453
454 /**
455 ****************************************************************************************************
456 * Lib::Bits2Number
457 *
458 * @brief
459 * Cat a array of binary bit to a number
460 *
461 * @return
462 * The number combined with the array of bits
463 ****************************************************************************************************
464 */
Bits2Number(UINT_32 bitNum,...)465 UINT_32 Lib::Bits2Number(
466 UINT_32 bitNum, ///< [in] how many bits
467 ...) ///< [in] varaible bits value starting from MSB
468 {
469 UINT_32 number = 0;
470 UINT_32 i;
471 va_list bits_ptr;
472
473 va_start(bits_ptr, bitNum);
474
475 for(i = 0; i < bitNum; i++)
476 {
477 number |= va_arg(bits_ptr, UINT_32);
478 number <<= 1;
479 }
480
481 number >>= 1;
482
483 va_end(bits_ptr);
484
485 return number;
486 }
487
488
489 ////////////////////////////////////////////////////////////////////////////////////////////////////
490 // Element lib
491 ////////////////////////////////////////////////////////////////////////////////////////////////////
492
493
494 /**
495 ****************************************************************************************************
496 * Lib::Flt32ToColorPixel
497 *
498 * @brief
499 * Convert a FLT_32 value to a depth/stencil pixel value
500 * @return
501 * ADDR_E_RETURNCODE
502 ****************************************************************************************************
503 */
Flt32ToDepthPixel(const ELEM_FLT32TODEPTHPIXEL_INPUT * pIn,ELEM_FLT32TODEPTHPIXEL_OUTPUT * pOut) const504 ADDR_E_RETURNCODE Lib::Flt32ToDepthPixel(
505 const ELEM_FLT32TODEPTHPIXEL_INPUT* pIn,
506 ELEM_FLT32TODEPTHPIXEL_OUTPUT* pOut) const
507 {
508 ADDR_E_RETURNCODE returnCode = ADDR_OK;
509
510 if (GetFillSizeFieldsFlags() == TRUE)
511 {
512 if ((pIn->size != sizeof(ELEM_FLT32TODEPTHPIXEL_INPUT)) ||
513 (pOut->size != sizeof(ELEM_FLT32TODEPTHPIXEL_OUTPUT)))
514 {
515 returnCode = ADDR_PARAMSIZEMISMATCH;
516 }
517 }
518
519 if (returnCode == ADDR_OK)
520 {
521 GetElemLib()->Flt32ToDepthPixel(pIn->format, pIn->comps, pOut->pPixel);
522
523 UINT_32 depthBase = 0;
524 UINT_32 stencilBase = 0;
525 UINT_32 depthBits = 0;
526 UINT_32 stencilBits = 0;
527
528 switch (pIn->format)
529 {
530 case ADDR_DEPTH_16:
531 depthBits = 16;
532 break;
533 case ADDR_DEPTH_X8_24:
534 case ADDR_DEPTH_8_24:
535 case ADDR_DEPTH_X8_24_FLOAT:
536 case ADDR_DEPTH_8_24_FLOAT:
537 depthBase = 8;
538 depthBits = 24;
539 stencilBits = 8;
540 break;
541 case ADDR_DEPTH_32_FLOAT:
542 depthBits = 32;
543 break;
544 case ADDR_DEPTH_X24_8_32_FLOAT:
545 depthBase = 8;
546 depthBits = 32;
547 stencilBits = 8;
548 break;
549 default:
550 break;
551 }
552
553 // Overwrite base since R800 has no "tileBase"
554 if (GetElemLib()->IsDepthStencilTilePlanar() == FALSE)
555 {
556 depthBase = 0;
557 stencilBase = 0;
558 }
559
560 depthBase *= 64;
561 stencilBase *= 64;
562
563 pOut->stencilBase = stencilBase;
564 pOut->depthBase = depthBase;
565 pOut->depthBits = depthBits;
566 pOut->stencilBits = stencilBits;
567 }
568
569 return returnCode;
570 }
571
572 /**
573 ****************************************************************************************************
574 * Lib::Flt32ToColorPixel
575 *
576 * @brief
577 * Convert a FLT_32 value to a red/green/blue/alpha pixel value
578 * @return
579 * ADDR_E_RETURNCODE
580 ****************************************************************************************************
581 */
Flt32ToColorPixel(const ELEM_FLT32TOCOLORPIXEL_INPUT * pIn,ELEM_FLT32TOCOLORPIXEL_OUTPUT * pOut) const582 ADDR_E_RETURNCODE Lib::Flt32ToColorPixel(
583 const ELEM_FLT32TOCOLORPIXEL_INPUT* pIn,
584 ELEM_FLT32TOCOLORPIXEL_OUTPUT* pOut) const
585 {
586 ADDR_E_RETURNCODE returnCode = ADDR_OK;
587
588 if (GetFillSizeFieldsFlags() == TRUE)
589 {
590 if ((pIn->size != sizeof(ELEM_FLT32TOCOLORPIXEL_INPUT)) ||
591 (pOut->size != sizeof(ELEM_FLT32TOCOLORPIXEL_OUTPUT)))
592 {
593 returnCode = ADDR_PARAMSIZEMISMATCH;
594 }
595 }
596
597 if (returnCode == ADDR_OK)
598 {
599 GetElemLib()->Flt32ToColorPixel(pIn->format,
600 pIn->surfNum,
601 pIn->surfSwap,
602 pIn->comps,
603 pOut->pPixel);
604 }
605
606 return returnCode;
607 }
608
609
610 /**
611 ****************************************************************************************************
612 * Lib::GetExportNorm
613 *
614 * @brief
615 * Check one format can be EXPORT_NUM
616 * @return
617 * TRUE if EXPORT_NORM can be used
618 ****************************************************************************************************
619 */
GetExportNorm(const ELEM_GETEXPORTNORM_INPUT * pIn) const620 BOOL_32 Lib::GetExportNorm(
621 const ELEM_GETEXPORTNORM_INPUT* pIn) const
622 {
623 ADDR_E_RETURNCODE returnCode = ADDR_OK;
624
625 BOOL_32 enabled = FALSE;
626
627 if (GetFillSizeFieldsFlags() == TRUE)
628 {
629 if (pIn->size != sizeof(ELEM_GETEXPORTNORM_INPUT))
630 {
631 returnCode = ADDR_PARAMSIZEMISMATCH;
632 }
633 }
634
635 if (returnCode == ADDR_OK)
636 {
637 enabled = GetElemLib()->PixGetExportNorm(pIn->format, pIn->num, pIn->swap);
638 }
639
640 return enabled;
641 }
642
643 /**
644 ****************************************************************************************************
645 * Lib::GetBpe
646 *
647 * @brief
648 * Get bits-per-element for specified format
649 * @return
650 * bits-per-element of specified format
651 ****************************************************************************************************
652 */
GetBpe(AddrFormat format) const653 UINT_32 Lib::GetBpe(AddrFormat format) const
654 {
655 return GetElemLib()->GetBitsPerPixel(format);
656 }
657
658 } // Addr
659