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