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