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