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_pElemLib(NULL)
111 {
112 m_configFlags.value = 0;
113 }
114
115 /**
116 ****************************************************************************************************
117 * Lib::Lib
118 *
119 * @brief
120 * Constructor for the AddrLib class with hClient as parameter
121 *
122 ****************************************************************************************************
123 */
Lib(const Client * pClient)124 Lib::Lib(const Client* pClient) :
125 Object(pClient),
126 m_chipFamily(ADDR_CHIP_FAMILY_IVLD),
127 m_chipRevision(0),
128 m_version(ADDRLIB_VERSION),
129 m_pipes(0),
130 m_banks(0),
131 m_pipeInterleaveBytes(0),
132 m_rowSize(0),
133 m_minPitchAlignPixels(1),
134 m_maxSamples(8),
135 m_pElemLib(NULL)
136 {
137 m_configFlags.value = 0;
138 }
139
140 /**
141 ****************************************************************************************************
142 * Lib::~AddrLib
143 *
144 * @brief
145 * Destructor for the AddrLib class
146 *
147 ****************************************************************************************************
148 */
~Lib()149 Lib::~Lib()
150 {
151 if (m_pElemLib)
152 {
153 delete m_pElemLib;
154 m_pElemLib = NULL;
155 }
156 }
157
158
159 ////////////////////////////////////////////////////////////////////////////////////////////////////
160 // Initialization/Helper
161 ////////////////////////////////////////////////////////////////////////////////////////////////////
162
163 /**
164 ****************************************************************************************************
165 * Lib::Create
166 *
167 * @brief
168 * Creates and initializes AddrLib object.
169 *
170 * @return
171 * ADDR_E_RETURNCODE
172 ****************************************************************************************************
173 */
Create(const ADDR_CREATE_INPUT * pCreateIn,ADDR_CREATE_OUTPUT * pCreateOut)174 ADDR_E_RETURNCODE Lib::Create(
175 const ADDR_CREATE_INPUT* pCreateIn, ///< [in] pointer to ADDR_CREATE_INPUT
176 ADDR_CREATE_OUTPUT* pCreateOut) ///< [out] pointer to ADDR_CREATE_OUTPUT
177 {
178 Lib* pLib = NULL;
179 ADDR_E_RETURNCODE returnCode = ADDR_OK;
180
181 if (pCreateIn->createFlags.fillSizeFields == TRUE)
182 {
183 if ((pCreateIn->size != sizeof(ADDR_CREATE_INPUT)) ||
184 (pCreateOut->size != sizeof(ADDR_CREATE_OUTPUT)))
185 {
186 returnCode = ADDR_PARAMSIZEMISMATCH;
187 }
188 }
189
190 if ((returnCode == ADDR_OK) &&
191 (pCreateIn->callbacks.allocSysMem != NULL) &&
192 (pCreateIn->callbacks.freeSysMem != NULL))
193 {
194 Client client = {
195 pCreateIn->hClient,
196 pCreateIn->callbacks
197 };
198
199 switch (pCreateIn->chipEngine)
200 {
201 case CIASICIDGFXENGINE_SOUTHERNISLAND:
202 switch (pCreateIn->chipFamily)
203 {
204 case FAMILY_SI:
205 pLib = SiHwlInit(&client);
206 break;
207 case FAMILY_VI:
208 case FAMILY_CZ:
209 case FAMILY_CI:
210 case FAMILY_KV: // CI based fusion
211 pLib = CiHwlInit(&client);
212 break;
213 default:
214 ADDR_ASSERT_ALWAYS();
215 break;
216 }
217 break;
218 case CIASICIDGFXENGINE_ARCTICISLAND:
219 switch (pCreateIn->chipFamily)
220 {
221 case FAMILY_AI:
222 case FAMILY_RV:
223 pLib = Gfx9HwlInit(&client);
224 break;
225 case FAMILY_NV:
226 case FAMILY_VGH:
227 pLib = Gfx10HwlInit(&client);
228 break;
229 default:
230 ADDR_ASSERT_ALWAYS();
231 break;
232 }
233 break;
234 default:
235 ADDR_ASSERT_ALWAYS();
236 break;
237 }
238 }
239
240 if (pLib != NULL)
241 {
242 BOOL_32 initValid;
243
244 // Pass createFlags to configFlags first since these flags may be overwritten
245 pLib->m_configFlags.noCubeMipSlicesPad = pCreateIn->createFlags.noCubeMipSlicesPad;
246 pLib->m_configFlags.fillSizeFields = pCreateIn->createFlags.fillSizeFields;
247 pLib->m_configFlags.useTileIndex = pCreateIn->createFlags.useTileIndex;
248 pLib->m_configFlags.useCombinedSwizzle = pCreateIn->createFlags.useCombinedSwizzle;
249 pLib->m_configFlags.checkLast2DLevel = pCreateIn->createFlags.checkLast2DLevel;
250 pLib->m_configFlags.useHtileSliceAlign = pCreateIn->createFlags.useHtileSliceAlign;
251 pLib->m_configFlags.allowLargeThickTile = pCreateIn->createFlags.allowLargeThickTile;
252 pLib->m_configFlags.forceDccAndTcCompat = pCreateIn->createFlags.forceDccAndTcCompat;
253 pLib->m_configFlags.nonPower2MemConfig = pCreateIn->createFlags.nonPower2MemConfig;
254 pLib->m_configFlags.enableAltTiling = pCreateIn->createFlags.enableAltTiling;
255 pLib->m_configFlags.disableLinearOpt = FALSE;
256
257 pLib->SetChipFamily(pCreateIn->chipFamily, pCreateIn->chipRevision);
258
259 pLib->SetMinPitchAlignPixels(pCreateIn->minPitchAlignPixels);
260
261 // Global parameters initialized and remaining configFlags bits are set as well
262 initValid = pLib->HwlInitGlobalParams(pCreateIn);
263
264 if (initValid)
265 {
266 pLib->m_pElemLib = ElemLib::Create(pLib);
267 }
268 else
269 {
270 pLib->m_pElemLib = NULL; // Don't go on allocating element lib
271 returnCode = ADDR_INVALIDGBREGVALUES;
272 }
273
274 if (pLib->m_pElemLib == NULL)
275 {
276 delete pLib;
277 pLib = NULL;
278 ADDR_ASSERT_ALWAYS();
279 }
280 else
281 {
282 pLib->m_pElemLib->SetConfigFlags(pLib->m_configFlags);
283 }
284 }
285
286 pCreateOut->hLib = pLib;
287
288 if ((pLib != NULL) &&
289 (returnCode == ADDR_OK))
290 {
291 pCreateOut->numEquations =
292 pLib->HwlGetEquationTableInfo(&pCreateOut->pEquationTable);
293
294 pLib->SetMaxAlignments();
295
296 }
297 else if ((pLib == NULL) &&
298 (returnCode == ADDR_OK))
299 {
300 // Unknown failures, we return the general error code
301 returnCode = ADDR_ERROR;
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 return static_cast<Addr::Lib*>(hLib);
378 }
379
380 /**
381 ****************************************************************************************************
382 * Lib::GetMaxAlignments
383 *
384 * @brief
385 * Gets maximum alignments for data surface (include FMask)
386 *
387 * @return
388 * ADDR_E_RETURNCODE
389 ****************************************************************************************************
390 */
GetMaxAlignments(ADDR_GET_MAX_ALIGNMENTS_OUTPUT * pOut) const391 ADDR_E_RETURNCODE Lib::GetMaxAlignments(
392 ADDR_GET_MAX_ALIGNMENTS_OUTPUT* pOut ///< [out] output structure
393 ) const
394 {
395 ADDR_E_RETURNCODE returnCode = ADDR_OK;
396
397 if (GetFillSizeFieldsFlags() == TRUE)
398 {
399 if (pOut->size != sizeof(ADDR_GET_MAX_ALIGNMENTS_OUTPUT))
400 {
401 returnCode = ADDR_PARAMSIZEMISMATCH;
402 }
403 }
404
405 if (returnCode == ADDR_OK)
406 {
407 if (m_maxBaseAlign != 0)
408 {
409 pOut->baseAlign = m_maxBaseAlign;
410 }
411 else
412 {
413 returnCode = ADDR_NOTIMPLEMENTED;
414 }
415 }
416
417 return returnCode;
418 }
419
420 /**
421 ****************************************************************************************************
422 * Lib::GetMaxMetaAlignments
423 *
424 * @brief
425 * Gets maximum alignments for metadata (CMask, DCC and HTile)
426 *
427 * @return
428 * ADDR_E_RETURNCODE
429 ****************************************************************************************************
430 */
GetMaxMetaAlignments(ADDR_GET_MAX_ALIGNMENTS_OUTPUT * pOut) const431 ADDR_E_RETURNCODE Lib::GetMaxMetaAlignments(
432 ADDR_GET_MAX_ALIGNMENTS_OUTPUT* pOut ///< [out] output structure
433 ) const
434 {
435 ADDR_E_RETURNCODE returnCode = ADDR_OK;
436
437 if (GetFillSizeFieldsFlags() == TRUE)
438 {
439 if (pOut->size != sizeof(ADDR_GET_MAX_ALIGNMENTS_OUTPUT))
440 {
441 returnCode = ADDR_PARAMSIZEMISMATCH;
442 }
443 }
444
445 if (returnCode == ADDR_OK)
446 {
447 if (m_maxMetaBaseAlign != 0)
448 {
449 pOut->baseAlign = m_maxMetaBaseAlign;
450 }
451 else
452 {
453 returnCode = ADDR_NOTIMPLEMENTED;
454 }
455 }
456
457 return returnCode;
458 }
459
460 /**
461 ****************************************************************************************************
462 * Lib::Bits2Number
463 *
464 * @brief
465 * Cat a array of binary bit to a number
466 *
467 * @return
468 * The number combined with the array of bits
469 ****************************************************************************************************
470 */
Bits2Number(UINT_32 bitNum,...)471 UINT_32 Lib::Bits2Number(
472 UINT_32 bitNum, ///< [in] how many bits
473 ...) ///< [in] varaible bits value starting from MSB
474 {
475 UINT_32 number = 0;
476 UINT_32 i;
477 va_list bits_ptr;
478
479 va_start(bits_ptr, bitNum);
480
481 for(i = 0; i < bitNum; i++)
482 {
483 number |= va_arg(bits_ptr, UINT_32);
484 number <<= 1;
485 }
486
487 number >>= 1;
488
489 va_end(bits_ptr);
490
491 return number;
492 }
493
494
495 ////////////////////////////////////////////////////////////////////////////////////////////////////
496 // Element lib
497 ////////////////////////////////////////////////////////////////////////////////////////////////////
498
499
500 /**
501 ****************************************************************************************************
502 * Lib::Flt32ToColorPixel
503 *
504 * @brief
505 * Convert a FLT_32 value to a depth/stencil pixel value
506 * @return
507 * ADDR_E_RETURNCODE
508 ****************************************************************************************************
509 */
Flt32ToDepthPixel(const ELEM_FLT32TODEPTHPIXEL_INPUT * pIn,ELEM_FLT32TODEPTHPIXEL_OUTPUT * pOut) const510 ADDR_E_RETURNCODE Lib::Flt32ToDepthPixel(
511 const ELEM_FLT32TODEPTHPIXEL_INPUT* pIn,
512 ELEM_FLT32TODEPTHPIXEL_OUTPUT* pOut) const
513 {
514 ADDR_E_RETURNCODE returnCode = ADDR_OK;
515
516 if (GetFillSizeFieldsFlags() == TRUE)
517 {
518 if ((pIn->size != sizeof(ELEM_FLT32TODEPTHPIXEL_INPUT)) ||
519 (pOut->size != sizeof(ELEM_FLT32TODEPTHPIXEL_OUTPUT)))
520 {
521 returnCode = ADDR_PARAMSIZEMISMATCH;
522 }
523 }
524
525 if (returnCode == ADDR_OK)
526 {
527 GetElemLib()->Flt32ToDepthPixel(pIn->format, pIn->comps, pOut->pPixel);
528
529 UINT_32 depthBase = 0;
530 UINT_32 stencilBase = 0;
531 UINT_32 depthBits = 0;
532 UINT_32 stencilBits = 0;
533
534 switch (pIn->format)
535 {
536 case ADDR_DEPTH_16:
537 depthBits = 16;
538 break;
539 case ADDR_DEPTH_X8_24:
540 case ADDR_DEPTH_8_24:
541 case ADDR_DEPTH_X8_24_FLOAT:
542 case ADDR_DEPTH_8_24_FLOAT:
543 depthBase = 8;
544 depthBits = 24;
545 stencilBits = 8;
546 break;
547 case ADDR_DEPTH_32_FLOAT:
548 depthBits = 32;
549 break;
550 case ADDR_DEPTH_X24_8_32_FLOAT:
551 depthBase = 8;
552 depthBits = 32;
553 stencilBits = 8;
554 break;
555 default:
556 break;
557 }
558
559 // Overwrite base since R800 has no "tileBase"
560 if (GetElemLib()->IsDepthStencilTilePlanar() == FALSE)
561 {
562 depthBase = 0;
563 stencilBase = 0;
564 }
565
566 depthBase *= 64;
567 stencilBase *= 64;
568
569 pOut->stencilBase = stencilBase;
570 pOut->depthBase = depthBase;
571 pOut->depthBits = depthBits;
572 pOut->stencilBits = stencilBits;
573 }
574
575 return returnCode;
576 }
577
578 /**
579 ****************************************************************************************************
580 * Lib::Flt32ToColorPixel
581 *
582 * @brief
583 * Convert a FLT_32 value to a red/green/blue/alpha pixel value
584 * @return
585 * ADDR_E_RETURNCODE
586 ****************************************************************************************************
587 */
Flt32ToColorPixel(const ELEM_FLT32TOCOLORPIXEL_INPUT * pIn,ELEM_FLT32TOCOLORPIXEL_OUTPUT * pOut) const588 ADDR_E_RETURNCODE Lib::Flt32ToColorPixel(
589 const ELEM_FLT32TOCOLORPIXEL_INPUT* pIn,
590 ELEM_FLT32TOCOLORPIXEL_OUTPUT* pOut) const
591 {
592 ADDR_E_RETURNCODE returnCode = ADDR_OK;
593
594 if (GetFillSizeFieldsFlags() == TRUE)
595 {
596 if ((pIn->size != sizeof(ELEM_FLT32TOCOLORPIXEL_INPUT)) ||
597 (pOut->size != sizeof(ELEM_FLT32TOCOLORPIXEL_OUTPUT)))
598 {
599 returnCode = ADDR_PARAMSIZEMISMATCH;
600 }
601 }
602
603 if (returnCode == ADDR_OK)
604 {
605 GetElemLib()->Flt32ToColorPixel(pIn->format,
606 pIn->surfNum,
607 pIn->surfSwap,
608 pIn->comps,
609 pOut->pPixel);
610 }
611
612 return returnCode;
613 }
614
615
616 /**
617 ****************************************************************************************************
618 * Lib::GetExportNorm
619 *
620 * @brief
621 * Check one format can be EXPORT_NUM
622 * @return
623 * TRUE if EXPORT_NORM can be used
624 ****************************************************************************************************
625 */
GetExportNorm(const ELEM_GETEXPORTNORM_INPUT * pIn) const626 BOOL_32 Lib::GetExportNorm(
627 const ELEM_GETEXPORTNORM_INPUT* pIn) const
628 {
629 ADDR_E_RETURNCODE returnCode = ADDR_OK;
630
631 BOOL_32 enabled = FALSE;
632
633 if (GetFillSizeFieldsFlags() == TRUE)
634 {
635 if (pIn->size != sizeof(ELEM_GETEXPORTNORM_INPUT))
636 {
637 returnCode = ADDR_PARAMSIZEMISMATCH;
638 }
639 }
640
641 if (returnCode == ADDR_OK)
642 {
643 enabled = GetElemLib()->PixGetExportNorm(pIn->format, pIn->num, pIn->swap);
644 }
645
646 return enabled;
647 }
648
649 /**
650 ****************************************************************************************************
651 * Lib::GetBpe
652 *
653 * @brief
654 * Get bits-per-element for specified format
655 * @return
656 * bits-per-element of specified format
657 ****************************************************************************************************
658 */
GetBpe(AddrFormat format) const659 UINT_32 Lib::GetBpe(AddrFormat format) const
660 {
661 return GetElemLib()->GetBitsPerPixel(format);
662 }
663
664 } // Addr
665