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  addrlib2.cpp
30 * @brief Contains the implementation for the AddrLib2 base class.
31 ************************************************************************************************************************
32 */
33 
34 #include "addrinterface.h"
35 #include "addrlib2.h"
36 #include "addrcommon.h"
37 
38 namespace Addr
39 {
40 namespace V2
41 {
42 
43 ////////////////////////////////////////////////////////////////////////////////////////////////////
44 //                               Static Const Member
45 ////////////////////////////////////////////////////////////////////////////////////////////////////
46 
47 const Dim2d Lib::Block256_2d[] = {{16, 16}, {16, 8}, {8, 8}, {8, 4}, {4, 4}};
48 
49 const Dim3d Lib::Block1K_3d[]  = {{16, 8, 8}, {8, 8, 8}, {8, 8, 4}, {8, 4, 4}, {4, 4, 4}};
50 
51 ////////////////////////////////////////////////////////////////////////////////////////////////////
52 //                               Constructor/Destructor
53 ////////////////////////////////////////////////////////////////////////////////////////////////////
54 
55 /**
56 ************************************************************************************************************************
57 *   Lib::Lib
58 *
59 *   @brief
60 *       Constructor for the Addr::V2::Lib class
61 *
62 ************************************************************************************************************************
63 */
Lib()64 Lib::Lib()
65     :
66     Addr::Lib(),
67     m_se(0),
68     m_rbPerSe(0),
69     m_maxCompFrag(0),
70     m_banksLog2(0),
71     m_pipesLog2(0),
72     m_seLog2(0),
73     m_rbPerSeLog2(0),
74     m_maxCompFragLog2(0),
75     m_pipeInterleaveLog2(0),
76     m_blockVarSizeLog2(0),
77     m_numEquations(0)
78 {
79 }
80 
81 /**
82 ************************************************************************************************************************
83 *   Lib::Lib
84 *
85 *   @brief
86 *       Constructor for the AddrLib2 class with hClient as parameter
87 *
88 ************************************************************************************************************************
89 */
Lib(const Client * pClient)90 Lib::Lib(const Client* pClient)
91     :
92     Addr::Lib(pClient),
93     m_se(0),
94     m_rbPerSe(0),
95     m_maxCompFrag(0),
96     m_banksLog2(0),
97     m_pipesLog2(0),
98     m_seLog2(0),
99     m_rbPerSeLog2(0),
100     m_maxCompFragLog2(0),
101     m_pipeInterleaveLog2(0),
102     m_blockVarSizeLog2(0),
103     m_numEquations(0)
104 {
105 }
106 
107 /**
108 ************************************************************************************************************************
109 *   Lib::~Lib
110 *
111 *   @brief
112 *       Destructor for the AddrLib2 class
113 *
114 ************************************************************************************************************************
115 */
~Lib()116 Lib::~Lib()
117 {
118 }
119 
120 /**
121 ************************************************************************************************************************
122 *   Lib::GetLib
123 *
124 *   @brief
125 *       Get Addr::V2::Lib pointer
126 *
127 *   @return
128 *      An Addr::V2::Lib class pointer
129 ************************************************************************************************************************
130 */
GetLib(ADDR_HANDLE hLib)131 Lib* Lib::GetLib(
132     ADDR_HANDLE hLib)   ///< [in] handle of ADDR_HANDLE
133 {
134     Addr::Lib* pAddrLib = Addr::Lib::GetLib(hLib);
135     if ((pAddrLib != NULL) &&
136         (pAddrLib->GetChipFamily() <= ADDR_CHIP_FAMILY_VI))
137     {
138         // only valid and GFX9+ ASIC can use AddrLib2 function.
139         ADDR_ASSERT_ALWAYS();
140         hLib = NULL;
141     }
142     return static_cast<Lib*>(hLib);
143 }
144 
145 
146 ////////////////////////////////////////////////////////////////////////////////////////////////////
147 //                               Surface Methods
148 ////////////////////////////////////////////////////////////////////////////////////////////////////
149 
150 
151 /**
152 ************************************************************************************************************************
153 *   Lib::ComputeSurfaceInfo
154 *
155 *   @brief
156 *       Interface function stub of AddrComputeSurfaceInfo.
157 *
158 *   @return
159 *       ADDR_E_RETURNCODE
160 ************************************************************************************************************************
161 */
ComputeSurfaceInfo(const ADDR2_COMPUTE_SURFACE_INFO_INPUT * pIn,ADDR2_COMPUTE_SURFACE_INFO_OUTPUT * pOut) const162 ADDR_E_RETURNCODE Lib::ComputeSurfaceInfo(
163      const ADDR2_COMPUTE_SURFACE_INFO_INPUT* pIn,    ///< [in] input structure
164      ADDR2_COMPUTE_SURFACE_INFO_OUTPUT*      pOut    ///< [out] output structure
165      ) const
166 {
167     ADDR_E_RETURNCODE returnCode = ADDR_OK;
168 
169     if (GetFillSizeFieldsFlags() == TRUE)
170     {
171         if ((pIn->size != sizeof(ADDR2_COMPUTE_SURFACE_INFO_INPUT)) ||
172             (pOut->size != sizeof(ADDR2_COMPUTE_SURFACE_INFO_OUTPUT)))
173         {
174             returnCode = ADDR_PARAMSIZEMISMATCH;
175         }
176     }
177 
178     // Adjust coming parameters.
179     ADDR2_COMPUTE_SURFACE_INFO_INPUT localIn = *pIn;
180     localIn.width        = Max(pIn->width, 1u);
181     localIn.height       = Max(pIn->height, 1u);
182     localIn.numMipLevels = Max(pIn->numMipLevels, 1u);
183     localIn.numSlices    = Max(pIn->numSlices, 1u);
184     localIn.numSamples   = Max(pIn->numSamples, 1u);
185     localIn.numFrags     = (localIn.numFrags == 0) ? localIn.numSamples : pIn->numFrags;
186 
187     UINT_32  expandX  = 1;
188     UINT_32  expandY  = 1;
189     ElemMode elemMode = ADDR_UNCOMPRESSED;
190 
191     if (returnCode == ADDR_OK)
192     {
193         // Set format to INVALID will skip this conversion
194         if (localIn.format != ADDR_FMT_INVALID)
195         {
196             // Get compression/expansion factors and element mode which indicates compression/expansion
197             localIn.bpp = GetElemLib()->GetBitsPerPixel(localIn.format,
198                                                         &elemMode,
199                                                         &expandX,
200                                                         &expandY);
201 
202             // Special flag for 96 bit surface. 96 (or 48 if we support) bit surface's width is
203             // pre-multiplied by 3 and bpp is divided by 3. So pitch alignment for linear-
204             // aligned does not meet 64-pixel in real. We keep special handling in hwl since hw
205             // restrictions are different.
206             // Also Mip 1+ needs an element pitch of 32 bits so we do not need this workaround
207             // but we use this flag to skip RestoreSurfaceInfo below
208 
209             if ((elemMode == ADDR_EXPANDED) && (expandX > 1))
210             {
211                 ADDR_ASSERT(IsLinear(localIn.swizzleMode));
212             }
213 
214             UINT_32 basePitch = 0;
215             GetElemLib()->AdjustSurfaceInfo(elemMode,
216                                             expandX,
217                                             expandY,
218                                             &localIn.bpp,
219                                             &basePitch,
220                                             &localIn.width,
221                                             &localIn.height);
222 
223             // Overwrite these parameters if we have a valid format
224         }
225 
226         if (localIn.bpp != 0)
227         {
228             localIn.width  = Max(localIn.width, 1u);
229             localIn.height = Max(localIn.height, 1u);
230         }
231         else // Rule out some invalid parameters
232         {
233             ADDR_ASSERT_ALWAYS();
234 
235             returnCode = ADDR_INVALIDPARAMS;
236         }
237     }
238 
239     if (returnCode == ADDR_OK)
240     {
241         returnCode = ComputeSurfaceInfoSanityCheck(&localIn);
242     }
243 
244     if (returnCode == ADDR_OK)
245     {
246         VerifyMipLevelInfo(pIn);
247 
248         if (IsLinear(pIn->swizzleMode))
249         {
250             // linear mode
251             returnCode = ComputeSurfaceInfoLinear(&localIn, pOut);
252         }
253         else
254         {
255             // tiled mode
256             returnCode = ComputeSurfaceInfoTiled(&localIn, pOut);
257         }
258 
259         if (returnCode == ADDR_OK)
260         {
261             pOut->bpp = localIn.bpp;
262             pOut->pixelPitch = pOut->pitch;
263             pOut->pixelHeight = pOut->height;
264             pOut->pixelMipChainPitch = pOut->mipChainPitch;
265             pOut->pixelMipChainHeight = pOut->mipChainHeight;
266             pOut->pixelBits = localIn.bpp;
267 
268             if (localIn.format != ADDR_FMT_INVALID)
269             {
270                 UINT_32 pixelBits = pOut->pixelBits;
271 
272                 GetElemLib()->RestoreSurfaceInfo(elemMode,
273                                                  expandX,
274                                                  expandY,
275                                                  &pOut->pixelBits,
276                                                  &pOut->pixelPitch,
277                                                  &pOut->pixelHeight);
278 
279                 GetElemLib()->RestoreSurfaceInfo(elemMode,
280                                                  expandX,
281                                                  expandY,
282                                                  &pixelBits,
283                                                  &pOut->pixelMipChainPitch,
284                                                  &pOut->pixelMipChainHeight);
285 
286                 if ((localIn.numMipLevels > 1) && (pOut->pMipInfo != NULL))
287                 {
288                     for (UINT_32 i = 0; i < localIn.numMipLevels; i++)
289                     {
290                         pOut->pMipInfo[i].pixelPitch  = pOut->pMipInfo[i].pitch;
291                         pOut->pMipInfo[i].pixelHeight = pOut->pMipInfo[i].height;
292 
293                         GetElemLib()->RestoreSurfaceInfo(elemMode,
294                                                          expandX,
295                                                          expandY,
296                                                          &pixelBits,
297                                                          &pOut->pMipInfo[i].pixelPitch,
298                                                          &pOut->pMipInfo[i].pixelHeight);
299                     }
300                 }
301             }
302 
303             if (localIn.flags.needEquation && (Log2(localIn.numFrags) == 0))
304             {
305                 pOut->equationIndex = GetEquationIndex(&localIn, pOut);
306             }
307 
308             if (localIn.flags.qbStereo)
309             {
310                 if (pOut->pStereoInfo != NULL)
311                 {
312                     ComputeQbStereoInfo(pOut);
313 #if DEBUG
314                     ValidateStereoInfo(pIn, pOut);
315 #endif
316                 }
317             }
318         }
319     }
320 
321     ADDR_ASSERT(pOut->surfSize != 0);
322 
323     ValidBaseAlignments(pOut->baseAlign);
324 
325     return returnCode;
326 }
327 
328 /**
329 ************************************************************************************************************************
330 *   Lib::ComputeSurfaceInfo
331 *
332 *   @brief
333 *       Interface function stub of AddrComputeSurfaceInfo.
334 *
335 *   @return
336 *       ADDR_E_RETURNCODE
337 ************************************************************************************************************************
338 */
ComputeSurfaceAddrFromCoord(const ADDR2_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT * pIn,ADDR2_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT * pOut) const339 ADDR_E_RETURNCODE Lib::ComputeSurfaceAddrFromCoord(
340     const ADDR2_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn,    ///< [in] input structure
341     ADDR2_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT*      pOut    ///< [out] output structure
342     ) const
343 {
344     ADDR_E_RETURNCODE returnCode = ADDR_OK;
345 
346     if (GetFillSizeFieldsFlags() == TRUE)
347     {
348         if ((pIn->size != sizeof(ADDR2_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT)) ||
349             (pOut->size != sizeof(ADDR2_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT)))
350         {
351             returnCode = ADDR_PARAMSIZEMISMATCH;
352         }
353     }
354 
355     ADDR2_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT localIn = *pIn;
356     localIn.unalignedWidth  = Max(pIn->unalignedWidth, 1u);
357     localIn.unalignedHeight = Max(pIn->unalignedHeight, 1u);
358     localIn.numMipLevels    = Max(pIn->numMipLevels, 1u);
359     localIn.numSlices       = Max(pIn->numSlices, 1u);
360     localIn.numSamples      = Max(pIn->numSamples, 1u);
361     localIn.numFrags        = Max(pIn->numFrags, 1u);
362 
363     if ((localIn.bpp < 8)        ||
364         (localIn.bpp > 128)      ||
365         ((localIn.bpp % 8) != 0) ||
366         (localIn.sample >= localIn.numSamples)  ||
367         (localIn.slice >= localIn.numSlices)    ||
368         (localIn.mipId >= localIn.numMipLevels) ||
369         (IsTex3d(localIn.resourceType) &&
370          (Valid3DMipSliceIdConstraint(localIn.numSlices, localIn.mipId, localIn.slice) == FALSE)))
371     {
372         returnCode = ADDR_INVALIDPARAMS;
373     }
374 
375     if (returnCode == ADDR_OK)
376     {
377         if (IsLinear(localIn.swizzleMode))
378         {
379             returnCode = ComputeSurfaceAddrFromCoordLinear(&localIn, pOut);
380         }
381         else
382         {
383             returnCode = ComputeSurfaceAddrFromCoordTiled(&localIn, pOut);
384         }
385 
386         if (returnCode == ADDR_OK)
387         {
388             pOut->prtBlockIndex = static_cast<UINT_32>(pOut->addr / (64 * 1024));
389         }
390     }
391 
392     return returnCode;
393 }
394 
395 /**
396 ************************************************************************************************************************
397 *   Lib::ComputeSurfaceCoordFromAddr
398 *
399 *   @brief
400 *       Interface function stub of ComputeSurfaceCoordFromAddr.
401 *
402 *   @return
403 *       ADDR_E_RETURNCODE
404 ************************************************************************************************************************
405 */
ComputeSurfaceCoordFromAddr(const ADDR2_COMPUTE_SURFACE_COORDFROMADDR_INPUT * pIn,ADDR2_COMPUTE_SURFACE_COORDFROMADDR_OUTPUT * pOut) const406 ADDR_E_RETURNCODE Lib::ComputeSurfaceCoordFromAddr(
407     const ADDR2_COMPUTE_SURFACE_COORDFROMADDR_INPUT* pIn,    ///< [in] input structure
408     ADDR2_COMPUTE_SURFACE_COORDFROMADDR_OUTPUT*      pOut    ///< [out] output structure
409     ) const
410 {
411     ADDR_E_RETURNCODE returnCode = ADDR_OK;
412 
413     if (GetFillSizeFieldsFlags() == TRUE)
414     {
415         if ((pIn->size != sizeof(ADDR2_COMPUTE_SURFACE_COORDFROMADDR_INPUT)) ||
416             (pOut->size != sizeof(ADDR2_COMPUTE_SURFACE_COORDFROMADDR_OUTPUT)))
417         {
418             returnCode = ADDR_PARAMSIZEMISMATCH;
419         }
420     }
421 
422     if ((pIn->bpp < 8)        ||
423         (pIn->bpp > 128)      ||
424         ((pIn->bpp % 8) != 0) ||
425         (pIn->bitPosition >= 8))
426     {
427         returnCode = ADDR_INVALIDPARAMS;
428     }
429 
430     if (returnCode == ADDR_OK)
431     {
432         if (IsLinear(pIn->swizzleMode))
433         {
434             returnCode = ComputeSurfaceCoordFromAddrLinear(pIn, pOut);
435         }
436         else
437         {
438             returnCode = ComputeSurfaceCoordFromAddrTiled(pIn, pOut);
439         }
440     }
441 
442     return returnCode;
443 }
444 
445 
446 ////////////////////////////////////////////////////////////////////////////////////////////////////
447 //                               CMASK/HTILE
448 ////////////////////////////////////////////////////////////////////////////////////////////////////
449 
450 /**
451 ************************************************************************************************************************
452 *   Lib::ComputeHtileInfo
453 *
454 *   @brief
455 *       Interface function stub of AddrComputeHtilenfo
456 *
457 *   @return
458 *       ADDR_E_RETURNCODE
459 ************************************************************************************************************************
460 */
ComputeHtileInfo(const ADDR2_COMPUTE_HTILE_INFO_INPUT * pIn,ADDR2_COMPUTE_HTILE_INFO_OUTPUT * pOut) const461 ADDR_E_RETURNCODE Lib::ComputeHtileInfo(
462     const ADDR2_COMPUTE_HTILE_INFO_INPUT*    pIn,    ///< [in] input structure
463     ADDR2_COMPUTE_HTILE_INFO_OUTPUT*         pOut    ///< [out] output structure
464     ) const
465 {
466     ADDR_E_RETURNCODE returnCode;
467 
468     if ((GetFillSizeFieldsFlags() == TRUE) &&
469         ((pIn->size != sizeof(ADDR2_COMPUTE_HTILE_INFO_INPUT)) ||
470          (pOut->size != sizeof(ADDR2_COMPUTE_HTILE_INFO_OUTPUT))))
471     {
472         returnCode = ADDR_INVALIDPARAMS;
473     }
474     else
475     {
476         returnCode = HwlComputeHtileInfo(pIn, pOut);
477 
478         ValidMetaBaseAlignments(pOut->baseAlign);
479     }
480 
481     return returnCode;
482 }
483 
484 /**
485 ************************************************************************************************************************
486 *   Lib::ComputeHtileAddrFromCoord
487 *
488 *   @brief
489 *       Interface function stub of AddrComputeHtileAddrFromCoord
490 *
491 *   @return
492 *       ADDR_E_RETURNCODE
493 ************************************************************************************************************************
494 */
ComputeHtileAddrFromCoord(const ADDR2_COMPUTE_HTILE_ADDRFROMCOORD_INPUT * pIn,ADDR2_COMPUTE_HTILE_ADDRFROMCOORD_OUTPUT * pOut)495 ADDR_E_RETURNCODE Lib::ComputeHtileAddrFromCoord(
496     const ADDR2_COMPUTE_HTILE_ADDRFROMCOORD_INPUT*   pIn,    ///< [in] input structure
497     ADDR2_COMPUTE_HTILE_ADDRFROMCOORD_OUTPUT*        pOut)   ///< [out] output structure
498 {
499     ADDR_E_RETURNCODE returnCode;
500 
501     if ((GetFillSizeFieldsFlags() == TRUE) &&
502         ((pIn->size != sizeof(ADDR2_COMPUTE_HTILE_ADDRFROMCOORD_INPUT)) ||
503          (pOut->size != sizeof(ADDR2_COMPUTE_HTILE_ADDRFROMCOORD_OUTPUT))))
504     {
505         returnCode = ADDR_INVALIDPARAMS;
506     }
507     else
508     {
509         returnCode = HwlComputeHtileAddrFromCoord(pIn, pOut);
510     }
511 
512     return returnCode;
513 }
514 
515 /**
516 ************************************************************************************************************************
517 *   Lib::ComputeHtileCoordFromAddr
518 *
519 *   @brief
520 *       Interface function stub of AddrComputeHtileCoordFromAddr
521 *
522 *   @return
523 *       ADDR_E_RETURNCODE
524 ************************************************************************************************************************
525 */
ComputeHtileCoordFromAddr(const ADDR2_COMPUTE_HTILE_COORDFROMADDR_INPUT * pIn,ADDR2_COMPUTE_HTILE_COORDFROMADDR_OUTPUT * pOut)526 ADDR_E_RETURNCODE Lib::ComputeHtileCoordFromAddr(
527     const ADDR2_COMPUTE_HTILE_COORDFROMADDR_INPUT*   pIn,    ///< [in] input structure
528     ADDR2_COMPUTE_HTILE_COORDFROMADDR_OUTPUT*        pOut)   ///< [out] output structure
529 {
530     ADDR_E_RETURNCODE returnCode;
531 
532     if ((GetFillSizeFieldsFlags() == TRUE) &&
533         ((pIn->size != sizeof(ADDR2_COMPUTE_HTILE_COORDFROMADDR_INPUT)) ||
534          (pOut->size != sizeof(ADDR2_COMPUTE_HTILE_COORDFROMADDR_OUTPUT))))
535     {
536         returnCode = ADDR_INVALIDPARAMS;
537     }
538     else
539     {
540         returnCode = HwlComputeHtileCoordFromAddr(pIn, pOut);
541     }
542 
543     return returnCode;
544 }
545 
546 /**
547 ************************************************************************************************************************
548 *   Lib::ComputeCmaskInfo
549 *
550 *   @brief
551 *       Interface function stub of AddrComputeCmaskInfo
552 *
553 *   @return
554 *       ADDR_E_RETURNCODE
555 ************************************************************************************************************************
556 */
ComputeCmaskInfo(const ADDR2_COMPUTE_CMASK_INFO_INPUT * pIn,ADDR2_COMPUTE_CMASK_INFO_OUTPUT * pOut) const557 ADDR_E_RETURNCODE Lib::ComputeCmaskInfo(
558     const ADDR2_COMPUTE_CMASK_INFO_INPUT*    pIn,    ///< [in] input structure
559     ADDR2_COMPUTE_CMASK_INFO_OUTPUT*         pOut    ///< [out] output structure
560     ) const
561 {
562     ADDR_E_RETURNCODE returnCode;
563 
564     if ((GetFillSizeFieldsFlags() == TRUE) &&
565         ((pIn->size != sizeof(ADDR2_COMPUTE_CMASK_INFO_INPUT)) ||
566          (pOut->size != sizeof(ADDR2_COMPUTE_CMASK_INFO_OUTPUT))))
567     {
568         returnCode = ADDR_INVALIDPARAMS;
569     }
570     else if (pIn->cMaskFlags.linear)
571     {
572         returnCode = ADDR_INVALIDPARAMS;
573     }
574     else
575     {
576         returnCode = HwlComputeCmaskInfo(pIn, pOut);
577 
578         ValidMetaBaseAlignments(pOut->baseAlign);
579     }
580 
581     return returnCode;
582 }
583 
584 /**
585 ************************************************************************************************************************
586 *   Lib::ComputeCmaskAddrFromCoord
587 *
588 *   @brief
589 *       Interface function stub of AddrComputeCmaskAddrFromCoord
590 *
591 *   @return
592 *       ADDR_E_RETURNCODE
593 ************************************************************************************************************************
594 */
ComputeCmaskAddrFromCoord(const ADDR2_COMPUTE_CMASK_ADDRFROMCOORD_INPUT * pIn,ADDR2_COMPUTE_CMASK_ADDRFROMCOORD_OUTPUT * pOut)595 ADDR_E_RETURNCODE Lib::ComputeCmaskAddrFromCoord(
596     const ADDR2_COMPUTE_CMASK_ADDRFROMCOORD_INPUT*   pIn,    ///< [in] input structure
597     ADDR2_COMPUTE_CMASK_ADDRFROMCOORD_OUTPUT*        pOut)   ///< [out] output structure
598 {
599     ADDR_E_RETURNCODE returnCode;
600 
601     if ((GetFillSizeFieldsFlags() == TRUE) &&
602         ((pIn->size != sizeof(ADDR2_COMPUTE_CMASK_ADDRFROMCOORD_INPUT)) ||
603          (pOut->size != sizeof(ADDR2_COMPUTE_CMASK_ADDRFROMCOORD_OUTPUT))))
604     {
605         returnCode = ADDR_INVALIDPARAMS;
606     }
607     else
608     {
609         returnCode = HwlComputeCmaskAddrFromCoord(pIn, pOut);
610     }
611 
612     return returnCode;
613 }
614 
615 /**
616 ************************************************************************************************************************
617 *   Lib::ComputeCmaskCoordFromAddr
618 *
619 *   @brief
620 *       Interface function stub of AddrComputeCmaskCoordFromAddr
621 *
622 *   @return
623 *       ADDR_E_RETURNCODE
624 ************************************************************************************************************************
625 */
ComputeCmaskCoordFromAddr(const ADDR2_COMPUTE_CMASK_COORDFROMADDR_INPUT * pIn,ADDR2_COMPUTE_CMASK_COORDFROMADDR_OUTPUT * pOut) const626 ADDR_E_RETURNCODE Lib::ComputeCmaskCoordFromAddr(
627     const ADDR2_COMPUTE_CMASK_COORDFROMADDR_INPUT*   pIn,    ///< [in] input structure
628     ADDR2_COMPUTE_CMASK_COORDFROMADDR_OUTPUT*        pOut    ///< [out] output structure
629     ) const
630 {
631     ADDR_E_RETURNCODE returnCode = ADDR_NOTIMPLEMENTED;
632 
633     ADDR_NOT_IMPLEMENTED();
634 
635     return returnCode;
636 }
637 
638 /**
639 ************************************************************************************************************************
640 *   Lib::ComputeFmaskInfo
641 *
642 *   @brief
643 *       Interface function stub of ComputeFmaskInfo.
644 *
645 *   @return
646 *       ADDR_E_RETURNCODE
647 ************************************************************************************************************************
648 */
ComputeFmaskInfo(const ADDR2_COMPUTE_FMASK_INFO_INPUT * pIn,ADDR2_COMPUTE_FMASK_INFO_OUTPUT * pOut)649 ADDR_E_RETURNCODE Lib::ComputeFmaskInfo(
650     const ADDR2_COMPUTE_FMASK_INFO_INPUT*    pIn,    ///< [in] input structure
651     ADDR2_COMPUTE_FMASK_INFO_OUTPUT*         pOut    ///< [out] output structure
652     )
653 {
654     ADDR_E_RETURNCODE returnCode;
655 
656     BOOL_32 valid = (IsZOrderSwizzle(pIn->swizzleMode) == TRUE) &&
657                     ((pIn->numSamples > 0) || (pIn->numFrags > 0));
658 
659     if (GetFillSizeFieldsFlags())
660     {
661         if ((pIn->size != sizeof(ADDR2_COMPUTE_FMASK_INFO_INPUT)) ||
662             (pOut->size != sizeof(ADDR2_COMPUTE_FMASK_INFO_OUTPUT)))
663         {
664             valid = FALSE;
665         }
666     }
667 
668     if (valid == FALSE)
669     {
670         returnCode = ADDR_INVALIDPARAMS;
671     }
672     else
673     {
674         ADDR2_COMPUTE_SURFACE_INFO_INPUT  localIn = {0};
675         ADDR2_COMPUTE_SURFACE_INFO_OUTPUT localOut = {0};
676 
677         localIn.size = sizeof(ADDR2_COMPUTE_SURFACE_INFO_INPUT);
678         localOut.size = sizeof(ADDR2_COMPUTE_SURFACE_INFO_OUTPUT);
679 
680         localIn.swizzleMode  = pIn->swizzleMode;
681         localIn.numSlices    = Max(pIn->numSlices, 1u);
682         localIn.width        = Max(pIn->unalignedWidth, 1u);
683         localIn.height       = Max(pIn->unalignedHeight, 1u);
684         localIn.bpp          = GetFmaskBpp(pIn->numSamples, pIn->numFrags);
685         localIn.flags.fmask  = 1;
686         localIn.numFrags     = 1;
687         localIn.numSamples   = 1;
688         localIn.resourceType = ADDR_RSRC_TEX_2D;
689 
690         if (localIn.bpp == 8)
691         {
692             localIn.format = ADDR_FMT_8;
693         }
694         else if (localIn.bpp == 16)
695         {
696             localIn.format = ADDR_FMT_16;
697         }
698         else if (localIn.bpp == 32)
699         {
700             localIn.format = ADDR_FMT_32;
701         }
702         else
703         {
704             localIn.format = ADDR_FMT_32_32;
705         }
706 
707         returnCode = ComputeSurfaceInfo(&localIn, &localOut);
708 
709         if (returnCode == ADDR_OK)
710         {
711             pOut->pitch      = localOut.pitch;
712             pOut->height     = localOut.height;
713             pOut->baseAlign  = localOut.baseAlign;
714             pOut->numSlices  = localOut.numSlices;
715             pOut->fmaskBytes = static_cast<UINT_32>(localOut.surfSize);
716             pOut->sliceSize  = static_cast<UINT_32>(localOut.sliceSize);
717             pOut->bpp        = localIn.bpp;
718             pOut->numSamples = 1;
719         }
720     }
721 
722     ValidBaseAlignments(pOut->baseAlign);
723 
724     return returnCode;
725 }
726 
727 /**
728 ************************************************************************************************************************
729 *   Lib::ComputeFmaskAddrFromCoord
730 *
731 *   @brief
732 *       Interface function stub of ComputeFmaskAddrFromCoord.
733 *
734 *   @return
735 *       ADDR_E_RETURNCODE
736 ************************************************************************************************************************
737 */
ComputeFmaskAddrFromCoord(const ADDR2_COMPUTE_FMASK_ADDRFROMCOORD_INPUT * pIn,ADDR2_COMPUTE_FMASK_ADDRFROMCOORD_OUTPUT * pOut) const738 ADDR_E_RETURNCODE Lib::ComputeFmaskAddrFromCoord(
739     const ADDR2_COMPUTE_FMASK_ADDRFROMCOORD_INPUT*   pIn,    ///< [in] input structure
740     ADDR2_COMPUTE_FMASK_ADDRFROMCOORD_OUTPUT*        pOut    ///< [out] output structure
741     ) const
742 {
743     ADDR_E_RETURNCODE returnCode = ADDR_NOTIMPLEMENTED;
744 
745     ADDR_NOT_IMPLEMENTED();
746 
747     return returnCode;
748 }
749 
750 /**
751 ************************************************************************************************************************
752 *   Lib::ComputeFmaskCoordFromAddr
753 *
754 *   @brief
755 *       Interface function stub of ComputeFmaskAddrFromCoord.
756 *
757 *   @return
758 *       ADDR_E_RETURNCODE
759 ************************************************************************************************************************
760 */
ComputeFmaskCoordFromAddr(const ADDR2_COMPUTE_FMASK_COORDFROMADDR_INPUT * pIn,ADDR2_COMPUTE_FMASK_COORDFROMADDR_OUTPUT * pOut) const761 ADDR_E_RETURNCODE Lib::ComputeFmaskCoordFromAddr(
762     const ADDR2_COMPUTE_FMASK_COORDFROMADDR_INPUT*  pIn,     ///< [in] input structure
763     ADDR2_COMPUTE_FMASK_COORDFROMADDR_OUTPUT*       pOut     ///< [out] output structure
764     ) const
765 {
766     ADDR_E_RETURNCODE returnCode = ADDR_NOTIMPLEMENTED;
767 
768     ADDR_NOT_IMPLEMENTED();
769 
770     return returnCode;
771 }
772 
773 /**
774 ************************************************************************************************************************
775 *   Lib::ComputeDccInfo
776 *
777 *   @brief
778 *       Interface function to compute DCC key info
779 *
780 *   @return
781 *       return code of HwlComputeDccInfo
782 ************************************************************************************************************************
783 */
ComputeDccInfo(const ADDR2_COMPUTE_DCCINFO_INPUT * pIn,ADDR2_COMPUTE_DCCINFO_OUTPUT * pOut) const784 ADDR_E_RETURNCODE Lib::ComputeDccInfo(
785     const ADDR2_COMPUTE_DCCINFO_INPUT*    pIn,    ///< [in] input structure
786     ADDR2_COMPUTE_DCCINFO_OUTPUT*         pOut    ///< [out] output structure
787     ) const
788 {
789     ADDR_E_RETURNCODE returnCode;
790 
791     if ((GetFillSizeFieldsFlags() == TRUE) &&
792         ((pIn->size != sizeof(ADDR2_COMPUTE_DCCINFO_INPUT)) ||
793          (pOut->size != sizeof(ADDR2_COMPUTE_DCCINFO_OUTPUT))))
794     {
795         returnCode = ADDR_INVALIDPARAMS;
796     }
797     else
798     {
799         returnCode = HwlComputeDccInfo(pIn, pOut);
800 
801         ValidMetaBaseAlignments(pOut->dccRamBaseAlign);
802     }
803 
804     return returnCode;
805 }
806 
807 /**
808 ************************************************************************************************************************
809 *   Lib::ComputeDccAddrFromCoord
810 *
811 *   @brief
812 *       Interface function stub of ComputeDccAddrFromCoord
813 *
814 *   @return
815 *       ADDR_E_RETURNCODE
816 ************************************************************************************************************************
817 */
ComputeDccAddrFromCoord(const ADDR2_COMPUTE_DCC_ADDRFROMCOORD_INPUT * pIn,ADDR2_COMPUTE_DCC_ADDRFROMCOORD_OUTPUT * pOut)818 ADDR_E_RETURNCODE Lib::ComputeDccAddrFromCoord(
819     const ADDR2_COMPUTE_DCC_ADDRFROMCOORD_INPUT* pIn,    ///< [in] input structure
820     ADDR2_COMPUTE_DCC_ADDRFROMCOORD_OUTPUT*      pOut)   ///< [out] output structure
821 {
822     ADDR_E_RETURNCODE returnCode;
823 
824     if ((GetFillSizeFieldsFlags() == TRUE) &&
825         ((pIn->size != sizeof(ADDR2_COMPUTE_DCC_ADDRFROMCOORD_INPUT)) ||
826          (pOut->size != sizeof(ADDR2_COMPUTE_DCC_ADDRFROMCOORD_OUTPUT))))
827     {
828         returnCode = ADDR_INVALIDPARAMS;
829     }
830     else
831     {
832         returnCode = HwlSupportComputeDccAddrFromCoord(pIn);
833 
834         if (returnCode == ADDR_OK)
835         {
836             HwlComputeDccAddrFromCoord(pIn, pOut);
837         }
838     }
839 
840     return returnCode;
841 }
842 
843 /**
844 ************************************************************************************************************************
845 *   Lib::ComputePipeBankXor
846 *
847 *   @brief
848 *       Interface function stub of Addr2ComputePipeBankXor.
849 *
850 *   @return
851 *       ADDR_E_RETURNCODE
852 ************************************************************************************************************************
853 */
ComputePipeBankXor(const ADDR2_COMPUTE_PIPEBANKXOR_INPUT * pIn,ADDR2_COMPUTE_PIPEBANKXOR_OUTPUT * pOut)854 ADDR_E_RETURNCODE Lib::ComputePipeBankXor(
855     const ADDR2_COMPUTE_PIPEBANKXOR_INPUT* pIn,
856     ADDR2_COMPUTE_PIPEBANKXOR_OUTPUT*      pOut)
857 {
858     ADDR_E_RETURNCODE returnCode;
859 
860     if ((GetFillSizeFieldsFlags() == TRUE) &&
861         ((pIn->size != sizeof(ADDR2_COMPUTE_PIPEBANKXOR_INPUT)) ||
862          (pOut->size != sizeof(ADDR2_COMPUTE_PIPEBANKXOR_OUTPUT))))
863     {
864         returnCode = ADDR_INVALIDPARAMS;
865     }
866     else
867     {
868         returnCode = HwlComputePipeBankXor(pIn, pOut);
869     }
870 
871     return returnCode;
872 }
873 
874 /**
875 ************************************************************************************************************************
876 *   Lib::ComputeSlicePipeBankXor
877 *
878 *   @brief
879 *       Interface function stub of Addr2ComputeSlicePipeBankXor.
880 *
881 *   @return
882 *       ADDR_E_RETURNCODE
883 ************************************************************************************************************************
884 */
ComputeSlicePipeBankXor(const ADDR2_COMPUTE_SLICE_PIPEBANKXOR_INPUT * pIn,ADDR2_COMPUTE_SLICE_PIPEBANKXOR_OUTPUT * pOut)885 ADDR_E_RETURNCODE Lib::ComputeSlicePipeBankXor(
886     const ADDR2_COMPUTE_SLICE_PIPEBANKXOR_INPUT* pIn,
887     ADDR2_COMPUTE_SLICE_PIPEBANKXOR_OUTPUT*      pOut)
888 {
889     ADDR_E_RETURNCODE returnCode;
890 
891     if ((GetFillSizeFieldsFlags() == TRUE) &&
892         ((pIn->size != sizeof(ADDR2_COMPUTE_SLICE_PIPEBANKXOR_INPUT)) ||
893          (pOut->size != sizeof(ADDR2_COMPUTE_SLICE_PIPEBANKXOR_OUTPUT))))
894     {
895         returnCode = ADDR_INVALIDPARAMS;
896     }
897     else if ((IsThin(pIn->resourceType, pIn->swizzleMode) == FALSE) ||
898              (IsNonPrtXor(pIn->swizzleMode) == FALSE) ||
899              (pIn->numSamples > 1))
900     {
901         returnCode = ADDR_NOTSUPPORTED;
902     }
903     else if ((pIn->bpe != 0) &&
904              (pIn->bpe != 8) &&
905              (pIn->bpe != 16) &&
906              (pIn->bpe != 32) &&
907              (pIn->bpe != 64) &&
908              (pIn->bpe != 128))
909     {
910         returnCode = ADDR_INVALIDPARAMS;
911     }
912     else
913     {
914         returnCode = HwlComputeSlicePipeBankXor(pIn, pOut);
915     }
916 
917     return returnCode;
918 }
919 
920 /**
921 ************************************************************************************************************************
922 *   Lib::ComputeSubResourceOffsetForSwizzlePattern
923 *
924 *   @brief
925 *       Interface function stub of Addr2ComputeSubResourceOffsetForSwizzlePattern.
926 *
927 *   @return
928 *       ADDR_E_RETURNCODE
929 ************************************************************************************************************************
930 */
ComputeSubResourceOffsetForSwizzlePattern(const ADDR2_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_INPUT * pIn,ADDR2_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_OUTPUT * pOut)931 ADDR_E_RETURNCODE Lib::ComputeSubResourceOffsetForSwizzlePattern(
932     const ADDR2_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_INPUT* pIn,
933     ADDR2_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_OUTPUT*      pOut)
934 {
935     ADDR_E_RETURNCODE returnCode;
936 
937     if ((GetFillSizeFieldsFlags() == TRUE) &&
938         ((pIn->size != sizeof(ADDR2_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_INPUT)) ||
939          (pOut->size != sizeof(ADDR2_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_OUTPUT))))
940     {
941         returnCode = ADDR_INVALIDPARAMS;
942     }
943     else
944     {
945         returnCode = HwlComputeSubResourceOffsetForSwizzlePattern(pIn, pOut);
946     }
947 
948     return returnCode;
949 }
950 
951 /**
952 ************************************************************************************************************************
953 *   Lib::ComputeNonBlockCompressedView
954 *
955 *   @brief
956 *       Interface function stub of Addr2ComputeNonBlockCompressedView.
957 *
958 *   @return
959 *       ADDR_E_RETURNCODE
960 ************************************************************************************************************************
961 */
ComputeNonBlockCompressedView(const ADDR2_COMPUTE_NONBLOCKCOMPRESSEDVIEW_INPUT * pIn,ADDR2_COMPUTE_NONBLOCKCOMPRESSEDVIEW_OUTPUT * pOut)962 ADDR_E_RETURNCODE Lib::ComputeNonBlockCompressedView(
963     const ADDR2_COMPUTE_NONBLOCKCOMPRESSEDVIEW_INPUT* pIn,
964     ADDR2_COMPUTE_NONBLOCKCOMPRESSEDVIEW_OUTPUT*      pOut)
965 {
966     ADDR_E_RETURNCODE returnCode;
967 
968     if ((GetFillSizeFieldsFlags() == TRUE) &&
969         ((pIn->size != sizeof(ADDR2_COMPUTE_NONBLOCKCOMPRESSEDVIEW_INPUT)) ||
970          (pOut->size != sizeof(ADDR2_COMPUTE_NONBLOCKCOMPRESSEDVIEW_OUTPUT))))
971     {
972         returnCode = ADDR_INVALIDPARAMS;
973     }
974     else
975     {
976         returnCode = HwlComputeNonBlockCompressedView(pIn, pOut);
977     }
978 
979     return returnCode;
980 }
981 
982 /**
983 ************************************************************************************************************************
984 *   Lib::ExtractPipeBankXor
985 *
986 *   @brief
987 *       Internal function to extract bank and pipe xor bits from combined xor bits.
988 *
989 *   @return
990 *       ADDR_E_RETURNCODE
991 ************************************************************************************************************************
992 */
ExtractPipeBankXor(UINT_32 pipeBankXor,UINT_32 bankBits,UINT_32 pipeBits,UINT_32 * pBankX,UINT_32 * pPipeX)993 ADDR_E_RETURNCODE Lib::ExtractPipeBankXor(
994     UINT_32  pipeBankXor,
995     UINT_32  bankBits,
996     UINT_32  pipeBits,
997     UINT_32* pBankX,
998     UINT_32* pPipeX)
999 {
1000     ADDR_E_RETURNCODE returnCode;
1001 
1002     if (pipeBankXor < (1u << (pipeBits + bankBits)))
1003     {
1004         *pPipeX = pipeBankXor % (1 << pipeBits);
1005         *pBankX = pipeBankXor >> pipeBits;
1006         returnCode = ADDR_OK;
1007     }
1008     else
1009     {
1010         ADDR_ASSERT_ALWAYS();
1011         returnCode = ADDR_INVALIDPARAMS;
1012     }
1013 
1014     return returnCode;
1015 }
1016 
1017 /**
1018 ************************************************************************************************************************
1019 *   Lib::ComputeSurfaceInfoSanityCheck
1020 *
1021 *   @brief
1022 *       Internal function to do basic sanity check before compute surface info
1023 *
1024 *   @return
1025 *       ADDR_E_RETURNCODE
1026 ************************************************************************************************************************
1027 */
ComputeSurfaceInfoSanityCheck(const ADDR2_COMPUTE_SURFACE_INFO_INPUT * pIn) const1028 ADDR_E_RETURNCODE Lib::ComputeSurfaceInfoSanityCheck(
1029     const ADDR2_COMPUTE_SURFACE_INFO_INPUT*  pIn   ///< [in] input structure
1030     ) const
1031 {
1032     ADDR_E_RETURNCODE returnCode;
1033 
1034     if ((GetFillSizeFieldsFlags() == TRUE) &&
1035         (pIn->size != sizeof(ADDR2_COMPUTE_SURFACE_INFO_INPUT)))
1036     {
1037         returnCode = ADDR_INVALIDPARAMS;
1038     }
1039     else
1040     {
1041         returnCode = HwlComputeSurfaceInfoSanityCheck(pIn);
1042     }
1043 
1044     return returnCode;
1045 }
1046 
1047 /**
1048 ************************************************************************************************************************
1049 *   Lib::ApplyCustomizedPitchHeight
1050 *
1051 *   @brief
1052 *       Helper function to override hw required row pitch/slice pitch by customrized one
1053 *
1054 *   @return
1055 *       ADDR_E_RETURNCODE
1056 ************************************************************************************************************************
1057 */
ApplyCustomizedPitchHeight(const ADDR2_COMPUTE_SURFACE_INFO_INPUT * pIn,UINT_32 elementBytes,UINT_32 pitchAlignInElement,UINT_32 * pPitch,UINT_32 * pHeight) const1058 ADDR_E_RETURNCODE Lib::ApplyCustomizedPitchHeight(
1059     const ADDR2_COMPUTE_SURFACE_INFO_INPUT* pIn,    ///< [in] input structure
1060     UINT_32  elementBytes,                          ///< [in] element bytes per element
1061     UINT_32  pitchAlignInElement,                   ///< [in] pitch alignment in element
1062     UINT_32* pPitch,                                ///< [in/out] pitch
1063     UINT_32* pHeight                                ///< [in/out] height
1064     ) const
1065 {
1066     ADDR_E_RETURNCODE returnCode = ADDR_OK;
1067 
1068     if (pIn->numMipLevels <= 1)
1069     {
1070         if (pIn->pitchInElement > 0)
1071         {
1072             if ((pIn->pitchInElement % pitchAlignInElement) != 0)
1073             {
1074                 returnCode = ADDR_INVALIDPARAMS;
1075             }
1076             else if (pIn->pitchInElement < (*pPitch))
1077             {
1078                 returnCode = ADDR_INVALIDPARAMS;
1079             }
1080             else
1081             {
1082                 *pPitch = pIn->pitchInElement;
1083             }
1084         }
1085 
1086         if (returnCode == ADDR_OK)
1087         {
1088             if (pIn->sliceAlign > 0)
1089             {
1090                 UINT_32 customizedHeight = pIn->sliceAlign / elementBytes / (*pPitch);
1091 
1092                 if (customizedHeight * elementBytes * (*pPitch) != pIn->sliceAlign)
1093                 {
1094                     returnCode = ADDR_INVALIDPARAMS;
1095                 }
1096                 else if ((pIn->numSlices > 1) && ((*pHeight) != customizedHeight))
1097                 {
1098                     returnCode = ADDR_INVALIDPARAMS;
1099                 }
1100                 else
1101                 {
1102                     *pHeight = customizedHeight;
1103                 }
1104             }
1105         }
1106     }
1107 
1108     return returnCode;
1109 }
1110 
1111 /**
1112 ************************************************************************************************************************
1113 *   Lib::ComputeSurfaceInfoLinear
1114 *
1115 *   @brief
1116 *       Internal function to calculate alignment for linear swizzle surface
1117 *
1118 *   @return
1119 *       ADDR_E_RETURNCODE
1120 ************************************************************************************************************************
1121 */
ComputeSurfaceInfoLinear(const ADDR2_COMPUTE_SURFACE_INFO_INPUT * pIn,ADDR2_COMPUTE_SURFACE_INFO_OUTPUT * pOut) const1122 ADDR_E_RETURNCODE Lib::ComputeSurfaceInfoLinear(
1123      const ADDR2_COMPUTE_SURFACE_INFO_INPUT* pIn,    ///< [in] input structure
1124      ADDR2_COMPUTE_SURFACE_INFO_OUTPUT*      pOut    ///< [out] output structure
1125      ) const
1126 {
1127     return HwlComputeSurfaceInfoLinear(pIn, pOut);
1128 }
1129 
1130 /**
1131 ************************************************************************************************************************
1132 *   Lib::ComputeSurfaceInfoTiled
1133 *
1134 *   @brief
1135 *       Internal function to calculate alignment for tiled swizzle surface
1136 *
1137 *   @return
1138 *       ADDR_E_RETURNCODE
1139 ************************************************************************************************************************
1140 */
ComputeSurfaceInfoTiled(const ADDR2_COMPUTE_SURFACE_INFO_INPUT * pIn,ADDR2_COMPUTE_SURFACE_INFO_OUTPUT * pOut) const1141 ADDR_E_RETURNCODE Lib::ComputeSurfaceInfoTiled(
1142      const ADDR2_COMPUTE_SURFACE_INFO_INPUT* pIn,    ///< [in] input structure
1143      ADDR2_COMPUTE_SURFACE_INFO_OUTPUT*      pOut    ///< [out] output structure
1144      ) const
1145 {
1146     return HwlComputeSurfaceInfoTiled(pIn, pOut);
1147 }
1148 
1149 /**
1150 ************************************************************************************************************************
1151 *   Lib::ComputeSurfaceAddrFromCoordLinear
1152 *
1153 *   @brief
1154 *       Internal function to calculate address from coord for linear swizzle surface
1155 *
1156 *   @return
1157 *       ADDR_E_RETURNCODE
1158 ************************************************************************************************************************
1159 */
ComputeSurfaceAddrFromCoordLinear(const ADDR2_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT * pIn,ADDR2_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT * pOut) const1160 ADDR_E_RETURNCODE Lib::ComputeSurfaceAddrFromCoordLinear(
1161      const ADDR2_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn,    ///< [in] input structure
1162      ADDR2_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT*      pOut    ///< [out] output structure
1163      ) const
1164 {
1165     ADDR_E_RETURNCODE returnCode = ADDR_OK;
1166     BOOL_32 valid = (pIn->numSamples <= 1) && (pIn->numFrags <= 1) && (pIn->pipeBankXor == 0);
1167 
1168     if (valid)
1169     {
1170         if (IsTex1d(pIn->resourceType))
1171         {
1172             valid = (pIn->y == 0);
1173         }
1174     }
1175 
1176     if (valid)
1177     {
1178         ADDR2_COMPUTE_SURFACE_INFO_INPUT  localIn  = {0};
1179         ADDR2_COMPUTE_SURFACE_INFO_OUTPUT localOut = {0};
1180         ADDR2_MIP_INFO                    mipInfo[MaxMipLevels];
1181 
1182         localIn.bpp          = pIn->bpp;
1183         localIn.flags        = pIn->flags;
1184         localIn.width        = Max(pIn->unalignedWidth, 1u);
1185         localIn.height       = Max(pIn->unalignedHeight, 1u);
1186         localIn.numSlices    = Max(pIn->numSlices, 1u);
1187         localIn.numMipLevels = Max(pIn->numMipLevels, 1u);
1188         localIn.resourceType = pIn->resourceType;
1189 
1190         if (localIn.numMipLevels <= 1)
1191         {
1192             localIn.pitchInElement = pIn->pitchInElement;
1193         }
1194 
1195         localOut.pMipInfo = mipInfo;
1196 
1197         returnCode = ComputeSurfaceInfoLinear(&localIn, &localOut);
1198 
1199         if (returnCode == ADDR_OK)
1200         {
1201             pOut->addr        = (localOut.sliceSize * pIn->slice) +
1202                                 mipInfo[pIn->mipId].offset +
1203                                 (pIn->y * mipInfo[pIn->mipId].pitch + pIn->x) * (pIn->bpp >> 3);
1204             pOut->bitPosition = 0;
1205         }
1206         else
1207         {
1208             valid = FALSE;
1209         }
1210     }
1211 
1212     if (valid == FALSE)
1213     {
1214         returnCode = ADDR_INVALIDPARAMS;
1215     }
1216 
1217     return returnCode;
1218 }
1219 
1220 /**
1221 ************************************************************************************************************************
1222 *   Lib::ComputeSurfaceAddrFromCoordTiled
1223 *
1224 *   @brief
1225 *       Internal function to calculate address from coord for tiled swizzle surface
1226 *
1227 *   @return
1228 *       ADDR_E_RETURNCODE
1229 ************************************************************************************************************************
1230 */
ComputeSurfaceAddrFromCoordTiled(const ADDR2_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT * pIn,ADDR2_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT * pOut) const1231 ADDR_E_RETURNCODE Lib::ComputeSurfaceAddrFromCoordTiled(
1232      const ADDR2_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn,    ///< [in] input structure
1233      ADDR2_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT*      pOut    ///< [out] output structure
1234      ) const
1235 {
1236     return HwlComputeSurfaceAddrFromCoordTiled(pIn, pOut);
1237 }
1238 
1239 /**
1240 ************************************************************************************************************************
1241 *   Lib::ComputeSurfaceCoordFromAddrLinear
1242 *
1243 *   @brief
1244 *       Internal function to calculate coord from address for linear swizzle surface
1245 *
1246 *   @return
1247 *       ADDR_E_RETURNCODE
1248 ************************************************************************************************************************
1249 */
ComputeSurfaceCoordFromAddrLinear(const ADDR2_COMPUTE_SURFACE_COORDFROMADDR_INPUT * pIn,ADDR2_COMPUTE_SURFACE_COORDFROMADDR_OUTPUT * pOut) const1250 ADDR_E_RETURNCODE Lib::ComputeSurfaceCoordFromAddrLinear(
1251      const ADDR2_COMPUTE_SURFACE_COORDFROMADDR_INPUT* pIn,    ///< [in] input structure
1252      ADDR2_COMPUTE_SURFACE_COORDFROMADDR_OUTPUT*      pOut    ///< [out] output structure
1253      ) const
1254 {
1255     ADDR_E_RETURNCODE returnCode = ADDR_OK;
1256 
1257     BOOL_32 valid = (pIn->numSamples <= 1) && (pIn->numFrags <= 1);
1258 
1259     if (valid)
1260     {
1261         if (IsTex1d(pIn->resourceType))
1262         {
1263             valid = (pIn->unalignedHeight == 1);
1264         }
1265     }
1266 
1267     if (valid)
1268     {
1269         ADDR2_COMPUTE_SURFACE_INFO_INPUT  localIn  = {0};
1270         ADDR2_COMPUTE_SURFACE_INFO_OUTPUT localOut = {0};
1271         localIn.bpp          = pIn->bpp;
1272         localIn.flags        = pIn->flags;
1273         localIn.width        = Max(pIn->unalignedWidth, 1u);
1274         localIn.height       = Max(pIn->unalignedHeight, 1u);
1275         localIn.numSlices    = Max(pIn->numSlices, 1u);
1276         localIn.numMipLevels = Max(pIn->numMipLevels, 1u);
1277         localIn.resourceType = pIn->resourceType;
1278         if (localIn.numMipLevels <= 1)
1279         {
1280             localIn.pitchInElement = pIn->pitchInElement;
1281         }
1282         returnCode = ComputeSurfaceInfoLinear(&localIn, &localOut);
1283 
1284         if (returnCode == ADDR_OK)
1285         {
1286             pOut->slice = static_cast<UINT_32>(pIn->addr / localOut.sliceSize);
1287             pOut->sample = 0;
1288 
1289             UINT_32 offsetInSlice = static_cast<UINT_32>(pIn->addr % localOut.sliceSize);
1290             UINT_32 elementBytes = pIn->bpp >> 3;
1291             UINT_32 mipOffsetInSlice = 0;
1292             UINT_32 mipSize = 0;
1293             UINT_32 mipId = 0;
1294             for (; mipId < pIn->numMipLevels ; mipId++)
1295             {
1296                 if (IsTex1d(pIn->resourceType))
1297                 {
1298                     mipSize = localOut.pitch * elementBytes;
1299                 }
1300                 else
1301                 {
1302                     UINT_32 currentMipHeight = (PowTwoAlign(localIn.height, (1 << mipId))) >> mipId;
1303                     mipSize = currentMipHeight * localOut.pitch * elementBytes;
1304                 }
1305 
1306                 if (mipSize == 0)
1307                 {
1308                     valid = FALSE;
1309                     break;
1310                 }
1311                 else if ((mipSize + mipOffsetInSlice) > offsetInSlice)
1312                 {
1313                     break;
1314                 }
1315                 else
1316                 {
1317                     mipOffsetInSlice += mipSize;
1318                     if ((mipId == (pIn->numMipLevels - 1)) ||
1319                         (mipOffsetInSlice >= localOut.sliceSize))
1320                     {
1321                         valid = FALSE;
1322                     }
1323                 }
1324             }
1325 
1326             if (valid)
1327             {
1328                 pOut->mipId = mipId;
1329 
1330                 UINT_32 elemOffsetInMip = (offsetInSlice - mipOffsetInSlice) / elementBytes;
1331                 if (IsTex1d(pIn->resourceType))
1332                 {
1333                     if (elemOffsetInMip < localOut.pitch)
1334                     {
1335                         pOut->x = elemOffsetInMip;
1336                         pOut->y = 0;
1337                     }
1338                     else
1339                     {
1340                         valid = FALSE;
1341                     }
1342                 }
1343                 else
1344                 {
1345                     pOut->y = elemOffsetInMip / localOut.pitch;
1346                     pOut->x = elemOffsetInMip % localOut.pitch;
1347                 }
1348 
1349                 if ((pOut->slice >= pIn->numSlices)    ||
1350                     (pOut->mipId >= pIn->numMipLevels) ||
1351                     (pOut->x >= Max((pIn->unalignedWidth >> pOut->mipId), 1u))  ||
1352                     (pOut->y >= Max((pIn->unalignedHeight >> pOut->mipId), 1u)) ||
1353                     (IsTex3d(pIn->resourceType) &&
1354                      (FALSE == Valid3DMipSliceIdConstraint(pIn->numSlices,
1355                                                            pOut->mipId,
1356                                                            pOut->slice))))
1357                 {
1358                     valid = FALSE;
1359                 }
1360             }
1361         }
1362         else
1363         {
1364             valid = FALSE;
1365         }
1366     }
1367 
1368     if (valid == FALSE)
1369     {
1370         returnCode = ADDR_INVALIDPARAMS;
1371     }
1372 
1373     return returnCode;
1374 }
1375 
1376 /**
1377 ************************************************************************************************************************
1378 *   Lib::ComputeSurfaceCoordFromAddrTiled
1379 *
1380 *   @brief
1381 *       Internal function to calculate coord from address for tiled swizzle surface
1382 *
1383 *   @return
1384 *       ADDR_E_RETURNCODE
1385 ************************************************************************************************************************
1386 */
ComputeSurfaceCoordFromAddrTiled(const ADDR2_COMPUTE_SURFACE_COORDFROMADDR_INPUT * pIn,ADDR2_COMPUTE_SURFACE_COORDFROMADDR_OUTPUT * pOut) const1387 ADDR_E_RETURNCODE Lib::ComputeSurfaceCoordFromAddrTiled(
1388      const ADDR2_COMPUTE_SURFACE_COORDFROMADDR_INPUT* pIn,    ///< [in] input structure
1389      ADDR2_COMPUTE_SURFACE_COORDFROMADDR_OUTPUT*      pOut    ///< [out] output structure
1390      ) const
1391 {
1392     ADDR_E_RETURNCODE returnCode = ADDR_NOTIMPLEMENTED;
1393 
1394     ADDR_NOT_IMPLEMENTED();
1395 
1396     return returnCode;
1397 }
1398 
1399 /**
1400 ************************************************************************************************************************
1401 *   Lib::ComputeBlockDimensionForSurf
1402 *
1403 *   @brief
1404 *       Internal function to get block width/height/depth in element from surface input params.
1405 *
1406 *   @return
1407 *       ADDR_E_RETURNCODE
1408 ************************************************************************************************************************
1409 */
ComputeBlockDimensionForSurf(UINT_32 * pWidth,UINT_32 * pHeight,UINT_32 * pDepth,UINT_32 bpp,UINT_32 numSamples,AddrResourceType resourceType,AddrSwizzleMode swizzleMode) const1410 ADDR_E_RETURNCODE Lib::ComputeBlockDimensionForSurf(
1411     UINT_32*         pWidth,
1412     UINT_32*         pHeight,
1413     UINT_32*         pDepth,
1414     UINT_32          bpp,
1415     UINT_32          numSamples,
1416     AddrResourceType resourceType,
1417     AddrSwizzleMode  swizzleMode) const
1418 {
1419     ADDR_E_RETURNCODE returnCode = ADDR_OK;
1420 
1421     if (IsThick(resourceType, swizzleMode))
1422     {
1423         ComputeThickBlockDimension(pWidth, pHeight, pDepth, bpp, resourceType, swizzleMode);
1424     }
1425     else if (IsThin(resourceType, swizzleMode))
1426     {
1427         ComputeThinBlockDimension(pWidth, pHeight, pDepth, bpp, numSamples, resourceType, swizzleMode);
1428     }
1429     else
1430     {
1431         ADDR_ASSERT_ALWAYS();
1432         returnCode = ADDR_INVALIDPARAMS;
1433     }
1434 
1435     return returnCode;
1436 }
1437 
1438 /**
1439 ************************************************************************************************************************
1440 *   Lib::ComputeThinBlockDimension
1441 *
1442 *   @brief
1443 *       Internal function to get thin block width/height/depth in element from surface input params.
1444 *
1445 *   @return
1446 *       N/A
1447 ************************************************************************************************************************
1448 */
ComputeThinBlockDimension(UINT_32 * pWidth,UINT_32 * pHeight,UINT_32 * pDepth,UINT_32 bpp,UINT_32 numSamples,AddrResourceType resourceType,AddrSwizzleMode swizzleMode) const1449 VOID Lib::ComputeThinBlockDimension(
1450     UINT_32*         pWidth,
1451     UINT_32*         pHeight,
1452     UINT_32*         pDepth,
1453     UINT_32          bpp,
1454     UINT_32          numSamples,
1455     AddrResourceType resourceType,
1456     AddrSwizzleMode  swizzleMode) const
1457 {
1458     ADDR_ASSERT(IsThin(resourceType, swizzleMode));
1459 
1460     // GFX9/GFX10 use different dimension amplifying logic: say for 128KB block + 1xAA + 1BPE, the dimension of thin
1461     // swizzle mode will be [256W * 512H] on GFX9 ASICs and [512W * 256H] on GFX10 ASICs. Since GFX10 is newer HWL so we
1462     // make its implementation into base class (in order to save future change on new HWLs)
1463     const UINT_32 log2BlkSize  = GetBlockSizeLog2(swizzleMode);
1464     const UINT_32 log2EleBytes = Log2(bpp >> 3);
1465     const UINT_32 log2Samples  = Log2(Max(numSamples, 1u));
1466     const UINT_32 log2NumEle   = log2BlkSize - log2EleBytes - log2Samples;
1467 
1468     // For "1xAA/4xAA cases" or "2xAA/8xAA + odd log2BlkSize cases", width == height or width == 2 * height;
1469     // For other cases, height == width or height == 2 * width
1470     const BOOL_32 widthPrecedent = ((log2Samples & 1) == 0) || ((log2BlkSize & 1) != 0);
1471     const UINT_32 log2Width      = (log2NumEle + (widthPrecedent ? 1 : 0)) / 2;
1472 
1473     *pWidth  = 1u << log2Width;
1474     *pHeight = 1u << (log2NumEle - log2Width);
1475     *pDepth  = 1;
1476 }
1477 
1478 /**
1479 ************************************************************************************************************************
1480 *   Lib::ComputeBlockDimension
1481 *
1482 *   @brief
1483 *       Internal function to get block width/height/depth in element without considering MSAA case
1484 *
1485 *   @return
1486 *       ADDR_E_RETURNCODE
1487 ************************************************************************************************************************
1488 */
ComputeBlockDimension(UINT_32 * pWidth,UINT_32 * pHeight,UINT_32 * pDepth,UINT_32 bpp,AddrResourceType resourceType,AddrSwizzleMode swizzleMode) const1489 ADDR_E_RETURNCODE Lib::ComputeBlockDimension(
1490     UINT_32*         pWidth,
1491     UINT_32*         pHeight,
1492     UINT_32*         pDepth,
1493     UINT_32          bpp,
1494     AddrResourceType resourceType,
1495     AddrSwizzleMode  swizzleMode) const
1496 {
1497     ADDR_E_RETURNCODE returnCode = ADDR_OK;
1498 
1499     if (IsThick(resourceType, swizzleMode))
1500     {
1501         ComputeThickBlockDimension(pWidth, pHeight, pDepth, bpp, resourceType, swizzleMode);
1502     }
1503     else if (IsThin(resourceType, swizzleMode))
1504     {
1505         ComputeThinBlockDimension(pWidth, pHeight, pDepth, bpp, 0, resourceType, swizzleMode);
1506     }
1507     else
1508     {
1509         ADDR_ASSERT_ALWAYS();
1510         returnCode = ADDR_INVALIDPARAMS;
1511     }
1512 
1513     return returnCode;
1514 }
1515 
1516 /**
1517 ************************************************************************************************************************
1518 *   Lib::ComputeThickBlockDimension
1519 *
1520 *   @brief
1521 *       Internal function to get block width/height/depth in element for thick swizzle mode
1522 *
1523 *   @return
1524 *       N/A
1525 ************************************************************************************************************************
1526 */
ComputeThickBlockDimension(UINT_32 * pWidth,UINT_32 * pHeight,UINT_32 * pDepth,UINT_32 bpp,AddrResourceType resourceType,AddrSwizzleMode swizzleMode) const1527 VOID Lib::ComputeThickBlockDimension(
1528     UINT_32*         pWidth,
1529     UINT_32*         pHeight,
1530     UINT_32*         pDepth,
1531     UINT_32          bpp,
1532     AddrResourceType resourceType,
1533     AddrSwizzleMode  swizzleMode) const
1534 {
1535     ADDR_ASSERT(IsThick(resourceType, swizzleMode));
1536 
1537     const UINT_32 log2BlkSize              = GetBlockSizeLog2(swizzleMode);
1538     const UINT_32 eleBytes                 = bpp >> 3;
1539     const UINT_32 microBlockSizeTableIndex = Log2(eleBytes);
1540 
1541     ADDR_ASSERT(microBlockSizeTableIndex < sizeof(Block1K_3d) / sizeof(Block1K_3d[0]));
1542 
1543     const UINT_32 log2blkSizeIn1KB = log2BlkSize - 10;
1544     const UINT_32 averageAmp       = log2blkSizeIn1KB / 3;
1545     const UINT_32 restAmp          = log2blkSizeIn1KB % 3;
1546 
1547     *pWidth  = Block1K_3d[microBlockSizeTableIndex].w << averageAmp;
1548     *pHeight = Block1K_3d[microBlockSizeTableIndex].h << (averageAmp + (restAmp / 2));
1549     *pDepth  = Block1K_3d[microBlockSizeTableIndex].d << (averageAmp + ((restAmp != 0) ? 1 : 0));
1550 }
1551 
1552 /**
1553 ************************************************************************************************************************
1554 *   Lib::GetMipTailDim
1555 *
1556 *   @brief
1557 *       Internal function to get out max dimension of first level in mip tail
1558 *
1559 *   @return
1560 *       Max Width/Height/Depth value of the first mip fitted in mip tail
1561 ************************************************************************************************************************
1562 */
GetMipTailDim(AddrResourceType resourceType,AddrSwizzleMode swizzleMode,UINT_32 blockWidth,UINT_32 blockHeight,UINT_32 blockDepth) const1563 Dim3d Lib::GetMipTailDim(
1564     AddrResourceType  resourceType,
1565     AddrSwizzleMode   swizzleMode,
1566     UINT_32           blockWidth,
1567     UINT_32           blockHeight,
1568     UINT_32           blockDepth) const
1569 {
1570     Dim3d   out         = {blockWidth, blockHeight, blockDepth};
1571     UINT_32 log2BlkSize = GetBlockSizeLog2(swizzleMode);
1572 
1573     if (IsThick(resourceType, swizzleMode))
1574     {
1575         UINT_32 dim = log2BlkSize % 3;
1576 
1577         if (dim == 0)
1578         {
1579             out.h >>= 1;
1580         }
1581         else if (dim == 1)
1582         {
1583             out.w >>= 1;
1584         }
1585         else
1586         {
1587             out.d >>= 1;
1588         }
1589     }
1590     else
1591     {
1592         ADDR_ASSERT(IsThin(resourceType, swizzleMode));
1593 
1594 #if DEBUG
1595         // GFX9/GFX10 use different dimension shrinking logic for mipmap tail: say for 128KB block + 2BPE, the maximum
1596         // dimension of mipmap tail level will be [256W * 128H] on GFX9 ASICs and [128W * 256H] on GFX10 ASICs. Since
1597         // GFX10 is newer HWL so we make its implementation into base class, in order to save future change on new HWLs.
1598         // And assert log2BlkSize will always be an even value on GFX9, so we never need the logic wrapped by DEBUG...
1599         if ((log2BlkSize & 1) && (m_chipFamily == ADDR_CHIP_FAMILY_AI))
1600         {
1601             // Should never go here...
1602             ADDR_ASSERT_ALWAYS();
1603 
1604             out.h >>= 1;
1605         }
1606         else
1607 #endif
1608         {
1609             out.w >>= 1;
1610         }
1611     }
1612 
1613     return out;
1614 }
1615 
1616 /**
1617 ************************************************************************************************************************
1618 *   Lib::ComputeSurface2DMicroBlockOffset
1619 *
1620 *   @brief
1621 *       Internal function to calculate micro block (256B) offset from coord for 2D resource
1622 *
1623 *   @return
1624 *       micro block (256B) offset for 2D resource
1625 ************************************************************************************************************************
1626 */
ComputeSurface2DMicroBlockOffset(const _ADDR2_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT * pIn) const1627 UINT_32 Lib::ComputeSurface2DMicroBlockOffset(
1628     const _ADDR2_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn) const
1629 {
1630     ADDR_ASSERT(IsThin(pIn->resourceType, pIn->swizzleMode));
1631 
1632     UINT_32 log2ElementBytes = Log2(pIn->bpp >> 3);
1633     UINT_32 microBlockOffset = 0;
1634     if (IsStandardSwizzle(pIn->resourceType, pIn->swizzleMode))
1635     {
1636         UINT_32 xBits = pIn->x << log2ElementBytes;
1637         microBlockOffset = (xBits & 0xf) | ((pIn->y & 0x3) << 4);
1638         if (log2ElementBytes < 3)
1639         {
1640             microBlockOffset |= (pIn->y & 0x4) << 4;
1641             if (log2ElementBytes == 0)
1642             {
1643                 microBlockOffset |= (pIn->y & 0x8) << 4;
1644             }
1645             else
1646             {
1647                 microBlockOffset |= (xBits & 0x10) << 3;
1648             }
1649         }
1650         else
1651         {
1652             microBlockOffset |= (xBits & 0x30) << 2;
1653         }
1654     }
1655     else if (IsDisplaySwizzle(pIn->resourceType, pIn->swizzleMode))
1656     {
1657         if (log2ElementBytes == 4)
1658         {
1659             microBlockOffset = (GetBit(pIn->x, 0) << 4) |
1660                                (GetBit(pIn->y, 0) << 5) |
1661                                (GetBit(pIn->x, 1) << 6) |
1662                                (GetBit(pIn->y, 1) << 7);
1663         }
1664         else
1665         {
1666             microBlockOffset = GetBits(pIn->x, 0, 3, log2ElementBytes)     |
1667                                GetBits(pIn->y, 1, 2, 3 + log2ElementBytes) |
1668                                GetBits(pIn->x, 3, 1, 5 + log2ElementBytes) |
1669                                GetBits(pIn->y, 3, 1, 6 + log2ElementBytes);
1670             microBlockOffset = GetBits(microBlockOffset, 0, 4, 0) |
1671                                (GetBit(pIn->y, 0) << 4) |
1672                                GetBits(microBlockOffset, 4, 3, 5);
1673         }
1674     }
1675     else if (IsRotateSwizzle(pIn->swizzleMode))
1676     {
1677         microBlockOffset = GetBits(pIn->y, 0, 3, log2ElementBytes) |
1678                            GetBits(pIn->x, 1, 2, 3 + log2ElementBytes) |
1679                            GetBits(pIn->x, 3, 1, 5 + log2ElementBytes) |
1680                            GetBits(pIn->y, 3, 1, 6 + log2ElementBytes);
1681         microBlockOffset = GetBits(microBlockOffset, 0, 4, 0) |
1682                            (GetBit(pIn->x, 0) << 4) |
1683                            GetBits(microBlockOffset, 4, 3, 5);
1684         if (log2ElementBytes == 3)
1685         {
1686            microBlockOffset = GetBits(microBlockOffset, 0, 6, 0) |
1687                               GetBits(pIn->x, 1, 2, 6);
1688         }
1689     }
1690 
1691     return microBlockOffset;
1692 }
1693 
1694 /**
1695 ************************************************************************************************************************
1696 *   Lib::ComputeSurface3DMicroBlockOffset
1697 *
1698 *   @brief
1699 *       Internal function to calculate micro block (1KB) offset from coord for 3D resource
1700 *
1701 *   @return
1702 *       micro block (1KB) offset for 3D resource
1703 ************************************************************************************************************************
1704 */
ComputeSurface3DMicroBlockOffset(const _ADDR2_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT * pIn) const1705 UINT_32 Lib::ComputeSurface3DMicroBlockOffset(
1706     const _ADDR2_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn) const
1707 {
1708     ADDR_ASSERT(IsThick(pIn->resourceType, pIn->swizzleMode));
1709 
1710     UINT_32 log2ElementBytes = Log2(pIn->bpp >> 3);
1711     UINT_32 microBlockOffset = 0;
1712     if (IsStandardSwizzle(pIn->resourceType, pIn->swizzleMode))
1713     {
1714         if (log2ElementBytes == 0)
1715         {
1716             microBlockOffset = ((pIn->slice & 4) >> 2) | ((pIn->y & 4) >> 1);
1717         }
1718         else if (log2ElementBytes == 1)
1719         {
1720             microBlockOffset = ((pIn->slice & 4) >> 2) | ((pIn->y & 4) >> 1);
1721         }
1722         else if (log2ElementBytes == 2)
1723         {
1724             microBlockOffset = ((pIn->y & 4) >> 2) | ((pIn->x & 4) >> 1);
1725         }
1726         else if (log2ElementBytes == 3)
1727         {
1728             microBlockOffset = (pIn->x & 6) >> 1;
1729         }
1730         else
1731         {
1732             microBlockOffset = pIn->x & 3;
1733         }
1734 
1735         microBlockOffset <<= 8;
1736 
1737         UINT_32 xBits = pIn->x << log2ElementBytes;
1738         microBlockOffset |= (xBits & 0xf) | ((pIn->y & 0x3) << 4) | ((pIn->slice & 0x3) << 6);
1739     }
1740     else if (IsZOrderSwizzle(pIn->swizzleMode))
1741     {
1742         UINT_32 xh, yh, zh;
1743 
1744         if (log2ElementBytes == 0)
1745         {
1746             microBlockOffset =
1747                 (pIn->x & 1) | ((pIn->y & 1) << 1) | ((pIn->x & 2) << 1) | ((pIn->y & 2) << 2);
1748             microBlockOffset = microBlockOffset | ((pIn->slice & 3) << 4) | ((pIn->x & 4) << 4);
1749 
1750             xh = pIn->x >> 3;
1751             yh = pIn->y >> 2;
1752             zh = pIn->slice >> 2;
1753         }
1754         else if (log2ElementBytes == 1)
1755         {
1756             microBlockOffset =
1757                 (pIn->x & 1) | ((pIn->y & 1) << 1) | ((pIn->x & 2) << 1) | ((pIn->y & 2) << 2);
1758             microBlockOffset = (microBlockOffset << 1) | ((pIn->slice & 3) << 5);
1759 
1760             xh = pIn->x >> 2;
1761             yh = pIn->y >> 2;
1762             zh = pIn->slice >> 2;
1763         }
1764         else if (log2ElementBytes == 2)
1765         {
1766             microBlockOffset =
1767                 (pIn->x & 1) | ((pIn->y & 1) << 1) | ((pIn->x & 2) << 1) | ((pIn->slice & 1) << 3);
1768             microBlockOffset = (microBlockOffset << 2) | ((pIn->y & 2) << 5);
1769 
1770             xh = pIn->x >> 2;
1771             yh = pIn->y >> 2;
1772             zh = pIn->slice >> 1;
1773         }
1774         else if (log2ElementBytes == 3)
1775         {
1776             microBlockOffset =
1777                 (pIn->x & 1) | ((pIn->y & 1) << 1) | ((pIn->slice & 1) << 2) | ((pIn->x & 2) << 2);
1778             microBlockOffset <<= 3;
1779 
1780             xh = pIn->x >> 2;
1781             yh = pIn->y >> 1;
1782             zh = pIn->slice >> 1;
1783         }
1784         else
1785         {
1786             microBlockOffset =
1787                 (((pIn->x & 1) | ((pIn->y & 1) << 1) | ((pIn->slice & 1) << 2)) << 4);
1788 
1789             xh = pIn->x >> 1;
1790             yh = pIn->y >> 1;
1791             zh = pIn->slice >> 1;
1792         }
1793 
1794         microBlockOffset |= ((MortonGen3d(xh, yh, zh, 1) << 7) & 0x380);
1795     }
1796 
1797     return microBlockOffset;
1798 }
1799 
1800 /**
1801 ************************************************************************************************************************
1802 *   Lib::GetPipeXorBits
1803 *
1804 *   @brief
1805 *       Internal function to get bits number for pipe/se xor operation
1806 *
1807 *   @return
1808 *       ADDR_E_RETURNCODE
1809 ************************************************************************************************************************
1810 */
GetPipeXorBits(UINT_32 macroBlockBits) const1811 UINT_32 Lib::GetPipeXorBits(
1812     UINT_32 macroBlockBits) const
1813 {
1814     ADDR_ASSERT(macroBlockBits >= m_pipeInterleaveLog2);
1815 
1816     // Total available xor bits
1817     UINT_32 xorBits = macroBlockBits - m_pipeInterleaveLog2;
1818 
1819     // Pipe/Se xor bits
1820     UINT_32 pipeBits = Min(xorBits, m_pipesLog2 + m_seLog2);
1821 
1822     return pipeBits;
1823 }
1824 
1825 /**
1826 ************************************************************************************************************************
1827 *   Lib::Addr2GetPreferredSurfaceSetting
1828 *
1829 *   @brief
1830 *       Internal function to get suggested surface information for cliet to use
1831 *
1832 *   @return
1833 *       ADDR_E_RETURNCODE
1834 ************************************************************************************************************************
1835 */
Addr2GetPreferredSurfaceSetting(const ADDR2_GET_PREFERRED_SURF_SETTING_INPUT * pIn,ADDR2_GET_PREFERRED_SURF_SETTING_OUTPUT * pOut) const1836 ADDR_E_RETURNCODE Lib::Addr2GetPreferredSurfaceSetting(
1837     const ADDR2_GET_PREFERRED_SURF_SETTING_INPUT* pIn,
1838     ADDR2_GET_PREFERRED_SURF_SETTING_OUTPUT*      pOut) const
1839 {
1840     ADDR_E_RETURNCODE returnCode;
1841 
1842     if ((GetFillSizeFieldsFlags() == TRUE) &&
1843         ((pIn->size != sizeof(ADDR2_GET_PREFERRED_SURF_SETTING_INPUT)) ||
1844          (pOut->size != sizeof(ADDR2_GET_PREFERRED_SURF_SETTING_OUTPUT))))
1845     {
1846         returnCode = ADDR_INVALIDPARAMS;
1847     }
1848     else
1849     {
1850         returnCode = HwlGetPreferredSurfaceSetting(pIn, pOut);
1851     }
1852 
1853     return returnCode;
1854 }
1855 
1856 /**
1857 ************************************************************************************************************************
1858 *   Lib::ComputeBlock256Equation
1859 *
1860 *   @brief
1861 *       Compute equation for block 256B
1862 *
1863 *   @return
1864 *       If equation computed successfully
1865 *
1866 ************************************************************************************************************************
1867 */
ComputeBlock256Equation(AddrResourceType rsrcType,AddrSwizzleMode swMode,UINT_32 elementBytesLog2,ADDR_EQUATION * pEquation) const1868 ADDR_E_RETURNCODE Lib::ComputeBlock256Equation(
1869     AddrResourceType rsrcType,
1870     AddrSwizzleMode swMode,
1871     UINT_32 elementBytesLog2,
1872     ADDR_EQUATION* pEquation) const
1873 {
1874     ADDR_E_RETURNCODE ret;
1875 
1876     if (IsBlock256b(swMode))
1877     {
1878         ret = HwlComputeBlock256Equation(rsrcType, swMode, elementBytesLog2, pEquation);
1879     }
1880     else
1881     {
1882         ADDR_ASSERT_ALWAYS();
1883         ret = ADDR_INVALIDPARAMS;
1884     }
1885 
1886     return ret;
1887 }
1888 
1889 /**
1890 ************************************************************************************************************************
1891 *   Lib::ComputeThinEquation
1892 *
1893 *   @brief
1894 *       Compute equation for 2D/3D resource which use THIN mode
1895 *
1896 *   @return
1897 *       If equation computed successfully
1898 *
1899 ************************************************************************************************************************
1900 */
ComputeThinEquation(AddrResourceType rsrcType,AddrSwizzleMode swMode,UINT_32 elementBytesLog2,ADDR_EQUATION * pEquation) const1901 ADDR_E_RETURNCODE Lib::ComputeThinEquation(
1902     AddrResourceType rsrcType,
1903     AddrSwizzleMode swMode,
1904     UINT_32 elementBytesLog2,
1905     ADDR_EQUATION* pEquation) const
1906 {
1907     ADDR_E_RETURNCODE ret;
1908 
1909     if (IsThin(rsrcType, swMode))
1910     {
1911         ret = HwlComputeThinEquation(rsrcType, swMode, elementBytesLog2, pEquation);
1912     }
1913     else
1914     {
1915         ADDR_ASSERT_ALWAYS();
1916         ret = ADDR_INVALIDPARAMS;
1917     }
1918 
1919     return ret;
1920 }
1921 
1922 /**
1923 ************************************************************************************************************************
1924 *   Lib::ComputeThickEquation
1925 *
1926 *   @brief
1927 *       Compute equation for 3D resource which use THICK mode
1928 *
1929 *   @return
1930 *       If equation computed successfully
1931 *
1932 ************************************************************************************************************************
1933 */
ComputeThickEquation(AddrResourceType rsrcType,AddrSwizzleMode swMode,UINT_32 elementBytesLog2,ADDR_EQUATION * pEquation) const1934 ADDR_E_RETURNCODE Lib::ComputeThickEquation(
1935     AddrResourceType rsrcType,
1936     AddrSwizzleMode swMode,
1937     UINT_32 elementBytesLog2,
1938     ADDR_EQUATION* pEquation) const
1939 {
1940     ADDR_E_RETURNCODE ret;
1941 
1942     if (IsThick(rsrcType, swMode))
1943     {
1944         ret = HwlComputeThickEquation(rsrcType, swMode, elementBytesLog2, pEquation);
1945     }
1946     else
1947     {
1948         ADDR_ASSERT_ALWAYS();
1949         ret = ADDR_INVALIDPARAMS;
1950     }
1951 
1952     return ret;
1953 }
1954 
1955 /**
1956 ************************************************************************************************************************
1957 *   Lib::ComputeQbStereoInfo
1958 *
1959 *   @brief
1960 *       Get quad buffer stereo information
1961 *   @return
1962 *       N/A
1963 ************************************************************************************************************************
1964 */
ComputeQbStereoInfo(ADDR2_COMPUTE_SURFACE_INFO_OUTPUT * pOut) const1965 VOID Lib::ComputeQbStereoInfo(
1966     ADDR2_COMPUTE_SURFACE_INFO_OUTPUT* pOut    ///< [in,out] updated pOut+pStereoInfo
1967     ) const
1968 {
1969     ADDR_ASSERT(pOut->bpp >= 8);
1970     ADDR_ASSERT((pOut->surfSize % pOut->baseAlign) == 0);
1971 
1972     // Save original height
1973     pOut->pStereoInfo->eyeHeight = pOut->height;
1974 
1975     // Right offset
1976     pOut->pStereoInfo->rightOffset = static_cast<UINT_32>(pOut->surfSize);
1977 
1978     // Double height
1979     pOut->height <<= 1;
1980 
1981     ADDR_ASSERT(pOut->height <= MaxSurfaceHeight);
1982 
1983     pOut->pixelHeight <<= 1;
1984 
1985     // Double size
1986     pOut->surfSize  <<= 1;
1987     pOut->sliceSize <<= 1;
1988 }
1989 
1990 /**
1991 ************************************************************************************************************************
1992 *   Lib::FilterInvalidEqSwizzleMode
1993 *
1994 *   @brief
1995 *       Filter out swizzle mode(s) if it doesn't have valid equation index
1996 *
1997 *   @return
1998 *       N/A
1999 ************************************************************************************************************************
2000 */
FilterInvalidEqSwizzleMode(ADDR2_SWMODE_SET & allowedSwModeSet,AddrResourceType resourceType,UINT_32 elemLog2) const2001 VOID Lib::FilterInvalidEqSwizzleMode(
2002     ADDR2_SWMODE_SET& allowedSwModeSet,
2003     AddrResourceType  resourceType,
2004     UINT_32           elemLog2
2005     ) const
2006 {
2007     if (resourceType != ADDR_RSRC_TEX_1D)
2008     {
2009         UINT_32       allowedSwModeSetVal = allowedSwModeSet.value;
2010         const UINT_32 rsrcTypeIdx         = static_cast<UINT_32>(resourceType) - 1;
2011         UINT_32       validSwModeSet      = allowedSwModeSetVal;
2012 
2013         for (UINT_32 swModeIdx = 1; validSwModeSet != 0; swModeIdx++)
2014         {
2015             if (validSwModeSet & 1)
2016             {
2017                 if (m_equationLookupTable[rsrcTypeIdx][swModeIdx][elemLog2] == ADDR_INVALID_EQUATION_INDEX)
2018                 {
2019                     allowedSwModeSetVal &= ~(1u << swModeIdx);
2020                 }
2021             }
2022 
2023             validSwModeSet >>= 1;
2024         }
2025 
2026         // Only apply the filtering if at least one valid swizzle mode remains
2027         if (allowedSwModeSetVal != 0)
2028         {
2029             allowedSwModeSet.value = allowedSwModeSetVal;
2030         }
2031     }
2032 }
2033 
2034 /**
2035 ************************************************************************************************************************
2036 *   Lib::IsBlockTypeAvaiable
2037 *
2038 *   @brief
2039 *       Determine whether a block type is allowed in a given blockSet
2040 *
2041 *   @return
2042 *       N/A
2043 ************************************************************************************************************************
2044 */
IsBlockTypeAvaiable(ADDR2_BLOCK_SET blockSet,AddrBlockType blockType)2045 BOOL_32 Lib::IsBlockTypeAvaiable(
2046     ADDR2_BLOCK_SET blockSet,
2047     AddrBlockType   blockType)
2048 {
2049     BOOL_32 avail;
2050 
2051     if (blockType == AddrBlockLinear)
2052     {
2053         avail = blockSet.linear ? TRUE : FALSE;
2054     }
2055     else
2056     {
2057         avail = blockSet.value & (1 << (static_cast<UINT_32>(blockType) - 1)) ? TRUE : FALSE;
2058     }
2059 
2060     return avail;
2061 }
2062 
2063 /**
2064 ************************************************************************************************************************
2065 *   Lib::BlockTypeWithinMemoryBudget
2066 *
2067 *   @brief
2068 *       Determine whether a new block type is acceptible based on memory waste ratio
2069 *
2070 *   @return
2071 *       N/A
2072 ************************************************************************************************************************
2073 */
BlockTypeWithinMemoryBudget(UINT_64 minSize,UINT_64 newBlockTypeSize,UINT_32 ratioLow,UINT_32 ratioHi,DOUBLE memoryBudget,BOOL_32 newBlockTypeBigger)2074 BOOL_32 Lib::BlockTypeWithinMemoryBudget(
2075     UINT_64 minSize,
2076     UINT_64 newBlockTypeSize,
2077     UINT_32 ratioLow,
2078     UINT_32 ratioHi,
2079     DOUBLE  memoryBudget,
2080     BOOL_32 newBlockTypeBigger)
2081 {
2082     BOOL_32 accept = FALSE;
2083 
2084     if (memoryBudget >= 1.0)
2085     {
2086         if (newBlockTypeBigger)
2087         {
2088             if ((static_cast<DOUBLE>(newBlockTypeSize) / minSize) <= memoryBudget)
2089             {
2090                 accept = TRUE;
2091             }
2092         }
2093         else
2094         {
2095             if ((static_cast<DOUBLE>(minSize) / newBlockTypeSize) > memoryBudget)
2096             {
2097                 accept = TRUE;
2098             }
2099         }
2100     }
2101     else
2102     {
2103         if (newBlockTypeBigger)
2104         {
2105             if ((newBlockTypeSize * ratioHi) <= (minSize * ratioLow))
2106             {
2107                 accept = TRUE;
2108             }
2109         }
2110         else
2111         {
2112             if ((newBlockTypeSize * ratioLow) < (minSize * ratioHi))
2113             {
2114                 accept = TRUE;
2115             }
2116         }
2117     }
2118 
2119     return accept;
2120 }
2121 
2122 #if DEBUG
2123 /**
2124 ************************************************************************************************************************
2125 *   Lib::ValidateStereoInfo
2126 *
2127 *   @brief
2128 *       Validate stereo info by checking a few typical cases
2129 *
2130 *   @return
2131 *       N/A
2132 ************************************************************************************************************************
2133 */
ValidateStereoInfo(const ADDR2_COMPUTE_SURFACE_INFO_INPUT * pIn,const ADDR2_COMPUTE_SURFACE_INFO_OUTPUT * pOut) const2134 VOID Lib::ValidateStereoInfo(
2135     const ADDR2_COMPUTE_SURFACE_INFO_INPUT*  pIn,   ///< [in] input structure
2136     const ADDR2_COMPUTE_SURFACE_INFO_OUTPUT* pOut   ///< [in] output structure
2137     ) const
2138 {
2139     ADDR2_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT addrIn = {};
2140     addrIn.size            = sizeof(addrIn);
2141     addrIn.swizzleMode     = pIn->swizzleMode;
2142     addrIn.flags           = pIn->flags;
2143     addrIn.flags.qbStereo  = 0;
2144     addrIn.resourceType    = pIn->resourceType;
2145     addrIn.bpp             = pIn->bpp;
2146     addrIn.unalignedWidth  = pIn->width;
2147     addrIn.numSlices       = pIn->numSlices;
2148     addrIn.numMipLevels    = pIn->numMipLevels;
2149     addrIn.numSamples      = pIn->numSamples;
2150     addrIn.numFrags        = pIn->numFrags;
2151 
2152     // Call Addr2ComputePipeBankXor() and validate different pbXor value if necessary...
2153     const UINT_32 pbXor = 0;
2154 
2155     ADDR2_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT addrOut = {};
2156     addrOut.size = sizeof(addrOut);
2157 
2158     // Make the array to be {0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096} for full test
2159     const UINT_32 TestCoord[] = {0};
2160 
2161     for (UINT_32 xIdx = 0; xIdx < sizeof(TestCoord) / sizeof(TestCoord[0]); xIdx++)
2162     {
2163         if (TestCoord[xIdx] < pIn->width)
2164         {
2165             addrIn.x = TestCoord[xIdx];
2166 
2167             for (UINT_32 yIdx = 0; yIdx  < sizeof(TestCoord) / sizeof(TestCoord[0]); yIdx++)
2168             {
2169                 if (TestCoord[yIdx] < pIn->height)
2170                 {
2171                     addrIn.y               = TestCoord[yIdx] + pOut->pStereoInfo->eyeHeight;
2172                     addrIn.pipeBankXor     = pbXor ^ pOut->pStereoInfo->rightSwizzle;
2173                     addrIn.unalignedHeight = pIn->height + pOut->pStereoInfo->eyeHeight;
2174 
2175                     ADDR_E_RETURNCODE ret = ComputeSurfaceAddrFromCoord(&addrIn, &addrOut);
2176                     ADDR_ASSERT(ret == ADDR_OK);
2177 
2178                     const UINT_64 rightEyeOffsetFromBase = addrOut.addr;
2179 
2180                     addrIn.y               = TestCoord[yIdx];
2181                     addrIn.pipeBankXor     = pbXor;
2182                     addrIn.unalignedHeight = pIn->height;
2183 
2184                     ret = ComputeSurfaceAddrFromCoord(&addrIn, &addrOut);
2185                     ADDR_ASSERT(ret == ADDR_OK);
2186 
2187                     const UINT_64 rightEyeOffsetRelative = addrOut.addr;
2188 
2189                     ADDR_ASSERT(rightEyeOffsetFromBase == rightEyeOffsetRelative + pOut->pStereoInfo->rightOffset);
2190                 }
2191             }
2192         }
2193     }
2194 }
2195 #endif
2196 
2197 } // V2
2198 } // Addr
2199 
2200