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