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